Packages

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

Classes

  • NIdentity
  • NPermission
  • NSimpleAuthenticator

Interfaces

  • IAuthenticator
  • IAuthorizator
  • IIdentity
  • IResource
  • IRole

Exceptions

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