Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • None
  • PHP

Classes

  • Identity
  • Permission
  • SimpleAuthenticator

Interfaces

  • IAuthenticator
  • IAuthorizator
  • IIdentity
  • IResource
  • IRole

Exceptions

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