Alex Tech Adventures The webs best tutorials!

Welcome, Guest
Please Login or Register.    Lost Password?

ACL dynamic assertions
(1 viewing) (1) Guest
Go to bottomPage: 1
TOPIC: ACL dynamic assertions
#743
ACL dynamic assertions 1 Year, 5 Months ago Karma: 16
** This thread discusses the content article: ACL dynamic assertions **

alexanderrv
Administrator
Posts: 279
graph
User Offline Click here to see the profile of this user
Gender: Male tmthv2 alexchatonly@hotmail.com Location: Freeport, Bahamas Birthdate: 1989-04-14
The administrator has disabled public write access.
 
#794
Re: ACL dynamic assertions 1 Year, 2 Months ago Karma: 0
Hello!
I wonder can I modify this approach in order to use it with additional table such as USER GROUPS?
In other words I must modificate my existing project in order to hadle users with levels(groups). The number of levels would be about 10.
No I have 3 roles: guest, user and admin.
Admin has full rights.
User has lesser rights.
With levels added to user role members should see some different data, run a bit modified sql queies and so on...
For example role user with level "5" can see some posts, user with level "6" can edit posts, user with level "7" can see some posts but with different columns from database. Only few things differs from each level. All this actions should be called from one controller's action depending wich group member has called this action.

Could it be done in such manner as for example:
Code:

class UserRole implements Zend_Acl_Role_Interface
{
      public $role = null;
      public $user_id = null;
      public $user_level = null;

       public function __construct(){
           $this->user_id = Zend_Auth::getInstance()->getIdentity()->user_id;
           $this->role = Zend_Auth::getInstance()->getIdentity()->role;
           $this->user_level = Zend_Auth::getInstance()->getIdentity()->level;
         }

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

       public function getLevel(){
           return $this->user_level;
       }
}
}

class Model_EntryAssertion implements Zend_Acl_Assert_Interface {

    public function assert(Zend_Acl $acl, Zend_Acl_Role_Interface $user = null,
                          Zend_Acl_Resource_Interface $entry = null,  $privilege = null, $level = null) {
        if(Zend_Registry::get('role') == 'admins'){
            return true;
        }

        if($user->user_level == $entry-level){
            return true;
        } else {
            return false;
        }
    }
}



    public function setDynamicPermissions() {
        $this->addResource('entry');
        $this->allow('users', 'list', 'edit', new Model_EntryAssertion());
    }


            if(Zend_Registry::get('acl')->isAllowed($userRole, $entryResource, 'entry') &&
                                (Zend_Registry::get('level')->'5') ){
                                 actions for fifth level';

                                         if level =='6'
                                       actions for sixth level
                                          and so on...
            }



?

Can't really imagine how to check permissions for specfied user levels and grant specific actions...
Really need your advice
Thank you!
01Kuzma
Fresh Boarder
Posts: 14
graphgraph
User Offline Click here to see the profile of this user
Last Edit: 2010/12/04 11:46 By 01Kuzma.
The administrator has disabled public write access.
 
#795
Re: ACL dynamic assertions 1 Year, 2 Months ago Karma: 16
I fear my answer will just be a useless ramble but here goes....


Try to use assertions along side strategy and/or/with state pattern. If you have your model objects well organized (say "comment" object and "edit field" object, you can query ACL for what the current user can do (which will become the state of the application). Then you can make a "comment" object editable by applying "edit field" to "comment" object's private property. So essentially you are creating a separate model object for every little peace of action ( edit, view this column, view that column - following "every class is responsible for only one thing" principle). Then you create larger model objects for resources ("the daily article" or smth).

Now, let the controller query the ACL for what the user needs to have access to, then create instances of the appropriate individual action objects dynamically (look up how to do dynamic class loading) and apply those instances to the properties of the main resources object. Make sure every action object implements same set of methods everywhere so the resoure object is able to use any one of them interchaingebly. Use those instances to display the appropriate content. So if you have a $columns private property of a post class:

You can do $this->columns->displayColumns();

And it should work no matter what class $this->columns instance points to because they all have displayColumns() method.
Code:


class dailyArticle() {
  public $column;  // public for example, use private with setters
  public function displayPost() {
     $this->column->displayColumns();
  }
}

class adminColumn implements columnsAbstract() {
 public function displayColumns() {
    // sql query for admin columns
 }
}

class userColumn implements columnsAbstract() {
  public function displayColumns() {
    // sql for users
  }
}

// controller stuff
$post = new dailyArticle();
$post->columns = new adminColumn(); // or new userColumn becuase Post() does not care. Loaded dynamically as explained bellow....
$post->displayPost();



In the end, if you did all normalization correctly you should not have a single "if" statement.


Now, your next part of question is how to figure out what gruop user belongs to and what actions should be loaded.

For permissions as dynamic as yours writing permissions out explicitly like that is not going to work. You will have to make resources, users, permission, assertions as variable as possible. Save all the relations between users, groups, resources and permissions in database. You will end up with a lot of tables. Base tables will be users, groups, permissions (probably only 2 records, allow and deny) and actions. Then you need relation tables that match the base tables: "user to group" relation, "groups to resources" relation, " "groups to resources" to actions permissions" relation etc. until your DB has a fully normalized structure of your permissions. Your goal is to be able to generate a single SQL query that will bring up one nice and long row describing what the user does and where. Or maybe multiple rows - if you need to query the other way around - who can do a resource. But I don't think that will be necessary since usually work from user's point of view, but its up to you how you want to visualize it.

Now you want to build the ACL classes. And by build, I don't mean write them yourself, I mean create a class that builds ACL classes. Like a factory pattern but should be simpler. (Now, don't take that literally - I am not saying you should generate PHP code and do eval() on it either )

All those strings in addResource(), addRole(), isAllowed() and just about anywhere you have a hardcoded value, need to be replaced with private variables of the ACL class. The values of those variables will come from the factory class. So essentially the ACL class never has to worry about how to get the data - one and only thing it will do is check if the current variables match or not. The actual data will be pushed on to it through public setters by the factory class which it in tern collects from the db tables you would have created in above paragraph.

This way factory pattern should align everything in a way where you can query the ACL class to figure out whether to load adminColumn() or userColumn() or, guestColumn() or even both, classes into $columns of dailyArticle class. I think "groups to resources" to actions permissions" relation table info will be the one which you want loaded into ACL class. Unfortunately, there is no ACL query for somethin like "what ALL am I allowed?" - only "am I allowed THIS?" query. So you can create a utility method in your ACL class that takes all actions availabe (again, taken from the factory) and filters out to see what is allowed from what is not. This collection of allowed actions it can keep in its own private array. Controller now can query this array and figure what actions to load into the dailyArticle().


I hope reading this (if you did) did not waste too much time.
alexanderrv
Administrator
Posts: 279
graph
User Offline Click here to see the profile of this user
Gender: Male tmthv2 alexchatonly@hotmail.com Location: Freeport, Bahamas Birthdate: 1989-04-14
The administrator has disabled public write access.
 
#796
Re: ACL dynamic assertions 1 Year, 2 Months ago Karma: 0
Thank you very mch for your promt reply!
Now I' ve some basic thoughts how to design this approach,
Thank you!
01Kuzma
Fresh Boarder
Posts: 14
graphgraph
User Offline Click here to see the profile of this user
The administrator has disabled public write access.
 
Go to topPage: 1
Moderators: alexanderrv
You are here: Home Forum

Statistics

Members : 1388
Content : 42
Web Links : 1
Content View Hits : 190537

Poll

Interested in TinyBrowser and TinyMce plugin for ZF?
 

Who's Online

We have 25 guests online