Skip to content

Commit f5cc76b

Browse files
author
euromark
committed
AuthUser shim for 3.x
1 parent a15b705 commit f5cc76b

File tree

4 files changed

+277
-6
lines changed

4 files changed

+277
-6
lines changed
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<?php
2+
App::uses('Hash', 'Utility');
3+
4+
if (!defined('USER_ROLE_KEY')) {
5+
define('USER_ROLE_KEY', 'Roles');
6+
}
7+
if (!defined('USER_RIGHT_KEY')) {
8+
define('USER_RIGHT_KEY', 'Rights');
9+
}
10+
11+
/**
12+
* Convenience wrapper to access Auth data and check on rights/roles.
13+
*
14+
* Simply add it at the class file:
15+
*
16+
* trait AuthUserTrait;
17+
*
18+
* But needs
19+
*
20+
* protected function _getUser() {}
21+
*
22+
* to be implemented in the using class.
23+
*
24+
* Expects the Role session infos to be either
25+
* - `Auth.User.role_id` (single) or
26+
* - `Auth.User.Role` (multi - flat array of roles, or array role data)
27+
* and can be adjusted via constants and defined().
28+
* Same goes for Right data.
29+
*
30+
* If roles are defined in configuration file (non-db roles setup) the constant
31+
* `USER_ROLE_KEY` has to be defined in `bootstrap.php`.
32+
* ```
33+
* // if role key in User model is role_id
34+
* define('USER_ROLE_KEY', 'role_id');
35+
* ```
36+
*
37+
* Note: This uses AuthComponent internally to work with both stateful and stateless auth.
38+
*
39+
* @author Mark Scherer
40+
* @license MIT
41+
*/
42+
trait AuthUserTrait {
43+
44+
/**
45+
* Get the user id of the current session.
46+
*
47+
* This can be used anywhere to check if a user is logged in.
48+
*
49+
* @param string $field Field name. Defaults to `id`.
50+
* @return mixed User id if existent, null otherwise.
51+
*/
52+
public function id($field = 'id') {
53+
return $this->user($field);
54+
}
55+
56+
/**
57+
* This check can be used to tell if a record that belongs to some user is the
58+
* current logged in user
59+
*
60+
* @param string|int $userId
61+
* @param string $field Field name. Defaults to `id`.
62+
* @return boolean
63+
*/
64+
public function isMe($userId, $field = 'id') {
65+
return ($userId && (string)$userId === (string)$this->user($field));
66+
}
67+
68+
/**
69+
* Get the user data of the current session.
70+
*
71+
* @param string $key Key in dot syntax.
72+
* @return mixed Data
73+
*/
74+
public function user($key = null) {
75+
$user = $this->_getUser();
76+
if ($key === null) {
77+
return $user;
78+
}
79+
return Hash::get($user, $key);
80+
}
81+
82+
/**
83+
* Get the role(s) of the current session.
84+
*
85+
* It will return the single role for single role setup, and a flat
86+
* list of roles for multi role setup.
87+
*
88+
* @return mixed String or array of roles or null if inexistent.
89+
*/
90+
public function roles() {
91+
$roles = $this->user(USER_ROLE_KEY);
92+
if (!is_array($roles)) {
93+
return $roles;
94+
}
95+
if (isset($roles[0]['id'])) {
96+
$roles = Hash::extract($roles, '{n}.id');
97+
}
98+
return $roles;
99+
}
100+
101+
/**
102+
* Check if the current session has this role.
103+
*
104+
* @param mixed $role
105+
* @param mixed $providedRoles
106+
* @return bool Success
107+
*/
108+
public function hasRole($expectedRole, $providedRoles = null) {
109+
if ($providedRoles !== null) {
110+
$roles = (array)$providedRoles;
111+
} else {
112+
$roles = (array)$this->roles();
113+
}
114+
if (empty($roles)) {
115+
return false;
116+
}
117+
118+
if (in_array($expectedRole, $roles)) {
119+
return true;
120+
}
121+
return false;
122+
}
123+
124+
/**
125+
* Check if the current session has one of these roles.
126+
*
127+
* You can either require one of the roles (default), or you can require all
128+
* roles to match.
129+
*
130+
* @param mixed $expectedRoles
131+
* @param bool $oneRoleIsEnough (if all $roles have to match instead of just one)
132+
* @param mixed $providedRoles
133+
* @return bool Success
134+
*/
135+
public function hasRoles($expectedRoles, $oneRoleIsEnough = true, $providedRoles = null) {
136+
if ($providedRoles !== null) {
137+
$roles = $providedRoles;
138+
} else {
139+
$roles = $this->roles();
140+
}
141+
$expectedRoles = (array)$expectedRoles;
142+
if (empty($expectedRoles)) {
143+
return false;
144+
}
145+
$count = 0;
146+
foreach ($expectedRoles as $expectedRole) {
147+
if ($this->hasRole($expectedRole, $roles)) {
148+
if ($oneRoleIsEnough) {
149+
return true;
150+
}
151+
$count++;
152+
} else {
153+
if (!$oneRoleIsEnough) {
154+
return false;
155+
}
156+
}
157+
}
158+
159+
if ($count === count($expectedRoles)) {
160+
return true;
161+
}
162+
return false;
163+
}
164+
165+
/**
166+
* Check if the current session has this right.
167+
*
168+
* Rights can be an additional element to give permissions, e.g.
169+
* the right to send messages/emails, to friend request other users,...
170+
* This can be set via Right model and stored in the Auth array upon login
171+
* the same way the roles are.
172+
*
173+
* @param mixed $role
174+
* @param mixed $providedRights
175+
* @return bool Success
176+
*/
177+
public function hasRight($expectedRight, $providedRights = null) {
178+
if ($providedRights !== null) {
179+
$rights = $providedRights;
180+
} else {
181+
$rights = $this->user(USER_RIGHT_KEY);
182+
}
183+
$rights = (array)$rights;
184+
if (array_key_exists($expectedRight, $rights) && !empty($rights[$expectedRight])) {
185+
return true;
186+
}
187+
return false;
188+
}
189+
190+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
App::uses('Component', 'Controller');
3+
App::uses('AuthUserTrait', 'Tools.Controller/Component/Auth');
4+
5+
/**
6+
* Authentication User component class
7+
*/
8+
class AuthUserComponent extends Component {
9+
10+
use AuthUserTrait;
11+
12+
public $components = ['Auth'];
13+
14+
/**
15+
* AuthUserComponent::beforeRender()
16+
*
17+
* @param Controller $controller
18+
* @return void
19+
*/
20+
public function beforeRender(Controller $controller) {
21+
$authUser = $this->_getUser();
22+
$controller->set(compact('authUser'));
23+
}
24+
25+
/**
26+
* AuthUserComponent::_getUser()
27+
*
28+
* @return array
29+
*/
30+
protected function _getUser() {
31+
return (array)$this->Auth->user();
32+
}
33+
34+
}

View/Helper/AuthUserHelper.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
App::uses('AppHelper', 'View/Helper');
3+
App::uses('AuthUserTrait', 'Tools.Controller/Component/Auth');
4+
5+
/**
6+
* Helper to access auth user data.
7+
*
8+
* @author Mark Scherer
9+
*/
10+
class AuthUserHelper extends AppHelper {
11+
12+
use AuthUserTrait;
13+
14+
/**
15+
* AuthUserHelper::_getUser()
16+
*
17+
* @return array
18+
*/
19+
protected function _getUser() {
20+
if (!isset($this->_View->viewVars['authUser'])) {
21+
throw new RuntimeException('AuthUser helper needs AuthUser component to function');
22+
}
23+
return $this->_View->viewVars['authUser'];
24+
}
25+
26+
}

View/Helper/HtmlExtHelper.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22
App::uses('HtmlShimHelper', 'Shim.View/Helper');
3+
App::uses('CommonComponent', 'Tools.Controller/Component');
34

45
/**
56
* HtmlExt Helper
@@ -142,12 +143,22 @@ public function completeUrl($url = null, $full = false, $escape = true) {
142143
*
143144
* @params same as Html::link($title, $url, $options, $confirmMessage)
144145
* @return string HTML Link
146+
* @deprecated Use HtmlExtHelper::resetLink() instead
145147
*/
146148
public function defaultLink($title, $url = null, $options = [], $confirmMessage = false) {
149+
return $this->resetLink($title, $url, $options, $confirmMessage);
150+
}
151+
152+
/**
153+
* Convenience function for normal links.
154+
* Useful for layout links and links inside elements etc if you don't want to
155+
* verbosely reset all parts of it (prefix, plugin, ...).
156+
*
157+
* @params same as Html::link($title, $url, $options, $confirmMessage)
158+
* @return string HTML Link
159+
*/
160+
public function resetLink($title, $url = null, $options = [], $confirmMessage = false) {
147161
if ($this->_linkDefaults === null) {
148-
if (!class_exists('CommonComponent')) {
149-
App::uses('CommonComponent', 'Tools.Controller/Component');
150-
}
151162
$this->_linkDefaults = CommonComponent::defaultUrlParams();
152163
}
153164
if (!defined('PREFIX_ADMIN')) {
@@ -174,12 +185,22 @@ public function defaultLink($title, $url = null, $options = [], $confirmMessage
174185
*
175186
* @params same as Html::url($url, $full)
176187
* @return string URL
188+
* @deprecated Use HtmlExtHelper::resetUrl() instead
177189
*/
178190
public function defaultUrl($url = null, $full = false) {
191+
return $this->resetUrl($url, $full);
192+
}
193+
194+
/**
195+
* Convenience function for normal urls.
196+
* Useful for layout links and links inside elements etc if you don't want to
197+
* verbosely reset all parts of it (prefix, plugin, ...).
198+
*
199+
* @params same as Html::url($url, $full)
200+
* @return string URL
201+
*/
202+
public function resetUrl($url = null, $full = false) {
179203
if ($this->_linkDefaults === null) {
180-
if (!class_exists('CommonComponent')) {
181-
App::uses('CommonComponent', 'Tools.Controller/Component');
182-
}
183204
$this->_linkDefaults = CommonComponent::defaultUrlParams();
184205
}
185206
if ($url !== null && is_array($url)) {

0 commit comments

Comments
 (0)