ACL Plugin for CakePHP 2.0
The core of CakePHP contains a system to control access rights based on Access control list. This mechanism is very useful, but I have to admit, not very easy to dive in the first time you try to use it.
Moreover, CakePHP doesn't provide out of the box an interface to configure the rights managed through ACL.
This plugin is such an interface allowing to manage permissions of your application's users and roles.
Technically, it allows to manage the content of the aros, acos and aros_acos tables, used by the CakePHP ACL Component. Its interface is partially inspired by the one you can find in the Croogo CMS, and a part of the code comes from this tutorial of the CakePHP documentation.

Prerequisites
CakePHP 2.0.x
a website whose access rights are managed through the ACL Component. A good introduction on how to use this Component can be found in the CakePHP documentation.
a table in your database containing the users (its name can be configured)
a table in your database containing the roles (its name can be configured). The example given in the tutorial above uses for instance a table called groups and not roles.
Features
creation of acos for each action of your controllers
automatic detection of new controllers and/or actions
clear display of roles permissions
clear display of users specific permissions
easy edition of roles permissions (through AJAX)
easy edition of users specific permissions (through AJAX)
Demo
A sample application containing the ACL plugin can be found here. It is built with CakePHP 1.3 and the corresponding plugin version, but the functionnalities are the same so far.
Download
This plugin is available on the downloads page.
Installation
copy the folder acl in your folder /app/plugins
configure the admin route (see http://book.cakephp.org/2.0/en/development/routing.html#prefix-routing)
copy the parameters found in Acl/Config/bootstrap.php in your file /app/Config/bootstrap.php or load the plugin with its own bootstrap.php file (
CakePlugin::load('Acl', array('bootstrap' => true));)access the plugin by navigating to /admin/acl
| parameter | explanation |
|---|---|
| acl.aro.role.model |
Name of the model representing the roles Typically: "Role" ou "Group" |
| acl.aro.role.primary_key |
Allows to force the name of the roles primary key Can be left empty if this name follows the CakePHP conventions ("id") |
| acl.aro.role.foreign_key |
Allows to force the name of the role foreign key Can be left empty if this name follows the CakePHP conventions (e.g. "role_id") |
| acl.aro.user.model |
Name of the model representing the users Typically: "User" |
| acl.aro.user.primary_key |
Allows to force the name of the users primary key Can be left empty if this name follows the CakePHP conventions ("id") |
| acl.aro.role.display_field |
Name of the field used to display the roles Typically: "name" |
| acl.role.access_plugin_role_ids |
An array containing the roles ids being in all cases allowed to access the plugin (by bypassing the ACL permissions). Useful to not being denied access from the ACL plugin when we manipulate the ACL permissions. |
| acl.role.access_plugin_user_ids |
An array containing the users ids being in all cases allowed to access the plugin (by bypassing the ACL permissions). Useful to not being denied access from the ACL plugin when we manipulate the ACL permissions. |
| acl.user.display_name |
The name of the field to use to display the users It can also be a SQL expression such as: CONCAT(User.lastname, ' ', User.firstname) for MySQL |
| acl.check_act_as_requester | Indicates wether the presence of the ACL Behavior configured as Requester in the user and role models must be automatically verified when the plugin is accessed |
| acl.gui.roles_permissions.ajax |
Indicates wether the roles permissions page must be loaded through AJAX. Depending on the number of permissions to check, this page may takes much time to load. To prevent a webserver timeout, it is possible to configure the page loading through AJAX. |
| acl.gui.users_permissions.ajax |
Indicates wether the users permissions page must be loaded through AJAX. Depending on the number of permissions to check, this page may takes much time to load. To prevent a webserver timeout, it is possible to configure the page loading through AJAX. |
FAQ
Looking for a CakePHP 1.3 version ?
Plugin ACL 
New comment
139 comments
when i acess URL: http://localhost/demo/admin/acl/aros/check
have error as bellow
Error: Table app_models for model AppModel was not found in datasource default.
---
I have 2 tables users and roles
User hasAndBelongsToMany Role model
I wonder if there is some planning to adapt the plugin to work in cakehp 2.3
I already use with 2.1 and I really like the tool!
Sincerely,
Rodrigo de Souza
I have set up plugin on my website, Proble here is how to check the permissions now for any function. Everything is fine with database setup. Just want to know how will we check if we have not granted permission for user to add (new user). Its not checking permissions.. any code on controller file or in view..??
Please kindly provide your help..
Thnx..in advance
if($specific_permission !== false && isset($specific_permission['Permission']) ) { //ORIGINAL BROKEN CODE : if($this->Acl->Aro->Permission->remove(array('Permission.id' => $specific_permission['Permission']['id']))) //had to write out the SQL code here..... $sql = "UPDATE `aros_acos` SET `_create` = '-1',`_read` = '-1',`_update` = '-1',`_delete` = '-1' WHERE `aros_acos`.`id` =".$specific_permission['Permission']['id']; $this->Acl->Aro->query($sql); return true; } else { /* * As $specific_permission_right has a value, we should never fall here, but who knows... ;-) */ trigger_error(__d('acl', 'The specific permission id could not be retrieved'), E_USER_NOTICE); return false; }good luck!
first off, this is a real life saver but Im having a weird little problem maybe you can help me with.
the scenario: when i go to take away permissions for a user i get this error:
Notice (1024): An error occured while deleting the specific permission[APP/Plugin/Acl/Controller/Component/AclManagerComponent.php, line 608
it appears the $specific_permission['Permission']['id'] is null, the whole array is null actually. This is strange because I get no errors when i give that user permissions, its only when i take them away....and it works fine with groups (taking and giving permissions)... is it something obvious that i am missing? thanks!
corey
I have tried to put your plugin on my site, based on cake 2.3.1.
It does not work.
It ask me something from another plugin.
Is it compatible with 2.3.1 ?
Thanks
Rudy
In my project i have 33 controllers.Is that the reason for which it takes a long time to load? How can i make it more faster?
Another thing i want to hide the links that won't be showed to the user if he is not permitted.Is this possible in here?
I noticed that the plugin loads jQuery. Unfortunately, in some situations, if jQuery was loaded prior to the ACLplugin loading it, any loaded jQuery plugins become dissociated.
I quick-fixed the issue by commenting out "echo $this->Html->script('/acl/js/jquery');" in the plugin .ctp files that had it.
The best way to fix this issue is to detect if jquery is already loaded. Maybe a beforeRender line in a helper element would allow this...
I noticed that the plugin loads jQuery. Unfortunately, in some situations, if jQuery was loaded prior to the ACLplugin loading it, any loaded jQuery plugins become dissociated.
I quick-fixed the issue by commenting out "echo $this->Html->script('/acl/js/jquery');" in the plugin .ctp files that had it.
The best way to fix this issue is to detect if jquery is already loaded. Maybe a beforeRender line in a helper element would allow this...
We are fighting the same demon!
Here is what I found -
- If I create a new user from scratch with my registration page, the user is correctly added to the ARO's table and I can modified the role through the interface.
- However, if I bulk load my users via SQL load (have 100's), then they are not properly entered into the ARO's table and I get the yellow caution sign. If I click on a grey check mark, I get the an "internal error" - different than what you are seeing.
"AclNode::node() - Couldn't find Aro node identified by "Array ( [Aro0.model] => Person [Aro0.foreign_key] => abb9976b-68b3-11e2-8321-000c293ce041 ) ""
Still battling on. Will let you know how it goes.
Happy coding!
Matt
So, now I've changed the field types in the tables to conform to CakeDC's usage, recreated my users and groups, and am now in the process of re-establishing the permissions. Everything seems to be working fine, except again, when attempting to assign Users Rules (admin/acl/aros/users). Now, I'm getting yellow triangles with an exclamation point next to every checkmark on the table.
The page source reveals the typical massive, hard to read error message, but the gist of it seems to be this:
I can't for the life me figure out why Aro would be an undefined index. Line 183 stems from this:
$aro = $this->Acl->Aro->find('first', array('conditions' => array('model' => $user_model_name, 'foreign_key' => $user[$user_model_name][$this->_get_user_primary_key_name()])));lib/cake/model includes the Aro model. It's got me.
Thanks a million. With add the false parameter to the save(), it did return a flash message that the user role had been updated, although all I've got is gray checkmarks under each role for each user. Also, when I extend to recursive = 2 and echo debug($users) on the admin_users view, I get 'Aro' => null, which leads me to think that it didn't actually save anything.
Also, at this point, I've got my three groups repeated in the aros table model field four times with the same foreign key and no parent id. Then the Groups repeat again once with the same parent id for each group. (The last one is correct, I'm pretty sure because the parent id is the id for the record with a "Groups" alias.
I only wish I knew enough about Cake and PHP to really do a fix on this otherwise excellent plugin.
You need to turn off validation in the Save function.
In AroController.php->admin_update_user_role(), change
if($this->{$user_model_name}->save($data))
to:
if($this->{$user_model_name}->save($data, false))
The second parameter will disable validation.
Best of luck.
Matt
Configure :: write('acl.aro.user.model', 'Users.User');
That didn't work; I got all kinds of error messages about my User model not being a requester (even though it was) and other things that led me to believe that the ACL plugin was just not finding the User model.
So, I tried loading the Users.User model in ArosController and substituting "User" for "$role_model_name" That got me a whole lot further.
However, now, when I go to /admin/acl/aros/users and attempt to assign a role to a user, I get this error message:
The user role could not be updated
username
Please enter a username.
email
Please enter a valid email address.
Of course, there are no fields to enter username and email on that page. I tinkered around some more and got past that only to get this error message:
Unknown column 'Users.User.username' in 'field list'
Can anyone give me a set of steps to make this plugin work with a Users plugin?
I'm looking for a better plugin integration (my User and Model are in a plugin, so there are little hacks to do for it to work...) I'll post here if I have more infos.
.toggle(function, function, ... ) removed :
http://jquery.com/upgrade-guide/1.9/#toggle-function-function-removed
/>
If you want to use new jQuery versions, you can add the missing jQuery function at the beggining of 'acl_plugin.js' :
jQuery.fn.jToggle = function(fn) { // Save reference to arguments for access in closure var args = arguments, guid = fn.guid || jQuery.guid++, i = 0, toggler = function( event ) { // Figure out which function to execute var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); // Make sure that clicks stop event.preventDefault(); // and execute the function return args[ lastToggle ].apply( this, arguments ) || false; }; // link all the functions, so any of them can unbind this click handler toggler.guid = guid; while ( i < args.length ) { args[ i++ ].guid = guid; } return this.click( toggler ); }and then replace all occurences of toggle(handler, handler) by :
[code]jToggle(handler, handler)[code]
This solution is probably not the best one but do the work !
In CakePHP 2.3 some things changes...
Model::find('first')So, Acl Manager should be updated : all verifications after a query are obsoletes...
For example
AclManager:597 ... $specific_permission = $this->Acl->Aro->Permission->find('first', array('conditions' => array('aro_id' => $aro_id, 'aco_id' => $aco_id))); if($specific_permission!==false) ...You should replace it (and all same procedures in the plugin) by :
Anyway thank you for the good work :)
Best regards,
GL
First, when I go to /admin/acl/aros/ajax_role_permissions, the page displays, but under each role for each action, the little rotating wait symbol displays literally forever. I left the page up all of last night and it is still going. I've got 23 model/controller combinations. Is that too many for it to handle? I also have three roles. I tried changing acl.gui.roles_permissions.ajax in bootstrap.php to false, and that didn't help.
Second, when I go to /admin/acl/aros/user_permissions, I get a fatal error saying " Table groups for model Group was not found in datasource default." (My 'group' table is 'roles' with a model of 'Role.' In the plugin's bootstrap.php file, I've got acl.aro.role.model set to Role in the plugin's bootstrap.php; it doesn't seem to be paying attention to that. I also have the ACL type set to 'requester' in the Role model.
Any ideas that you have on these will be greatly appreciated.
how can i do it?