Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • Identity
  • Permission
  • SimpleAuthenticator
  • User

Interfaces

  • IAuthenticator
  • IAuthorizator
  • IIdentity
  • IResource
  • IRole
  • IUserStorage

Exceptions

  • AuthenticationException
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  */
 11: 
 12: namespace Nette\Security;
 13: 
 14: use Nette;
 15: 
 16: 
 17: 
 18: /**
 19:  * Access control list (ACL) functionality and privileges management.
 20:  *
 21:  * This solution is mostly based on Zend_Acl (c) Zend Technologies USA Inc. (http://www.zend.com), new BSD license
 22:  *
 23:  * @copyright  Copyright (c) 2005, 2007 Zend Technologies USA Inc.
 24:  * @author     David Grudl
 25:  *
 26:  * @property-read array $roles
 27:  * @property-read array $resources
 28:  * @property-read mixed $queriedRole
 29:  * @property-read mixed $queriedResource
 30:  */
 31: class Permission extends Nette\Object implements IAuthorizator
 32: {
 33:     /** @var array  Role storage */
 34:     private $roles = array();
 35: 
 36:     /** @var array  Resource storage */
 37:     private $resources = array();
 38: 
 39:     /** @var array  Access Control List rules; whitelist (deny everything to all) by default */
 40:     private $rules = array(
 41:         'allResources' => array(
 42:             'allRoles' => array(
 43:                 'allPrivileges' => array(
 44:                     'type' => self::DENY,
 45:                     'assert' => NULL,
 46:                 ),
 47:                 'byPrivilege' => array(),
 48:             ),
 49:             'byRole' => array(),
 50:         ),
 51:         'byResource' => array(),
 52:     );
 53: 
 54:     /** @var mixed */
 55:     private $queriedRole, $queriedResource;
 56: 
 57: 
 58: 
 59:     /********************* roles ****************d*g**/
 60: 
 61: 
 62: 
 63:     /**
 64:      * Adds a Role to the list. The most recently added parent
 65:      * takes precedence over parents that were previously added.
 66:      * @param  string
 67:      * @param  string|array
 68:      * @throws Nette\InvalidArgumentException
 69:      * @throws Nette\InvalidStateException
 70:      * @return Permission  provides a fluent interface
 71:      */
 72:     public function addRole($role, $parents = NULL)
 73:     {
 74:         $this->checkRole($role, FALSE);
 75:         if (isset($this->roles[$role])) {
 76:             throw new Nette\InvalidStateException("Role '$role' already exists in the list.");
 77:         }
 78: 
 79:         $roleParents = array();
 80: 
 81:         if ($parents !== NULL) {
 82:             if (!is_array($parents)) {
 83:                 $parents = array($parents);
 84:             }
 85: 
 86:             foreach ($parents as $parent) {
 87:                 $this->checkRole($parent);
 88:                 $roleParents[$parent] = TRUE;
 89:                 $this->roles[$parent]['children'][$role] = TRUE;
 90:             }
 91:         }
 92: 
 93:         $this->roles[$role] = array(
 94:             'parents'  => $roleParents,
 95:             'children' => array(),
 96:         );
 97: 
 98:         return $this;
 99:     }
100: 
101: 
102: 
103:     /**
104:      * Returns TRUE if the Role exists in the list.
105:      * @param  string
106:      * @return bool
107:      */
108:     public function hasRole($role)
109:     {
110:         $this->checkRole($role, FALSE);
111:         return isset($this->roles[$role]);
112:     }
113: 
114: 
115: 
116:     /**
117:      * Checks whether Role is valid and exists in the list.
118:      * @param  string
119:      * @param  bool
120:      * @throws Nette\InvalidStateException
121:      * @return void
122:      */
123:     private function checkRole($role, $need = TRUE)
124:     {
125:         if (!is_string($role) || $role === '') {
126:             throw new Nette\InvalidArgumentException("Role must be a non-empty string.");
127: 
128:         } elseif ($need && !isset($this->roles[$role])) {
129:             throw new Nette\InvalidStateException("Role '$role' does not exist.");
130:         }
131:     }
132: 
133: 
134: 
135:     /**
136:      * Returns all Roles.
137:      * @return array
138:      */
139:     public function getRoles()
140:     {
141:         return array_keys($this->roles);
142:     }
143: 
144: 
145: 
146:     /**
147:      * Returns existing Role's parents ordered by ascending priority.
148:      * @param  string
149:      * @return array
150:      */
151:     public function getRoleParents($role)
152:     {
153:         $this->checkRole($role);
154:         return array_keys($this->roles[$role]['parents']);
155:     }
156: 
157: 
158: 
159:     /**
160:      * Returns TRUE if $role inherits from $inherit. If $onlyParents is TRUE,
161:      * then $role must inherit directly from $inherit.
162:      * @param  string
163:      * @param  string
164:      * @param  bool
165:      * @throws Nette\InvalidStateException
166:      * @return bool
167:      */
168:     public function roleInheritsFrom($role, $inherit, $onlyParents = FALSE)
169:     {
170:         $this->checkRole($role);
171:         $this->checkRole($inherit);
172: 
173:         $inherits = isset($this->roles[$role]['parents'][$inherit]);
174: 
175:         if ($inherits || $onlyParents) {
176:             return $inherits;
177:         }
178: 
179:         foreach ($this->roles[$role]['parents'] as $parent => $foo) {
180:             if ($this->roleInheritsFrom($parent, $inherit)) {
181:                 return TRUE;
182:             }
183:         }
184: 
185:         return FALSE;
186:     }
187: 
188: 
189: 
190:     /**
191:      * Removes the Role from the list.
192:      *
193:      * @param  string
194:      * @throws Nette\InvalidStateException
195:      * @return Permission  provides a fluent interface
196:      */
197:     public function removeRole($role)
198:     {
199:         $this->checkRole($role);
200: 
201:         foreach ($this->roles[$role]['children'] as $child => $foo) {
202:             unset($this->roles[$child]['parents'][$role]);
203:         }
204: 
205:         foreach ($this->roles[$role]['parents'] as $parent => $foo) {
206:             unset($this->roles[$parent]['children'][$role]);
207:         }
208: 
209:         unset($this->roles[$role]);
210: 
211:         foreach ($this->rules['allResources']['byRole'] as $roleCurrent => $rules) {
212:             if ($role === $roleCurrent) {
213:                 unset($this->rules['allResources']['byRole'][$roleCurrent]);
214:             }
215:         }
216: 
217:         foreach ($this->rules['byResource'] as $resourceCurrent => $visitor) {
218:             if (isset($visitor['byRole'])) {
219:                 foreach ($visitor['byRole'] as $roleCurrent => $rules) {
220:                     if ($role === $roleCurrent) {
221:                         unset($this->rules['byResource'][$resourceCurrent]['byRole'][$roleCurrent]);
222:                     }
223:                 }
224:             }
225:         }
226: 
227:         return $this;
228:     }
229: 
230: 
231: 
232:     /**
233:      * Removes all Roles from the list.
234:      *
235:      * @return Permission  provides a fluent interface
236:      */
237:     public function removeAllRoles()
238:     {
239:         $this->roles = array();
240: 
241:         foreach ($this->rules['allResources']['byRole'] as $roleCurrent => $rules) {
242:             unset($this->rules['allResources']['byRole'][$roleCurrent]);
243:         }
244: 
245:         foreach ($this->rules['byResource'] as $resourceCurrent => $visitor) {
246:             foreach ($visitor['byRole'] as $roleCurrent => $rules) {
247:                 unset($this->rules['byResource'][$resourceCurrent]['byRole'][$roleCurrent]);
248:             }
249:         }
250: 
251:         return $this;
252:     }
253: 
254: 
255: 
256:     /********************* resources ****************d*g**/
257: 
258: 
259: 
260:     /**
261:      * Adds a Resource having an identifier unique to the list.
262:      *
263:      * @param  string
264:      * @param  string
265:      * @throws Nette\InvalidArgumentException
266:      * @throws Nette\InvalidStateException
267:      * @return Permission  provides a fluent interface
268:      */
269:     public function addResource($resource, $parent = NULL)
270:     {
271:         $this->checkResource($resource, FALSE);
272: 
273:         if (isset($this->resources[$resource])) {
274:             throw new Nette\InvalidStateException("Resource '$resource' already exists in the list.");
275:         }
276: 
277:         if ($parent !== NULL) {
278:             $this->checkResource($parent);
279:             $this->resources[$parent]['children'][$resource] = TRUE;
280:         }
281: 
282:         $this->resources[$resource] = array(
283:             'parent'   => $parent,
284:             'children' => array()
285:         );
286: 
287:         return $this;
288:     }
289: 
290: 
291: 
292:     /**
293:      * Returns TRUE if the Resource exists in the list.
294:      * @param  string
295:      * @return bool
296:      */
297:     public function hasResource($resource)
298:     {
299:         $this->checkResource($resource, FALSE);
300:         return isset($this->resources[$resource]);
301:     }
302: 
303: 
304: 
305:     /**
306:      * Checks whether Resource is valid and exists in the list.
307:      * @param  string
308:      * @param  bool
309:      * @throws Nette\InvalidStateException
310:      * @return void
311:      */
312:     private function checkResource($resource, $need = TRUE)
313:     {
314:         if (!is_string($resource) || $resource === '') {
315:             throw new Nette\InvalidArgumentException("Resource must be a non-empty string.");
316: 
317:         } elseif ($need && !isset($this->resources[$resource])) {
318:             throw new Nette\InvalidStateException("Resource '$resource' does not exist.");
319:         }
320:     }
321: 
322: 
323: 
324:     /**
325:      * Returns all Resources.
326:      * @return array
327:      */
328:     public function getResources()
329:     {
330:         return array_keys($this->resources);
331:     }
332: 
333: 
334: 
335:     /**
336:      * Returns TRUE if $resource inherits from $inherit. If $onlyParents is TRUE,
337:      * then $resource must inherit directly from $inherit.
338:      *
339:      * @param  string
340:      * @param  string
341:      * @param  bool
342:      * @throws Nette\InvalidStateException
343:      * @return bool
344:      */
345:     public function resourceInheritsFrom($resource, $inherit, $onlyParent = FALSE)
346:     {
347:         $this->checkResource($resource);
348:         $this->checkResource($inherit);
349: 
350:         if ($this->resources[$resource]['parent'] === NULL) {
351:             return FALSE;
352:         }
353: 
354:         $parent = $this->resources[$resource]['parent'];
355:         if ($inherit === $parent) {
356:             return TRUE;
357: 
358:         } elseif ($onlyParent) {
359:             return FALSE;
360:         }
361: 
362:         while ($this->resources[$parent]['parent'] !== NULL) {
363:             $parent = $this->resources[$parent]['parent'];
364:             if ($inherit === $parent) {
365:                 return TRUE;
366:             }
367:         }
368: 
369:         return FALSE;
370:     }
371: 
372: 
373: 
374:     /**
375:      * Removes a Resource and all of its children.
376:      *
377:      * @param  string
378:      * @throws Nette\InvalidStateException
379:      * @return Permission  provides a fluent interface
380:      */
381:     public function removeResource($resource)
382:     {
383:         $this->checkResource($resource);
384: 
385:         $parent = $this->resources[$resource]['parent'];
386:         if ($parent !== NULL) {
387:             unset($this->resources[$parent]['children'][$resource]);
388:         }
389: 
390:         $removed = array($resource);
391:         foreach ($this->resources[$resource]['children'] as $child => $foo) {
392:             $this->removeResource($child);
393:             $removed[] = $child;
394:         }
395: 
396:         foreach ($removed as $resourceRemoved) {
397:             foreach ($this->rules['byResource'] as $resourceCurrent => $rules) {
398:                 if ($resourceRemoved === $resourceCurrent) {
399:                     unset($this->rules['byResource'][$resourceCurrent]);
400:                 }
401:             }
402:         }
403: 
404:         unset($this->resources[$resource]);
405:         return $this;
406:     }
407: 
408: 
409: 
410:     /**
411:      * Removes all Resources.
412:      * @return Permission  provides a fluent interface
413:      */
414:     public function removeAllResources()
415:     {
416:         foreach ($this->resources as $resource => $foo) {
417:             foreach ($this->rules['byResource'] as $resourceCurrent => $rules) {
418:                 if ($resource === $resourceCurrent) {
419:                     unset($this->rules['byResource'][$resourceCurrent]);
420:                 }
421:             }
422:         }
423: 
424:         $this->resources = array();
425:         return $this;
426:     }
427: 
428: 
429: 
430:     /********************* defining rules ****************d*g**/
431: 
432: 
433: 
434:     /**
435:      * Allows one or more Roles access to [certain $privileges upon] the specified Resource(s).
436:      * If $assertion is provided, then it must return TRUE in order for rule to apply.
437:      *
438:      * @param  string|array|Permission::ALL  roles
439:      * @param  string|array|Permission::ALL  resources
440:      * @param  string|array|Permission::ALL  privileges
441:      * @param  callable    assertion
442:      * @return Permission  provides a fluent interface
443:      */
444:     public function allow($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL, $assertion = NULL)
445:     {
446:         $this->setRule(TRUE, self::ALLOW, $roles, $resources, $privileges, $assertion);
447:         return $this;
448:     }
449: 
450: 
451: 
452:     /**
453:      * Denies one or more Roles access to [certain $privileges upon] the specified Resource(s).
454:      * If $assertion is provided, then it must return TRUE in order for rule to apply.
455:      *
456:      * @param  string|array|Permission::ALL  roles
457:      * @param  string|array|Permission::ALL  resources
458:      * @param  string|array|Permission::ALL  privileges
459:      * @param  callable    assertion
460:      * @return Permission  provides a fluent interface
461:      */
462:     public function deny($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL, $assertion = NULL)
463:     {
464:         $this->setRule(TRUE, self::DENY, $roles, $resources, $privileges, $assertion);
465:         return $this;
466:     }
467: 
468: 
469: 
470:     /**
471:      * Removes "allow" permissions from the list in the context of the given Roles, Resources, and privileges.
472:      *
473:      * @param  string|array|Permission::ALL  roles
474:      * @param  string|array|Permission::ALL  resources
475:      * @param  string|array|Permission::ALL  privileges
476:      * @return Permission  provides a fluent interface
477:      */
478:     public function removeAllow($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL)
479:     {
480:         $this->setRule(FALSE, self::ALLOW, $roles, $resources, $privileges);
481:         return $this;
482:     }
483: 
484: 
485: 
486:     /**
487:      * Removes "deny" restrictions from the list in the context of the given Roles, Resources, and privileges.
488:      *
489:      * @param  string|array|Permission::ALL  roles
490:      * @param  string|array|Permission::ALL  resources
491:      * @param  string|array|Permission::ALL  privileges
492:      * @return Permission  provides a fluent interface
493:      */
494:     public function removeDeny($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL)
495:     {
496:         $this->setRule(FALSE, self::DENY, $roles, $resources, $privileges);
497:         return $this;
498:     }
499: 
500: 
501: 
502:     /**
503:      * Performs operations on Access Control List rules.
504:      * @param  bool  operation add?
505:      * @param  bool  type
506:      * @param  string|array|Permission::ALL  roles
507:      * @param  string|array|Permission::ALL  resources
508:      * @param  string|array|Permission::ALL  privileges
509:      * @param  callable    assertion
510:      * @throws Nette\InvalidStateException
511:      * @return Permission  provides a fluent interface
512:      */
513:     protected function setRule($toAdd, $type, $roles, $resources, $privileges, $assertion = NULL)
514:     {
515:         // ensure that all specified Roles exist; normalize input to array of Roles or NULL
516:         if ($roles === self::ALL) {
517:             $roles = array(self::ALL);
518: 
519:         } else {
520:             if (!is_array($roles)) {
521:                 $roles = array($roles);
522:             }
523: 
524:             foreach ($roles as $role) {
525:                 $this->checkRole($role);
526:             }
527:         }
528: 
529:         // ensure that all specified Resources exist; normalize input to array of Resources or NULL
530:         if ($resources === self::ALL) {
531:             $resources = array(self::ALL);
532: 
533:         } else {
534:             if (!is_array($resources)) {
535:                 $resources = array($resources);
536:             }
537: 
538:             foreach ($resources as $resource) {
539:                 $this->checkResource($resource);
540:             }
541:         }
542: 
543:         // normalize privileges to array
544:         if ($privileges === self::ALL) {
545:             $privileges = array();
546: 
547:         } elseif (!is_array($privileges)) {
548:             $privileges = array($privileges);
549:         }
550: 
551:         $assertion = $assertion ? callback($assertion) : NULL;
552: 
553:         if ($toAdd) { // add to the rules
554:             foreach ($resources as $resource) {
555:                 foreach ($roles as $role) {
556:                     $rules = & $this->getRules($resource, $role, TRUE);
557:                     if (count($privileges) === 0) {
558:                         $rules['allPrivileges']['type'] = $type;
559:                         $rules['allPrivileges']['assert'] = $assertion;
560:                         if (!isset($rules['byPrivilege'])) {
561:                             $rules['byPrivilege'] = array();
562:                         }
563:                     } else {
564:                         foreach ($privileges as $privilege) {
565:                             $rules['byPrivilege'][$privilege]['type'] = $type;
566:                             $rules['byPrivilege'][$privilege]['assert'] = $assertion;
567:                         }
568:                     }
569:                 }
570:             }
571: 
572:         } else { // remove from the rules
573:             foreach ($resources as $resource) {
574:                 foreach ($roles as $role) {
575:                     $rules = & $this->getRules($resource, $role);
576:                     if ($rules === NULL) {
577:                         continue;
578:                     }
579:                     if (count($privileges) === 0) {
580:                         if ($resource === self::ALL && $role === self::ALL) {
581:                             if ($type === $rules['allPrivileges']['type']) {
582:                                 $rules = array(
583:                                     'allPrivileges' => array(
584:                                         'type' => self::DENY,
585:                                         'assert' => NULL
586:                                         ),
587:                                     'byPrivilege' => array()
588:                                     );
589:                             }
590:                             continue;
591:                         }
592:                         if ($type === $rules['allPrivileges']['type']) {
593:                             unset($rules['allPrivileges']);
594:                         }
595:                     } else {
596:                         foreach ($privileges as $privilege) {
597:                             if (isset($rules['byPrivilege'][$privilege]) &&
598:                                 $type === $rules['byPrivilege'][$privilege]['type']) {
599:                                 unset($rules['byPrivilege'][$privilege]);
600:                             }
601:                         }
602:                     }
603:                 }
604:             }
605:         }
606:         return $this;
607:     }
608: 
609: 
610: 
611:     /********************* querying the ACL ****************d*g**/
612: 
613: 
614: 
615:     /**
616:      * Returns TRUE if and only if the Role has access to [certain $privileges upon] the Resource.
617:      *
618:      * This method checks Role inheritance using a depth-first traversal of the Role list.
619:      * The highest priority parent (i.e., the parent most recently added) is checked first,
620:      * and its respective parents are checked similarly before the lower-priority parents of
621:      * the Role are checked.
622:      *
623:      * @param  string|Permission::ALL|IRole  role
624:      * @param  string|Permission::ALL|IResource  resource
625:      * @param  string|Permission::ALL  privilege
626:      * @throws Nette\InvalidStateException
627:      * @return bool
628:      */
629:     public function isAllowed($role = self::ALL, $resource = self::ALL, $privilege = self::ALL)
630:     {
631:         $this->queriedRole = $role;
632:         if ($role !== self::ALL) {
633:             if ($role instanceof IRole) {
634:                 $role = $role->getRoleId();
635:             }
636:             $this->checkRole($role);
637:         }
638: 
639:         $this->queriedResource = $resource;
640:         if ($resource !== self::ALL) {
641:             if ($resource instanceof IResource) {
642:                 $resource = $resource->getResourceId();
643:             }
644:             $this->checkResource($resource);
645:         }
646: 
647:         do {
648:             // depth-first search on $role if it is not 'allRoles' pseudo-parent
649:             if ($role !== NULL && NULL !== ($result = $this->searchRolePrivileges($privilege === self::ALL, $role, $resource, $privilege))) {
650:                 break;
651:             }
652: 
653:             if ($privilege === self::ALL) {
654:                 if ($rules = $this->getRules($resource, self::ALL)) { // look for rule on 'allRoles' psuedo-parent
655:                     foreach ($rules['byPrivilege'] as $privilege => $rule) {
656:                         if (self::DENY === ($result = $this->getRuleType($resource, NULL, $privilege))) {
657:                             break 2;
658:                         }
659:                     }
660:                     if (NULL !== ($result = $this->getRuleType($resource, NULL, NULL))) {
661:                         break;
662:                     }
663:                 }
664:             } else {
665:                 if (NULL !== ($result = $this->getRuleType($resource, NULL, $privilege))) { // look for rule on 'allRoles' pseudo-parent
666:                     break;
667: 
668:                 } elseif (NULL !== ($result = $this->getRuleType($resource, NULL, NULL))) {
669:                     break;
670:                 }
671:             }
672: 
673:             $resource = $this->resources[$resource]['parent']; // try next Resource
674:         } while (TRUE);
675: 
676:         $this->queriedRole = $this->queriedResource = NULL;
677:         return $result;
678:     }
679: 
680: 
681: 
682:     /**
683:      * Returns real currently queried Role. Use by assertion.
684:      * @return mixed
685:      */
686:     public function getQueriedRole()
687:     {
688:         return $this->queriedRole;
689:     }
690: 
691: 
692: 
693:     /**
694:      * Returns real currently queried Resource. Use by assertion.
695:      * @return mixed
696:      */
697:     public function getQueriedResource()
698:     {
699:         return $this->queriedResource;
700:     }
701: 
702: 
703: 
704:     /********************* internals ****************d*g**/
705: 
706: 
707: 
708:     /**
709:      * Performs a depth-first search of the Role DAG, starting at $role, in order to find a rule
710:      * allowing/denying $role access to a/all $privilege upon $resource.
711:      * @param  bool  all (true) or one?
712:      * @param  string
713:      * @param  string
714:      * @param  string  only for one
715:      * @return mixed  NULL if no applicable rule is found, otherwise returns ALLOW or DENY
716:      */
717:     private function searchRolePrivileges($all, $role, $resource, $privilege)
718:     {
719:         $dfs = array(
720:             'visited' => array(),
721:             'stack' => array($role),
722:         );
723: 
724:         while (NULL !== ($role = array_pop($dfs['stack']))) {
725:             if (isset($dfs['visited'][$role])) {
726:                 continue;
727:             }
728:             if ($all) {
729:                 if ($rules = $this->getRules($resource, $role)) {
730:                     foreach ($rules['byPrivilege'] as $privilege2 => $rule) {
731:                         if (self::DENY === $this->getRuleType($resource, $role, $privilege2)) {
732:                             return self::DENY;
733:                         }
734:                     }
735:                     if (NULL !== ($type = $this->getRuleType($resource, $role, NULL))) {
736:                         return $type;
737:                     }
738:                 }
739:             } else {
740:                 if (NULL !== ($type = $this->getRuleType($resource, $role, $privilege))) {
741:                     return $type;
742: 
743:                 } elseif (NULL !== ($type = $this->getRuleType($resource, $role, NULL))) {
744:                     return $type;
745:                 }
746:             }
747: 
748:             $dfs['visited'][$role] = TRUE;
749:             foreach ($this->roles[$role]['parents'] as $roleParent => $foo) {
750:                 $dfs['stack'][] = $roleParent;
751:             }
752:         }
753:         return NULL;
754:     }
755: 
756: 
757: 
758:     /**
759:      * Returns the rule type associated with the specified Resource, Role, and privilege.
760:      * @param  string|Permission::ALL
761:      * @param  string|Permission::ALL
762:      * @param  string|Permission::ALL
763:      * @return mixed  NULL if a rule does not exist or assertion fails, otherwise returns ALLOW or DENY
764:      */
765:     private function getRuleType($resource, $role, $privilege)
766:     {
767:         if (!$rules = $this->getRules($resource, $role)) {
768:             return NULL;
769:         }
770: 
771:         if ($privilege === self::ALL) {
772:             if (isset($rules['allPrivileges'])) {
773:                 $rule = $rules['allPrivileges'];
774:             } else {
775:                 return NULL;
776:             }
777:         } elseif (!isset($rules['byPrivilege'][$privilege])) {
778:             return NULL;
779: 
780:         } else {
781:             $rule = $rules['byPrivilege'][$privilege];
782:         }
783: 
784:         if ($rule['assert'] === NULL || $rule['assert']->__invoke($this, $role, $resource, $privilege)) {
785:             return $rule['type'];
786: 
787:         } elseif ($resource !== self::ALL || $role !== self::ALL || $privilege !== self::ALL) {
788:             return NULL;
789: 
790:         } elseif (self::ALLOW === $rule['type']) {
791:             return self::DENY;
792: 
793:         } else {
794:             return self::ALLOW;
795:         }
796:     }
797: 
798: 
799: 
800:     /**
801:      * Returns the rules associated with a Resource and a Role, or NULL if no such rules exist.
802:      * If the $create parameter is TRUE, then a rule set is first created and then returned to the caller.
803:      * @param  string|Permission::ALL
804:      * @param  string|Permission::ALL
805:      * @param  bool
806:      * @return array|NULL
807:      */
808:     private function & getRules($resource, $role, $create = FALSE)
809:     {
810:         $null = NULL;
811:         if ($resource === self::ALL) {
812:             $visitor = & $this->rules['allResources'];
813:         } else {
814:             if (!isset($this->rules['byResource'][$resource])) {
815:                 if (!$create) {
816:                     return $null;
817:                 }
818:                 $this->rules['byResource'][$resource] = array();
819:             }
820:             $visitor = & $this->rules['byResource'][$resource];
821:         }
822: 
823:         if ($role === self::ALL) {
824:             if (!isset($visitor['allRoles'])) {
825:                 if (!$create) {
826:                     return $null;
827:                 }
828:                 $visitor['allRoles']['byPrivilege'] = array();
829:             }
830:             return $visitor['allRoles'];
831:         }
832: 
833:         if (!isset($visitor['byRole'][$role])) {
834:             if (!$create) {
835:                 return $null;
836:             }
837:             $visitor['byRole'][$role]['byPrivilege'] = array();
838:         }
839: 
840:         return $visitor['byRole'][$role];
841:     }
842: 
843: }
844: 
Nette Framework 2.0.3 API API documentation generated by ApiGen 2.7.0