danilovl/permission-middleware-bundle
Installation:
composer require danilovl/permission-middleware-bundle
Ensure Danilovl\PermissionMiddlewareBundle\PermissionMiddlewareBundle::class is registered in config/bundles.php.
Basic Configuration:
Add to config/packages/danilovl_permission_middleware.yaml:
danilovl_permission_middleware:
kernel_controller_priority: 2048 # Default: 2048 (high priority)
kernel_response_priority: 0 # Default: 0 (low priority)
First Use Case: Annotate a controller method to restrict access:
use Danilovl\PermissionMiddlewareBundle\Annotation\Permission;
class AdminController extends AbstractController
{
#[Permission('ROLE_ADMIN')]
public function dashboard(): Response
{
return $this->render('admin/dashboard.html.twig');
}
}
#[Permission('ROLE_SUPER_ADMIN')]
class AdminController extends AbstractController
{
// All methods require ROLE_SUPER_ADMIN
}
class UserController extends AbstractController
{
#[Permission('ROLE_USER')]
public function profile(): Response { ... }
#[Permission('ROLE_EDITOR')]
public function editProfile(): Response { ... }
}
#[Permission(function (Request $request): bool {
return $request->get('token') === 'secret';
})]
public function secureAction(): Response { ... }
# config/packages/security.yaml
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
Use the bundle for additional middleware checks (e.g., method-level overrides).PermissionProviderInterface:
use Danilovl\PermissionMiddlewareBundle\Permission\PermissionProviderInterface;
class CustomPermissionProvider implements PermissionProviderInterface
{
public function hasPermission(string $permission, Request $request): bool
{
// Custom logic (e.g., check database, API, etc.)
return true;
}
}
Register in services:
services:
Danilovl\PermissionMiddlewareBundle\Permission\PermissionProviderInterface:
class: App\Service\CustomPermissionProvider
config/packages/danilovl_permission_middleware.yaml:
danilovl_permission_middleware:
kernel_controller_priority: 1024 # Lower = earlier execution
kernel_response_priority: 1024 # Higher = later execution
Annotation Caching:
php bin/console cache:clear) after adding/removing annotations.#[Permission] only on public methods—private/protected methods are ignored.Priority Conflicts:
kernel_controller_priority vs. other middleware (e.g., Symfony’s SecurityMiddleware).2048 works for most cases, but adjust if using custom middleware.Dynamic Permissions in Tests:
PermissionProviderInterface in PHPUnit:
$this->mockBuilder->setMethods(['hasPermission'])
->getMock()
->method('hasPermission')
->willReturn(true);
Symfony 8+ Compatibility:
autowire: true is enabled in config/services.yaml for dependency injection to work.danilovl_permission_middleware:
debug: true # Logs denied permissions to Symfony's profiler
PermissionMiddlewareBundle events in the Symfony profiler under "Middleware."Custom Attributes:
Permission attribute to add metadata:
#[Attribute]
class CustomPermission extends Permission
{
public function __construct(public string $scope) {}
}
PermissionReader to handle custom attributes.Event Listeners:
permission.denied events:
use Danilovl\PermissionMiddlewareBundle\Event\PermissionDeniedEvent;
public function onPermissionDenied(PermissionDeniedEvent $event): void
{
$event->setResponse(new RedirectResponse('/unauthorized'));
}
Register in config/services.yaml:
services:
App\EventListener\PermissionListener:
tags:
- { name: kernel.event_listener, event: permission.denied, method: onPermissionDenied }
Performance:
#[Permission(cache: true, ttl: 3600)] // Cache for 1 hour
public function cachedAction(): Response { ... }
config/packages/overrides/danilovl_permission_middleware.php) for complex logic:
return [
'kernel_controller_priority' => getenv('PERMISSION_PRIORITY') ?: 2048,
];
%env() in YAML:
danilovl_permission_middleware:
debug: '%kernel.debug%'
How can I help you explore Laravel packages today?