Installation
composer require atoolo/extranet-bundle
Add to config/bundles.php:
return [
// ...
Atoolo\ExtranetBundle\AtooloExtranetBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console config:dump-reference AtooloExtranetBundle
Update config/packages/atoolo_extranet.yaml:
atoolo_extranet:
enabled: true
graphql_access_control: true
controller_access_control: true
First Use Case Secure a GraphQL endpoint by annotating your resolver:
use Atoolo\ExtranetBundle\Annotation\Secure;
#[Secure]
class MyResolver {
// ...
}
GraphQL Security
@Secure on resolvers or fields to enforce access control.AtooloExtranetBundle\Event\AccessControlEvent listeners.#[Secure(roles: ['ROLE_CLIENT'])]
public function resolveClientData() { ... }
Controller Security
#[Secure]
#[Route('/api/client-data', name: 'client_data')]
public function getClientData(): Response { ... }
#[Secure]
class ClientController { ... }
Integration with Symfony Security
ROLE_* roles or custom voter logic:
# config/packages/security.yaml
access_control:
- { path: ^/api/client, roles: ROLE_CLIENT }
Custom Access Logic
extranet.access_control event:
$eventDispatcher->addListener(
AtooloExtranetBundle\Event\AccessControlEvent::class,
fn(AccessControlEvent $event) => $event->allowIf(
$event->getUser()->hasRole('CUSTOM_ROLE')
)
);
Namespace Conflicts
Atoolo\ExtranetBundle\Annotation\Secure is imported correctly (not mixed with Symfony’s @Secure).GraphQL Caching
@Secure with dynamic rules:
# config/packages/graphql.yaml
overblog_graphql:
resolvers:
MyResolver:
cache: false
Role Inheritance
ROLE_CLIENT requiring ROLE_ADMIN which requires ROLE_CLIENT).Performance Overhead
$event->allowIf($event->getUser()->isGranted('IS_AUTHENTICATED_FULLY'));
Enable Verbose Logging
# config/packages/atoolo_extranet.yaml
debug: true
Logs access control decisions to var/log/dev.log.
Check Event Dispatching
Use Symfony’s profiler (/_profiler) to verify AccessControlEvent listeners fire.
Custom Annotations
Extend Secure via traits or new annotations:
#[Attribute]
class CustomSecure extends Secure {
public function __construct(public string $customRule) {}
}
Database-Backed Rules
Store rules in a extranet_rules table and hydrate them in a listener:
$event->allowIf($this->ruleRepository->isAllowed($event->getUser(), $event->getPath()));
IP Whitelisting
Combine with Symfony’s IpWhitelistVoter:
security:
access_control:
- { path: ^/api/admin, roles: ROLE_ADMIN, ip: 192.168.1.0/24 }
How can I help you explore Laravel packages today?