Recent Posts
- (09/10) Fixing Warning: the ECDSA host key for 'github.com' differs from the key for the IP addressTAGS:Web Server Admin
- (12/26) CakePHP 3 - Getting List of Column Definitions from a Table (like schema())TAGS:CakephpCake3
- (09/14) Change Order of Loaded Behaviors in CakePHP 3TAGS:Cake3CakephpWeb ProgrammingPhp
- (05/29) CakePHP 3 - Accept JSON Header Only Working When Debug FalseTAGS:Web ProgrammingCakephpCake3
- (05/23) Remove All Events from Google Calendar (Reset Calendar)TAGS:Web ProgrammingPhp
- (11/08) Google Tag Manager (GTM) Not Firing Default PageView EventTAGS:Web ProgrammingJavascriptGoogle Tag Manager
- (10/13) In PHP, how do you get __toString() Magic Method Result without calling echo?TAGS:CakephpCake3Cakephp 13PhpWeb Programming
- (11/14) Getting output from shell_exec() at all timesTAGS:Web ProgrammingWeb Server Admin
Subscribe to my feed
MainelyDesign.com Blog
Getting All ACL Permissions in One Lookup (CakePHP 1.3)
Posted on 09/19/2010 at 11:36 am by Kevin Wentworth
Viewed 21,266 times | 1 comment
The biggest hurdle I've had to overcome migrating my CakePHP application from 1.2 to the much improved 1.3 branch involves Plugins and the ACL component. A while back I noticed that my backend was kind of sluggish due to all of the ACL lookups (that happen with each request) so I optimized my ACL database tables. At that same time, I also discovered an incredible mysql query that would lookup all of the ACL permissions for a particular ARO. This setup worked great... until I started upgrading to CakePHP 1.3.
ACL Now Includes Plugin Name (controllers/Plugin/PluginController/action)
In CakePHP 1.3, the ACL component added in another level of parent for Plugins. I agree with this change (now you can can allow/deny for an entire plugin in one ACO/ARO definition) but it broke that crazy query. Now, I tried and tried to implement that additional layer of parent relationship into the query that worked for 1.2 but I just couldn't get it working. I learned a little bit about MySQL sub-sub-sub queries but didn't end up with a working solution.
Get All ACL Permissions On Login
The beauty in Neil Crookes' approach was that you could get all of the permissions as a user logged in and then dynamically generate a list of all permissions for each user. I used this approach to customize the menus based on the level of user that was logged in to Site Avenger. I depended on this functionality and built my entire back-end system to use dynamic menus based on the access list of the logged in user. I had to recreate this functionality... but I'm not a mysql genius so I decided to do it another way...
Introducing the Permissions Array Component
- /**
- * CakePHP Permissions Array by Kevin Wentworth (Saco Design, Inc.)
- *
- * Handles retrieving all ACL Permissions and storing them in an array.
- *
- *
- * Comments and bug reports welcome at kevin at sacodesign dot com
- *
- * Licensed under UYOR (Use at Your Own Risk)
- */
- class PermissionsArrayComponent extends Object {
- //used for recursive variable setting/checking
- //called before Controller::beforeFilter()
- // saving the controller reference for later use
- $this->controller =& $controller;
- }
- //called after Controller::beforeFilter()
- function startup(&$controller) {
- }
- //called after Controller::beforeRender()
- function beforeRender(&$controller) {
- }
- //called after Controller::render()
- function shutdown(&$controller) {
- }
- //called before Controller::redirect()
- function beforeRedirect(&$controller, $url, $status=null, $exit=true) {
- }
- //GET ACL PERMISSIONS
- $acos = $this->Acl->Aco->find('threaded');
- $group_aro = $this->Acl->Aro->find('threaded',array('conditions'=>array('Aro.foreign_key'=>$group_id, 'Aro.model'=>'Group')));
- foreach($group_perms[0] as $value) {
- $gpAco[$value['id']] = $value;
- }
- $this->perms = $gpAco;
- $this->_addPermissions($acos, $this->options['model'], $this->options['field'], 0, '');
- $this->Session->write('Auth.Permissions', $this->permissionsArray);
- return $this->controller->redirect($this->Auth->redirect());
- }
- function _addPermissions($acos, $modelName, $fieldName, $level, $alias) {
- foreach ($acos as $key=>$val)
- {
- $thisAlias = $alias . $val[$modelName][$fieldName];
- $curr_perm = $this->perms[$val[$modelName]['id']];
- if($curr_perm['Permission']['_create'] == 1) {
- $this->permissionsArray[] = $thisAlias;
- $this->inheritPermission[$level] = 1;
- } else {
- $this->inheritPermission[$level] = -1;
- }
- } else {
- //echo $level.'::'.$thisAlias;
- //var_dump($this->inheritPermission);
- //check for inheritedPermissions, by checking closest array element
- if($revPerms[0] == 1) {
- $this->permissionsArray[] = $thisAlias; //the level above was set to 1, so this should be a 1
- }
- }
- }
- $old_alias = $alias;
- $alias .= $val[$modelName][$fieldName] .'/';
- $this->_addPermissions($val['children'], $modelName, $fieldName, $level+1, $alias);
- unset($this->inheritPermission[$level+1]); //don't want the last level's inheritance, in case it was set
- $alias = $old_alias;
- }
- }
- return;
- }
- }
Used in conjunction with hasPermission() in app_helper.php (thanks Neil)
- function hasPermission($url) {
- return false;
- }
- $plugin = Inflector::camelize($plugin);
- }
- $controller = $this->params['controller'];
- }
- $controller = Inflector::camelize($controller);
- $action = $this->params['action'];
- }
- $_admin = Configure::read('Routing.admin');
- $action = $_admin.'_'.$action;
- }
- $controller = $plugin.'/'.$controller;
- }
- $permission = 'controllers/'.$controller.'/'.$action;
- }
Tell Auth Component to Stop Hijacking Login() function
In order to get the PermissionsArray->create() function to work, you must stop the Auth component from auto-redirecting. This will allow any logic in the login() function to run after the Auth component has done it's part. Place this wherever you define your Auth component settings:
- //in Auth config:
- $this->Auth->autoRedirect = false;
Then, Initialize CakePHP Permissions Array at Login
- function avenger_login($data = null) {
- Configure::write('debug', 0);
- if ($this->Auth->user()) {
- $this->PermissionsArray->create($this->Auth->user('group_id'));
- }
- }
Cheers,
-Kevin Wentworth
Tags for Getting All ACL Permissions in One Lookup (CakePHP 1.3)
Cakephp | Component | Database | Example | Mysql | Tutorial | Upgrade | Usage | Web Programming
Comments for this Posting
Sorry, comments are closed for this posting.
Please Email Kevin if you have any questions. Thanks!
Posted by Geoff Douglas
on 1/10/10
Thanks Kevin. This is great stuff. I will try it out and let you know if I have any issues, questions, additions...
www.neverbehind.com