Create isGranted View Helper for Mezzio Application with mezzio-authorization-acl component
This post is inspired by @KiwiJuicer question at Laminas’s Slack, about how to verify granted access on resource in the layout or view part, eg:
<?php if ($this->isGranted('admin.add')) : ?> <button name="add">Add</button> <?php endif; ?>
OR
<?php if ($this->isGranted('admin.edit', ['id' => 1])) : ?> <button name="edit">Edit</button> <?php endif; ?>
We can use Mezzio\Authorization\LaminasAcl
service, but it requires a Psr\Http\Message\ServerRequestInterface
instance to be passed at 2nd parameter as signature:
public function isGranted(string $role, ServerRequestInterface $request) : bool { }
We can pull the role from session, but how about Psr\Http\Message\ServerRequestInterface
instance? Well, we don’t need middleware to fill that! We can create a RouteResult from Mezzio\Router\LaminasRouter
service with utilize Mezzio\LaminasView\UrlHelper
to get path from route name as resource name, with use Laminas\Diactoros\ServerRequestFactory
to create Laminas\Diactoros\ServerRequest
instance, so, the view helper can be as follow:
<?php // src/App/View/Helper/IsGranted.php declare(strict_types=1); namespace App\View\Helper; use Laminas\Diactoros\ServerRequestFactory; use Laminas\Diactoros\Uri; use Laminas\View\Helper\AbstractHelper; use Mezzio\Authorization\Acl\LaminasAcl; use Mezzio\LaminasView\UrlHelper; use Mezzio\Router\LaminasRouter; use Mezzio\Router\RouteResult; class IsGranted extends AbstractHelper { private $acl; private $getRole; private $url; private $router; public function __construct( LaminasAcl $acl, GetRole $getRole, UrlHelper $url, LaminasRouter $router ) { $this->acl = $acl; $this->getRole = $getRole; $this->url = $url; $this->router = $router; } public function __invoke( string $resource, array $routeParams = [], array $queryParams = [] ): bool { $request = ServerRequestFactory::fromGlobals(); $request = $request->withUri( new Uri(($this->url)($resource, $routeParams, $queryParams)) ); $request = $request->withAttribute( RouteResult::class, $this->router->match($request) ); return $this->acl->isGranted(($this->getRole)(), $request); } }
Above, I assume that you already have another view helper or service to get role, eg, named App\View\Helper\GetRole
so the factory for the isGranted
view helper can be as follow:
<?php // src/App/View/Helper/IsGrantedFactory.php declare(strict_types=1); namespace App\View\Helper; use Laminas\View\HelperPluginManager; use Mezzio\Authorization\Acl\LaminasAcl; use Mezzio\Router\LaminasRouter; use Psr\Container\ContainerInterface; class IsGrantedFactory { public function __invoke(ContainerInterface $container): IsGranted { $acl = $container->get(LaminasAcl::class); $helperPluginManager = $container->get(HelperPluginManager::class); $getRole = $helperPluginManager->get('getRole'); $url = $helperPluginManager->get('url'); $router = $container->get(LaminasRouter::class); return new IsGranted($acl, $getRole, $url, $router); } }
We can register the view helper to App\ConfigProvider
class:
<?php // src/App/ConfigProvider.php declare(strict_types=1); namespace App; class ConfigProvider { public function __invoke(): array { return [ 'dependencies' => $this->getDependencies(), 'templates' => $this->getTemplates(), 'view_helpers' => [ 'invokables' => [ 'getRole' => View\Helper\GetRole::class, ], 'factories' => [ 'isGranted' => View\Helper\IsGrantedFactory::class, ], ], ]; } public function getDependencies(): array { /* */ } public function getTemplates(): array { /* */ } }
Now, we can check use “$this->isGranted($resource)” or “$this->isGranted($resource, $routeParams, $queryParams)” check in the layout or view.
This source code example can be found at samsonasik/mezzio-authentication-with-authorization repository that you can try yourself 😉
leave a comment