Zend_Acl and a dynamic Assert

595 views Asked by At

I'm trying to imply some dynamic assertions into my Zend code and have been using an article by [Ralph Schindler][1] but I couldn't get it to work. What I wanna do is make an "allow" rule in de Acl that checks if the person logged in is actually the owner of a piece of UserContent.

I have the a User class and a UserContent class (deleted all the unneccessary bits):

class User implements Zend_Acl_Role_Interface {
    private $_roleId;
    public function getRoleId() { return $this->_roleId; }
}

class UserContent implements Zend_Acl_Resource_Interface {
    private $_resourceId;
    private $_userId;

    public function getResourceId() { return $this->_resourceId; }
    public function getUserId() { return $this->_userId; }
}

Now in my Acl class My_Acl I have defined a 'member' role, a 'usercontent' resource and a 'edit' privilege, and would like to create the following allow rule:

$this->allow('member', 'usercontent', 'edit', new My_Acl_Assert_IsOwner());

where the Assert implements the class Zend_Acl_Assert_Interface:

class My_Acl_Assert_IsOwner implements Zend_Acl_Assert_Interface {

    public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role=null, Zend_Acl_Resource_Interface $resource=null, $privilege = null) {
        [return true if the user logged in is owner of the userContent]
    }
}

where I'm still struggling with what to put in the actual assert method.

Let's say I am logged in as a member (so my $_roleId='member'), and want to check if I'm allowed to edit a piece of UserContent, something like this:

$userContentMapper = new Application_Model_Mapper_UserContent();
$userContent = $userContentMapper->find(123);
if ($this->isAllowed($userContent, 'delete')) echo "You are allowed to delete this";

In the assert method I would like to put something like:

$resource->getUserId();

but this gives me the error messages *Call to undefined method Zend_Acl_Resource::getUserId()*. Strange, cos if I test if the resource is an instance of the UserContent I get a confirmation: adding the following line to the asset method:

if ($resource instanceof UserContent) echo "True!";

I get a true indeed. What goes wrong?

For a test I have added an extra public variable ownerId to the UserContent class, definied as follows:

private $_id;
public $ownerId;
public function setId($id) {$this->_id = $id; $this->ownerId = $id;

Now if I add $resource->ownerId to the assert method, I get no error message, it simply reads the value from the class. What is going wrong? $resource is an instance of UserContent, but I can't call the method getUserId, but I can call the public variable $ownerId??

[1] http://ralphschindler.com/2009/08/13/dynamic-assertions-for-zend_acl-in-zf

1

There are 1 answers

0
Gerard Roche On

As @pieter pointed out, the acl rule is being called in another place within your app which is why when you check that the resource is an instance of UserContent it is echoing True.

The acl rule you declare is checking for an "edit" privilege:

$this->allow('member', 'usercontent', 'edit', new My_Acl_Assert_IsOwner());

but when you're testing for a "delete" privilege:

if ($this->isAllowed($userContent, 'delete')) echo "You are allowed to delete this";

Try adding this to your acl:

$this->allow('member', 'usercontent', 'delete', new My_Acl_Assert_IsOwner());