Zend_Acl, How to check a user with multiple roles for resource access
Asked Answered
H

1

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.

Haslett answered 26/1, 2013 at 19:1 Comment(1)
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...Ferrol
E
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);
    }
}
Est answered 26/1, 2013 at 19:9 Comment(4)
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.Asleyaslope
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.Est
If anyone have trouble extending; this page helped me laravel.com/docs/5.0/extendingGovea
Clever solution, might be cleaner to split into a separate method like isUserAllowed($user, $resource = null, $privilege = null) or alike, but it works.Pacific

© 2022 - 2024 — McMap. All rights reserved.