Implementing ACL In Cakephp 2.1 and Upper Versions 24Jun, 2015

Hello friends! Time and again the idea of using ACL to designate specific permissions for specific groups have dreaded most of us. This happens because of the ambiguous behaviour shown by ACL at times. Well, the behaviour we perceive as ambiguous is due to limited understanding of the process involved in its implementation.

Today, while implementing the ACL second time I still had to verify everything closely to resolve the errors associated with permissions. Having said that, I decided to split the ACL implementation into steps.

Let’s start :-

Step 1: The first and foremost requirement without which the ACL implementation would be futile is not using auth. Therefore, presence of auth component in our application will always be a pre-requisite before moving towards ACL implementation.

Step 2: After you have used auth in your application, declare ACL in components section in your app controller like this:

public $components = array(
        'Acl',
        'Auth' => array(
            'authorize' => array(
                'Actions' => array('actionPath' => 'controllers')
            )
        )        
    );

Step 3: Now in your UsersController and Groups controller add the following:

public function beforeFilter() {
    parent::beforeFilter();    
    $this->Auth->allow();
}

You can remove this after we are done with adding groups and few users in our database.

Step 4: Now run the following command in app/ directory through terminal

./Console/cake schema create DbAcl

Say yes to dropping and creating the tables. This will create basic ACL tables for you viz. acos, aros, aros_acos. The entries in this table will take place at later stages.

Step 5: Add following to User model, User.php file

class User extends AppModel {
    public $belongsTo = array('Group');
    public $actsAs = array('Acl' => array('type' => 'requester'));

    public function parentNode() {
        if (!$this->id && empty($this->data)) {
            return null;
        }
        if (isset($this->data['User']['group_id'])) {
            $groupId = $this->data['User']['group_id'];
        } else {
            $groupId = $this->field('group_id');
        }
        if (!$groupId) {
            return null;
        } else {
            return array('Usertype' => array('id' => $groupId));
        }
    }
}

And in Group.php add this

class Group extends AppModel {
      public $hasMany = array(
        'User' => array(
            'className' => 'User',
            'foreignKey' => 'group_id',
            'dependent' => false,
        )
    );

    public $actsAs = array('Acl' => array('type' => 'requester'));

    public function parentNode() {
        return null;
    }
}

If you want to assign permissions based on groups only, change –> public $actsAs = array(‘Acl’ => array(‘type’ => ‘requester’)); to public $actsAs = array(‘Acl’ => array(‘type’ => ‘requester’), ‘enabled’ => false);

This will deny any entry to the aros table while a new user is created. Please don’t make any such change in Group.php.

Further, add following to User.php for group based permissions:

public function bindNode($user) {
      return array('model' => 'Group', 'foreign_key' => $user['User']['group_id']);
}

Step 6: Now to populate a list of our controllers and controller actions in acos table, go to The GitHub Downloads page and download AclExtras plugin. Unzip it and place it into app/Plugin/ folder. Now add this

CakePlugin::load('AclExtras');

to your app/Config/boostrap.php file to load the plugin on application start up. Execute the following command in app directory from the terminal

./Console/cake AclExtras.AclExtras aco_sync

This should populate your acos table with all controllers and their actions.

Step 7: Setting up the permissions

Add following method to UsersController

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

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

    // allow managers to posts and widgets
    $group->id = 2;
    $this->Acl->deny($group, 'controllers');
    $this->Acl->allow($group, 'controllers/Posts');
    $this->Acl->allow($group, 'controllers/Widgets');

    // allow users to only add and edit on posts and widgets
    $group->id = 3;
    $this->Acl->deny($group, 'controllers');
    $this->Acl->allow($group, 'controllers/Posts/add');
    $this->Acl->allow($group, 'controllers/Posts/edit');
    $this->Acl->allow($group, 'controllers/Widgets/add');
    $this->Acl->allow($group, 'controllers/Widgets/edit');

    // allow basic users to log out
    $this->Acl->allow($group, 'controllers/users/logout');

    // we add an exit to avoid an ugly "missing views" error message
    echo "all done";
    exit;
}

And pass this function in auth like this:

$this->Auth->allow('initDB');

Here we can declare the permissions as required by individual groups. After running this function from our browser, it should populate the aros_acos table, but make sure you don’t run this until you have added users and data in your Groups table.

Step 8: Now add Groups from the browser, add few users, run initDB from browser. After logging in, the logged in user should only be able to access the controllers that are allowed for the group which the user belongs to in initDB function in UsersController.

Posted by: VirenderSingh / In: Cakephp and Tagged ,
Cam

Leave a Reply

Your email address will not be published.