Example #1
0
 /**
  * @dataProvider runProvider
  */
 public function testRun($input, $expected)
 {
     $parser = new PermissionParser();
     $actual = $parser->run($input);
     $this->assertEquals($expected, $actual);
 }
Example #2
0
 /**
  * Runs a permission check. Permissions are encoded as strings, where
  * the ':' character acts as a separator for dynamic parts and
  * sub-permissions.
  * Apart from the route-based rules defined in permissions.yml, the
  * following special cases are available:.
  *
  * "overview:$contenttype" - view the overview for the content type. Alias
  *                           for "contenttype:$contenttype:view".
  * "contenttype:$contenttype",
  * "contenttype:$contenttype:view",
  * "contenttype:$contenttype:view:$id" - View any item or a particular item
  *                                       of the specified content type.
  * "contenttype:$contenttype:edit",
  * "contenttype:$contenttype:edit:$id" - Edit any item or a particular item
  *                                       of the specified content type.
  * "contenttype:$contenttype:create" - Create a new item of the specified
  *                                     content type. (It doesn't make sense
  *                                     to provide this permission on a
  *                                     per-item basis, for obvious reasons)
  * "contenttype:$contenttype:change-ownership",
  * "contenttype:$contenttype:change-ownership:$id" - Change the ownership
  *                                of the specified content type or item.
  * Further, permissions can be combined with the special keywords 'and' and
  * 'or' (case-insensitive), or their symbolic aliases '&' (or '&&') and '|'
  * (or '||'). To override the default precedence (with 'or' binding tighter
  * than 'and'), or to make precedence explicit, use parentheses. Ex.:
  *
  * "contenttype:$contenttype:edit or contenttype:$contenttype:view"
  *
  * @param string               $what      The desired permission, as elaborated upon above.
  * @param mixed                $user      The user to check permissions against.
  * @param string|array|Content $content   Optional: Content object/array or ContentType slug.
  *                                        If specified, $what is taken to be a relative permission (e.g. 'edit')
  *                                        rather than an absolute one (e.g. 'contenttype:pages:edit').
  * @param integer              $contentId Only used if $content is given, to further specifiy the content item.
  *
  * @return boolean TRUE if the permission is granted, FALSE if denied.
  */
 public function isAllowed($what, $user, $content = null, $contentId = null)
 {
     if (is_array($content)) {
         $contenttypeSlug = $content['slug'];
     } elseif ($content instanceof \Bolt\Content) {
         $contenttypeSlug = $content->contenttype['slug'];
     } else {
         $contenttypeSlug = $content;
     }
     $this->audit("Checking permission query '{$what}' for user '{$user['username']}' with contenttype '{$contenttypeSlug}' and contentid '{$contentId}'");
     // First, let's see if we have the check in the per-request cache.
     $rqCacheKey = $user['id'] . '//' . $what . '//' . $contenttypeSlug . '//' . $contentId;
     if (isset($this->rqcache[$rqCacheKey])) {
         return $this->rqcache[$rqCacheKey];
     }
     $cacheKey = "_permission_rule:{$what}";
     if ($this->app['cache']->contains($cacheKey)) {
         $rule = json_decode($this->app['cache']->fetch($cacheKey), true);
     } else {
         $parser = new PermissionParser();
         $rule = $parser->run($what);
         $this->app['cache']->save($cacheKey, json_encode($rule));
     }
     $userRoles = $this->getEffectiveRolesForUser($user);
     $isAllowed = $this->isAllowedRule($rule, $user, $userRoles, $content, $contenttypeSlug, $contentId);
     // Cache for the current request
     $this->rqcache[$rqCacheKey] = $isAllowed;
     return $isAllowed;
 }