Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Utils
  • none
  • Tracy
    • Bridges
      • Nette

Classes

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