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