ZF-3390: Inheritage of roles: rules are checked by parent roles

Description

Hi,

I think there is a problem of inheritage of roles. If an inhertited role is checked by isAllowed(), the rules are checked on an instance (Zend_Acl_Role) of the parent and not on the instance of the current role.

Example:

ACL definitions


class TestAcl extends Zend_Acl {

    public function __construct() {
        $this->add(new Zend_Acl_Resource('video'));

        $this->addRole(new Zend_Acl_Role('guest'));
        $this->addRole(new Zend_Acl_Role('member'), 'guest');

        $this->allow('guest', 'video', 'watch', new VideoWatchAssertion());
        $this->allow('member');
    }
}

class Video implements Zend_Acl_Resource_Interface {

    public $property;

    public function __construct($p) {
        $this->property = 0;
        if($p) {
            $this->property = 1;
        }
    }
    
    public function getResourceId() {
        return 'video';
    }
}

class User implements Zend_Acl_Role_Interface {

    public $property;
    private $roleId;

    public function __construct($role, $p) {
        $this->roleId = $role;
        $this->property = 0;
        if($p) {
            $this->property = 1;
        }
    }
    
    public function getRoleId() {   
        return $this->roleId;
    }
}

class VideoWatchAssertion implements Zend_Acl_Assert_Interface {

    public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $user=null, Zend_Acl_Resource_Interface $video=null, $privilege=null) {
        
        if($video->property == 1) {
            if($user->property != 1) {
                return false;
            }
        }

        return true;
    }
}

Check for access:


$acl = new TestAcl();
$user = new User('member', true);
$video = new Video(true);
$result = $acl->isAllowed($user, $video, 'watch');

The assertion is called by an instance of Zend_Acl_Role (roleId = guest) and not by an instance of User; but the check of the User instance for access to object specific properties/methods would be absolutly necessary. It would be very helpful if the rules of the parent role is checked by the instance of the current role.

Of course it is possible to bypass this problem by defining the rules for each single role, but it is not very nice.


$this->allow('guest', 'video', 'watch', new VideoWatchAssertion());
$this->allow('member', 'video', 'watch', new VideoWatchAssertion());
$this->allow('member');

Comments

In your TestAcl::__construct() you assigned standard Zend_Acl_Role and Zend_Acl_Resource objects so objects of these types are stored. Why donĀ“t you pass the User and Video objects?

$result = $acl->isAllowed($user, $video, 'watch') only extracts the IDs of your custom objects and looks in the registry for existing objects with that IDs, and then of course the standard ones will be found and used for the assertions.

You are right, your solution uses the correct class. But I have to work with the current instance that the assertion can handle the object specific properties.

Assigning to Ralph to get closure on this issues.

There is a fix in place for ZF-1721 and ZF-1722 which I think will fix this issues, please test r17317 in trunk.