To Configure array( 'adapter' => 'Permissions', 'model' => 'app\models\Perms', 'defaultNoUser' => array(), 'defaultUser' => array( 'route' => array( 'users' => array( 'logout', 'account' ) ) ), 'userIdentifier' => 'PrincipalID' ) )); Perms::applyFilter('find', function($self, $params, $chain) { if($params['type'] != 'first') { return $chain->next($self, $params, $chain); } $cacheKey = 'permissions_' . $params['options']['conditions']['id']; $cache = Cache::read('default', $cacheKey); if($cache) { return $cache; } $result = $chain->next($self, $params, $chain); Cache::write('default', $cacheKey, $result, '+1 day'); return $result; }); ?> 'app\models\perms', 'defaultNoUser' => array(), 'defaultUser' => array(), 'userIdentifier' => 'id' ); parent::__construct($config + $defaults); $this->_model = $this->_config['model']; } /** * @throws \lithium\core\ConfigException * @param $user * @param $request * @param array $options * @return array */ public function check($user, $request, array $options = array()) { $config = $this->_config; $model = $this->_model; $params = compact('user', 'request', 'options'); return $this->_filter(__METHOD__, $params, function($self, $params) use($config, $model) { $user = $params['user']; $request = $params['request']; $options = $params['options']; $reqIsObject = is_object($request); $path = array(); switch (true) { case $reqIsObject: $path = array( Permissions::pathRoute, $request->params['controller'], $request->params['action'] ); break; case (!$reqIsObject && is_string($request)): $path = explode('.', $request); array_unshift($path, Permissions::pathCustom); break; case (!$reqIsObject && is_array($request)): $path = $request; break; } switch(true) { case !$user: $hasAccess = $self->_processPath($path, $config['defaultNoUser']); return $hasAccess ? false : $options; case ($result = $self->_processPath($path, $config['defaultUser'])): return $result ? false : $options; default: $userId = $config['userIdentifier']; if(!isset($user[$userId])) { $message = "The user identifier '{$userId}' is not available."; throw new ConfigException($message); } $perms = $model::find('first', array( 'conditions' => array( 'id' => $user[$userId] ) )); if(!$perms) { return false; } $userPath = unserialize($perms->perms); $result = $self->_processPath($path, $userPath); return $result ? array() : $options; } }); } /** * Adds a custom route to the users permission list. * * $customRoute is formatted as a dot path string, this is done as 'foo.bar.baz' for example. * Asterisks are usable at the end of the path however not in the middle. A user with access * to 'foo.bar.*' will have access to foo.bar.baz, foo.bar.aaa etc. * * @param $user * @param $customRoute * @return bool */ public function addCustomPath($user, $customRoute) { if(!is_string($customRoute)) { return false; } $parts = explode('.', $customRoute); $value = array_pop($parts); $parts = array_merge((array)self::pathCustom, $parts, (array)0); return $this->add($user, Set::expand(array(implode('.', $parts) => $value))); } /** * Adds an action to the users permission list. If the action is set to * the user will have * access to all of the controllers actions. */ public function addAction($user, $controller, $action) { return $this->add($user, array( self::pathRoute => array( $controller => array( $action ) ) )); } /** * $user must contain the 'userIdentifier' key defined in config * $paths are the paths which are to be added this is an array representation of the path and * is from the origin, so 'route' or 'custom' must be specified. Multiple paths can be defined * using this function * * @throws \lithium\core\ConfigException * @param $user * @param array $paths * @return bool */ public function add($user, array $paths = array()) { $model = $this->_model; $userId = $this->_config['userIdentifier']; $params = compact('model', 'userId', 'user', 'paths'); return $this->_filter(__METHOD__, $params, function($self, $params) { $model = $params['model']; $userId = $params['userId']; $user = $params['user']; $paths = $params['paths']; if(!isset($user[$userId])) { throw new ConfigException("The user identifier '{$userId}' is not available."); } $result = $model::find('first', array( 'conditions' => array( 'id' => $user[$userId] ) )); if(!$result) { $perms = $model::create(array( 'id' => $user[$userId], 'perms' => serialize($paths) )); return $perms->save(); } $allowedPaths = unserialize($result->perms); $allowedPaths = array_merge_recursive($allowedPaths, $paths); $result->perms = serialize($allowedPaths); return $result->save(); }); } public function removeCustomPath($user, $customRoute) { if(!is_string($customRoute)) { return false; } $parts = explode('.', $customRoute); $value = array_pop($parts); $parts = array_merge((array)self::pathCustom, $parts, (array)0); return $this->remove($user, Set::expand(array(implode('.', $parts) => $value))); } /** * Removes an action from a users permission list. Setting action to * removes all actions * in the controller thus removing the controller from the users permission list. */ public function removeAction($user, $controller, $action) { return $this->remove($user, array( self::pathRoute => array( $controller => array( $action ) ) )); } /** * use this to remove permissions from a user, multiple permissions can be defined in the paths * array. The user must have the configured userIdentifier available. * * @throws \lithium\core\ConfigException * @param $user * @param array $paths * @return bool */ public function remove($user, array $paths = array()) { $model = $this->_model; $userId = $this->_config['userIdentifier']; $params = compact('model', 'userId', 'user', 'paths'); return $this->_filter(__METHOD__, $params, function($self, $params) { $model = $params['model']; $userId = $params['userId']; $user = $params['user']; $paths = $params['paths']; if (!isset($user[$userId])) { throw new ConfigException("The user identifier '{$userId}' is not available."); } $result = $model::find('first', array( 'conditions' => array( 'id' => $user[$userId] ) )); if (!$result) { return true; } $allowedPaths = unserialize($result->perms); $pathsFlat = Set::flatten($paths); foreach ($pathsFlat as $path => $value) { $pointer = &$allowedPaths; $pathParts = explode('.', $path); array_pop($pathParts); foreach ($pathParts as $pathPart) { if (!isset($pointer[$pathPart])) { unset($pointer); $pointer = null; break; } $pointer = &$pointer[$pathPart]; } switch(true) { case !$pointer: break; case $value == '*': $pointer = null; break; case (($index = array_search($value, $pointer)) !== false): unset($pointer[$index]); break; } } $result->perms = serialize($self->_cleanPaths($allowedPaths)); return $result->save(); }); } public function listPerms($user) { $userId = $user[$this->_config['userIdentifier']]; $model = $this->_model; $result = $model::find('first', array( 'conditions' => array( 'id' => $userId ) )); return $result ? unserialize($result->perms) : array(); } public function _cleanPaths($paths) { foreach ($paths as &$path) { if (is_array($path)) { $path = $this->_cleanPaths($path); } } return array_filter($paths); } public function _processPath($path, &$allowedPaths) { $pointer = &$allowedPaths; foreach($path as $item) { switch(true) { case (in_array('*', $pointer)): return true; case (in_array($item, $pointer)): $pointer = array(); continue; case (!isset($pointer[$item])): return false; } $pointer = &$pointer[$item]; } return true; } } ?>