Julian
Julian

Reputation: 9140

How to pass custom data to a Zend Acl custom Assertion

The Zend Acl docs show an example on using a custom assertion:

$acl->allow(null, null, null, new MyCustomAssertion());

The problem is that the above code is executed while creating the rules not while checking them. In my controller I can only do something like:

 $acl->isAllowed('someUser', 'someResource') 

Unlike Zend Rbac the assertion class is already instantiated and I cannot pass it a user ID and post ID to check if the user has access to that post in particular.

Is checking if a user has access to a post from a controller achievable (in a maintainable way) with Zend Acl?

Note 1: I'm not using the Zend framework for this, just the Zend Acl component. Note 2: The reason I'm not using Rbac is because I need the "deny" feature that Acl has and Rbac doesn't.

Upvotes: 1

Views: 150

Answers (1)

Jannes Botis
Jannes Botis

Reputation: 11242

One way is to create your own implementation of a role and a resource:

class MyCustomAssertion implements Zend\Permissions\Acl\Assertion\AssertionInterface
{
    public function assert(Zend\Permissions\Acl\Acl $acl,
        Zend\Permissions\Acl\Role\RoleInterface $role = null,
        Zend\Permissions\Acl\Resource\ResourceInterface $resource = null,
        $privilege = null)
    {
        if(is_a($role, UserRole::class) && is_a($resource, PostResource::class)) {
            $post_id = $resource->getResourceId();
            $user_id = $role->getId();
            // find out if the user has access to this post id(eg with a database query)
            // return true or false.
            return true;
        }

        return true;
    }

}

class PostResource implements Zend\Permissions\Acl\Resource\ResourceInterface
{
    private $post_id;

    public function __construct($post_id)
    {
        $this->post_id = $post_id;
    }

    public function getId()
    {
        return$this->post_id;
    }
    public function getResourceId()
    {
        return 'post';
    }
}

class UserRole implements Zend\Permissions\Acl\Role\RoleInterface
{

    private $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

    public function getId()
    {
        return $this->id;
    }
    public function getRoleId()
    {
        return 'user';
    }
}


use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Role\GenericRole as Role;
use Zend\Permissions\Acl\Resource\GenericResource as Resource;

$acl = new Acl();

$acl->addRole(new Role('user'));

$acl->addResource(new Resource('post'));

$acl->allow(null, null, null, new MyCustomAssertion());

// lets check if user with id 11 has access to post with id 5.
$acl->isAllowed(new UserRole(11), new PostResource(5));

Yes, this way you can add this check in a controller using the last line above.

Upvotes: 2

Related Questions