CakePhp and user permissions

烂漫一生 提交于 2020-01-05 07:15:23

问题


I need a system that will allow users to modify data that is related to them.

Like a shopping center, with several stores and a shared catalog. I want the stores to be able to edit and add items, from and in, the global pool. but i want to limit the access of a store to its own items.

how it is done with acl & auth (the concept of course)?


回答1:


I've seen this question a few times. From the cake's doc it says:

Access control lists, or ACL, handle two main things: things that want stuff, and things that are wanted.

so in theory, you could handle all the items in your application using ACL, but I see a few problems doing that:

  • lets say you have 10k elements per store in your items table, well, you'll have the same amount of elements in your ACO table. Now if you add a user, you'll have to give him access to the items in the ARO_ACO table (another 10k items FOR EACH USER!)
  • .. ok maybe I exaggerated on the first example. Because you could group the items and in the ACO table, and only set the permissions per group in the ACO_ARO table. But now it might be a nightmare to make the queries in your application, imagine if you want to make a filtered paginated list of items. You'd have to ask the ACO (which now is in a tree structure) and the ARO_ACO table to count and paginate the items... and even if it's done automatically you'd have a performance problem

In my opinion, it's better to use the ACL to only grant permission to the controllers methods (CRUD) and manage the item permissions in your code by setting the condition in your queries:

$this->Items->find('all',array('conditions'=>array('store_id'=>$this->Auth->user('store_id'))))

But you might need to repeat this condition everywhere so you could create a Behavior that will modify the queries in order to add a condition in the WHERE clause, so you would always return/edit the items of the current store. For example, create a behavior like this:

    /** 
     * Filter query conditions with the correct `type' field condition. 
     */ 
    function beforeFind(&$model, $query) 
    {
        /**
         * Condition for the paginators that uses joins
        */
        if(isset($query['joins']) && !empty($query['joins'])){
            foreach($query['joins'] as $key => $joinTable){
                if(ClassRegistry::init($joinTable['alias'])->hasField('store_id')){
                    $query['joins'][$key]['conditions'][] = $joinTable['alias'].".store_id = '".$_SESSION['store_id']."'";
                }
            }
        }

        /**
         * condition for the normal find queries
        */
        if($model->hasField('store_id') && $model->name != "User"){
            $query['conditions'][$model->name.'.store_id'] = $_SESSION['store_id'];
        }
        return $query;
    }

In the controller I'd just need to call the find method normally

$this->Items->find('all');

This way you don't have to make more queries to see if the user can access an item. I've used something like this on a website and it works fine for me.



来源:https://stackoverflow.com/questions/6745683/cakephp-and-user-permissions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!