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

Classes

  • Identity
  • Permission
  • SimpleAuthenticator
  • User

Interfaces

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

Exceptions

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