From ce27e2699d11cadf0b06cd83ae3f4fb27f25b27c Mon Sep 17 00:00:00 2001 From: Corie Slate Date: Mon, 17 Jun 2013 11:16:19 +0200 Subject: [PATCH 01/16] Support aliases in ARO table Added option in bootstrap to define fields to use from ARO Model as an alias field in the ARO table. --- Config/bootstrap.php | 5 +++++ Controller/AclController.php | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/Config/bootstrap.php b/Config/bootstrap.php index 920a51b..6562d5a 100755 --- a/Config/bootstrap.php +++ b/Config/bootstrap.php @@ -19,6 +19,11 @@ */ Configure::write('AclManager.aros', array('Role', 'User')); +/** + * Aliases to write into ARO table + */ +// Configure::write('AclManager.aro_aliases', array('Group' => 'name', 'User' => 'username')); + /** * Limit used to paginate AROs * Replace {alias} with ARO alias diff --git a/Controller/AclController.php b/Controller/AclController.php index 4166a9e..1299ba1 100755 --- a/Controller/AclController.php +++ b/Controller/AclController.php @@ -359,6 +359,10 @@ public function update_aros() { 'foreign_key' => $Model->id ); + if ($alias = Configure::read("AclManager.aro_aliases.{$Model->name}")) { + $data['alias'] = $item[$alias]; + } + // Creating ARO $this->Acl->{$type}->create($data); $this->Acl->{$type}->save(); From 5a3b55dfc2edf620108312738154a951cb8f3292 Mon Sep 17 00:00:00 2001 From: houseoftech Date: Thu, 19 Mar 2015 21:53:03 +0100 Subject: [PATCH 02/16] Move config variables to config file Use plugin's bootstrap file to merge plugin config with local app config. --- Config/acl_manager.php | 55 ++++++++++++++++++++++++++++++++++++ Config/bootstrap.php | 64 ++++++++---------------------------------- 2 files changed, 67 insertions(+), 52 deletions(-) create mode 100755 Config/acl_manager.php diff --git a/Config/acl_manager.php b/Config/acl_manager.php new file mode 100755 index 0000000..b7b932f --- /dev/null +++ b/Config/acl_manager.php @@ -0,0 +1,55 @@ + array('Role', 'User'), + + /** + * Aliases to write into ARO table + */ + // 'aro_aliases' => array('Group' => 'name', 'User' => 'username'), + + /** + * Limit used to paginate AROs + * Replace {alias} with ARO alias + * '{alias}' => array('limit' => 3) + */ + // 'Role' => array('limit' => 3), + + /** + * Routing Prefix + * Set the prefix you would like to restrict the plugin to + * @see Configure::read('Routing.prefixes') + */ + // 'prefix' => 'admin', + + /** + * Ugly identation? + * Turn off when using CSS + */ + 'uglyIdent' => true, + + /** + * Actions to ignore when looking for new ACOs + * Format: 'action', 'Controller/action' or 'Plugin.Controller/action' + */ + 'ignoreActions' => array('isAuthorized'), + + /** + * List of ARO models to load + * Use only if AclManager.aros aliases are different from model name + */ + // 'models' => array('Group', 'Customer'), + + 'version' => "1.2.4" +); diff --git a/Config/bootstrap.php b/Config/bootstrap.php index 6562d5a..4387f98 100755 --- a/Config/bootstrap.php +++ b/Config/bootstrap.php @@ -13,60 +13,20 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -/** - * List of AROs (Class aliases) - * Order is important! Parent to Children - */ -Configure::write('AclManager.aros', array('Role', 'User')); - -/** - * Aliases to write into ARO table - */ -// Configure::write('AclManager.aro_aliases', array('Group' => 'name', 'User' => 'username')); - -/** - * Limit used to paginate AROs - * Replace {alias} with ARO alias - * Configure::write('AclManager.{alias}.limit', 3) - */ -// Configure::write('AclManager.Role.limit', 3); - -/** - * Routing Prefix - * Set the prefix you would like to restrict the plugin to - * @see Configure::read('Routing.prefixes') - */ -// Configure::write('AclManager.prefix', 'admin'); - -/** - * Ugly identation? - * Turn off when using CSS - */ -Configure::write('AclManager.uglyIdent', true); - -/** - * Actions to ignore when looking for new ACOs - * Format: 'action', 'Controller/action' or 'Plugin.Controller/action' - */ -Configure::write('AclManager.ignoreActions', array('isAuthorized')); - -/** - * List of ARO models to load - * Use only if AclManager.aros aliases are different than model name - */ -// Configure::write('AclManager.models', array('Group', 'Customer')); +// Default to Plugin config which can be overwritten by local app config +Configure::load('AclManager.acl_manager'); +$defaultConfig = Configure::read('AclManager'); + +$config = array(); +// Local app config +if (file_exists(APP . 'Config' . DS . 'acl_manager.php')) { + Configure::load('acl_manager', 'default', false); + $config = Configure::read('AclManager'); +} -/** - * END OF USER SETTINGS - */ +$config = array_merge($defaultConfig, $config); +Configure::write('AclManager', $config); -Configure::write("AclManager.version", "1.2.4"); -if (!is_array(Configure::read('AclManager.aros'))) { - Configure::write('AclManager.aros', array(Configure::read('AclManager.aros'))); -} -if (!is_array(Configure::read('AclManager.ignoreActions'))) { - Configure::write('AclManager.ignoreActions', array(Configure::read('AclManager.ignoreActions'))); -} if (!Configure::read('AclManager.models')) { Configure::write('AclManager.models', Configure::read('AclManager.aros')); } From a7820ff8f40f624c35a26979f3e00c05d1cbefee Mon Sep 17 00:00:00 2001 From: houseoftech Date: Thu, 19 Mar 2015 22:02:23 +0100 Subject: [PATCH 03/16] Cache ACOs to speed up listing of permissions Add new cacheConfig configuration variable so you can choose a custom length to cache for. --- Config/acl_manager.php | 5 +++++ Controller/AclController.php | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Config/acl_manager.php b/Config/acl_manager.php index b7b932f..44423fc 100755 --- a/Config/acl_manager.php +++ b/Config/acl_manager.php @@ -45,6 +45,11 @@ */ 'ignoreActions' => array('isAuthorized'), + /** + * Cache configuration to use for caching ACOs + */ + 'cacheConfig' => 'default', + /** * List of ARO models to load * Use only if AclManager.aros aliases are different from model name diff --git a/Controller/AclController.php b/Controller/AclController.php index 1299ba1..5e80667 100755 --- a/Controller/AclController.php +++ b/Controller/AclController.php @@ -98,7 +98,10 @@ public function permissions() { $this->Acl->deny($node, $action); } } - } + } + + // remove cached acos file when updating permissions + Cache::delete('acos', Configure::read('AclManager.cacheConfig')); } $model = isset($this->request->params['named']['aro']) ? $this->request->params['named']['aro'] : null; @@ -114,7 +117,12 @@ public function permissions() { /** * Build permissions info */ - $this->acos = $acos = $this->Acl->Aco->find('all', array('order' => 'Aco.lft ASC', 'recursive' => 1)); + $acos = Cache::read('acos', Configure::read('AclManager.cacheConfig')); + if (!$acos) { + $acos = $this->Acl->Aco->find('all', array('order' => 'Aco.lft ASC', 'recursive' => 1)); + Cache::write('acos', $acos, Configure::read('AclManager.cacheConfig')); + } + $this->acos = $acos; $perms = array(); $parents = array(); foreach ($acos as $key => $data) { @@ -144,6 +152,7 @@ public function permissions() { $this->request->data = array('Perms' => $perms); $this->set('aroAlias', $Aro->alias); $this->set('aroDisplayField', $Aro->displayField); + $this->set('aroList', array_values($this->{$Aro->alias}->find('list'))); $this->set(compact('acos', 'aros')); } @@ -293,6 +302,9 @@ public function update_acos() { $this->Acl->Aco->deleteAll(array('Aco.id' => $acoIds)); } + // remove cached acos file when updating ACOs + Cache::delete('acos', Configure::read('AclManager.cacheConfig')); + $this->Session->setFlash(sprintf(__("%d ACOs have been created/updated"), $count)); $this->redirect($this->request->referer()); } From 4fb4b303303c69d3a41baac288577be311077bca Mon Sep 17 00:00:00 2001 From: houseoftech Date: Thu, 19 Mar 2015 22:09:01 +0100 Subject: [PATCH 04/16] Bootstraperize the permissions page --- View/Acl/permissions.ctp | 95 ++++++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 14 deletions(-) diff --git a/View/Acl/permissions.ctp b/View/Acl/permissions.ctp index 52e80cc..3d7c99c 100755 --- a/View/Acl/permissions.ctp +++ b/View/Acl/permissions.ctp @@ -1,13 +1,33 @@

-

Paginator->counter(array('format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%'))); ?>

-
- Paginator->prev('<< ' . __('previous'), array(), null, array('class'=>'disabled'));?> - | Paginator->numbers();?> | - Paginator->next(__('next') . ' >>', array(), null, array('class' => 'disabled'));?> + +
+
+ Form->create('Page', array('default' => false));?> + Form->input('group_id', array('id' => 'AroSelector', 'div' => false, 'label' => 'Jump to...', 'options' => $aroList, 'empty' => $aroAlias, 'value' => isset($this->params['named']['page']) ? $this->params['named']['page'] -1 : ''));?> + Form->end(null);?> +
+ +
+ Paginator->pagination(array( + 'modulus' => '4', + 'first_title' => '«', + 'last_title' => '»', + 'prev_title' => '‹ prev', + 'next_title' => 'next ›', + 'ul' => 'pagination pagination-sm pull-right', + ));?> + +

+ Paginator->counter( + '{:count} results, showing {:start} - {:end}' + );?>   +

+
+ Form->create('Perms'); ?> - +
@@ -36,7 +56,21 @@ foreach ($acos as $id => $aco) { $allowed = $this->Form->value("Perms." . str_replace("/", ":", $action) . ".{$aroAlias}:{$aro[$aroAlias]['id']}"); $value = $inherit ? 'inherit' : null; $icon = $this->Html->image(($allowed ? 'test-pass-icon.png' : 'test-fail-icon.png')); ?> - +
Action Form->select("Perms." . str_replace("/", ":", $action) . ".{$aroAlias}:{$aro[$aroAlias]['id']}", array(array('inherit' => __('Inherit'), 'allow' => __('Allow'), 'deny' => __('Deny'))), array('empty' => __('No change'), 'value' => $value)); ?> + Form->input("Perms." . str_replace("/", ":", $action) . ".{$aroAlias}:{$aro[$aroAlias]['id']}", array( + 'options' => array( + 'inherit' => __('Inherit'), + 'allow' => __('Allow'), + 'deny' => __('Deny') + ), + 'empty' => __('No change'), + 'value' => $value, + 'div' => false, + 'label' => false, + 'wrapInput' => false, + 'class' => 'input-sm' + )); ?> +
Form->end(__("Save")); +echo $this->Form->submit(__("Save"), array('class' => 'btn btn-primary')); +echo $this->Form->end(null); ?> -

Paginator->counter(array('format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%'))); ?>

-
- Paginator->prev('<< ' . __('previous'), array(), null, array('class'=>'disabled'));?> - | Paginator->numbers();?> | - Paginator->next(__('next') . ' >>', array(), null, array('class' => 'disabled'));?> -
+ +Paginator->pagination(array( + 'modulus' => '4', + 'first_title' => '«', + 'last_title' => '»', + 'prev_title' => '‹ prev', + 'next_title' => 'next ›', + 'ul' => 'pagination pagination-sm pull-right', +));?> + +

+ Paginator->counter( + '{:count} results, showing {:start} - {:end}' + );?>   +

+

@@ -75,3 +120,25 @@ echo $this->Form->end(__("Save"));
  • Html->link(__('Drop permissions'), array('action' => 'drop_perms'), array(), __("Do you want to drop all the permissions?")); ?>
  • + + $this->params['prefix'], + 'plugin' => $this->params['plugin'], + 'controller' => $this->params['controller'], + 'action' => $this->params['action'] + ); +?> + + \ No newline at end of file From 5622202736e6bcfb56beba714cb48e021e6b3de9 Mon Sep 17 00:00:00 2001 From: houseoftech Date: Thu, 19 Mar 2015 22:18:30 +0100 Subject: [PATCH 05/16] Bump to version 1.2.5 likah they said --- Config/acl_manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config/acl_manager.php b/Config/acl_manager.php index 44423fc..ad735af 100755 --- a/Config/acl_manager.php +++ b/Config/acl_manager.php @@ -56,5 +56,5 @@ */ // 'models' => array('Group', 'Customer'), - 'version' => "1.2.4" + 'version' => "1.2.5" ); From 80edc84d5d9f3bfa1e1a62182a05cf8c271ba50a Mon Sep 17 00:00:00 2001 From: houseoftech Date: Thu, 19 Mar 2015 22:23:01 +0100 Subject: [PATCH 06/16] Point composer to houseoftech fork --- composer.json | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 02f3aff..e74f331 100644 --- a/composer.json +++ b/composer.json @@ -1,11 +1,15 @@ { - "name": "fmcorz/acl-manager", - "type": "cakephp-plugin", - "description": "AclManager for CakePHP 2.x", - "homepage": "http://github.com/FMCorz/AclManager", - "license": "MIT", - "require": { - "php": ">=5.2.8", - "composer/installers": "*" - } + "name": "houseoftech/acl-manager", + "type": "cakephp-plugin", + "description": "AclManager for CakePHP 2.x", + "homepage": "http://github.com/houseoftech/AclManager", + "license": "MIT", + "require": { + "php": ">=5.2.8", + "composer/installers": "*" + }, + "repositories": { + "type": "vcs", + "url": "https://github.com/houseoftech/AclManager.git" + } } From fe5bd856d10c818f93a287fba3414fa63526eaa1 Mon Sep 17 00:00:00 2001 From: houseoftech Date: Fri, 20 Mar 2015 07:19:39 +0100 Subject: [PATCH 07/16] Update composer.json --- composer.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/composer.json b/composer.json index e74f331..3c1cb20 100644 --- a/composer.json +++ b/composer.json @@ -7,9 +7,5 @@ "require": { "php": ">=5.2.8", "composer/installers": "*" - }, - "repositories": { - "type": "vcs", - "url": "https://github.com/houseoftech/AclManager.git" } } From 7dbbba41c2e66b07aa657d2f24c7e226dabca5e1 Mon Sep 17 00:00:00 2001 From: Corie Slate Date: Mon, 23 Mar 2015 14:39:41 +0100 Subject: [PATCH 08/16] Update composer.json --- composer.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 3c1cb20..31124da 100644 --- a/composer.json +++ b/composer.json @@ -1,11 +1,14 @@ { - "name": "houseoftech/acl-manager", + "name": "houseoftech/cakephp-acl-manager", "type": "cakephp-plugin", "description": "AclManager for CakePHP 2.x", - "homepage": "http://github.com/houseoftech/AclManager", + "homepage": "http://github.com/houseoftech/cakephp-acl-manager", "license": "MIT", "require": { "php": ">=5.2.8", "composer/installers": "*" + }, + "extra": { + "installer-name": "AclManager" } } From 077149e4791bf4ae18cbcf85aef16c8a9958178b Mon Sep 17 00:00:00 2001 From: Oxicode Date: Mon, 25 Jan 2016 14:55:46 -0500 Subject: [PATCH 09/16] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f26ed4d..e47a56b 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ Download the stable branch (https://github.com/FMCorz/AclManager/archive/stable. #### With Composer 1. [Install composer](http://getcomposer.org/doc/00-intro.md#locally) in the `app/` folder of your project. -2. Add `"fmcorz/acl-manager": "stable"` to your `require` key in your `composer.json` file. ([More about this](http://getcomposer.org/doc/01-basic-usage.md#the-require-key)) +2. Add `"houseoftech/acl-manager": "stable"` to your `require` key in your `composer.json` file. ([More about this](http://getcomposer.org/doc/01-basic-usage.md#the-require-key)) 3. Run `php composer.phar install` to install the plugin. [Composer documentation](http://getcomposer.org/doc/) From 0a51e14aee81e964d1b6db0c3dc212c1160227d6 Mon Sep 17 00:00:00 2001 From: houseoftech Date: Wed, 17 Feb 2016 07:05:44 -0500 Subject: [PATCH 10/16] Update paths in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e47a56b..1815b87 100644 --- a/README.md +++ b/README.md @@ -73,12 +73,12 @@ function isAuthorized($user) { #### Manually -Download the stable branch (https://github.com/FMCorz/AclManager/archive/stable.zip) and paste the content in your `app/Plugin/` directory. +Download the stable branch (https://github.com/houseoftech/cakephp-acl-manager/archive/stable.zip) and paste the content in your `app/Plugin/` directory. #### With Composer 1. [Install composer](http://getcomposer.org/doc/00-intro.md#locally) in the `app/` folder of your project. -2. Add `"houseoftech/acl-manager": "stable"` to your `require` key in your `composer.json` file. ([More about this](http://getcomposer.org/doc/01-basic-usage.md#the-require-key)) +2. Add `"houseoftech/cakephp-acl-manager": "stable"` to your `require` key in your `composer.json` file. ([More about this](http://getcomposer.org/doc/01-basic-usage.md#the-require-key)) 3. Run `php composer.phar install` to install the plugin. [Composer documentation](http://getcomposer.org/doc/) From 0d2025580cdfa7728de2f00bede079ec39c8c93b Mon Sep 17 00:00:00 2001 From: houseoftech Date: Wed, 16 Mar 2016 21:29:13 +0100 Subject: [PATCH 11/16] Optimize permissions lookup The front end paginator is only requesting one group at a time so we only need to get the Aco and Permission records. This should speed things up quite a bit if the acos table is very large. --- Controller/AclController.php | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/Controller/AclController.php b/Controller/AclController.php index 5e80667..5480a85 100755 --- a/Controller/AclController.php +++ b/Controller/AclController.php @@ -119,7 +119,31 @@ public function permissions() { */ $acos = Cache::read('acos', Configure::read('AclManager.cacheConfig')); if (!$acos) { - $acos = $this->Acl->Aco->find('all', array('order' => 'Aco.lft ASC', 'recursive' => 1)); + $aroRecords = $this->Acl->Aro->find('all', array( + 'conditions' => array( + 'Aro.model' => $model, + 'Aro.foreign_key' => Hash::extract($aros, '{n}.{s}.id') + ), + 'recursive' => -1 + )); + $aroIds = implode(',', Hash::extract($aroRecords, '{n}.Aro.id')); + + $acos = $this->Acl->Aco->query( + "SELECT * FROM acos as Aco + LEFT JOIN aros_acos as Permission on Permission.aco_id = Aco.id AND + Permission.aro_id IN({$aroIds}) + ORDER BY Aco.lft ASC + " + ); + foreach($acos as $key => $row) { + $extractedAros = Hash::extract($aroRecords, '{n}.Aro'); + if (count($aroRecords) == 1) { + $acos[$key]['Aro'] = array_shift($extractedAros); + } else { + $acos[$key]['Aro'] = $extractedAros; + } + } + Cache::write('acos', $acos, Configure::read('AclManager.cacheConfig')); } $this->acos = $acos; @@ -159,10 +183,9 @@ public function permissions() { /** * Recursive function to find permissions avoiding slow $this->Acl->check(). */ - private function _evaluate_permissions($permKeys, $aro, $aco, $aco_index) { - $permissions = Set::extract("/Aro[model={$aro['alias']}][foreign_key={$aro['id']}]/Permission/.", $aco); - $permissions = array_shift($permissions); - + private function _evaluate_permissions($permKeys, $aro, $aco, $aco_index) { + $permissions = $aco['Permission']; + $allowed = false; $inherited = false; $inheritedPerms = array(); From be2d5f34ebbb3b1951fa033bb0cd5c2cab030f1a Mon Sep 17 00:00:00 2001 From: houseoftech Date: Wed, 16 Mar 2016 21:29:58 +0100 Subject: [PATCH 12/16] The $acos array is already formatted --- Controller/AclController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Controller/AclController.php b/Controller/AclController.php index 5480a85..99c2c71 100755 --- a/Controller/AclController.php +++ b/Controller/AclController.php @@ -151,7 +151,6 @@ public function permissions() { $parents = array(); foreach ($acos as $key => $data) { $aco =& $acos[$key]; - $aco = array('Aco' => $data['Aco'], 'Aro' => $data['Aro'], 'Action' => array()); $id = $aco['Aco']['id']; // Generate path From 83074e07abe47df6bf440fbeb6e439592f157500 Mon Sep 17 00:00:00 2001 From: houseoftech Date: Wed, 16 Mar 2016 21:30:25 +0100 Subject: [PATCH 13/16] Remove extra whitespace --- Controller/AclController.php | 102 +++++++++++++++++------------------ 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/Controller/AclController.php b/Controller/AclController.php index 99c2c71..e862ad8 100755 --- a/Controller/AclController.php +++ b/Controller/AclController.php @@ -12,7 +12,7 @@ * @link http://github.com/FMCorz/AclManager * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - + class AclController extends AclManagerAppController { public $paginate = array(); @@ -24,7 +24,7 @@ class AclController extends AclManagerAppController { */ public function beforeFilter() { parent::beforeFilter(); - + /** * Loading required Model */ @@ -32,7 +32,7 @@ public function beforeFilter() { foreach ($aros as $aro) { $this->loadModel($aro); } - + /** * Pagination */ @@ -56,7 +56,7 @@ public function drop() { $this->Session->setFlash(__("Both ACOs and AROs have been dropped")); $this->redirect(array("action" => "index")); } - + /** * Delete all permissions */ @@ -99,11 +99,11 @@ public function permissions() { } } } - + // remove cached acos file when updating permissions Cache::delete('acos', Configure::read('AclManager.cacheConfig')); } - + $model = isset($this->request->params['named']['aro']) ? $this->request->params['named']['aro'] : null; if (!$model || !in_array($model, Configure::read('AclManager.aros'))) { $model = Configure::read('AclManager.aros'); @@ -113,7 +113,7 @@ public function permissions() { $Aro = $this->{$model}; $aros = $this->paginate($Aro->alias); $permKeys = $this->_getKeys(); - + /** * Build permissions info */ @@ -152,7 +152,7 @@ public function permissions() { foreach ($acos as $key => $data) { $aco =& $acos[$key]; $id = $aco['Aco']['id']; - + // Generate path if ($aco['Aco']['parent_id'] && isset($parents[$aco['Aco']['parent_id']])) { $parents[$id] = $parents[$aco['Aco']['parent_id']] . '/' . $aco['Aco']['alias']; @@ -166,7 +166,7 @@ public function permissions() { foreach($aros as $aro) { $aroId = $aro[$Aro->alias][$Aro->primaryKey]; $evaluate = $this->_evaluate_permissions($permKeys, array('id' => $aroId, 'alias' => $Aro->alias), $aco, $key); - + $perms[str_replace('/', ':', $acoNode)][$Aro->alias . ":" . $aroId . '-inherit'] = $evaluate['inherited']; $perms[str_replace('/', ':', $acoNode)][$Aro->alias . ":" . $aroId] = $evaluate['allowed']; } @@ -178,7 +178,7 @@ public function permissions() { $this->set('aroList', array_values($this->{$Aro->alias}->find('list'))); $this->set(compact('acos', 'aros')); } - + /** * Recursive function to find permissions avoiding slow $this->Acl->check(). */ @@ -189,7 +189,7 @@ private function _evaluate_permissions($permKeys, $aro, $aco, $aco_index) { $inherited = false; $inheritedPerms = array(); $allowedPerms = array(); - + /** * Manually checking permission * Part of this logic comes from DbAcl::check() @@ -208,7 +208,7 @@ private function _evaluate_permissions($permKeys, $aro, $aco, $aco_index) { $inheritedPerms[$key] = 0; } } - + if (count($allowedPerms) === count($permKeys)) { $allowed = true; } elseif (count($inheritedPerms) === count($permKeys)) { @@ -224,7 +224,7 @@ private function _evaluate_permissions($permKeys, $aro, $aco, $aco_index) { } else { /** - * Do not use Set::extract here. First of all it is terribly slow, + * Do not use Set::extract here. First of all it is terribly slow, * besides this we need the aco array index ($key) to cache are result. */ foreach ($this->acos as $key => $a) { @@ -237,19 +237,19 @@ private function _evaluate_permissions($permKeys, $aro, $aco, $aco_index) { if (isset($parent_aco['evaluated'][$aro['id']])) { return $parent_aco['evaluated'][$aro['id']]; } - + // Perform lookup of parent aco $evaluate = $this->_evaluate_permissions($permKeys, $aro, $parent_aco, $key); - + // Store result in acos array so we need less recursion for the next lookup $this->acos[$key]['evaluated'][$aro['id']] = $evaluate; $this->acos[$key]['evaluated'][$aro['id']]['inherited'] = true; - + $allowed = $evaluate['allowed']; } $inherited = true; } - + return array( 'allowed' => $allowed, 'inherited' => $inherited, @@ -261,10 +261,10 @@ private function _evaluate_permissions($permKeys, $aro, $aco, $aco_index) { * Sets the missing actions in the database */ public function update_acos() { - + $count = 0; $knownAcos = $this->_getAcos(); - + // Root node $aco = $this->_action(array(), ''); if (!$rootNode = $this->Acl->Aco->node($aco)) { @@ -272,17 +272,17 @@ public function update_acos() { $count++; } $knownAcos = $this->_removeActionFromAcos($knownAcos, $aco); - + // Loop around each controller and its actions $allActions = $this->_getActions(); foreach ($allActions as $controller => $actions) { if (empty($actions)) { continue; } - + $parentNode = $rootNode; list($plugin, $controller) = pluginSplit($controller); - + // Plugin $aco = $this->_action(array('plugin' => $plugin), '/:plugin/'); $aco = rtrim($aco, '/'); // Remove trailing slash @@ -293,7 +293,7 @@ public function update_acos() { } $parentNode = $newNode; $knownAcos = $this->_removeActionFromAcos($knownAcos, $aco); - + // Controller $aco = $this->_action(array('controller' => $controller, 'plugin' => $plugin), '/:plugin/:controller'); if (!$newNode = $this->Acl->Aco->node($aco)) { @@ -323,10 +323,10 @@ public function update_acos() { $acoIds = Set::extract('/Aco/id', $knownAcos); $this->Acl->Aco->deleteAll(array('Aco.id' => $acoIds)); } - + // remove cached acos file when updating ACOs Cache::delete('acos', Configure::read('AclManager.cacheConfig')); - + $this->Session->setFlash(sprintf(__("%d ACOs have been created/updated"), $count)); $this->redirect($this->request->referer()); } @@ -336,22 +336,22 @@ public function update_acos() { * Sets the missing AROs in the database */ public function update_aros() { - + // Debug off to enable redirect Configure::write('debug', 0); - + $count = 0; $type = 'Aro'; - + // Over each ARO Model $objects = Configure::read("AclManager.aros"); foreach ($objects as $object) { - + $Model = $this->{$object}; $items = $Model->find('all'); foreach ($items as $item) { - + $item = $item[$Model->alias]; $Model->create(); $Model->id = $item['id']; @@ -361,7 +361,7 @@ public function update_aros() { } catch (Exception $e) { $node = false; } - + // Node exists if ($node) { $parent = $Model->parentNode(); @@ -369,7 +369,7 @@ public function update_aros() { $parent = $Model->node($parent, $type); } $parent = isset($parent[0][$type]['id']) ? $parent[0][$type]['id'] : null; - + // Parent is incorrect if ($parent != $node[0][$type]['parent_id']) { // Remove Aro here, otherwise we've got duplicate Aros @@ -378,10 +378,10 @@ public function update_aros() { $node = null; } } - + // Missing Node or incorrect if (empty($node)) { - + // Extracted from AclBehavior::afterSave (and adapted) $parent = $Model->parentNode(); if (!empty($parent)) { @@ -392,11 +392,11 @@ public function update_aros() { 'model' => $Model->name, 'foreign_key' => $Model->id ); - + if ($alias = Configure::read("AclManager.aro_aliases.{$Model->name}")) { $data['alias'] = $item[$alias]; } - + // Creating ARO $this->Acl->{$type}->create($data); $this->Acl->{$type}->save(); @@ -404,7 +404,7 @@ public function update_aros() { } } } - + $this->Session->setFlash(sprintf(__("%d AROs have been created"), $count)); $this->redirect($this->request->referer()); } @@ -416,7 +416,7 @@ protected function _action($request = array(), $path = '/:plugin/:controller/:ac $plugin = empty($request['plugin']) ? null : Inflector::camelize($request['plugin']) . '/'; $params = array_merge(array('controller' => null, 'action' => null, 'plugin' => null), $request); $request = new CakeRequest(null, false); - $request->addParams($params); + $request->addParams($params); $authorizer = $this->_getAuthorizer(); return $authorizer->action($request, $path); } @@ -437,12 +437,12 @@ protected function _buildAcoNode($alias, $parent_id = null) { /** * Returns all the Actions found in the Controllers - * + * * Ignores: * - protected and private methods (starting with _) * - Controller methods * - methods matching Configure::read('AclManager.ignoreActions') - * + * * @return array('Controller' => array('action1', 'action2', ... )) */ protected function _getActions() { @@ -451,13 +451,13 @@ protected function _getActions() { foreach($methods as $method) { $ignore[] = $method; } - + $controllers = $this->_getControllers(); $actions = array(); foreach ($controllers as $controller) { - + list($plugin, $name) = pluginSplit($controller); - + $methods = get_class_methods($name . "Controller"); $methods = array_diff($methods, $ignore); foreach ($methods as $key => $method) { @@ -467,7 +467,7 @@ protected function _getActions() { } $actions[$controller] = $methods; } - + return $actions; } @@ -478,10 +478,10 @@ protected function _getAcos() { $acos = $this->Acl->Aco->find('all', array('order' => 'Aco.lft ASC', 'recursive' => -1)); $parents = array(); foreach ($acos as $key => $data) { - + $aco =& $acos[$key]; $id = $aco['Aco']['id']; - + // Generate path if ($aco['Aco']['parent_id'] && isset($parents[$aco['Aco']['parent_id']])) { $parents[$id] = $parents[$aco['Aco']['parent_id']] . '/' . $aco['Aco']['alias']; @@ -505,7 +505,7 @@ protected function _getAuthorizer() { if (!$object instanceOf ActionsAuthorize) { continue; } - $this->_authorizer = $object; + $this->_authorizer = $object; break; } if (empty($this->_authorizer)) { @@ -522,7 +522,7 @@ protected function _getAuthorizer() { * @return array('Controller1', 'Plugin.Controller2') */ protected function _getControllers() { - + // Getting Cake controllers $objects = array('Cake' => array()); $objects['Cake'] = App::objects('Controller'); @@ -530,12 +530,12 @@ protected function _getControllers() { if ($unsetIndex !== false) { unset($objects['Cake'][$unsetIndex]); } - + // App::objects does not return PagesController if (!in_array('PagesController', $objects['Cake'])) { array_unshift($objects['Cake'], 'PagesController'); } - + // Getting Plugins controllers $plugins = CakePlugin::loaded(); foreach ($plugins as $plugin) { @@ -578,7 +578,7 @@ protected function _getKeys() { } return $newKeys; } - + /** * Returns an array without the corresponding action */ From 3d79ea5f17b15908b75e54ba39c03e998f0d059b Mon Sep 17 00:00:00 2001 From: houseoftech Date: Thu, 17 Mar 2016 09:11:40 +0100 Subject: [PATCH 14/16] Remove cacheing of acos Cache actually won't work anymore because we're only getting one Aro and set of permissions at a time. It's actually faster this way than reading from a giant cache file. --- Config/acl_manager.php | 5 ---- Controller/AclController.php | 56 +++++++++++++++--------------------- 2 files changed, 23 insertions(+), 38 deletions(-) diff --git a/Config/acl_manager.php b/Config/acl_manager.php index ad735af..e5a4b4c 100755 --- a/Config/acl_manager.php +++ b/Config/acl_manager.php @@ -45,11 +45,6 @@ */ 'ignoreActions' => array('isAuthorized'), - /** - * Cache configuration to use for caching ACOs - */ - 'cacheConfig' => 'default', - /** * List of ARO models to load * Use only if AclManager.aros aliases are different from model name diff --git a/Controller/AclController.php b/Controller/AclController.php index e862ad8..9ffff8f 100755 --- a/Controller/AclController.php +++ b/Controller/AclController.php @@ -99,9 +99,6 @@ public function permissions() { } } } - - // remove cached acos file when updating permissions - Cache::delete('acos', Configure::read('AclManager.cacheConfig')); } $model = isset($this->request->params['named']['aro']) ? $this->request->params['named']['aro'] : null; @@ -117,35 +114,31 @@ public function permissions() { /** * Build permissions info */ - $acos = Cache::read('acos', Configure::read('AclManager.cacheConfig')); - if (!$acos) { - $aroRecords = $this->Acl->Aro->find('all', array( - 'conditions' => array( - 'Aro.model' => $model, - 'Aro.foreign_key' => Hash::extract($aros, '{n}.{s}.id') - ), - 'recursive' => -1 - )); - $aroIds = implode(',', Hash::extract($aroRecords, '{n}.Aro.id')); - - $acos = $this->Acl->Aco->query( - "SELECT * FROM acos as Aco - LEFT JOIN aros_acos as Permission on Permission.aco_id = Aco.id AND - Permission.aro_id IN({$aroIds}) - ORDER BY Aco.lft ASC - " - ); - foreach($acos as $key => $row) { - $extractedAros = Hash::extract($aroRecords, '{n}.Aro'); - if (count($aroRecords) == 1) { - $acos[$key]['Aro'] = array_shift($extractedAros); - } else { - $acos[$key]['Aro'] = $extractedAros; - } + $aroRecords = $this->Acl->Aro->find('all', array( + 'conditions' => array( + 'Aro.model' => $model, + 'Aro.foreign_key' => Hash::extract($aros, '{n}.{s}.id') + ), + 'recursive' => -1 + )); + $aroIds = implode(',', Hash::extract($aroRecords, '{n}.Aro.id')); + $acos = $this->Acl->Aco->query( + "SELECT * FROM acos as Aco + LEFT JOIN aros_acos as Permission on Permission.aco_id = Aco.id AND + Permission.aro_id IN({$aroIds}) + ORDER BY Aco.lft ASC + " + ); + // add Aro key along side each Aco + foreach($acos as $key => $row) { + $extractedAros = Hash::extract($aroRecords, '{n}.Aro'); + if (count($aroRecords) == 1) { + $acos[$key]['Aro'] = array_shift($extractedAros); + } else { + $acos[$key]['Aro'] = $extractedAros; } - - Cache::write('acos', $acos, Configure::read('AclManager.cacheConfig')); } + $this->acos = $acos; $perms = array(); $parents = array(); @@ -324,9 +317,6 @@ public function update_acos() { $this->Acl->Aco->deleteAll(array('Aco.id' => $acoIds)); } - // remove cached acos file when updating ACOs - Cache::delete('acos', Configure::read('AclManager.cacheConfig')); - $this->Session->setFlash(sprintf(__("%d ACOs have been created/updated"), $count)); $this->redirect($this->request->referer()); } From 919dcdf432a78fd46d6b6e3c431ffc07e7807796 Mon Sep 17 00:00:00 2001 From: houseoftech Date: Thu, 17 Mar 2016 09:11:49 +0100 Subject: [PATCH 15/16] Update version --- Config/acl_manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config/acl_manager.php b/Config/acl_manager.php index e5a4b4c..b850a28 100755 --- a/Config/acl_manager.php +++ b/Config/acl_manager.php @@ -51,5 +51,5 @@ */ // 'models' => array('Group', 'Customer'), - 'version' => "1.2.5" + 'version' => "1.3.1" ); From c5cd19327aea8c129930b876df0c892c9542629f Mon Sep 17 00:00:00 2001 From: houseoftech Date: Sat, 19 Mar 2016 07:50:45 +0100 Subject: [PATCH 16/16] Support wildcards in ignoreActions setting --- Controller/AclController.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Controller/AclController.php b/Controller/AclController.php index 9ffff8f..d16283d 100755 --- a/Controller/AclController.php +++ b/Controller/AclController.php @@ -528,6 +528,25 @@ protected function _getControllers() { // Getting Plugins controllers $plugins = CakePlugin::loaded(); + + // remove ignored plugins + $ignore = Configure::read('AclManager.ignoreActions'); + $ignoredPlugins = $ignoredControllers = array(); + foreach($ignore as $path) { + if (stristr($path, '.*')) { + list($plugin, $controllerAction) = pluginSplit($path); + $ignoredPlugins[] = $plugin; + } elseif (stristr($path, '/*')) { + list($plugin, $controller) = pluginSplit($path); + if ($plugin == '') { + $plugin = 'Cake'; + } + $controller = str_ireplace('/*', '', $controller); + $ignoredControllers[$plugin][] = $controller; + } + } + $plugins = array_diff($plugins, $ignoredPlugins); + foreach ($plugins as $plugin) { $objects[$plugin] = App::objects($plugin . '.Controller'); $unsetIndex = array_search($plugin . "AppController", $objects[$plugin]); @@ -541,6 +560,9 @@ protected function _getControllers() { foreach ($objects as $plugin => $controllers) { $controllers = str_replace("Controller", "", $controllers); foreach ($controllers as $controller) { + if (isset($ignoredControllers[$plugin]) && in_array($controller, $ignoredControllers[$plugin])) { + continue; + } if ($plugin !== "Cake") { $controller = $plugin . "." . $controller; }