zend-frameworkzend-navigationzend-authzend-acl

Zend Navigation Multiple ACL roles


I am trying to create an ACL where users may have different roles in different departments.

The user is given a role in the form of role::guest or role::user depending if they are logged in. This is their userRole. (There is also a role::superuser that has access to all departments).

I have also added departmental roles to the ACL in the form of department::role (Eg. bookings::user). This is their departmentRole.

The users departmental roles are stored in the Zend_Auth identity.

The access control part works by extending Zend_Acl and over-riding the isAllowed function. This successfully allows or denys each user.

public function isAllowed($role = null, $resource = null, $privilege = null)
    {
    $identity = Zend_Auth::getInstance()->getIdentity();

    $userRole = $identity->role;
    $departmentRoles = $identity->departmentRoles; 

    if (parent::isAllowed($userRole, $resource, $privilege))
        {
        return parent::isAllowed($userRole, $resource, $privilege);
        }
        else    {
                foreach ($departmentRoles as $departmentRole)
                    {
                    if(parent::isAllowed($departmentRole, $resource, $privilege))
                        {
                        return true;
                        }
                    }
                }

    return false;       
    }

The problem I am having is that Zend_Navigation requires an instance of the Acl and a single user role. My view script which builds the navigation menu uses $this->navigation()->accept($page) which only validates against the single user role.

How can I have multiple Acl roles for each user and have Zend_Navigation display menu items that they have access to?

If there is a better / different / correct approach to this please share.

Thanks

EDIT:

The fact that this approach meant over riding a core function in isAllowed() got me thinking this can't be the correct way to do this.

Now, in my ACL model I fetch all users, departments and associations and loop through creating an array for each user made up of their various roles within their relevant departments. I then create one role for each user and inherit the roles in the array previously created.

This is working well up to now and also means I can also add the users as resources and allow the relevant admin and department managers rights to amend their details etc.

It also means that I can pass a single role to Zend_Navigation and the menu structure should be relevant to their department roles.


Solution

  • IMHO having multiple ACL roles for single user looks like anti-pattern. Zend_Navigation rules are binded to (multiple) resources for single role which makes perferct sense. What are your constraints that forbids you to allow resources for your (department) roles? You can always use inheritance for your ACL roles.

    If you prefer having multiple roles for single user, you might need to have separate ACL rules.

     Zend_View_Helper_Navigation_HelperAbstract::setDefaultAcl($acl);
    
     Zend_View_Helper_Navigation_HelperAbstract::setDefaultRole($role);