Commit 19a31f8f45f319e828f9972cffb629ce2ae326bc

Authored by Etienne Pallier
1 parent c7e9e701

ajout de tests sur easyACL && nombreux bugfixes (merci les tests) !!!

src/Controller/AppController.php
... ... @@ -56,7 +56,8 @@ class AppController extends Controller {
56 56 private $CURRENT_ROLE = null;
57 57  
58 58 // EP 08/2017
59   - protected $easyACL = array(
  59 + //protected $easyACL = array(
  60 + const easyACL = array(
60 61  
61 62 /** Default ACL for ALL (logged) users
62 63 *
... ... @@ -72,7 +73,10 @@ class AppController extends Controller {
72 73 // CRUD actions :
73 74 //'edit' => 'N', // update
74 75 //'delete' => 'N',
75   - 'autre' => 'Y',
  76 + 'autre1' => 'Y',
  77 + 'autre2' => 'N',
  78 + 'autre3' => 'Y',
  79 + 'autre4' => 'N',
76 80 ),
77 81  
78 82 // Ajoute des ACL plus spécifiques (ci-dessus) pour le profil USER qui est plus restreint
... ... @@ -119,6 +123,13 @@ class AppController extends Controller {
119 123 ),
120 124 ); // $easyACL
121 125  
  126 + //if (isset($this->easyACL['DEFAULT'][$action])) {
  127 + public function hasACLRule($easyACL, $role, $action) {
  128 + //return isset($this->easyACL[$role][$action]);
  129 + //return (null !== self::easyACL[$role][$action]);
  130 + //return array_key_exists($role, self::easyACL) && array_key_exists($action, self::easyACL[$role]);
  131 + return array_key_exists($role, $easyACL) && array_key_exists($action, $easyACL[$role]);
  132 + }
122 133  
123 134 //@todo
124 135 public function startsWith($haystack, $needle) {
... ... @@ -142,9 +153,11 @@ class AppController extends Controller {
142 153 public function evalSpecificRule($condition, AppController $controller, $user, $role, $action, $id=null) {
143 154 // if starts with "&&" eval DEFAULT rule && specific rule
144 155 if ($this->startsWith($condition,'&&')) {
145   - if (! isset($controller->easyACL['DEFAULT'][$action])) return new \Exception('bad rule');
  156 + //debug($condition);
  157 + //if (! isset($controller::easyACL['DEFAULT'][$action])) return new \Exception('bad rule');
  158 + if (! array_key_exists($action, $controller::easyACL['DEFAULT']) ) return new \Exception('bad rule');
146 159 //return $this->evalACL($controller->easyACL['DEFAULT'][$action]) && $this->evalACL($condition);
147   - return $this->evalACL($controller->easyACL['DEFAULT'][$action]) . $this->evalACL($condition);
  160 + return $this->evalACL($controller::easyACL['DEFAULT'][$action]).' '.$this->evalACL($condition);
148 161 }
149 162 // otherwise, eval only specific rule
150 163 return $this->evalACL($condition);
... ... @@ -156,7 +169,11 @@ class AppController extends Controller {
156 169 * @param string $action
157 170 * @param string $id
158 171 */
159   - public function isAuthorizedAction(AppController $controller, $user, $roleLong, $action, $id=null) {
  172 + //public function isAuthorizedAction(AppController $controller, $roleLong, $action, $id=null, $user=null) {
  173 + public function isAuthorizedAction($controller, $roleLong, $action, $id=null, $user=null) {
  174 +
  175 + $doDEBUG=true;
  176 + $doDEBUG=false;
160 177  
161 178 switch ($roleLong) {
162 179 case 'Utilisateur': $role='USER'; break;
... ... @@ -166,20 +183,38 @@ class AppController extends Controller {
166 183 case 'Super Administrateur': $role='SUPERADMIN'; break;
167 184 }
168 185 // 1) controller specific (role) rule for action
169   - if (isset($controller->easyACL[$role][$action]))
170   - return $this->evalSpecificRule($controller->easyACL[$role][$action], $controller, $user, $role, $action);
  186 + //if (isset($controller->easyACL[$role][$action])) {
  187 + if (self::hasACLRule($controller::easyACL, $role, $action)) {
  188 + if ($doDEBUG) debug("CAS1");
  189 + return $this->evalSpecificRule($controller::easyACL[$role][$action], $controller, $user, $role, $action);
  190 + }
171 191  
172 192 // 2) AppController ($this) specific (role) rule for action
173   - if (isset($this->easyACL[$role][$action]))
174   - return $this->evalSpecificRule($this->easyACL[$role][$action], $this, $user, $role, $action);
  193 + //if (isset($this->easyACL[$role][$action])) {
  194 + if (self::hasACLRule(self::easyACL, $role, $action)) {
  195 + if ($doDEBUG) debug("CAS2");
  196 + return $this->evalSpecificRule(self::easyACL[$role][$action], $this, $user, $role, $action);
  197 + }
175 198  
176 199 // 3) controller general (DEFAULT) rule for action
177   - if (isset($controller->easyACL['DEFAULT'][$action]))
178   - return $this->evalACL($controller->easyACL['DEFAULT'][$action]);
  200 + //if (null !== $controller::easyACL['DEFAULT'][$action]) {
  201 + if (self::hasACLRule($controller::easyACL, 'DEFAULT', $action)) {
  202 + if ($doDEBUG) debug("CAS3");
  203 + return $this->evalACL($controller::easyACL['DEFAULT'][$action]);
  204 + }
179 205  
  206 + // 4) AppController general (DEFAULT) rule for action
  207 + //if (isset($this->easyACL['DEFAULT'][$action])) {
  208 + //if (self::hasACLRule('DEFAULT',$action)) {
  209 + if (self::hasACLRule(self::easyACL, 'DEFAULT',$action)) {
  210 + if ($doDEBUG) debug("CAS4");
  211 + return $this->evalACL(self::easyACL['DEFAULT'][$action]);
  212 + //return $this->evalACL(parent::getACLRule('DEFAULT',$action));
  213 + }
  214 +
180 215 /*
181 216 * (RECURSIVE CALL)
182   - * 4) controller previous specific (role) rule for action
  217 + * 5) controller previous specific (role) rule for action
183 218 * ex: if role is 'SUPER', use 'ADMIN' rule
184 219 * ex: if role is 'ADMIN', use 'RESP' rule
185 220 * ex: if role is 'RESP', use 'USER' rule
... ... @@ -187,8 +222,12 @@ class AppController extends Controller {
187 222 * Stop recursive call if role is 'USER' => no rule found, so default is authorize (Y)
188 223 */
189 224 //if ($role == 'USER') return true;
190   - if ($role == 'USER') return 'Y';
191   - return $this->isAuthorizedAction($controller, $user, $this->getPreviousRole($role), $action, $id);
  225 + if ($role == 'USER') {
  226 + if ($doDEBUG) debug("CAS5");
  227 + return 'Y';
  228 + }
  229 + if ($doDEBUG) debug("CAS6");
  230 + return $this->isAuthorizedAction($controller, $this->getPreviousRole($role), $action, $id, $user);
192 231  
193 232 }
194 233  
... ...
src/Controller/MaterielsController.php
... ... @@ -39,8 +39,9 @@ class MaterielsController extends AppController {
39 39 );
40 40  
41 41 // EP 08/2017
42   - protected $easyACL = array(
43   -
  42 + //protected $easyACL = array(
  43 + const easyACL = array(
  44 +
44 45 /** Default ACL for ALL (logged) users
45 46 *
46 47 * Les actions non mentionnées sont accessibles à tous (par défaut),
... ... @@ -59,13 +60,16 @@ class MaterielsController extends AppController {
59 60 //'find' => 'Y', // create
60 61 'edit' => '(status == CREATED || status == VALIDATED)', // update
61 62 'delete' => '(status == CREATED)',
62   - 'autre' => 'N',
  63 + 'autre1' => 'N',
  64 + 'autre2' => 'Y',
  65 + //'autre3' => 'N',
  66 + //'autre4' => 'NN',
63 67 ),
64 68  
65 69 // Ajoute des ACL plus spécifiques (ci-dessus) pour le profil USER qui est plus restreint
66 70 // Les actions absentes ne sont pas surchargées (elles sont exécutées selon les conditions définies pour 'ALL')
67 71 'USER' => array (
68   - 'edit' => '&& (is_creator [[ is_user)', // is_owner = (nom_createur == CURRENT_USER_NAME)
  72 + 'edit' => '&& (is_creator || is_user)', // is_owner = (nom_createur == CURRENT_USER_NAME)
69 73 // except fields status, owner, etiquette, and admin data, VALIDATED (only some fields, cf $modifiableFields in View/Materiels/scaffold.form.ctp)
70 74 'delete' => '&& is_owner',
71 75 /* ceci n'a aucun sens car l'action sur le modèle "Pages" s'appelle toujours "display" (et non pas tools, infos, ou printers...)
... ... @@ -186,7 +190,7 @@ class MaterielsController extends AppController {
186 190 *
187 191 * Tout le reste en dessous de cette ligne devient inutile !!!
188 192 */
189   - $this->myDebug("isAuthorizedAction ? ".$this->isAuthorizedAction($this, $user, $role, $action, $id));
  193 + $this->myDebug("isAuthorizedAction ? ".$this->isAuthorizedAction($this, $role, $action, $id, $user));
190 194  
191 195 /*
192 196 * Structure mise en place:
... ...
tests/TestCase/Controller/MaterielsControllerTest.php
... ... @@ -7,6 +7,7 @@ use App\Controller\MaterielsController;
7 7 use Cake\ORM\TableRegistry;
8 8 //use phpDocumentor\Reflection\Types\Self_;
9 9 use Cake\Core\Configure;
  10 +use App\Controller\AppController;
10 11  
11 12 /**
12 13 * App\Controller\MaterielsController Test Case
... ... @@ -127,6 +128,34 @@ class MaterielsControllerTest extends General {
127 128 * Chaque test d'une ACTION doit tester l'appel de cette action pour chaque ROLE
128 129 *
129 130 */
  131 +
  132 + /*
  133 + * *****************************************************************************
  134 + * Basic ACL testing ($easyACL array rules)
  135 + * *****************************************************************************
  136 + */
  137 + public function testEasyACL() {
  138 + $role = 'USER_from_ldap';
  139 + $this->authAs($role);
  140 + $roleLong = (new AppController())->getUserRole();
  141 + $matCont = new MaterielsController();
  142 + $this->_testEasyACL('N', $matCont, $roleLong, 'autre1');
  143 + $this->_testEasyACL('Y', $matCont, $roleLong, 'autre2');
  144 + $this->_testEasyACL('Y', $matCont, $roleLong, 'autre3');
  145 + $this->_testEasyACL('N', $matCont, $roleLong, 'autre4');
  146 + $this->_testEasyACL('Y', $matCont, $roleLong, 'unknown');
  147 + $this->_testEasyACL('Y', $matCont, $roleLong, 'add');
  148 + $this->_testEasyACL('(status == CREATED || status == VALIDATED) && (is_creator || is_user)', $matCont, $roleLong, 'edit');
  149 + /*
  150 + $action='autre4';
  151 + $rule = $matCont->isAuthorizedAction($matCont, $roleLong, $action);
  152 + $this->assertEquals('N', $rule, $roleLong.' do '.$action);
  153 + */
  154 + }
  155 + private function _testEasyACL($expectedRule, AppController $controller, $roleLong, $action) {
  156 + $rule = $controller->isAuthorizedAction($controller, $roleLong, $action);
  157 + $this->assertEquals($expectedRule, $rule, $roleLong.' do '.$action);
  158 + }
130 159  
131 160  
132 161 /*
... ...