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