| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- To Configure
- <?php
- Access::config(array(
- 'permissions' => 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;
- });
- ?>
- <?php
- namespace li3_access\extensions\adapter\security\access;
- use lithium\core\ConfigException;
- use lithium\util\Set;
- class Permissions extends \lithium\core\Object {
- const pathRoute = 'route';
- const pathCustom = 'custom';
- protected $_model = null;
- public function __construct(array $config = array()) {
- $defaults = array(
- 'model' => '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;
- }
- }
- ?>
|