6


i am implementing RBAC for my app, and everything is managed from database.

for example i am storing all resources/permissions in a table called permission , all roles in role table, and another table called role_permission to define which role have access to which resources/permissions.

the purpose for going with this approach is because i want the administrator of the app to create the role and assign the permission to role by himself.

User of the app can have multiple roles for example administrator, supervisor, player, referee etc.

I created a model class for Zend_Acl to add roles and resources and assign permission to it.

Below is what i did.

foreach($this->_roles as $role) {
    $this->addRole(new Zend_Acl_Role($role['id']));
}
foreach($this->_permissions as $permmission) {
    $this->addResource(new Zend_Acl_Resource($permmission['id']));
}
foreach($this->_rolePermissions as $value) {
    $this->allow($value['role_id'], $value['permmission_id']);
}
$this->allow($this->_roleAdmin);

it works fine if i want to check wether a permission exist for a particular role for example by using this code.

echo $acl->isAllowed($role, $permission) ? 'allowed' : 'denied';

however i want to check with multiple roles wether the current permission exist for a user with multiple roles.

how am i supposed to check wether the user with multiple roles such as referee, supervisor has the access to resource create report. with isAllowed() you can only check for permission for only 1 role.

Ibrahim Azhar Armar
  • 25,288
  • 35
  • 131
  • 207
  • Its been awhile, but IIRC the Zend_ACL was hierarchical so you would take role at a certain point and it would resolve the permissions baesd on the the tree... ofcours if your roles are different trees then that doesnt help... – prodigitalson Jan 26 '13 at 19:07

1 Answers1

10

The approach I usually take is to create a class that extends Zend_Acl, and extend the isAllowed() function so it can take my user object as a parameter instead. It then loops through that user's roles performing the check for each one. E.g.:

public function isAllowed($roleOrUser = null, $resource = null, $privilege = null)
{
    if ($roleOrUser instanceof Users_Model_User) {
        // check each of that user's roles
        foreach ($roleOrUser->roles as $role) {
            if (parent::isAllowed($role, $resource, $privilege)) {
                return true;
            }
        }

        return false;
    } else {
        return parent::isAllowed($roleOrUser, $resource, $privilege);
    }
}
Tim Fountain
  • 33,093
  • 5
  • 41
  • 69
  • I'm trying to create a way that scales so I'm attempting to drop loops if possible. Is there a way to access all the roles that are allowed for a given resource from the acl object? That way I can check my array of roles and see if it is one of the ones allowed to access the resource. – Greg Jan 09 '14 at 01:35
  • Such a method would still need to loop through the roles and check them in succession. Presumably users don't have that many roles so I doubt this would be any sort of performance problem. – Tim Fountain Jan 09 '14 at 11:16
  • If anyone have trouble extending; this page helped me http://laravel.com/docs/5.0/extending – jrewing Jun 03 '15 at 08:14
  • Clever solution, might be cleaner to split into a separate method like `isUserAllowed($user, $resource = null, $privilege = null)` or alike, but it works. – i-- Mar 08 '16 at 15:35