A free and open-source book on ZF3 for beginners


17.14. Adding Access Controller Plugin and View Helper

To query RbacManager inside of controllers and view templates, we need to create a special controller plugin (which we will name Access) and a special view helper (which we will name Access too).

17.14.1. Access Controller Plugin

Sometimes it is required to check some permission inside the controller. For example, this is needed for the profile.own.view permission, which uses the dynamic assertion. For this purpose, we will create the Access controller plugin.

The plugin code will be located inside the AccessPlugin.php file inside the Controller/Plugin directory of the User module's source directory:

<?php
namespace User\Controller\Plugin;

use Zend\Mvc\Controller\Plugin\AbstractPlugin;

/**
 * This controller plugin is used for role-based access control (RBAC).
 */
class AccessPlugin extends AbstractPlugin
{
    private $rbacManager;
    
    public function __construct($rbacManager)
    {
        $this->rbacManager = $rbacManager;
    }
    
    /**
     * Checks whether the currently logged in user has the given permission.
     * @param string $permission Permission name.
     * @param array $params Optional params (used only if an assertion is associated with permission).
     */
    public function __invoke($permission, $params = [])
    {
        return $this->rbacManager->isGranted(null, $permission, $params);
    }
}

The Access plugin's factory looks like the following:

<?php
namespace User\Controller\Plugin\Factory;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use User\Service\RbacManager;
use User\Controller\Plugin\AccessPlugin;

/**
 * This is the factory for AccessPlugin. Its purpose is to instantiate the plugin
 * and inject dependencies into its constructor.
 */
class AccessPluginFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {   
        $rbacManager = $container->get(RbacManager::class);
        
        return new AccessPlugin($rbacManager);
    }
}

The plugin is registered inside the module.config.php file as follows:

// We register module-provided controller plugins under this key.
'controller_plugins' => [
    'factories' => [
        Controller\Plugin\AccessPlugin::class => Controller\Plugin\Factory\AccessPluginFactory::class,
    ],
    'aliases' => [
        'access' => Controller\Plugin\AccessPlugin::class,
    ],
],

So, in your controller's action, you can easily call this plugin like the following:

if (!$this->access('profile.own.view', ['user'=>$user])) {
    return $this->redirect()->toRoute('not-authorized');
}        

17.14.2. Access View Helper

Sometimes, it may be required to query the RbacManager inside a view template. For example, you may need to hide or show some HTML block based on current user's permissions. To do that, we will implement the Access view helper.

The view helper's code will be located inside the Access.php file inside the View/Helper directory of the User module's source directory:

<?php
namespace User\View\Helper;

use Zend\View\Helper\AbstractHelper;

/**
 * This view helper is used to check user permissions.
 */
class Access extends AbstractHelper 
{
    private $rbacManager = null;
    
    public function __construct($rbacManager) 
    {
        $this->rbacManager = $rbacManager;
    }
    
    public function __invoke($permission, $params = [])
    {
        return $this->rbacManager->isGranted(null, $permission, $params);
    }
}

The Access view helper's factory looks like the following:

<?php
namespace User\View\Helper\Factory;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use User\Service\RbacManager;
use User\View\Helper\Access;

/**
 * This is the factory for Access view helper. Its purpose is to instantiate the helper
 * and inject dependencies into its constructor.
 */
class AccessFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {   
        $rbacManager = $container->get(RbacManager::class);
        
        return new Access($rbacManager);
    }
}

The view helper is registered inside the module.config.php config file as follows:

// We register module-provided view helpers under this key.
'view_helpers' => [
    'factories' => [
        View\Helper\Access::class => View\Helper\Factory\AccessFactory::class,
    ],
    'aliases' => [
        'access' => View\Helper\Access::class,
    ],
],

So, you can easily call the view helper from any of your view templates as follows:

if ($this->access('profile.own.view, ['user'=>$user]))) {
   // do something...
}

Top