I am having a web project where some access decisions are dependant on the page itself (e.g. /logout
which shall only be visible to logged in users) and some are dependant on dynamic model objects (e.g. /article/delete/1234
where we have to check if 1234
was written by the logged in user or if he is an admin).
Now, I am facing the problem of how to bring both things together. No matter how I tried, I cannot rely on any of the two alone:
- Some pages do not use any models, so I cannot setup any model rules there
- On the other hand, I cannot create dynamic assertions for a modular approach, because
Comment
is just acomment
and not adefault/comment
. AComment
is not restricted to the default module, it may also be used in the admin module.
With modular ACL I am trying to check for each page if a user is allowed to visit it, e.g.
if (!$acl->isAllowed($user, 'default/secrets', 'mysecrets')) {
$this->forward('auth', 'login');
$this->setDispatched(false);
}
And with dynamic assertions I am checking if somebody is allowed to edit a specific model object.
// $comment has a method getResourceId() returning 'comment'
if ($acl->isAllowed($user, $comment, 'delete')) {
// display a link for deletion
}
Of course it would be nice if the check for
- deletion of a specific comment, and
- accessing the /comment/delete/???? page
would be the same, but I guess this is not possible and I would have to create two rules:
$acl->allow('member', 'default/comment', 'delete');
$acl->allow('member', 'comment', 'delete', new Acl_Assert_CommentAuthor());
$acl->allow('admin', 'comment', 'delete');
Now, this seems not perfect to me as this can lead to duplicate work in some cases.
Is there some better method to approach this problem? Or is the only method to at least create a coherent naming scheme like: mvc:default/comment
, model:comment
The way i did it, custom sql queries that restrict results, functions that check before insert/delete/modify sql
and then an ACL plugin i wrote that checks permission and uses these 5 tables
Code:
You can then add your code(which i ommited for shortness) to remember the request and redirect you there after login.