Page 1 of 1

ACL and problem of the self

Posted: Sat Jul 05, 2008 8:33 am
by koen.h
Everyone has to deal with access restrictions. A lot of solutions can be found on the web. Unfortunately, one problem, I think, all solutions fail at is in addressing the problem of allowing access if a user is the owner of a resource.

An example is a forum with lots of posts. Each user can edit his/her own posts. In Zend_Acl this would mean adding a rule for every post made. Not ideal.

A solution could be to have your post (or category) code look at who made the post and decide additional access upon that. But that's far from ideal since we're sort of splitting the ACL in two to gain performance.

I hope there exists some solution I'm not seeing at the moment. Ideas appreciated.

Re: ACL and problem of the self

Posted: Sat Jul 05, 2008 9:02 am
by Eran
Personally I don't use a concrete ACL solution, I always found it to be too inflexible for web usage. I implement access decisions such as the one you described at the model or view level. For example, if the posts you mentioned are returned as a set of objects, each object will have a canEdit() method which checks the post user identifier against the current user identifier.

Re: ACL and problem of the self

Posted: Sat Jul 05, 2008 9:29 am
by koen.h
pytrin wrote:Personally I don't use a concrete ACL solution, I always found it to be too inflexible for web usage. I implement access decisions such as the one you described at the model or view level. For example, if the posts you mentioned are returned as a set of objects, each object will have a canEdit() method which checks the post user identifier against the current user identifier.
I don't agree about the inflexibility. I think the problem lies more in that we don't have unlimited access to the database calls and server memory.

Re: ACL and problem of the self

Posted: Sat Jul 05, 2008 9:36 am
by Eran
That's exactly what I meant by inflexible for web usage... lack of real persistence prevents ACL from being really viable

Re: ACL and problem of the self

Posted: Sun Jul 06, 2008 3:34 pm
by koen.h
I think the best I can do is allow client code to tell the acl how the owner can be found. If I can map the owner of a post to the author column in a table or getAuthor method in an object that would solve my problem without needing additional resources.

The client code should be able to get a list of the posts a user is allowed to edit. This could be covered by this rule:

$acl->allow('owner', 'edit', 'post')

This rule says the owner of a post can edit his/her post. Getting all rules that apply to the user is one db query and fast enough. Then , whenever a client code wants access to resources it should be able to have the acl help determine which resources get a green light. Something like:

$resource->mapOwner('owner','author');

comes to my mind. The owner of a post is mapped to the author column (assuming we're using an sql version of the acl).

Re: ACL and problem of the self

Posted: Fri Jul 11, 2008 12:55 pm
by koen.h
I have been thinking further on this and have decided my approach.

Code: Select all

class Acl
{
    public function allow($resource = null, $action = null, array $conditions = array()) {}
    public function getConditions($resource = null, $action = null, array $conditions = array()) {}
    public function isAllowed($resource = null, $action = null, array $conditions = array()) {}
    public function addHelper(AclHelper $helper);
}
Client code would be something like this:

Code: Select all

// example 1
// allow moderators to edit sticky posts
$acl->allow('post', 'edit', array('role' => 'moderator', 'type' => 'sticky'));
 
// note: role is external to 'post' so there will be a helper added to deal with this
if ($acl->is_allowed($post, 'edit', array('type' =>  'sticky')))
{
    // edit $post
}
 
// example 2
// allow owners of a post to edit it
$acl->allow('post', 'edit', array('role' => 'registered', 'user' => 'owner'));
 
// note: same as above for user: a helper is called when looping through the requirements
if ($acl->is_allowed($post, 'edit'))
{
    // edit $post
}
 
// example 3
// allow premium members to view a special category with premium articles
$acl->allow('posts', 'view', array('category' => array(4, 5, 7)));
$acl->allow('posts', 'view', array('category' => 'premium articles with id 3', 'role' => 'premium member', 'status' => 'published'));
 
// we're on the blog front page that lists the latest articles
// also note that 'posts' isn't an object but a name for a collection of objects
if ($acl->is_allowed('posts', 'view')) // result = yes
{
    $conditions = $acl->getConditions('blog', 'view'); // eg cat = 4, 5, 7 & status = published 
    // get posts with these conditions
}
Maybe the last one is a surprise. Think about it like this: because you are allowed access to the store that doesn't mean you are allowed access to everything in the store.

edit: modified errors pytrin noticed

Re: ACL and problem of the self

Posted: Fri Jul 11, 2008 2:41 pm
by Eran
Interesting interface. Why are you passing the isAllowed conditions as a string and not as an array?

Re: ACL and problem of the self

Posted: Fri Jul 11, 2008 3:55 pm
by koen.h
pytrin wrote:Interesting interface. Why are you passing the isAllowed conditions as a string and not as an array?
The reason is because I've made a mistake. Should add 'array' as type hint also.