Passed
Branch php-cs-fixer (b9836a)
by Fabio
15:02
created

TAuthorizationRule::getRoles()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * TAuthorizationRule, TAuthorizationRuleCollection class file
4
 *
5
 * @author Qiang Xue <[email protected]>
6
 * @link https://github.com/pradosoft/prado
7
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 * @package Prado\Security
10
 */
11
12
namespace Prado\Security;
13
14
use Prado\Exceptions\TInvalidDataValueException;
15
16
/**
17
 * TAuthorizationRule class
18
 *
19
 * TAuthorizationRule represents a single authorization rule.
20
 * A rule is specified by an action (required), a list of users (optional),
21
 * a list of roles (optional), a verb (optional), and a list of IP rules (optional).
22
 * Action can be either 'allow' or 'deny'.
23
 * Guest (anonymous, unauthenticated) users are represented by question mark '?'.
24
 * All users (including guest users) are represented by asterisk '*'.
25
 * Authenticated users are represented by '@'.
26
 * Users/roles are case-insensitive.
27
 * Different users/roles are separated by comma ','.
28
 * Verb can be either 'get' or 'post'. If it is absent, it means both.
29
 * IP rules are separated by comma ',' and can contain wild card in the rules (e.g. '192.132.23.33, 192.122.*.*')
30
 *
31
 * @author Qiang Xue <[email protected]>
32
 * @package Prado\Security
33
 * @since 3.0
34
 */
35
class TAuthorizationRule extends \Prado\TComponent
36
{
37
	/**
38
	 * @var string action, either 'allow' or 'deny'
39
	 */
40
	private $_action;
41
	/**
42
	 * @var array list of user IDs
43
	 */
44
	private $_users;
45
	/**
46
	 * @var array list of roles
47
	 */
48
	private $_roles;
49
	/**
50
	 * @var string verb, may be empty, 'get', or 'post'.
51
	 */
52
	private $_verb;
53
	/**
54
	 * @var string IP patterns
55
	 */
56
	private $_ipRules;
57
	/**
58
	 * @var boolean if this rule applies to everyone
59
	 */
60
	private $_everyone;
61
	/**
62
	 * @var boolean if this rule applies to guest user
63
	 */
64
	private $_guest;
65
	/**
66
	 * @var boolean if this rule applies to authenticated users
67
	 */
68
	private $_authenticated;
69
70
	/**
71
	 * Constructor.
72
	 * @param string action, either 'deny' or 'allow'
73
	 * @param string a comma separated user list
74
	 * @param string a comma separated role list
75
	 * @param string verb, can be empty, 'get', or 'post'
76
	 * @param string IP rules (separated by comma, can contain wild card *)
0 ignored issues
show
Bug introduced by
The type Prado\Security\IP was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
77
	 */
78
	public function __construct($action, $users, $roles, $verb = '', $ipRules = '')
79
	{
80
		$action = strtolower(trim($action));
81
		if($action === 'allow' || $action === 'deny')
82
			$this->_action = $action;
83
		else
84
			throw new TInvalidDataValueException('authorizationrule_action_invalid', $action);
85
		$this->_users = [];
86
		$this->_roles = [];
87
		$this->_ipRules = [];
0 ignored issues
show
Documentation Bug introduced by
It seems like array() of type array is incompatible with the declared type string of property $_ipRules.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
88
		$this->_everyone = false;
89
		$this->_guest = false;
90
		$this->_authenticated = false;
91
92
		if(trim($users) === '')
93
			$users = '*';
94
		foreach(explode(',', $users) as $user)
95
		{
96
			if(($user = trim(strtolower($user))) !== '')
97
			{
98
				if($user === '*')
99
				{
100
					$this->_everyone = true;
101
					break;
102
				}
103
				elseif($user === '?')
104
					$this->_guest = true;
105
				elseif($user === '@')
106
					$this->_authenticated = true;
107
				else
108
					$this->_users[] = $user;
109
			}
110
		}
111
112
		if(trim($roles) === '')
113
			$roles = '*';
114
		foreach(explode(',', $roles) as $role)
115
		{
116
			if(($role = trim(strtolower($role))) !== '')
117
				$this->_roles[] = $role;
118
		}
119
120
		if(($verb = trim(strtolower($verb))) === '')
121
			$verb = '*';
122
		if($verb === '*' || $verb === 'get' || $verb === 'post')
123
			$this->_verb = $verb;
124
		else
125
			throw new TInvalidDataValueException('authorizationrule_verb_invalid', $verb);
126
127
		if(trim($ipRules) === '')
128
			$ipRules = '*';
129
		foreach(explode(',', $ipRules) as $ipRule)
130
		{
131
			if(($ipRule = trim($ipRule)) !== '')
132
				$this->_ipRules[] = $ipRule;
133
		}
134
	}
135
136
	/**
137
	 * @return string action, either 'allow' or 'deny'
138
	 */
139
	public function getAction()
140
	{
141
		return $this->_action;
142
	}
143
144
	/**
145
	 * @return array list of user IDs
146
	 */
147
	public function getUsers()
148
	{
149
		return $this->_users;
150
	}
151
152
	/**
153
	 * @return array list of roles
154
	 */
155
	public function getRoles()
156
	{
157
		return $this->_roles;
158
	}
159
160
	/**
161
	 * @return string verb, may be empty, 'get', or 'post'.
162
	 */
163
	public function getVerb()
164
	{
165
		return $this->_verb;
166
	}
167
168
	/**
169
	 * @return array list of IP rules.
170
	 * @since 3.1.1
171
	 */
172
	public function getIPRules()
173
	{
174
		return $this->_ipRules;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_ipRules returns the type string which is incompatible with the documented return type array.
Loading history...
175
	}
176
177
	/**
178
	 * @return boolean if this rule applies to everyone
179
	 */
180
	public function getGuestApplied()
181
	{
182
		return $this->_guest || $this->_everyone;
183
	}
184
185
	/**
186
	 * @return boolean if this rule applies to everyone
187
	 */
188
	public function getEveryoneApplied()
189
	{
190
		return $this->_everyone;
191
	}
192
193
	/**
194
	 * @return boolean if this rule applies to authenticated users
195
	 */
196
	public function getAuthenticatedApplied()
197
	{
198
		return $this->_authenticated || $this->_everyone;
199
	}
200
201
	/**
202
	 * @param IUser the user object
0 ignored issues
show
Bug introduced by
The type Prado\Security\the was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
203
	 * @param string the request verb (GET, PUT)
204
	 * @param string the request IP address
205
	 * @return integer 1 if the user is allowed, -1 if the user is denied, 0 if the rule does not apply to the user
206
	 */
207
	public function isUserAllowed(IUser $user, $verb, $ip)
208
	{
209
		if($this->isVerbMatched($verb) && $this->isIpMatched($ip) && $this->isUserMatched($user) && $this->isRoleMatched($user))
210
			return ($this->_action === 'allow')?1:-1;
211
		else
212
			return 0;
213
	}
214
215
	private function isIpMatched($ip)
216
	{
217
		if(empty($this->_ipRules))
218
			return 1;
219
		foreach($this->_ipRules as $rule)
0 ignored issues
show
Bug introduced by
The expression $this->_ipRules of type string is not traversable.
Loading history...
220
		{
221
			if($rule === '*' || $rule === $ip || (($pos = strpos($rule, '*')) !== false && strncmp($ip, $rule, $pos) === 0))
222
				return 1;
223
		}
224
		return 0;
225
	}
226
227
	private function isUserMatched($user)
228
	{
229
		return ($this->_everyone || ($this->_guest && $user->getIsGuest()) || ($this->_authenticated && !$user->getIsGuest()) || in_array(strtolower($user->getName()), $this->_users));
230
	}
231
232
	private function isRoleMatched($user)
233
	{
234
		foreach($this->_roles as $role)
235
		{
236
			if($role === '*' || $user->isInRole($role))
237
				return true;
238
		}
239
		return false;
240
	}
241
242
	private function isVerbMatched($verb)
243
	{
244
		return ($this->_verb === '*' || strcasecmp($verb, $this->_verb) === 0);
245
	}
246
}