These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * AnnotationChecker.php |
||
4 | * |
||
5 | * @copyright More in license.md |
||
6 | * @license http://www.ipublikuj.eu |
||
7 | * @author Adam Kadlec http://www.ipublikuj.eu |
||
8 | * @package iPublikuj:Permissions! |
||
9 | * @subpackage Access |
||
10 | * @since 1.0.0 |
||
11 | * |
||
12 | * @date 13.10.14 |
||
13 | */ |
||
14 | |||
15 | declare(strict_types = 1); |
||
16 | |||
17 | namespace IPub\Permissions\Access; |
||
18 | |||
19 | use Nette; |
||
20 | use Nette\Application\UI; |
||
21 | use Nette\Utils; |
||
22 | use Nette\Security as NS; |
||
23 | |||
24 | use IPub; |
||
25 | use IPub\Permissions\Entities; |
||
26 | use IPub\Permissions\Exceptions; |
||
27 | use IPub\Permissions\Security; |
||
28 | |||
29 | /** |
||
30 | * Presenter & component annotation access checker |
||
31 | * |
||
32 | * @package iPublikuj:Permissions! |
||
33 | * @subpackage Access |
||
34 | * |
||
35 | * @author Adam Kadlec <[email protected]> |
||
36 | */ |
||
37 | 1 | final class AnnotationChecker extends Nette\Object implements IChecker, ICheckRequirements |
|
38 | { |
||
39 | /** |
||
40 | * @var NS\User |
||
41 | */ |
||
42 | private $user; |
||
43 | |||
44 | /** |
||
45 | * @param NS\User $user |
||
46 | */ |
||
47 | public function __construct(NS\User $user) |
||
48 | { |
||
49 | 1 | $this->user = $user; |
|
50 | 1 | } |
|
51 | |||
52 | /** |
||
53 | * {@inheritdoc} |
||
54 | */ |
||
55 | public function isAllowed($element) : bool |
||
56 | { |
||
57 | // Check annotations only if element have to be secured |
||
58 | if ( |
||
59 | 1 | ($element instanceof UI\ComponentReflection || $element instanceof UI\MethodReflection) |
|
60 | 1 | && $element->hasAnnotation('Secured') |
|
61 | ) { |
||
62 | 1 | return $this->checkUser($element) |
|
63 | 1 | && $this->checkResources($element)/* |
|
0 ignored issues
–
show
|
|||
64 | && $this->checkPrivileges($element)*/ |
||
65 | 1 | && $this->checkPermission($element) |
|
66 | 1 | && $this->checkRoles($element); |
|
67 | |||
68 | } else { |
||
69 | 1 | return TRUE; |
|
70 | } |
||
71 | } |
||
72 | |||
73 | /** |
||
74 | * @param UI\ComponentReflection|UI\MethodReflection $element |
||
75 | * |
||
76 | * @return bool |
||
77 | * |
||
78 | * @throws Exceptions\InvalidArgumentException |
||
79 | */ |
||
80 | View Code Duplication | private function checkUser($element) : bool |
|
81 | { |
||
82 | // Check if element has @Secured\User annotation |
||
83 | 1 | if ($element->hasAnnotation('Secured\User')) { |
|
84 | // Get user annotation |
||
85 | 1 | $user = $element->getAnnotation('Secured\User'); |
|
86 | |||
87 | // Annotation is single string |
||
88 | 1 | if (is_string($user) && in_array($user, ['loggedIn', 'guest'], TRUE)) { |
|
89 | // User have to be logged in and is not |
||
90 | 1 | if ($user === 'loggedIn' && $this->user->isLoggedIn() === FALSE) { |
|
91 | return FALSE; |
||
92 | |||
93 | // User have to be logged out and is logged in |
||
94 | 1 | } elseif ($user === 'guest' && $this->user->isLoggedIn() === TRUE) { |
|
95 | 1 | return FALSE; |
|
96 | } |
||
97 | |||
98 | // Annotation have wrong definition |
||
99 | } else { |
||
100 | throw new Exceptions\InvalidArgumentException('In @Security\User annotation is allowed only one from two strings: \'loggedIn\' & \'guest\''); |
||
101 | } |
||
102 | |||
103 | 1 | return TRUE; |
|
104 | } |
||
105 | |||
106 | 1 | return TRUE; |
|
107 | } |
||
108 | |||
109 | /** |
||
110 | * @param UI\ComponentReflection|UI\MethodReflection $element |
||
111 | * |
||
112 | * @return bool |
||
113 | * |
||
114 | * @throws Exceptions\InvalidStateException |
||
115 | */ |
||
116 | private function checkResources($element) : bool |
||
117 | { |
||
118 | // Check if element has @Security\Resource annotation & @Secured\Privilege annotation |
||
119 | 1 | if ($element->hasAnnotation('Secured\Resource')) { |
|
120 | 1 | $resources = UI\ComponentReflection::parseAnnotation($element, 'Secured\Resource'); |
|
121 | |||
122 | 1 | if (count($resources) != 1) { |
|
123 | throw new Exceptions\InvalidStateException('Invalid resources count in @Security\Resource annotation!'); |
||
124 | } |
||
125 | |||
126 | 1 | $privileges = UI\ComponentReflection::parseAnnotation($element, 'Secured\Privilege'); |
|
127 | |||
128 | 1 | View Code Duplication | foreach ($resources as $resource) { |
129 | 1 | if ($privileges !== FALSE) { |
|
130 | 1 | foreach ($privileges as $privilege) { |
|
131 | 1 | if ($this->user->isAllowed($resource, $privilege)) { |
|
132 | 1 | return TRUE; |
|
133 | } |
||
134 | } |
||
135 | |||
136 | } else { |
||
137 | if ($this->user->isAllowed($resource)) { |
||
138 | return TRUE; |
||
139 | } |
||
140 | } |
||
141 | } |
||
142 | |||
143 | return FALSE; |
||
144 | } |
||
145 | |||
146 | 1 | return TRUE; |
|
147 | } |
||
148 | |||
149 | /** |
||
150 | * @param UI\ComponentReflection|UI\MethodReflection $element |
||
151 | * |
||
152 | * @return bool |
||
153 | * |
||
154 | * @throws Exceptions\InvalidStateException |
||
155 | */ |
||
156 | View Code Duplication | private function checkPrivileges($element) : bool |
|
0 ignored issues
–
show
|
|||
157 | { |
||
158 | // Check if element has @Secured\Privilege annotation & hasn't @Secured\Resource annotation |
||
159 | if (!$element->hasAnnotation('Secured\Resource') && $element->hasAnnotation('Secured\Privilege')) { |
||
160 | $privileges = UI\ComponentReflection::parseAnnotation($element, 'Secured\Privilege'); |
||
161 | |||
162 | if (count($privileges) != 1) { |
||
163 | throw new Exceptions\InvalidStateException('Invalid privileges count in @Security\Privilege annotation!'); |
||
164 | } |
||
165 | |||
166 | foreach ($privileges as $privilege) { |
||
167 | // Check if privilege name is defined |
||
168 | if ($privilege === TRUE) { |
||
169 | continue; |
||
170 | } |
||
171 | |||
172 | if ($this->user->isAllowed(NS\IAuthorizator::ALL, $privilege)) { |
||
173 | return TRUE; |
||
174 | } |
||
175 | } |
||
176 | |||
177 | return FALSE; |
||
178 | } |
||
179 | |||
180 | return TRUE; |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * @param UI\ComponentReflection|UI\MethodReflection $element |
||
185 | * |
||
186 | * @return bool |
||
187 | */ |
||
188 | View Code Duplication | private function checkPermission($element) : bool |
|
189 | { |
||
190 | // Check if element has @Secured\Permission annotation |
||
191 | 1 | if ($element->hasAnnotation('Secured\Permission')) { |
|
192 | 1 | $permissions = UI\ComponentReflection::parseAnnotation($element, 'Secured\Permission'); |
|
193 | |||
194 | 1 | foreach ($permissions as $permission) { |
|
195 | // Check if parameters are defined |
||
196 | 1 | if ($permission === TRUE) { |
|
197 | continue; |
||
198 | } |
||
199 | |||
200 | // Parse resource & privilege from permission |
||
201 | 1 | list($resource, $privilege) = explode(Entities\IPermission::DELIMITER, $permission); |
|
202 | |||
203 | // Remove white spaces |
||
204 | 1 | $resource = Utils\Strings::trim($resource); |
|
205 | 1 | $privilege = Utils\Strings::trim($privilege); |
|
206 | |||
207 | 1 | if ($this->user->isAllowed($resource, $privilege)) { |
|
208 | 1 | return TRUE; |
|
209 | } |
||
210 | } |
||
211 | |||
212 | return FALSE; |
||
213 | } |
||
214 | |||
215 | 1 | return TRUE; |
|
216 | } |
||
217 | |||
218 | /** |
||
219 | * @param UI\ComponentReflection|UI\MethodReflection $element |
||
220 | * |
||
221 | * @return bool |
||
222 | */ |
||
223 | private function checkRoles($element) : bool |
||
224 | { |
||
225 | // Check if element has @Secured\Role annotation |
||
226 | 1 | if ($element->hasAnnotation('Secured\Role')) { |
|
227 | 1 | $roles = UI\ComponentReflection::parseAnnotation($element, 'Secured\Role'); |
|
228 | |||
229 | 1 | foreach ($roles as $role) { |
|
230 | // Check if role name is defined |
||
231 | 1 | if ($role === TRUE) { |
|
232 | continue; |
||
233 | } |
||
234 | |||
235 | 1 | if ($this->user->isInRole($role)) { |
|
236 | 1 | return TRUE; |
|
237 | } |
||
238 | } |
||
239 | |||
240 | 1 | return FALSE; |
|
241 | } |
||
242 | |||
243 | 1 | return TRUE; |
|
244 | } |
||
245 | } |
||
246 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.