I am building a basic site skeleton (currently using 1.12.1) that
allows users with sufficient rights to modify the ACL from within the
site itself. Roles, resources and rules are all saved in a database. I
created a Security Administrator role that has full access to
everything in the security module. So far, so good. However, I would
like to allow users to add/remove role members but prevent users of
ANY role - including members of Security Administrator or its
descendants - from editing or deleting the role.

I tried this:

        $this->deny(null, 'Security_Model_Role, 'edit' , new
Application_Acl_Assert_IsSecurityAdministratorRole());

but it didn't quite work because the null will never supersede an
explicit allow($role, ...) statement, regardless of the order added to
the ACL.

Next, I tried this at the end of a method that loads all the roles
from the table:

        foreach ($this->getRoles() as $role) {
            $this->deny($role, 'Security_Model_Role', 'edit', new
Application_Acl_Assert_IsSecurityAdministratorRole());
            $this->deny($role, 'Security_Model_Role', 'delete', new
Application_Acl_Assert_IsSecurityAdministratorRole());
        }

It works, but it seems somewhat heavy to have to add these two rules
for EVERY role in the entire ACL. (Most sites won't have that many
roles, so fortunately it shouldn't be much of a performance issue.) It
also does not prevent code elsewhere from adding a new role and/or
permission to override this.

This led me to try overriding the isAllowed method with this:

    public function isAllowed($role = null, $resource = null, $privilege = null)
    {

        $resource_id = ($resource instanceof
Zend_Acl_Resource_Interface) ? $resource->getResourceId() : $resource;
        if (null !== $role && $resource_id == 'Security_Model_Role') {
            $this->removeAllow($role, 'Security_Model_Role', 'delete');
            $this->removeAllow($role, 'Security_Model_Role', 'edit');
            $this->deny($role, 'Security_Model_Role', 'edit', new
Application_Acl_Assert_IsSecurityAdministratorRole());
            $this->deny($role, 'Security_Model_Role', 'delete', new
Application_Acl_Assert_IsSecurityAdministratorRole());
        }
        return parent::isAllowed($role, $resource, $privilege);
    }


Now no matter how late I add a role or rule to the ACL it prevents
undesired activity (so it works) but it still seems it makes the rules
list heavy and it also seems somewhat "wrong" to add rule logic to the
isAllowed method. Is there a better way to approach this?

Also, I saw some discussion in the issue tracker
(http://framework.zend.com/issues/browse/ZF-5369) that I believe is
pertinent to this that suggested the only way to do a deny-to-all
would cause a BC break and would have to be deferred to ZF2. Given
that the ACL documentation for ZF2 looks pretty much identical to
1.12.1, and the issue status is still unresolved/postponed, is this
issue still true of ZF2?

Andrew

-- 
List: [email protected]
Info: http://framework.zend.com/archives
Unsubscribe: [email protected]


Reply via email to