zendframework / zend-permissions-acl

BSD 3-Clause "New" or "Revised" License
60 stars 23 forks source link

Ownership assertion #3

Closed nikolaposa closed 6 years ago

nikolaposa commented 9 years ago

Intent

When setting up permissions for some application, there is a common use case of allowing some role to manipulate with resources owned by the user which has that certain role. For example, blog author should have permission to write new posts, but he/she should also have permission to modify his/her own posts, and not posts of other authors.

Solution

Entities:

namespace MyApp\Entity;

use Zend\Permissions\Acl;

class User implements Acl\Role\RoleInterface, Acl\ProprietaryInterface
{
    protected $id;

    protected $role = 'guest';

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

    public function getRoleId()
    {
        return $this->role;
    }

    public function getOwnerId()
    {
        return $this->id;
    }
}

class BlogPost implements Acl\Resource\ResourceInterface, Acl\ProprietaryInterface
{
    public $author = null;

    public function getResourceId()
    {
        return 'blogPost';
    }

    public function getOwnerId()
    {
        if ($this->author === null) {
            return null;
        }

        return $this->author->getOwnerId();
    }
}

Usage example:

namespace MyApp;

use MyApp\Entity;
use Zend\Permissions\Acl;

$acl = new Acl\Acl();
$acl->addRole('guest');
$acl->addRole('member', 'guest');
$acl->addRole('author', 'member');
$acl->addRole('admin');

$acl->addResource('blogPost');
$acl->addResource('comment');

$acl->allow('guest', 'blogPost', 'view');
$acl->allow('guest', 'comment', array('view', 'submit'));
$acl->allow('author', 'blogPost', 'write');
$acl->allow('author', 'blogPost', 'edit', new Acl\Assertion\OwnershipAssertion());
$acl->allow('admin');

$author1 = new User(1, 'author');
$author2 = new User(2, 'author');

$blogPost = new BlogPost();
$blogPost->author = $author1;

$acl->isAllowed($author1, 'blogPost', 'write'); //true
$acl->isAllowed($author1, $blogPost, 'edit'); //true
$acl->isAllowed($author2, 'blogPost', 'write'); //true
$acl->isAllowed($author2, $blogPost, 'edit'); //FALSE
nikolaposa commented 9 years ago

Is there anything else I should do in order for this PR to be accepted? Any other comments?

weierophinney commented 6 years ago

Thanks, @nikolaposa! I have created documentation for the feature during merge, and this will release with 2.7.0.