diff options
author | Michael Francis <edude03@gmail.com> | 2011-05-28 13:28:16 -0400 |
---|---|---|
committer | Michael Francis <edude03@gmail.com> | 2011-05-28 13:28:16 -0400 |
commit | 2389d66da849798f8d4ec5f10e3b07c11da49185 (patch) | |
tree | e22556d12982395b469a23420c662662e3e064cc /ACL.php | |
download | otakuhub-2389d66da849798f8d4ec5f10e3b07c11da49185.tar.xz |
Initial Commit
Diffstat (limited to 'ACL.php')
-rw-r--r-- | ACL.php | 319 |
1 files changed, 319 insertions, 0 deletions
@@ -0,0 +1,319 @@ +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; + } +} + +?>
\ No newline at end of file |