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