-1

Ok, I'll preface this by saying i'm a noob to cake and ACL, and MVC architecture. I'm following a cakephp tutorial from its site, http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/part-two.html. I understand the content of the tutorial, but wonder about the easiest way to take this simple group based ACL to the next level. I've searched SO to no avail. So, on with the question.

Lets take a slightly modified version of the function in the above tutorial, for example. It simply sets up ARO permissions for ACOs.

There are many districts, and many departments, all with many users, in each.

relationships are as follows: A district hasMany Departments -- one to many. A district has many users, and users can potentially have many districts(so long as they belong to a dept in that district). A department hasAnBelongsToMany Users -- many to many.

public function initDB() {
    $group = $this->User->Group;

    //Allow admins to everything
    $group->id = 1;
    $this->Acl->allow($group, 'controllers');

    // issue 1) allow district managers to districts, departments, users
    $group->id = 2;
    $this->Acl->deny($group, 'controllers');
    $this->Acl->allow($group, 'controllers/Districts');
    $this->Acl->allow($group, 'controllers/Departments');
    $this->Acl->allow($group, 'controllers/Users');

    //issue 2) allow department managers to edit departments and users
    $group->id = 3;
    $this->Acl->deny($group, 'controllers');
    $this->Acl->allow($group, 'controllers/Departments');
    $this->Acl->allow($group, 'controllers/Users');
    //we add an exit to avoid an ugly "missing views" error message
    echo "all done";
    exit;

}

Ok, so these permissions being set-up, although it's definitely convenient, really solve a small part of the problem. As it stands, I've really only prevented the department admins from performing district level functions. Both district admins and dept admins can perform user CRUD without restrictions

What i'd like to do, is limit the scope of each of the admin types USER CRUD to only those users residing within their department or district. for example, Department Admin Foo can't delete another Dept Admin's Users, and Dist Admin Bar can't change all of another Dist Admin's Users first names to nancy.

lol. I'm seriously at a loss with how to accomplish this.

I guess one approach would be get an administrators rank, dist admin for example, then figure out in which district he is a user. lastly, return all of the users in this district into a variable $userScope. Again, I am new to cake php and would be unsure of how to carry out the this proposal, even if it were a good idea and the best way to handle this. Any suggestions?? Thanks in advance!!!

edit: helpful answer, @nicolae.

however, it still seems that i could write a function that returns all users that any given admin(of any given aco) is permitted to edit. is seems this way to me because i'm assuming the admin, him/herself to be a part of the returned user base. for example, dist admin of dist 9, resides in dist 9; likewise, dept admin of dept 1, resides in dept 1.

could i write something like:

 public getUserScope(){
 $id = $this->Auth->user('id');
 $dept = $this...
 $dist = $this...
 $access_level = $this->Session->read('Auth.User.group_id');
 if($access_level == 3){
      //get all users in this user's dept
 } elseif($access_level == 2) {
     //find all users in this user's dist
 } elseif($access_level == 1) {
      //find all users
 }
}

ouch. granted all of the join tables involved in bringing this info together, this is bound to look like medusas hair when actually typed up. can you see my line of logic. this is a bit difficult for me to articulate. let me know if i should clarify anything further.

Todd
  • 5,314
  • 3
  • 28
  • 45

1 Answers1

1

So you're trying to set up an ACL system that manages restrictions based on more than group ID and controller/action - you need department- and district-based restrictions.
As far as I know, the embedded ACL system in CakePHP can not manage this level of restrictions.

As a solution, I recommend you allow the users to the places they need to access (e.g. dept admins have ACL access to the user CRUD interface) and insert specific restrictions in the controller.

function editUserFromDepartment($userId = NULL) {
    // Custom ACL check
    if (! $this->__checkDepartmentByUserId($userId)) {
        // Show the user a custom error message and redirect him to index page
    }

    // User editing code ...
}

function __checkDepartmentByUserId($userId) {
    $dept = $this->Department->getByUserId($userId);

    // Check if the current user belongs to this department
    $currentUserDepartmentId = $this->Session->read('Auth.User.department_id');

    return ($dept['Department']['id'] != $currentUserDepartmentId);
}

Good luck and let me know if my explanation was clear enough.

Nicolae

Edit (trying to answer to @Todd's edit): I get your point. Your code aims at obtaining all users of that the current user has access of. Rather than that, I would have an event-based approach: when the user X tries to be edited, perform a query that finds if Auth.User is allowed to perform this action on user X.

E.g. You (Todd) are trying to edit my profile (NicolaeS) to change my employee ID, as my current one is wrong.
The function $this->getUserScope('user-ID-of-NicolaeS') will check if your department ID or district ID is the same as main and allow/disallow you to continue in your actions according to this check.

Does this look clear/straightforward enough?

Greets, Nicolae

NicolaeS
  • 423
  • 2
  • 7