Zend permissions rbac - Inheritance permissions

expressive

#1

Hi, I’m using right now the component zend-permissions-rbac to achieve the authorization process in my expressive application. I’m struggling to figure out how to solve the following problem that crossed my mind:

The component automatically allow to any role to inherit the permissions of their children which is a beautiful feature that go along with almost all my permissions.
I want to be able to avoid this feature only with some specific permissions, so that only the role associated with it can access it.

Example of a hierarchy structure of roles:

$role=$rbac->addRole('role');
$subRole = $rbac->addRole('subrole');
$role->addChild($subRole);

$role->addPermission('permission1');
$role->addPermission('permission2');

// This permission should be not accessible by the role parent
$subRole->addPermission('permission3');

// This permission must be accessibile by the role parent
$subRole->addPermission('permission4');




I want to maintain the hierarchy structure of the roles, this means that I don’t want to remove children for the role which can cause the explained problem and I don’t really like the first solution.

Solutions:

  1. Creating an assert associated with the right permissions which do the following check:
class AssertOnlyMyRole implements AssertionInterface
{
    public function assert(Rbac $rbac)
    {
        if($permission='permission3'){
           return $this->role=='subrole';
        }
    }
}
  1. Overwriting the hasPermission() of the AbstractRole class in this way:
class MyRole extends AbstractRole{

private $excludePermissionsCheckOnChildren=['permission3'];

 public function hasPermission($name)
    {
        if (isset($this->permissions[$name])) {
            return true;
        }
        if(!in_array($name, $excludePermissionsCheckOnChildren)){
           $it = new RecursiveIteratorIterator($this, RecursiveIteratorIterator::CHILD_FIRST);
           foreach ($it as $leaf) {
            /** @var RoleInterface $leaf */
               if ($leaf->hasPermission($name)) {
                  return true;
               }
            }
            return false;
        }
    }
}

Can someone suggest improvements to my ideas or help me?

Thank you.


#2

If $subRole is a child of $role all the permissions of $subRole are valid for $role, so you cannot have permission3 of $subRole that not accessible by parent role ($role). You need to change the hierarchy model.

That said, you can implement a custom AssertionInterface, as you suggested, using the latest changes (still in review) of the interface:

assert(Rbac $rbac, string $permission = null, RoleInterface $role = null)

More info here: https://github.com/zendframework/zend-permissions-rbac/pull/34