Browse Source

AuthUser shim for 3.x

euromark 10 years ago
parent
commit
f5cc76b8cc

+ 190 - 0
Controller/Component/Auth/AuthUserTrait.php

@@ -0,0 +1,190 @@
+<?php
+App::uses('Hash', 'Utility');
+
+if (!defined('USER_ROLE_KEY')) {
+	define('USER_ROLE_KEY', 'Roles');
+}
+if (!defined('USER_RIGHT_KEY')) {
+	define('USER_RIGHT_KEY', 'Rights');
+}
+
+/**
+ * Convenience wrapper to access Auth data and check on rights/roles.
+ *
+ * Simply add it at the class file:
+ *
+ *   trait AuthUserTrait;
+ *
+ * But needs
+ *
+ *   protected function _getUser() {}
+ *
+ * to be implemented in the using class.
+ *
+ * Expects the Role session infos to be either
+ * 	- `Auth.User.role_id` (single) or
+ * 	- `Auth.User.Role` (multi - flat array of roles, or array role data)
+ * and can be adjusted via constants and defined().
+ * Same goes for Right data.
+ *
+ * If roles are defined in configuration file (non-db roles setup) the constant
+ * `USER_ROLE_KEY` has to be defined in `bootstrap.php`.
+ * ```
+ * // if role key in User model is role_id
+ * define('USER_ROLE_KEY', 'role_id');
+ * ```
+ *
+ * Note: This uses AuthComponent internally to work with both stateful and stateless auth.
+ *
+ * @author Mark Scherer
+ * @license MIT
+ */
+trait AuthUserTrait {
+
+	/**
+	 * Get the user id of the current session.
+	 *
+	 * This can be used anywhere to check if a user is logged in.
+	 *
+	 * @param string $field Field name. Defaults to `id`.
+	 * @return mixed User id if existent, null otherwise.
+	 */
+	public function id($field = 'id') {
+		return $this->user($field);
+	}
+
+	/**
+	 * This check can be used to tell if a record that belongs to some user is the
+	 * current logged in user
+	 *
+	 * @param string|int $userId
+	 * @param string $field Field name. Defaults to `id`.
+	 * @return boolean
+	 */
+	public function isMe($userId, $field = 'id') {
+		return ($userId && (string)$userId === (string)$this->user($field));
+	}
+
+	/**
+	 * Get the user data of the current session.
+	 *
+	 * @param string $key Key in dot syntax.
+	 * @return mixed Data
+	 */
+	public function user($key = null) {
+		$user = $this->_getUser();
+		if ($key === null) {
+			return $user;
+		}
+		return Hash::get($user, $key);
+	}
+
+	/**
+	 * Get the role(s) of the current session.
+	 *
+	 * It will return the single role for single role setup, and a flat
+	 * list of roles for multi role setup.
+	 *
+	 * @return mixed String or array of roles or null if inexistent.
+	 */
+	public function roles() {
+		$roles = $this->user(USER_ROLE_KEY);
+		if (!is_array($roles)) {
+			return $roles;
+		}
+		if (isset($roles[0]['id'])) {
+			$roles = Hash::extract($roles, '{n}.id');
+		}
+		return $roles;
+	}
+
+	/**
+	 * Check if the current session has this role.
+	 *
+	 * @param mixed $role
+	 * @param mixed $providedRoles
+	 * @return bool Success
+	 */
+	public function hasRole($expectedRole, $providedRoles = null) {
+		if ($providedRoles !== null) {
+			$roles = (array)$providedRoles;
+		} else {
+			$roles = (array)$this->roles();
+		}
+		if (empty($roles)) {
+			return false;
+		}
+
+		if (in_array($expectedRole, $roles)) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Check if the current session has one of these roles.
+	 *
+	 * You can either require one of the roles (default), or you can require all
+	 * roles to match.
+	 *
+	 * @param mixed $expectedRoles
+	 * @param bool $oneRoleIsEnough (if all $roles have to match instead of just one)
+	 * @param mixed $providedRoles
+	 * @return bool Success
+	 */
+	public function hasRoles($expectedRoles, $oneRoleIsEnough = true, $providedRoles = null) {
+		if ($providedRoles !== null) {
+			$roles = $providedRoles;
+		} else {
+			$roles = $this->roles();
+		}
+		$expectedRoles = (array)$expectedRoles;
+		if (empty($expectedRoles)) {
+			return false;
+		}
+		$count = 0;
+		foreach ($expectedRoles as $expectedRole) {
+			if ($this->hasRole($expectedRole, $roles)) {
+				if ($oneRoleIsEnough) {
+					return true;
+				}
+				$count++;
+			} else {
+				if (!$oneRoleIsEnough) {
+					return false;
+				}
+			}
+		}
+
+		if ($count === count($expectedRoles)) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Check if the current session has this right.
+	 *
+	 * Rights can be an additional element to give permissions, e.g.
+	 * the right to send messages/emails, to friend request other users,...
+	 * This can be set via Right model and stored in the Auth array upon login
+	 * the same way the roles are.
+	 *
+	 * @param mixed $role
+	 * @param mixed $providedRights
+	 * @return bool Success
+	 */
+	public function hasRight($expectedRight, $providedRights = null) {
+		if ($providedRights !== null) {
+			$rights = $providedRights;
+		} else {
+			$rights = $this->user(USER_RIGHT_KEY);
+		}
+		$rights = (array)$rights;
+		if (array_key_exists($expectedRight, $rights) && !empty($rights[$expectedRight])) {
+			return true;
+		}
+		return false;
+	}
+
+}

+ 34 - 0
Controller/Component/AuthUserComponent.php

@@ -0,0 +1,34 @@
+<?php
+App::uses('Component', 'Controller');
+App::uses('AuthUserTrait', 'Tools.Controller/Component/Auth');
+
+/**
+ * Authentication User component class
+ */
+class AuthUserComponent extends Component {
+
+	use AuthUserTrait;
+
+	public $components = ['Auth'];
+
+	/**
+	 * AuthUserComponent::beforeRender()
+	 *
+	 * @param Controller $controller
+	 * @return void
+	 */
+	public function beforeRender(Controller $controller) {
+		$authUser = $this->_getUser();
+		$controller->set(compact('authUser'));
+	}
+
+	/**
+	 * AuthUserComponent::_getUser()
+	 *
+	 * @return array
+	 */
+	protected function _getUser() {
+		return (array)$this->Auth->user();
+	}
+
+}

+ 26 - 0
View/Helper/AuthUserHelper.php

@@ -0,0 +1,26 @@
+<?php
+App::uses('AppHelper', 'View/Helper');
+App::uses('AuthUserTrait', 'Tools.Controller/Component/Auth');
+
+/**
+ * Helper to access auth user data.
+ *
+ * @author Mark Scherer
+ */
+class AuthUserHelper extends AppHelper {
+
+	use AuthUserTrait;
+
+	/**
+	 * AuthUserHelper::_getUser()
+	 *
+	 * @return array
+	 */
+	protected function _getUser() {
+		if (!isset($this->_View->viewVars['authUser'])) {
+			throw new RuntimeException('AuthUser helper needs AuthUser component to function');
+		}
+		return $this->_View->viewVars['authUser'];
+	}
+
+}

+ 27 - 6
View/Helper/HtmlExtHelper.php

@@ -1,5 +1,6 @@
 <?php
 App::uses('HtmlShimHelper', 'Shim.View/Helper');
+App::uses('CommonComponent', 'Tools.Controller/Component');
 
 /**
  * HtmlExt Helper
@@ -142,12 +143,22 @@ class HtmlExtHelper extends HtmlShimHelper {
 	 *
 	 * @params same as Html::link($title, $url, $options, $confirmMessage)
 	 * @return string HTML Link
+	 * @deprecated Use HtmlExtHelper::resetLink() instead
 	 */
 	public function defaultLink($title, $url = null, $options = [], $confirmMessage = false) {
+		return $this->resetLink($title, $url, $options, $confirmMessage);
+	}
+
+	/**
+	 * Convenience function for normal links.
+	 * Useful for layout links and links inside elements etc if you don't want to
+	 * verbosely reset all parts of it (prefix, plugin, ...).
+	 *
+	 * @params same as Html::link($title, $url, $options, $confirmMessage)
+	 * @return string HTML Link
+	 */
+	public function resetLink($title, $url = null, $options = [], $confirmMessage = false) {
 		if ($this->_linkDefaults === null) {
-			if (!class_exists('CommonComponent')) {
-				App::uses('CommonComponent', 'Tools.Controller/Component');
-			}
 			$this->_linkDefaults = CommonComponent::defaultUrlParams();
 		}
 		if (!defined('PREFIX_ADMIN')) {
@@ -174,12 +185,22 @@ class HtmlExtHelper extends HtmlShimHelper {
 	 *
 	 * @params same as Html::url($url, $full)
 	 * @return string URL
+	 * @deprecated Use HtmlExtHelper::resetUrl() instead
 	 */
 	public function defaultUrl($url = null, $full = false) {
+		return $this->resetUrl($url, $full);
+	}
+
+	/**
+	 * Convenience function for normal urls.
+	 * Useful for layout links and links inside elements etc if you don't want to
+	 * verbosely reset all parts of it (prefix, plugin, ...).
+	 *
+	 * @params same as Html::url($url, $full)
+	 * @return string URL
+	 */
+	public function resetUrl($url = null, $full = false) {
 		if ($this->_linkDefaults === null) {
-			if (!class_exists('CommonComponent')) {
-				App::uses('CommonComponent', 'Tools.Controller/Component');
-			}
 			$this->_linkDefaults = CommonComponent::defaultUrlParams();
 		}
 		if ($url !== null && is_array($url)) {