1 | <?php |
||
2 | |||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||
3 | declare(strict_types=1); |
||
4 | |||
5 | namespace Casbin; |
||
6 | |||
7 | use Casbin\Constant\Constants; |
||
8 | use Casbin\Exceptions\CasbinException; |
||
9 | use Casbin\Exceptions\EmptyConditionException; |
||
10 | use Casbin\Exceptions\ObjConditionException; |
||
11 | use Casbin\Util\Util; |
||
12 | |||
13 | /** |
||
14 | * Enforcer = ManagementEnforcer + RBAC API. |
||
15 | * |
||
16 | * @author [email protected] |
||
0 ignored issues
–
show
Content of the @author tag must be in the form "Display Name <[email protected]>"
![]() |
|||
17 | */ |
||
0 ignored issues
–
show
|
|||
18 | class Enforcer extends ManagementEnforcer |
||
19 | { |
||
20 | /** |
||
21 | * Gets the roles that a user has. |
||
22 | * |
||
23 | * @param string $name |
||
0 ignored issues
–
show
|
|||
24 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
25 | * @return string[] |
||
0 ignored issues
–
show
|
|||
26 | */ |
||
27 | 30 | public function getRolesForUser(string $name, string ...$domain): array |
|
28 | { |
||
29 | 30 | return $this->model['g']['g']->rm->getRoles($name, ...$domain); |
|
30 | } |
||
31 | |||
32 | /** |
||
33 | * Gets the users that has a role. |
||
34 | * |
||
35 | * @param string $name |
||
0 ignored issues
–
show
|
|||
36 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
37 | * |
||
38 | * @return string[] |
||
39 | */ |
||
40 | 6 | public function getUsersForRole(string $name, string ...$domain): array |
|
41 | { |
||
42 | 6 | return $this->model['g']['g']->rm->getUsers($name, ...$domain); |
|
43 | } |
||
44 | |||
45 | /** |
||
46 | * Determines whether a user has a role. |
||
47 | * |
||
48 | * @param string $name |
||
0 ignored issues
–
show
|
|||
49 | * @param string $role |
||
0 ignored issues
–
show
|
|||
50 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
51 | * |
||
52 | * @return bool |
||
53 | */ |
||
54 | 9 | public function hasRoleForUser(string $name, string $role, string ...$domain): bool |
|
55 | { |
||
56 | 9 | $roles = $this->getRolesForUser($name, ...$domain); |
|
57 | |||
58 | 9 | return in_array($role, $roles, true); |
|
59 | } |
||
60 | |||
61 | /** |
||
62 | * Adds a role for a user. |
||
63 | * returns false if the user already has the role (aka not affected). |
||
64 | * |
||
65 | * @param string $user |
||
0 ignored issues
–
show
|
|||
66 | * @param string $role |
||
0 ignored issues
–
show
|
|||
67 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
68 | * @return bool |
||
0 ignored issues
–
show
|
|||
69 | */ |
||
70 | 6 | public function addRoleForUser(string $user, string $role, string ...$domain): bool |
|
71 | { |
||
72 | 6 | return $this->addGroupingPolicy(...array_merge([$user, $role], $domain)); |
|
73 | } |
||
74 | |||
75 | /** |
||
0 ignored issues
–
show
|
|||
76 | * @param string $user |
||
0 ignored issues
–
show
|
|||
77 | * @param string[] $roles |
||
0 ignored issues
–
show
|
|||
78 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
79 | * |
||
80 | * @return bool |
||
81 | */ |
||
82 | 3 | public function addRolesForUser(string $user, array $roles, string ...$domain): bool |
|
83 | { |
||
84 | 3 | return $this->addGroupingPolicies( |
|
85 | 1 | array_map(function ($role) use ($user, $domain) { |
|
0 ignored issues
–
show
|
|||
86 | 3 | return array_merge([$user, $role], $domain); |
|
87 | 3 | }, $roles) |
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
![]() |
|||
88 | 1 | ); |
|
89 | } |
||
90 | |||
91 | /** |
||
92 | * Deletes a role for a user. |
||
93 | * returns false if the user does not have the role (aka not affected). |
||
94 | * |
||
95 | * @param string $user |
||
0 ignored issues
–
show
|
|||
96 | * @param string $role |
||
0 ignored issues
–
show
|
|||
97 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
98 | * |
||
99 | * @return bool |
||
100 | */ |
||
101 | 9 | public function deleteRoleForUser(string $user, string $role, string ...$domain): bool |
|
102 | { |
||
103 | 9 | return $this->removeGroupingPolicy(...array_merge([$user, $role], $domain)); |
|
104 | } |
||
105 | |||
106 | /** |
||
107 | * Deletes all roles for a user. |
||
108 | * Returns false if the user does not have any roles (aka not affected). |
||
109 | * |
||
110 | * @param string $user |
||
0 ignored issues
–
show
|
|||
111 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
112 | * |
||
113 | * @return bool |
||
114 | * @throws CasbinException |
||
115 | */ |
||
116 | 3 | public function deleteRolesForUser(string $user, string ...$domain): bool |
|
117 | { |
||
118 | 3 | if (count($domain) > 1) { |
|
119 | throw new CasbinException('error: domain should be 1 parameter'); |
||
120 | } |
||
121 | |||
122 | 3 | return $this->removeFilteredGroupingPolicy(0, ...array_merge([$user, ''], $domain)); |
|
123 | } |
||
124 | |||
125 | /** |
||
126 | * Deletes a user. |
||
127 | * Returns false if the user does not exist (aka not affected). |
||
128 | * |
||
129 | * @param string $user |
||
0 ignored issues
–
show
|
|||
130 | * |
||
131 | * @return bool |
||
132 | */ |
||
133 | 3 | public function deleteUser(string $user): bool |
|
134 | { |
||
135 | 3 | $res1 = $this->removeFilteredGroupingPolicy(0, $user); |
|
136 | |||
137 | 3 | $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX); |
|
138 | 3 | $res2 = $this->removeFilteredPolicy($subIndex, $user); |
|
139 | |||
140 | 3 | return $res1 || $res2; |
|
141 | } |
||
142 | |||
143 | /** |
||
144 | * Deletes a role. |
||
145 | * |
||
146 | * @param string $role |
||
0 ignored issues
–
show
|
|||
147 | * @return bool |
||
0 ignored issues
–
show
|
|||
148 | */ |
||
149 | 3 | public function deleteRole(string $role): bool |
|
150 | { |
||
151 | 3 | $res1 = $this->removeFilteredGroupingPolicy(1, $role); |
|
152 | |||
153 | 3 | $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX); |
|
154 | 3 | $res2 = $this->removeFilteredPolicy($subIndex, $role); |
|
155 | |||
156 | 3 | return $res1 || $res2; |
|
157 | } |
||
158 | |||
159 | /** |
||
160 | * Deletes a permission. |
||
161 | * Returns false if the permission does not exist (aka not affected). |
||
162 | * |
||
163 | * @param string ...$permission |
||
0 ignored issues
–
show
|
|||
164 | * |
||
165 | * @return bool |
||
166 | */ |
||
167 | 6 | public function deletePermission(string ...$permission): bool |
|
168 | { |
||
169 | 6 | return $this->removeFilteredPolicy(1, ...$permission); |
|
170 | } |
||
171 | |||
172 | /** |
||
173 | * Adds a permission for a user or role. |
||
174 | * Returns false if the user or role already has the permission (aka not affected). |
||
175 | * |
||
176 | * @param string $user |
||
0 ignored issues
–
show
|
|||
177 | * @param string ...$permission |
||
0 ignored issues
–
show
|
|||
178 | * |
||
179 | * @return bool |
||
180 | */ |
||
181 | 12 | public function addPermissionForUser(string $user, string ...$permission): bool |
|
182 | { |
||
183 | 12 | $params = array_merge([$user], $permission); |
|
184 | |||
185 | 12 | return $this->addPolicy(...$params); |
|
186 | } |
||
187 | |||
188 | /** |
||
189 | * AddPermissionsForUser adds multiple permissions for a user or role. |
||
190 | * Returns false if the user or role already has one of the permissions (aka not affected). |
||
191 | * |
||
192 | * @param string $user |
||
0 ignored issues
–
show
|
|||
193 | * @param array ...$permissions |
||
0 ignored issues
–
show
|
|||
194 | * @return bool |
||
0 ignored issues
–
show
|
|||
195 | */ |
||
196 | 3 | public function addPermissionsForUser(string $user, array ...$permissions): bool |
|
197 | { |
||
198 | 3 | $rules = []; |
|
199 | 3 | foreach ($permissions as $permission) { |
|
200 | 3 | $rules[] = array_merge([$user], $permission); |
|
201 | } |
||
202 | 3 | return $this->addPolicies($rules); |
|
203 | } |
||
204 | |||
205 | /** |
||
206 | * Deletes a permission for a user or role. |
||
207 | * Returns false if the user or role does not have the permission (aka not affected). |
||
208 | * |
||
209 | * @param string $user |
||
0 ignored issues
–
show
|
|||
210 | * @param string ...$permission |
||
0 ignored issues
–
show
|
|||
211 | * |
||
212 | * @return bool |
||
213 | */ |
||
214 | 3 | public function deletePermissionForUser(string $user, string ...$permission): bool |
|
215 | { |
||
216 | 3 | $params = array_merge([$user], $permission); |
|
217 | |||
218 | 3 | return $this->removePolicy(...$params); |
|
219 | } |
||
220 | |||
221 | /** |
||
222 | * Deletes permissions for a user or role. |
||
223 | * Returns false if the user or role does not have any permissions (aka not affected). |
||
224 | * |
||
225 | * @param string $user |
||
0 ignored issues
–
show
|
|||
226 | * |
||
227 | * @return bool |
||
228 | */ |
||
229 | 6 | public function deletePermissionsForUser(string $user): bool |
|
230 | { |
||
231 | 6 | $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX); |
|
232 | 3 | return $this->removeFilteredPolicy($subIndex, $user); |
|
233 | } |
||
234 | |||
235 | /** |
||
236 | * Gets permissions for a user or role. |
||
237 | * |
||
238 | * @param string $user |
||
0 ignored issues
–
show
|
|||
239 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
240 | * |
||
241 | * @return array |
||
242 | */ |
||
243 | 15 | public function getPermissionsForUser(string $user, string ...$domain): array |
|
244 | { |
||
245 | 15 | $permission = []; |
|
246 | 15 | foreach ($this->model['p'] as $ptype => $assertion) { |
|
247 | 15 | $args = []; |
|
248 | 15 | $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX); |
|
249 | 15 | $args[$subIndex] = $user; |
|
250 | 15 | if (\count($domain) > 0) { |
|
251 | 3 | $domIndex = $this->model->getFieldIndex($ptype, Constants::DOMAIN_INDEX); |
|
252 | 3 | $args[$domIndex] = $domain[0]; |
|
253 | } |
||
254 | 15 | $perm = $this->getFilteredPolicy(0, ...$args); |
|
255 | 15 | $permission = array_merge($permission, $perm); |
|
256 | } |
||
257 | 15 | return $permission; |
|
258 | } |
||
259 | |||
260 | /** |
||
261 | * Determines whether a user has a permission. |
||
262 | * |
||
263 | * @param string $user |
||
0 ignored issues
–
show
|
|||
264 | * @param string ...$permission |
||
0 ignored issues
–
show
|
|||
265 | * |
||
266 | * @return bool |
||
267 | */ |
||
268 | 3 | public function hasPermissionForUser(string $user, string ...$permission): bool |
|
269 | { |
||
270 | 3 | $params = array_merge([$user], $permission); |
|
271 | |||
272 | 3 | return $this->hasPolicy($params); |
|
273 | } |
||
274 | |||
275 | /** |
||
276 | * Gets implicit roles that a user has. |
||
277 | * Compared to getRolesForUser(), this function retrieves indirect roles besides direct roles. |
||
278 | * For example: |
||
279 | * g, alice, role:admin |
||
280 | * g, role:admin, role:user. |
||
281 | * |
||
282 | * getRolesForUser("alice") can only get: ["role:admin"]. |
||
0 ignored issues
–
show
|
|||
283 | * But getImplicitRolesForUser("alice") will get: ["role:admin", "role:user"]. |
||
284 | * |
||
285 | * @param string $name |
||
0 ignored issues
–
show
|
|||
286 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
287 | * |
||
288 | * @return array |
||
289 | */ |
||
290 | 12 | public function getImplicitRolesForUser(string $name, string ...$domain): array |
|
291 | { |
||
292 | 12 | $res = []; |
|
293 | 12 | $roleSet = []; |
|
294 | 12 | $roleSet[$name] = true; |
|
295 | |||
296 | 12 | $q = []; |
|
297 | 12 | $q[] = $name; |
|
298 | |||
299 | 12 | for (; count($q) > 0;) { |
|
300 | 12 | $name = $q[0]; |
|
301 | 12 | $q = array_slice($q, 1); |
|
302 | |||
303 | 12 | foreach ($this->rmMap as $rm) { |
|
304 | 12 | $roles = $rm->getRoles($name, ...$domain); |
|
305 | 12 | foreach ($roles as $r) { |
|
306 | 12 | if (!isset($roleSet[$r])) { |
|
307 | 12 | $res[] = $r; |
|
308 | 12 | $q[] = $r; |
|
309 | 12 | $roleSet[$r] = true; |
|
310 | } |
||
311 | } |
||
312 | } |
||
313 | } |
||
314 | |||
315 | 12 | return $res; |
|
316 | } |
||
317 | |||
318 | /** |
||
319 | * GetImplicitUsersForRole gets implicit users for a role. |
||
320 | * |
||
321 | * @param string $name |
||
0 ignored issues
–
show
|
|||
322 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
323 | * @return array |
||
0 ignored issues
–
show
|
|||
324 | */ |
||
325 | 6 | public function getImplicitUsersForRole(string $name, string ...$domain): array |
|
326 | { |
||
327 | 6 | $res = []; |
|
328 | 6 | $roleSet = []; |
|
329 | 6 | $roleSet[$name] = true; |
|
330 | |||
331 | 6 | $q = []; |
|
332 | 6 | $q[] = $name; |
|
333 | |||
334 | 6 | for (; count($q) > 0;) { |
|
335 | 6 | $name = $q[0]; |
|
336 | 6 | $q = array_slice($q, 1); |
|
337 | |||
338 | 6 | foreach ($this->rmMap as $rm) { |
|
339 | 6 | $roles = $rm->getUsers($name, ...$domain); |
|
340 | 6 | foreach ($roles as $r) { |
|
341 | 6 | if (!isset($roleSet[$r])) { |
|
342 | 6 | $res[] = $r; |
|
343 | 6 | $q[] = $r; |
|
344 | 6 | $roleSet[$r] = true; |
|
345 | } |
||
346 | } |
||
347 | } |
||
348 | } |
||
349 | 6 | return $res; |
|
350 | } |
||
351 | |||
352 | /** |
||
353 | * GetImplicitResourcesForUser returns all policies that user obtaining in domain |
||
354 | * |
||
355 | * @param string $user |
||
0 ignored issues
–
show
|
|||
356 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
357 | * @return array |
||
0 ignored issues
–
show
|
|||
358 | */ |
||
359 | 3 | public function getImplicitResourcesForUser(string $user, string ...$domain): array |
|
360 | { |
||
361 | 3 | $permissions = $this->getImplicitPermissionsForUser($user, ...$domain); |
|
362 | |||
363 | 3 | $res = []; |
|
364 | 3 | foreach ($permissions as $permission) { |
|
365 | 3 | if ($permission[0] == $user) { |
|
366 | 3 | $res[] = $permission; |
|
367 | 3 | continue; |
|
368 | } |
||
369 | 3 | $resLocal = [[$user]]; |
|
370 | 3 | $tokensLength = count($permission); |
|
371 | 3 | $t = [[]]; |
|
372 | 3 | foreach (array_slice($permission, 1) as $token) { |
|
373 | 3 | $tokens = $this->getImplicitUsersForRole($token, ...$domain); |
|
374 | 3 | $tokens[] = $token; |
|
375 | 3 | $t[] = $tokens; |
|
376 | } |
||
377 | |||
378 | 3 | for ($i = 1; $i < $tokensLength; $i++) { |
|
379 | 3 | $n = []; |
|
380 | 3 | foreach ($t[$i] as $tokens) { |
|
381 | 3 | foreach ($resLocal as $policy) { |
|
382 | 3 | $temp = []; |
|
383 | 3 | $temp = array_merge($temp, $policy); |
|
384 | 3 | $temp[] = $tokens; |
|
385 | 3 | $n[] = $temp; |
|
386 | } |
||
387 | } |
||
388 | 3 | $resLocal = $n; |
|
389 | } |
||
390 | 3 | $res = array_merge($res, $resLocal); |
|
391 | } |
||
392 | 3 | return $res; |
|
393 | } |
||
394 | |||
395 | /** |
||
396 | * Gets implicit permissions for a user or role. |
||
397 | * Compared to getPermissionsForUser(), this function retrieves permissions for inherited roles. |
||
398 | * For example: |
||
399 | * p, admin, data1, read |
||
400 | * p, alice, data2, read |
||
401 | * g, alice, admin. |
||
402 | * |
||
403 | * getPermissionsForUser("alice") can only get: [["alice", "data2", "read"]]. |
||
0 ignored issues
–
show
|
|||
404 | * But getImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]]. |
||
405 | * |
||
406 | * @param string $user |
||
0 ignored issues
–
show
|
|||
407 | * @param string ...$domain |
||
0 ignored issues
–
show
|
|||
408 | * |
||
409 | * @return array |
||
410 | * @throws CasbinException |
||
411 | */ |
||
412 | 9 | public function getImplicitPermissionsForUser(string $user, string ...$domain): array |
|
413 | { |
||
414 | 9 | $roles = array_merge( |
|
415 | 9 | [$user], |
|
416 | 9 | $this->getImplicitRolesForUser($user, ...$domain) |
|
417 | 3 | ); |
|
418 | |||
419 | 9 | $len = \count($domain); |
|
420 | 9 | if ($len > 1) { |
|
421 | throw new CasbinException('error: domain should be 1 parameter'); |
||
422 | } |
||
423 | |||
424 | 9 | $res = []; |
|
425 | 9 | foreach ($roles as $role) { |
|
426 | 9 | if (1 == $len) { |
|
427 | 3 | $permissions = $this->getPermissionsForUserInDomain($role, $domain[0]); |
|
428 | } else { |
||
429 | 9 | $permissions = $this->getPermissionsForUser($role); |
|
430 | } |
||
431 | |||
432 | 9 | $res = array_merge($res, $permissions); |
|
433 | } |
||
434 | |||
435 | 9 | return $res; |
|
436 | } |
||
437 | |||
438 | /** |
||
439 | * Gets implicit users for a permission. |
||
440 | * For example: |
||
441 | * p, admin, data1, read |
||
442 | * p, bob, data1, read |
||
443 | * g, alice, admin |
||
444 | * getImplicitUsersForPermission("data1", "read") will get: ["alice", "bob"]. |
||
445 | * Note: only users will be returned, roles (2nd arg in "g") will be excluded. |
||
446 | * |
||
447 | * @param string ...$permission |
||
0 ignored issues
–
show
|
|||
448 | * |
||
449 | * @return array |
||
450 | * @throws CasbinException |
||
451 | */ |
||
452 | 3 | public function getImplicitUsersForPermission(string ...$permission): array |
|
453 | { |
||
454 | 3 | $pSubjects = $this->getAllSubjects(); |
|
455 | 3 | $gInherit = $this->model->getValuesForFieldInPolicyAllTypes("g", 1); |
|
456 | 3 | $gSubjects = $this->model->getValuesForFieldInPolicyAllTypes("g", 0); |
|
457 | |||
458 | 3 | $subjects = array_merge($pSubjects, $gSubjects); |
|
459 | 3 | Util::ArrayRemoveDuplicates($subjects); |
|
460 | |||
461 | 3 | $subjects = array_diff($subjects, $gInherit); |
|
462 | |||
463 | 3 | $res = []; |
|
464 | 3 | foreach ($subjects as $user) { |
|
465 | 3 | $req = $permission; |
|
466 | 3 | array_unshift($req, $user); |
|
467 | 3 | $allowed = $this->enforce(...$req); |
|
468 | |||
469 | 3 | if ($allowed) { |
|
470 | 3 | $res[] = $user; |
|
471 | } |
||
472 | } |
||
473 | |||
474 | 3 | return $res; |
|
475 | } |
||
476 | |||
477 | /** |
||
478 | * Convert permissions to string as a hash to deduplicate. |
||
479 | * |
||
480 | * @param array $permissions |
||
0 ignored issues
–
show
|
|||
481 | * |
||
482 | * @return array |
||
483 | */ |
||
484 | 6 | private function removeDumplicatePermissions(array $permissions): array |
|
0 ignored issues
–
show
|
|||
485 | { |
||
486 | 6 | $permissionsSet = []; |
|
487 | 6 | $res = []; |
|
488 | |||
489 | 6 | foreach ($permissions as $permission) { |
|
490 | 6 | $permissionStr = Util::arrayToString($permission); |
|
491 | |||
492 | 6 | if (isset($permissionsSet[$permissionStr])) { |
|
493 | 3 | continue; |
|
494 | } |
||
495 | |||
496 | 6 | $permissionsSet[$permissionStr] = true; |
|
497 | 6 | $res[] = $permission; |
|
498 | } |
||
499 | 6 | return $res; |
|
500 | } |
||
501 | |||
502 | /** |
||
503 | * GetAllowedObjectConditions returns a string array of object conditions that the user can access. |
||
504 | * For example: conditions, err := e.GetAllowedObjectConditions("alice", "read", "r.obj.") |
||
505 | * Note: |
||
506 | * |
||
507 | * 0. prefix: You can customize the prefix of the object conditions, and "r.obj." is commonly used as a prefix. |
||
508 | * After removing the prefix, the remaining part is the condition of the object. |
||
509 | * If there is an obj policy that does not meet the prefix requirement, an ObjConditionException will be thrown. |
||
510 | * |
||
511 | * 1. If the 'objectConditions' array is empty, an EmptyConditionException will be thrown. |
||
512 | * This error is thrown because some data adapters' ORM return full table data by default |
||
513 | * when they receive an empty condition, which tends to behave contrary to expectations.(e.g. DBALAdapter) |
||
514 | * If you are using an adapter that does not behave like this, you can choose to ignore this error. |
||
515 | * |
||
516 | * @param string $user |
||
0 ignored issues
–
show
|
|||
517 | * @param string $action |
||
0 ignored issues
–
show
|
|||
518 | * @param string $prefix |
||
0 ignored issues
–
show
|
|||
519 | * |
||
520 | * @return array |
||
521 | * @throws ObjConditionException |
||
522 | * @throws EmptyConditionException |
||
523 | */ |
||
524 | 3 | public function getAllowedObjectConditions(string $user, string $action, string $prefix): array |
|
525 | { |
||
526 | 3 | $permission = $this->getImplicitPermissionsForUser($user); |
|
527 | |||
528 | 3 | $objectConditions = []; |
|
529 | 3 | foreach ($permission as $policy) { |
|
530 | 3 | if ($policy[2] == $action) { |
|
531 | 3 | if (strpos($policy[1], $prefix) !== 0) { |
|
532 | 3 | throw new ObjConditionException('need to meet the prefix required by the object condition'); |
|
533 | } |
||
534 | |||
535 | 3 | $objectConditions[] = substr($policy[1], strlen($prefix)); |
|
536 | } |
||
537 | } |
||
538 | |||
539 | 3 | if (empty($objectConditions)) { |
|
540 | 3 | throw new EmptyConditionException('GetAllowedObjectConditions have an empty condition'); |
|
541 | } |
||
542 | |||
543 | 3 | return $objectConditions; |
|
544 | } |
||
545 | |||
546 | /** |
||
547 | * GetImplicitUsersForResource return implicit user based on resource. |
||
548 | * For example: |
||
549 | * p, alice, data1, read |
||
550 | * p, bob, data2, write |
||
551 | * p, data2_admin, data2, read |
||
552 | * p, data2_admin, data2, write |
||
553 | * g, alice, data2_admin |
||
554 | * GetImplicitUsersForResource("data2") will return [[bob data2 write] [alice data2 read] [alice data2 write]] |
||
555 | * GetImplicitUsersForResource("data1") will return [[alice data1 read]] |
||
556 | * Note: only users will be returned, roles (2nd arg in "g") will be excluded. |
||
557 | * |
||
558 | * @param string $resource |
||
0 ignored issues
–
show
|
|||
559 | * |
||
560 | * @return array |
||
561 | */ |
||
562 | 3 | public function getImplicitUsersForResource(string $resource): array |
|
563 | { |
||
564 | 3 | $permissions = []; |
|
565 | 3 | $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX); |
|
566 | 3 | $objIndex = $this->model->getFieldIndex('p', Constants::OBJECT_INDEX); |
|
567 | 3 | $rm = $this->getRoleManager(); |
|
568 | |||
569 | 3 | $roles = $this->getAllRoles(); |
|
570 | 3 | $isRole = array_flip($roles); |
|
571 | |||
572 | 3 | foreach ($this->model['p']['p']->policy as $rule) { |
|
573 | 3 | $obj = $rule[$objIndex]; |
|
574 | 3 | if ($obj != $resource) { |
|
575 | 3 | continue; |
|
576 | } |
||
577 | |||
578 | 3 | $sub = $rule[$subIndex]; |
|
579 | |||
580 | 3 | if (!isset($isRole[$sub])) { |
|
581 | 3 | $permissions[] = $rule; |
|
582 | } else { |
||
583 | 3 | $users = $rm->getUsers($sub); |
|
584 | |||
585 | 3 | foreach ($users as $user) { |
|
586 | 3 | $implicitRule = array_merge([], $rule); |
|
587 | 3 | $implicitRule[$subIndex] = $user; |
|
588 | 3 | $permissions[] = $implicitRule; |
|
589 | } |
||
590 | } |
||
591 | } |
||
592 | |||
593 | 3 | $res = $this->removeDumplicatePermissions($permissions); |
|
594 | 3 | return $res; |
|
595 | } |
||
596 | |||
597 | /** |
||
598 | * GetImplicitUsersForResourceByDomain return implicit user based on resource and domain. |
||
599 | * Compared to GetImplicitUsersForResource, domain is supported. |
||
600 | * |
||
601 | * @param string $resource |
||
0 ignored issues
–
show
|
|||
602 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
603 | * |
||
604 | * @return array |
||
605 | */ |
||
606 | 3 | public function getImplicitUsersForResourceByDomain(string $resource, string $domain): array |
|
607 | { |
||
608 | 3 | $permissions = []; |
|
609 | 3 | $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX); |
|
610 | 3 | $objIndex = $this->model->getFieldIndex('p', Constants::OBJECT_INDEX); |
|
611 | 3 | $domIndex = $this->model->getFieldIndex('p', Constants::DOMAIN_INDEX); |
|
612 | 3 | $rm = $this->getRoleManager(); |
|
613 | |||
614 | 3 | $roles = $this->getAllRolesByDomain($domain); |
|
615 | 3 | $isRole = array_flip($roles); |
|
616 | |||
617 | 3 | foreach ($this->model['p']['p']->policy as $rule) { |
|
618 | 3 | $obj = $rule[$objIndex]; |
|
619 | 3 | if ($obj != $resource) { |
|
620 | 3 | continue; |
|
621 | } |
||
622 | |||
623 | 3 | $sub = $rule[$subIndex]; |
|
624 | |||
625 | 3 | if (!isset($isRole[$sub])) { |
|
626 | $permissions[] = $rule; |
||
627 | } else { |
||
628 | 3 | if ($rule[$domIndex] != $domain) { |
|
629 | 3 | continue; |
|
630 | } |
||
631 | |||
632 | 3 | $users = $rm->getUsers($sub, $domain); |
|
633 | 3 | foreach ($users as $user) { |
|
634 | 3 | $implicitRule = array_merge([], $rule); |
|
635 | 3 | $implicitRule[$subIndex] = $user; |
|
636 | 3 | $permissions[] = $implicitRule; |
|
637 | } |
||
638 | } |
||
639 | } |
||
640 | |||
641 | 3 | $res = $this->removeDumplicatePermissions($permissions); |
|
642 | 3 | return $res; |
|
643 | } |
||
644 | |||
645 | /** |
||
646 | * GetAllUsersByDomain would get all users associated with the domain. |
||
647 | * |
||
648 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
649 | * @return string[] |
||
0 ignored issues
–
show
|
|||
650 | */ |
||
651 | 3 | public function getAllUsersByDomain(string $domain): array |
|
652 | { |
||
653 | 3 | $m = []; |
|
654 | 3 | $g = $this->model['g']['g']; |
|
655 | 3 | $p = $this->model['p']['p']; |
|
656 | 3 | $users = []; |
|
657 | 3 | $index = $this->model->getFieldIndex('p', Constants::DOMAIN_INDEX); |
|
658 | |||
659 | 1 | $getUser = function (int $index, array $policies, string $domain, array $m): array { |
|
660 | 3 | if (count($policies) == 0 || count($policies[0]) <= $index) { |
|
661 | return []; |
||
662 | } |
||
663 | 3 | $res = []; |
|
664 | 3 | foreach ($policies as $policy) { |
|
665 | 3 | $ok = isset($m[$policy[0]]); |
|
666 | 3 | if ($policy[$index] == $domain && !$ok) { |
|
667 | 3 | $res[] = $policy[0]; |
|
668 | 3 | $m[$policy[0]] = []; |
|
669 | } |
||
670 | } |
||
671 | 3 | return $res; |
|
672 | 3 | }; |
|
673 | |||
674 | 3 | $users = array_merge($users, $getUser(2, $g->policy, $domain, $m)); |
|
675 | 3 | $users = array_merge($users, $getUser($index, $p->policy, $domain, $m)); |
|
676 | 3 | return $users; |
|
677 | } |
||
678 | |||
679 | /** |
||
680 | * Gets the users that has a role inside a domain. Add by Gordon. |
||
681 | * |
||
682 | * @param string $name |
||
0 ignored issues
–
show
|
|||
683 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
684 | * |
||
685 | * @return array |
||
686 | */ |
||
687 | 3 | public function getUsersForRoleInDomain(string $name, string $domain): array |
|
688 | { |
||
689 | 3 | return $this->model['g']['g']->rm->getUsers($name, $domain); |
|
690 | } |
||
691 | |||
692 | /** |
||
693 | * Gets the roles that a user has inside a domain. |
||
694 | * |
||
695 | * @param string $name |
||
0 ignored issues
–
show
|
|||
696 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
697 | * |
||
698 | * @return array |
||
699 | */ |
||
700 | 3 | public function getRolesForUserInDomain(string $name, string $domain): array |
|
701 | { |
||
702 | 3 | return $this->model['g']['g']->rm->getRoles($name, $domain); |
|
703 | } |
||
704 | |||
705 | /** |
||
706 | * Gets permissions for a user or role inside a domain. |
||
707 | * |
||
708 | * @param string $name |
||
0 ignored issues
–
show
|
|||
709 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
710 | * |
||
711 | * @return array |
||
712 | */ |
||
713 | 6 | public function getPermissionsForUserInDomain(string $name, string $domain): array |
|
714 | { |
||
715 | 6 | return $this->getFilteredPolicy(0, $name, $domain); |
|
716 | } |
||
717 | |||
718 | /** |
||
719 | * Adds a role for a user inside a domain. |
||
720 | * returns false if the user already has the role (aka not affected). |
||
721 | * |
||
722 | * @param string $user |
||
0 ignored issues
–
show
|
|||
723 | * @param string $role |
||
0 ignored issues
–
show
|
|||
724 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
725 | * |
||
726 | * @return bool |
||
727 | */ |
||
728 | 9 | public function addRoleForUserInDomain(string $user, string $role, string $domain): bool |
|
729 | { |
||
730 | 9 | return $this->addGroupingPolicy($user, $role, $domain); |
|
731 | } |
||
732 | |||
733 | /** |
||
734 | * Deletes a role for a user inside a domain. |
||
735 | * Returns false if the user does not have the role (aka not affected). |
||
736 | * |
||
737 | * @param string $user |
||
0 ignored issues
–
show
|
|||
738 | * @param string $role |
||
0 ignored issues
–
show
|
|||
739 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
740 | * |
||
741 | * @return bool |
||
742 | */ |
||
743 | 6 | public function deleteRoleForUserInDomain(string $user, string $role, string $domain): bool |
|
744 | { |
||
745 | 6 | return $this->removeGroupingPolicy($user, $role, $domain); |
|
746 | } |
||
747 | |||
748 | /** |
||
749 | * DeleteRolesForUserInDomain deletes all roles for a user inside a domain. |
||
750 | * Returns false if the user does not have any roles (aka not affected). |
||
751 | * |
||
752 | * @param string $user |
||
0 ignored issues
–
show
|
|||
753 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
754 | * |
||
755 | * @return bool |
||
756 | */ |
||
757 | 3 | public function deleteRolesForUserInDomain(string $user, string $domain): bool |
|
758 | { |
||
759 | 3 | $roles = $this->model['g']['g']->rm->getRoles($user, $domain); |
|
760 | |||
761 | 3 | $rules = []; |
|
762 | 3 | foreach ($roles as $role) { |
|
763 | 3 | $rules[] = [$user, $role, $domain]; |
|
764 | } |
||
765 | |||
766 | 3 | return $this->removeGroupingPolicies($rules); |
|
767 | } |
||
768 | |||
769 | /** |
||
770 | * DeleteAllUsersByDomain would delete all users associated with the domain. |
||
771 | * |
||
772 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
773 | * @return bool |
||
0 ignored issues
–
show
|
|||
774 | */ |
||
775 | 6 | public function deleteAllUsersByDomain(string $domain): bool |
|
776 | { |
||
777 | 6 | $g = $this->model['g']['g']; |
|
778 | 6 | $p = $this->model['p']['p']; |
|
779 | 6 | $index = $this->model->getFieldIndex('p', Constants::DOMAIN_INDEX); |
|
780 | |||
781 | 2 | $getUser = function (int $index, array $policies, string $domain): array { |
|
782 | 6 | if (count($policies) == 0 || count($policies[0]) <= $index) { |
|
783 | return []; |
||
784 | } |
||
785 | 6 | $res = []; |
|
786 | 6 | foreach ($policies as $policy) { |
|
787 | 6 | if ($policy[$index] == $domain) { |
|
788 | 6 | $res[] = $policy; |
|
789 | } |
||
790 | } |
||
791 | 6 | return $res; |
|
792 | 6 | }; |
|
793 | |||
794 | 6 | $users = $getUser(2, $g->policy, $domain); |
|
795 | 6 | $this->removeGroupingPolicies($users); |
|
796 | 6 | $users = $getUser($index, $p->policy, $domain); |
|
797 | 6 | $this->removePolicies($users); |
|
798 | 6 | return true; |
|
799 | } |
||
800 | |||
801 | /** |
||
802 | * DeleteDomains would delete all associated users and roles. |
||
803 | * It would delete all domains if parameter is not provided. |
||
804 | * |
||
805 | * @param string ...$domains |
||
0 ignored issues
–
show
|
|||
806 | * @return bool |
||
0 ignored issues
–
show
|
|||
807 | */ |
||
808 | 3 | public function deleteDomains(string ...$domains): bool |
|
809 | { |
||
810 | 3 | if (count($domains) == 0) { |
|
811 | 3 | $this->clearPolicy(); |
|
812 | 3 | return true; |
|
813 | } |
||
814 | 3 | foreach ($domains as $domain) { |
|
815 | 3 | $this->deleteAllUsersByDomain($domain); |
|
816 | } |
||
817 | 3 | return true; |
|
818 | } |
||
819 | |||
820 | /** |
||
821 | * GetAllDomains would get all domains. |
||
822 | * |
||
823 | * @return array |
||
824 | */ |
||
825 | public function getAllDomains(): array |
||
826 | { |
||
827 | return $this->getRoleManager()->getAllDomains(); |
||
828 | } |
||
829 | |||
830 | /** |
||
831 | * GetAllRolesByDomain would get all roles associated with the domain. |
||
832 | * Note: Not applicable to Domains with inheritance relationship (implicit roles) |
||
833 | * |
||
834 | * @param string $domain |
||
0 ignored issues
–
show
|
|||
835 | * |
||
836 | * @return array |
||
837 | */ |
||
838 | 3 | public function getAllRolesByDomain(string $domain): array |
|
839 | { |
||
840 | 3 | $g = $this->model['g']['g']; |
|
841 | 3 | $policies = $g->policy; |
|
842 | 3 | $roles = []; |
|
843 | 3 | $existMap = []; |
|
844 | |||
845 | 3 | foreach ($policies as $policy) { |
|
846 | 3 | if ($policy[count($policy) - 1] == $domain) { |
|
847 | 3 | $role = $policy[count($policy) - 2]; |
|
848 | 3 | if (!isset($existMap[$role])) { |
|
849 | 3 | $roles[] = $role; |
|
850 | 3 | $existMap[$role] = true; |
|
851 | } |
||
852 | } |
||
853 | } |
||
854 | |||
855 | 3 | return $roles; |
|
856 | } |
||
857 | } |
||
858 |