Alex Tech Adventures The webs best tutorials!

ACL dynamic assertions

E-mail Print PDF
(0 votes, average 0 out of 5)
Assertions allow fine grained access control not only based on module/controller/action combination but on unlimited set of critier, most common one, the author of a certain resource such as a blog comment or a forum thread. See how Zend_Acl helps us accomplish a per-user based set of permissions.



Key notes in the presentation:

This will work only in 1.9.1 or greater

  • Look at how dynamic assertion classes work together in Zend_Acl.
  • Create classes for roles and resources that implement their respective interfaces.
  • Adjusting model to generate data only allowed by the dynamic assertion.
  • Adjusting ACL model class so that it can call necessery classes after MVC structure is set up.

Download source

Zend Framework API

Last Updated ( Thursday, 17 December 2009 02:51 )  
Discuss (13 posts)
ACL dynamic assertions
Jan 12 2010 23:02:08
Hi Alex,

Great tutorials. Found an interesting issue. When an action is being accessed that has an issue, it is going to throw an exception like the following:

Fatal error: Uncaught exception 'Zend_Acl_Exception' with message 'Resource id 'comment' already exists

I found that what was happening was that the setDynamicPermissions function was being called twice. In any event, if I placed a

if(!$this->has('comment')) around the addResource function, it took care of it.

Hope this helps
#315
Re:ACL dynamic assertions
Jan 13 2010 18:34:36
Yes, thats because when performing internal redirect, preDispatch is ran again therefore hitting setDynamicPermissions a second time. Need to address that when I do my error handling.
#319
Re:ACL dynamic assertions
Jan 16 2010 22:56:24
Hi Alex,

sorry to hijack this thread but wanted to ask if you could post the database structure etc for the tutorial.

I tried using the database structure and reproduce it watching your videos but I'm still getting errors.

Thanks,
Phil
#333
Re:ACL dynamic assertions
Jan 18 2010 18:47:37
I had to change the code & sql to work. What error are you getting?
#341
Re:ACL dynamic assertions
Jan 22 2010 15:32:54
Again thanks for the great video lessons!

Just a small question about the dynamic assertions: How would you solve the problem when you have an array of roles per user instead of just a single string?

Any suggestions?

Thanks!
#376
Re:ACL dynamic assertions
Jan 22 2010 15:39:28
As far as I know ACL does not accept arrays.
Maybe something like:
Code:


$roles = array('read', 'write', 'whatever');
foreach($roles as $role){
$this->allow('user', 'article', $role); //other parts can come from pre-existing arrays too.
}



or am I thinking too simplistically?
#377
Re:ACL dynamic assertions
Jan 23 2010 15:50:50
I used this before I tried assertions. With the assertions in as well I couldn't get it to work. However I do think I might have implemented the assertions slightly incorrect as well. Next weekend I'll give it another try...

I don't really understand why multiple roles handling isn't build into ACL by default though. Many websites, even very small ones, often use multiple roles per user..
#382
Re:ACL dynamic assertions
Jan 23 2010 22:08:56
Actually I lied.
I don't know what made me think you can't pass an array as a parameter. In one of the code examples at framework.zend.com/manual/en/zend.acl.refining.html they do just that.
So you can have:
$permissions = array('read', 'write');
$this->allow('reporter', 'article', $permissions);
#383
Re:ACL dynamic assertions
Jan 24 2010 00:06:13
Adding permissions as an array works, but that doesn't solve the multiple roles per user problem. But I'll have another proper look into it next weekend. Maybe I went wrong somewhere with the resources or something..
#384
Re:ACL dynamic assertions
Jan 24 2010 23:52:34
Looking at your source code, I still don't really understand it..

Where do "Library_Model_UserRole" and "Library_Model_CommentResource" get instantiated? Am I missing something?

Second I still wonder where to fix the multiple roles problem, since you would need "Library_Model_UserRole" to allow an array instead of a string. You could ofcourse create a "Library_Model_UserRole" for every role, which is not very smart...

Maybe I am just missing the point, but I can't seem to figure it out.
#390
Re:ACL dynamic assertions
Jan 26 2010 17:09:59
Finally, I fixed it.

I did need some ticks and magic to get it done though. It isn't the most elegant solution but it does the trick. For others that might have the same problem a bit of explanation:

First of all, notice that the tutorial Alexander has made (which really is great and helped me out a lot) might not be exactly the same as what you might need in your website. In my case things are a bit different:
- my users have an array of roles instead of just one as a string
- my roles can't be hardcoded (except for my guest role which is an exception) since they come from the database
- some users are allowed certain priveleges depending on the resource, not just the role
- roles can conflict
- I used the assertions for the routing in my system, user (or guests) are allowed to go to a certain page depending on their role AND the assertion

Especially the last point is quite hard to solve in my case since a user has for example the priveleges to add a book, but not to edit or delete it. If you would look just at the roles you might never get to the page where the use can edit his own book details (which it is allowed to do->assertions)

Here is some relevant code I used:


/* accessCheck.php (plugin), as you can see I don't act on just the roles */

<?php
public function preDispatch(Zend_Controller_Request_Abstract $request){
$module = $request->getModuleName();
$controller = $request->getControllerName();
$resource = $module . ':' . $controller;
$action = $request->getActionName();

$allowed = FALSE;
$roles = Zend_Registry::get('userRoles');
foreach($roles as $id => $role_data){
if($this->_acl->isAllowed($role_data['role'], $resource, $action)){
$allowed = TRUE;
}
}

if(!$allowed){
Zend_Registry::set('Acl_Role_Allowed', FALSE);
}else{
Zend_Registry::set('Acl_Role_Allowed', TRUE);
}

$this->_acl->setDynamicPermissions();
}
?>


/* The assertion: */

<?php

public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $role = null, Zend_Acl_Resource_Interface $resource = null, $privelege = null){
if(Zend_Registry::get('Acl_Role_Allowed')){
return TRUE;
}else{
if($role->getUserId() == $resource->getOwnerId()){
return TRUE;
}else{
return FALSE;
}
}
}
?>


/* Adding a book: No assertion need, just the roles need to be checked */

<?php
public function addAction()
{
if(!Zend_Registry::get('Acl_Role_Allowed')){
if(Zend_Auth::getInstance()->hasIdentity()){
$this->_redirect('/');
}else{
$this->_redirect('/authentication/login');
}
}
etc.
}
?>


/* editting a book, if either a role or the user is allowed, there is no redirect */

<?php
public function editAction()
{
$userRole = new Model_Acl_UserRole();
$albumResource = new Administration_Model_Acl_Resource_Album();

$album_id = $this->_getParam('id', 0);
if($album_id > 0){
$albums = new Administration_Model_DbTable_Albums();
$data = $albums->getAlbum($album_id);
}else{
throw new Exception('Error with album id');
}

$albumResource->setOwnerId($data['user_id']);

if(!Zend_Registry::get('Acl_Role_Allowed') && !Zend_Registry::get('acl')->isAllowed($userRole, $albumResource, 'edit')){
if(Zend_Auth::getInstance()->hasIdentity()){
$this->_redirect('/');
}else{
$this->_redirect('/authentication/login');
}
}
etc.
}
?>


I actually don't like doing this much work in the controllers, but haven't found an easy work around to fix this. What I might do next:
- make one folder contain all the assertions.
- if the assertion file for a certain module, controller, privelege combination exists: handle the rest like I do above in the controller and assertion
- if the file does not exist: let the preDispatcher handle it (since it only depends on the roles).

Hope this helps anybody, if there is anybody that can make it all a bit more elegant, let me know!
#426
Re:ACL dynamic assertions
Feb 08 2010 10:37:43
Hello Alex,
thank you very much for another great lesson, there is just one question, i was hoping you would answer.
As in the tutorial, there are on the top accordion pane, books listed with the ids 1,2,3 ...when your logged in as "john" your book are id 1 and 3, but not id = 2 ...so youll get the edit links ..../books/list/id/1 and /books/list/id/3 ...but what would happend when you type manually the url .../books/list/id/2 ...which doesnt belong to you ? can you still edit it? What to do against this ?

Thank you very much in advance.
-Ben
#522
Re:ACL dynamic assertions
Feb 10 2010 09:37:34
I'm quite sure that you would be able to edit them depending on your role (meaning that you still can't edit your own comment if you don't have the role permissions). I solved this problem, see my post before yours
#530

You need to login or register to post comments.
Discuss...
You are here: Home Development Zend Framework ACL dynamic assertions

Statistics

Members : 568
Content : 36
Web Links : 1
Content View Hits : 39035

Who's Online

We have 22 guests online