euromark 14 years ago
parent
commit
652e753f9b
1 changed files with 184 additions and 0 deletions
  1. 184 0
      Controller/Component/Auth/TinyAuthorize.php

+ 184 - 0
Controller/Component/Auth/TinyAuthorize.php

@@ -0,0 +1,184 @@
+<?php
+App::uses('Inflector', 'Utility');
+
+if (!defined('AUTH_CACHE')) {
+	define('AUTH_CACHE', CACHE.'persistent'.DS);
+}
+if (!defined('ROLE_CONFIGS')) {
+	define('ROLE_CONFIGS', 'roles.ini');
+}
+
+/**
+ * Probably the most simple and fastest Acl out there.
+ * Only one config file `roles.ini` necessary
+ * Doesnt even need a Role Model/table
+ * @link http://www.dereuromark.de/2011/12/18/tinyauth-the-fastest-and-easiest-authorization-for-cake2
+ * 
+ * Usage:
+ * Include it in your beforeFilter() method of the AppController
+ * $this->Auth->authorize = array('Tools.Tiny');
+ * 
+ * Or with admin prefix protection only
+ * $this->Auth->authorize = array('Tools.Tiny'=>array('allowUser'=>true));
+ * 
+ * @author Mark Scherer
+ * @cakephp 2.0
+ * @license MIT
+ * 2011-12-17 ms
+ */
+class TinyAuthorize extends BaseAuthorize {
+
+	protected $_matchArray = array();
+
+	protected $_defaults = array(
+		'allowUser' => false, # quick way to allow user access to non prefixed urls
+		'adminPrefix' => 'admin_'
+	);
+
+	public function __construct(ComponentCollection $Collection, $settings = array()) {
+		$settings = am($this->_defaults, $settings);
+		parent::__construct($Collection, $settings);
+
+		$this->_matchArray = $this->_getRoles();
+	}
+	
+	/**
+	 * Authorize a user using the AclComponent.
+	 * allows single or multi role based authorization 
+	 *
+	 * @param array $user The user to authorize
+	 * @param CakeRequest $request The request needing authorization.
+	 * @return boolean
+	 */
+	public function authorize($user, CakeRequest $request) {
+		if (isset($user['Role'])) {
+			$roles = (array)$user['Role'];
+		} else {
+			$roles = array($user['role_id']);
+		}
+		return $this->validate($roles, $request->params['plugin'], $request->params['controller'], $request->params['action']);
+	}
+
+	/**
+	 * validate the url to the role(s)
+	 * allows single or multi role based authorization
+	 * @return bool $success
+	 */
+	public function validate($roles, $plugin, $controller, $action) {
+		$action = Inflector::underscore($action);
+		$controller = Inflector::underscore($controller);
+		$plugin = Inflector::underscore($plugin);
+		
+		if (!empty($this->settings['allowUser'])) {
+			# all user actions are accessable for logged in users
+			if (mb_strpos($action, $this->settings['adminPrefix']) !== 0) {
+				return true;
+			}
+		}
+		
+		if (isset($this->_matchArray[$controller]['*'])) {
+			$matchArray = $this->_matchArray[$controller]['*'];
+			if (in_array(-1, $matchArray)) {
+				return true;
+			}
+			foreach ($roles as $role) {
+				if (in_array($role, $matchArray)) {
+					return true;
+				}
+			}
+		}
+		if (!empty($controller) && !empty($action)) {
+			if (array_key_exists($controller, $this->_matchArray) && !empty($this->_matchArray[$controller][$action])) {
+				$matchArray = $this->_matchArray[$controller][$action];
+
+				# direct access? (even if he has no roles = GUEST)
+				if (in_array(-1, $matchArray)) {
+					return true;
+				}
+
+				# normal access (rolebased)
+				foreach ($roles as $role) {
+					if (in_array($role, $matchArray)) {
+						return true;
+					}
+				}
+			}
+		}
+		return false;
+	}
+	
+	public function getModel() {
+		return ClassRegistry::init(CLASS_USER); 
+	}
+
+	/**
+	 * parse ini files
+	 */	
+	protected function _getRoles() {
+		$res = array();
+		if (file_exists(AUTH_CACHE.'roles.tmp') && Configure::read('debug') > 0) {
+			unlink(AUTH_CACHE.'roles.tmp');
+		}
+		if (file_exists(AUTH_CACHE.'roles.tmp')) {
+			include(AUTH_CACHE.'roles.tmp');
+			return $roles;
+		}
+		if (!file_exists(APP . 'Config' . DS . ROLE_CONFIGS)) {
+			touch(APP . 'Config' . DS . ROLE_CONFIGS);
+		}
+		$iniArray = parse_ini_file(APP . 'Config' . DS . ROLE_CONFIGS, true);
+		
+		$availableRoles = Configure::read('Role');
+		if (!is_array($availableRoles)) {
+			$Model = $this->getModel();
+			$availableRoles = $Model->Role->find('list', array('fields'=>array('alias', 'id')));
+			Configure::write('Role', $availableRoles);
+		}
+		if (!is_array($availableRoles) || !is_array($iniArray)) {
+			trigger_error('Invalid Role Setup for TinyAuthorize (no roles found)');
+			return false;
+		}
+		
+		foreach ($iniArray as $key => $array) {
+			list($plugin, $controllerName) = pluginSplit($key);
+			$controllerName = Inflector::underscore($controllerName);
+			
+			foreach ($array as $actions => $roles) {
+				$actions = explode(',', $actions);
+				$roles = explode(',', $roles);
+				
+				foreach ($roles as $key => $role) {
+					if (!($role = trim($role))) {
+						continue;
+					}
+					if ($role == '*') {
+						unset($roles[$key]);
+						$roles = array_merge($roles, array_keys(Configure::read('Role')));
+					}
+				}
+				
+				foreach ($actions as $action) {
+					if (!($action = trim($action))) {
+						continue;
+					}
+					$actionName = Inflector::underscore($action);
+					
+					foreach ($roles as $role) {
+						if (!($role = trim($role)) || $role == '*') {
+							continue;
+						}
+						$newRole = Configure::read('Role.'.strtolower($role));
+						if (!empty($res[$controllerName][$actionName]) && in_array($newRole, $res[$controllerName][$actionName])) {
+							continue;
+						}
+						$res[$controllerName][$actionName][] = $newRole;
+					}
+				}
+			}
+		}
+		
+		file_put_contents(AUTH_CACHE.'roles.tmp', '<?php $roles = ' . var_export($res, true). ';');
+		return $res;
+	}
+		
+}