Issues (1460)

src/Enforcer.php (104 issues)

1
<?php
2
0 ignored issues
show
Missing file doc comment
Loading history...
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]>"
Loading history...
17
 */
0 ignored issues
show
Missing @category tag in class comment
Loading history...
Missing @package tag in class comment
Loading history...
Missing @license tag in class comment
Loading history...
Missing @link tag in class comment
Loading history...
18
class Enforcer extends ManagementEnforcer
19
{
20
    /**
21
     * Gets the roles that a user has.
22
     *
23
     * @param string $name
0 ignored issues
show
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
24
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
25
     * @return string[]
0 ignored issues
show
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
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
Missing parameter comment
Loading history...
36
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
49
     * @param string $role
0 ignored issues
show
Missing parameter comment
Loading history...
50
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
66
     * @param string $role
0 ignored issues
show
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
67
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
68
     * @return bool
0 ignored issues
show
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
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
Missing short description in doc comment
Loading history...
76
     * @param string $user
0 ignored issues
show
Missing parameter comment
Loading history...
Expected 3 spaces after parameter type; 1 found
Loading history...
77
     * @param string[] $roles
0 ignored issues
show
Missing parameter comment
Loading history...
78
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
Expected 3 spaces after parameter type; 1 found
Loading history...
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
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
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.
Loading history...
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
Missing parameter comment
Loading history...
96
     * @param string $role
0 ignored issues
show
Missing parameter comment
Loading history...
97
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
111
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
147
     * @return bool
0 ignored issues
show
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
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
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
177
     * @param string ...$permission
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
193
     * @param array  ...$permissions
0 ignored issues
show
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
194
     * @return bool
0 ignored issues
show
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
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
Missing parameter comment
Loading history...
210
     * @param string ...$permission
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
239
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
264
     * @param string ...$permission
0 ignored issues
show
Missing parameter comment
Loading history...
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
Doc comment long description must start with a capital letter
Loading history...
283
     * But getImplicitRolesForUser("alice") will get: ["role:admin", "role:user"].
284
     *
285
     * @param string $name
0 ignored issues
show
Missing parameter comment
Loading history...
286
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
322
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
323
     * @return array
0 ignored issues
show
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
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
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
356
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
357
     * @return array
0 ignored issues
show
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
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
Doc comment long description must start with a capital letter
Loading history...
404
     * But getImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]].
405
     *
406
     * @param string $user
0 ignored issues
show
Missing parameter comment
Loading history...
407
     * @param string ...$domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
481
     * 
482
     * @return array
483
     */
484 6
    private function removeDumplicatePermissions(array $permissions): array
0 ignored issues
show
Private method name "Enforcer::removeDumplicatePermissions" must be prefixed with an underscore
Loading history...
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
Missing parameter comment
Loading history...
517
     * @param string $action
0 ignored issues
show
Missing parameter comment
Loading history...
518
     * @param string $prefix
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
602
     * @param string $domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
649
     * @return string[]
0 ignored issues
show
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
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
Missing parameter comment
Loading history...
683
     * @param string $domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
696
     * @param string $domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
709
     * @param string $domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
723
     * @param string $role
0 ignored issues
show
Missing parameter comment
Loading history...
724
     * @param string $domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
738
     * @param string $role
0 ignored issues
show
Missing parameter comment
Loading history...
739
     * @param string $domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Missing parameter comment
Loading history...
753
     * @param string $domain
0 ignored issues
show
Missing parameter comment
Loading history...
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
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
Missing parameter comment
Loading history...
773
     * @return bool
0 ignored issues
show
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
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
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
Missing parameter comment
Loading history...
806
     * @return bool
0 ignored issues
show
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
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
Missing parameter comment
Loading history...
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