Issues (1357)

src/Enforcer.php (2 issues)

Checks doc comment long not capital

Coding Style Informational
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Casbin;
6
7
use Casbin\Constant\Constants;
8
use Casbin\Exceptions\CasbinException;
9
use Casbin\Util\Util;
10
11
/**
12
 * Enforcer = ManagementEnforcer + RBAC API.
13
 *
14
 * @author [email protected]
15
 */
16
class Enforcer extends ManagementEnforcer
17
{
18
    /**
19
     * Gets the roles that a user has.
20
     *
21
     * @param string $name
22
     * @param string ...$domain
23
     * @return string[]
24
     */
25 30
    public function getRolesForUser(string $name, string ...$domain): array
26
    {
27 30
        return $this->model['g']['g']->rm->getRoles($name, ...$domain);
28
    }
29
30
    /**
31
     * Gets the users that has a role.
32
     *
33
     * @param string $name
34
     * @param string ...$domain
35
     *
36
     * @return string[]
37
     */
38 6
    public function getUsersForRole(string $name, string ...$domain): array
39
    {
40 6
        return $this->model['g']['g']->rm->getUsers($name, ...$domain);
41
    }
42
43
    /**
44
     * Determines whether a user has a role.
45
     *
46
     * @param string $name
47
     * @param string $role
48
     * @param string ...$domain
49
     *
50
     * @return bool
51
     */
52 9
    public function hasRoleForUser(string $name, string $role, string ...$domain): bool
53
    {
54 9
        $roles = $this->getRolesForUser($name, ...$domain);
55
56 9
        return in_array($role, $roles, true);
57
    }
58
59
    /**
60
     * Adds a role for a user.
61
     * returns false if the user already has the role (aka not affected).
62
     *
63
     * @param string $user
64
     * @param string $role
65
     * @param string ...$domain
66
     * @return bool
67
     */
68 6
    public function addRoleForUser(string $user, string $role, string ...$domain): bool
69
    {
70 6
        return $this->addGroupingPolicy(...array_merge([$user, $role], $domain));
71
    }
72
73
    /**
74
     * @param string $user
75
     * @param string[] $roles
76
     * @param string ...$domain
77
     *
78
     * @return bool
79
     */
80 3
    public function addRolesForUser(string $user, array $roles, string ...$domain): bool
81
    {
82 3
        return $this->addGroupingPolicies(
83 1
            array_map(function ($role) use ($user, $domain) {
84 3
                return array_merge([$user, $role], $domain);
85 3
            }, $roles)
86 1
        );
87
    }
88
89
    /**
90
     * Deletes a role for a user.
91
     * returns false if the user does not have the role (aka not affected).
92
     *
93
     * @param string $user
94
     * @param string $role
95
     * @param string ...$domain
96
     *
97
     * @return bool
98
     */
99 9
    public function deleteRoleForUser(string $user, string $role, string ...$domain): bool
100
    {
101 9
        return $this->removeGroupingPolicy(...array_merge([$user, $role], $domain));
102
    }
103
104
    /**
105
     * Deletes all roles for a user.
106
     * Returns false if the user does not have any roles (aka not affected).
107
     *
108
     * @param string $user
109
     * @param string ...$domain
110
     *
111
     * @return bool
112
     * @throws CasbinException
113
     */
114 3
    public function deleteRolesForUser(string $user, string ...$domain): bool
115
    {
116 3
        if (count($domain) > 1) {
117
            throw new CasbinException('error: domain should be 1 parameter');
118
        }
119
120 3
        return $this->removeFilteredGroupingPolicy(0, ...array_merge([$user, ''], $domain));
121
    }
122
123
    /**
124
     * Deletes a user.
125
     * Returns false if the user does not exist (aka not affected).
126
     *
127
     * @param string $user
128
     *
129
     * @return bool
130
     */
131 3
    public function deleteUser(string $user): bool
132
    {
133 3
        $res1 = $this->removeFilteredGroupingPolicy(0, $user);
134
135 3
        $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX);
136 3
        $res2 = $this->removeFilteredPolicy($subIndex, $user);
137
138 3
        return $res1 || $res2;
139
    }
140
141
    /**
142
     * Deletes a role.
143
     *
144
     * @param string $role
145
     * @return bool
146
     */
147 3
    public function deleteRole(string $role): bool
148
    {
149 3
        $res1 = $this->removeFilteredGroupingPolicy(1, $role);
150
151 3
        $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX);
152 3
        $res2 = $this->removeFilteredPolicy($subIndex, $role);
153
154 3
        return $res1 || $res2;
155
    }
156
157
    /**
158
     * Deletes a permission.
159
     * Returns false if the permission does not exist (aka not affected).
160
     *
161
     * @param string ...$permission
162
     *
163
     * @return bool
164
     */
165 6
    public function deletePermission(string ...$permission): bool
166
    {
167 6
        return $this->removeFilteredPolicy(1, ...$permission);
168
    }
169
170
    /**
171
     * Adds a permission for a user or role.
172
     * Returns false if the user or role already has the permission (aka not affected).
173
     *
174
     * @param string $user
175
     * @param string ...$permission
176
     *
177
     * @return bool
178
     */
179 12
    public function addPermissionForUser(string $user, string ...$permission): bool
180
    {
181 12
        $params = array_merge([$user], $permission);
182
183 12
        return $this->addPolicy(...$params);
184
    }
185
186
    /**
187
     * AddPermissionsForUser adds multiple permissions for a user or role.
188
     * Returns false if the user or role already has one of the permissions (aka not affected).
189
     *
190
     * @param string $user
191
     * @param array  ...$permissions
192
     * @return bool
193
     */
194 3
    public function addPermissionsForUser(string $user, array ...$permissions): bool
195
    {
196 3
        $rules = [];
197 3
        foreach ($permissions as $permission) {
198 3
            $rules[] = array_merge([$user], $permission);
199
        }
200 3
        return $this->addPolicies($rules);
201
    }
202
203
    /**
204
     * Deletes a permission for a user or role.
205
     * Returns false if the user or role does not have the permission (aka not affected).
206
     *
207
     * @param string $user
208
     * @param string ...$permission
209
     *
210
     * @return bool
211
     */
212 3
    public function deletePermissionForUser(string $user, string ...$permission): bool
213
    {
214 3
        $params = array_merge([$user], $permission);
215
216 3
        return $this->removePolicy(...$params);
217
    }
218
219
    /**
220
     * Deletes permissions for a user or role.
221
     * Returns false if the user or role does not have any permissions (aka not affected).
222
     *
223
     * @param string $user
224
     *
225
     * @return bool
226
     */
227 6
    public function deletePermissionsForUser(string $user): bool
228
    {
229 6
        $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX);
230 3
        return $this->removeFilteredPolicy($subIndex, $user);
231
    }
232
233
    /**
234
     * Gets permissions for a user or role.
235
     *
236
     * @param string $user
237
     * @param string ...$domain
238
     *
239
     * @return array
240
     */
241 12
    public function getPermissionsForUser(string $user, string ...$domain): array
242
    {
243 12
        $permission = [];
244 12
        foreach ($this->model['p'] as $ptype => $assertion) {
245 12
            $args = [];
246 12
            $subIndex = $this->model->getFieldIndex('p', Constants::SUBJECT_INDEX);
247 12
            $args[$subIndex] = $user;
248 12
            if (\count($domain) > 0) {
249 3
                $domIndex = $this->model->getFieldIndex($ptype, Constants::DOMAIN_INDEX);
250 3
                $args[$domIndex] = $domain[0];
251
            }
252 12
            $perm = $this->getFilteredPolicy(0, ...$args);
253 12
            $permission = array_merge($permission, $perm);
254
        }
255 12
        return $permission;
256
    }
257
258
    /**
259
     * Determines whether a user has a permission.
260
     *
261
     * @param string $user
262
     * @param string ...$permission
263
     *
264
     * @return bool
265
     */
266 3
    public function hasPermissionForUser(string $user, string ...$permission): bool
267
    {
268 3
        $params = array_merge([$user], $permission);
269
270 3
        return $this->hasPolicy($params);
271
    }
272
273
    /**
274
     * Gets implicit roles that a user has.
275
     * Compared to getRolesForUser(), this function retrieves indirect roles besides direct roles.
276
     * For example:
277
     * g, alice, role:admin
278
     * g, role:admin, role:user.
279
     *
280
     * getRolesForUser("alice") can only get: ["role:admin"].
0 ignored issues
show
Doc comment long description must start with a capital letter
Loading history...
281
     * But getImplicitRolesForUser("alice") will get: ["role:admin", "role:user"].
282
     *
283
     * @param string $name
284
     * @param string ...$domain
285
     *
286
     * @return array
287
     */
288 9
    public function getImplicitRolesForUser(string $name, string ...$domain): array
289
    {
290 9
        $res = [];
291 9
        $roleSet = [];
292 9
        $roleSet[$name] = true;
293
294 9
        $q = [];
295 9
        $q[] = $name;
296
297 9
        for (; count($q) > 0;) {
298 9
            $name = $q[0];
299 9
            $q = array_slice($q, 1);
300
301 9
            foreach ($this->rmMap as $rm) {
302 9
                $roles = $rm->getRoles($name, ...$domain);
303 9
                foreach ($roles as $r) {
304 9
                    if (!isset($roleSet[$r])) {
305 9
                        $res[] = $r;
306 9
                        $q[] = $r;
307 9
                        $roleSet[$r] = true;
308
                    }
309
                }
310
            }
311
        }
312
313 9
        return $res;
314
    }
315
316
    /**
317
     * GetImplicitUsersForRole gets implicit users for a role.
318
     *
319
     * @param string $name
320
     * @param string ...$domain
321
     * @return array
322
     */
323 6
    public function getImplicitUsersForRole(string $name, string ...$domain): array
324
    {
325 6
        $res = [];
326 6
        $roleSet = [];
327 6
        $roleSet[$name] = true;
328
329 6
        $q = [];
330 6
        $q[] = $name;
331
332 6
        for (; count($q) > 0;) {
333 6
            $name = $q[0];
334 6
            $q = array_slice($q, 1);
335
336 6
            foreach ($this->rmMap as $rm) {
337 6
                $roles = $rm->getUsers($name, ...$domain);
338 6
                foreach ($roles as $r) {
339 6
                    if (!isset($roleSet[$r])) {
340 6
                        $res[] = $r;
341 6
                        $q[] = $r;
342 6
                        $roleSet[$r] = true;
343
                    }
344
                }
345
            }
346
        }
347 6
        return $res;
348
    }
349
350
    /**
351
     * GetImplicitResourcesForUser returns all policies that user obtaining in domain
352
     *
353
     * @param string $user
354
     * @param string ...$domain
355
     * @return array
356
     */
357 3
    public function getImplicitResourcesForUser(string $user, string ...$domain): array
358
    {
359 3
        $permissions = $this->getImplicitPermissionsForUser($user, ...$domain);
360
        
361 3
        $res = [];
362 3
        foreach ($permissions as $permission) {
363 3
            if ($permission[0] == $user) {
364 3
                $res[] = $permission;
365 3
                continue;
366
            }
367 3
            $resLocal = [[$user]];
368 3
            $tokensLength = count($permission);
369 3
            $t = [[]];
370 3
            foreach (array_slice($permission, 1) as $token) {
371 3
                $tokens = $this->getImplicitUsersForRole($token, ...$domain);
372 3
                $tokens[] = $token;
373 3
                $t[] = $tokens;
374
            }
375
376 3
            for ($i = 1; $i < $tokensLength; $i++) {
377 3
                $n = [];
378 3
                foreach ($t[$i] as $tokens) {
379 3
                    foreach ($resLocal as $policy) {
380 3
                        $temp = [];
381 3
                        $temp = array_merge($temp, $policy);
382 3
                        $temp[] = $tokens;
383 3
                        $n[] = $temp;
384
                    }
385
                }
386 3
                $resLocal = $n;
387
            }
388 3
            $res = array_merge($res, $resLocal);
389
        }
390 3
        return $res;
391
    }
392
393
    /**
394
     * Gets implicit permissions for a user or role.
395
     * Compared to getPermissionsForUser(), this function retrieves permissions for inherited roles.
396
     * For example:
397
     * p, admin, data1, read
398
     * p, alice, data2, read
399
     * g, alice, admin.
400
     *
401
     * getPermissionsForUser("alice") can only get: [["alice", "data2", "read"]].
0 ignored issues
show
Doc comment long description must start with a capital letter
Loading history...
402
     * But getImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]].
403
     *
404
     * @param string $user
405
     * @param string ...$domain
406
     *
407
     * @return array
408
     * @throws CasbinException
409
     */
410 6
    public function getImplicitPermissionsForUser(string $user, string ...$domain): array
411
    {
412 6
        $roles = array_merge(
413 6
            [$user],
414 6
            $this->getImplicitRolesForUser($user, ...$domain)
415 2
        );
416
417 6
        $len = \count($domain);
418 6
        if ($len > 1) {
419
            throw new CasbinException('error: domain should be 1 parameter');
420
        }
421
422 6
        $res = [];
423 6
        foreach ($roles as $role) {
424 6
            if (1 == $len) {
425 3
                $permissions = $this->getPermissionsForUserInDomain($role, $domain[0]);
426
            } else {
427 6
                $permissions = $this->getPermissionsForUser($role);
428
            }
429
430 6
            $res = array_merge($res, $permissions);
431
        }
432
433 6
        return $res;
434
    }
435
436
    /**
437
     * Gets implicit users for a permission.
438
     * For example:
439
     * p, admin, data1, read
440
     * p, bob, data1, read
441
     * g, alice, admin
442
     * getImplicitUsersForPermission("data1", "read") will get: ["alice", "bob"].
443
     * Note: only users will be returned, roles (2nd arg in "g") will be excluded.
444
     *
445
     * @param string ...$permission
446
     *
447
     * @return array
448
     * @throws CasbinException
449
     */
450 3
    public function getImplicitUsersForPermission(string ...$permission): array
451
    {
452 3
        $pSubjects = $this->getAllSubjects();
453 3
        $gInherit = $this->model->getValuesForFieldInPolicyAllTypes("g", 1);
454 3
        $gSubjects = $this->model->getValuesForFieldInPolicyAllTypes("g", 0);
455
456 3
        $subjects = array_merge($pSubjects, $gSubjects);
457 3
        Util::ArrayRemoveDuplicates($subjects);
458
459 3
        $subjects = array_diff($subjects, $gInherit);
460
461 3
        $res = [];
462 3
        foreach ($subjects as $user) {
463 3
            $req = $permission;
464 3
            array_unshift($req, $user);
465 3
            $allowed = $this->enforce(...$req);
466
467 3
            if ($allowed) {
468 3
                $res[] = $user;
469
            }
470
        }
471
472 3
        return $res;
473
    }
474
475
    /**
476
     * GetAllUsersByDomain would get all users associated with the domain.
477
     *
478
     * @param string $domain
479
     * @return string[]
480
     */
481 3
    public function getAllUsersByDomain(string $domain): array
482
    {
483 3
        $m = [];
484 3
        $g = $this->model['g']['g'];
485 3
        $p = $this->model['p']['p'];
486 3
        $users = [];
487 3
        $index = $this->model->getFieldIndex('p', Constants::DOMAIN_INDEX);
488
489 1
        $getUser = function (int $index, array $policies, string $domain, array $m): array {
490 3
            if (count($policies) == 0 || count($policies[0]) <= $index) {
491
                return [];
492
            }
493 3
            $res = [];
494 3
            foreach ($policies as $policy) {
495 3
                $ok = isset($m[$policy[0]]);
496 3
                if ($policy[$index] == $domain && !$ok) {
497 3
                    $res[] = $policy[0];
498 3
                    $m[$policy[0]] = [];
499
                }
500
            }
501 3
            return $res;
502 3
        };
503
504 3
        $users = array_merge($users, $getUser(2, $g->policy, $domain, $m));
505 3
        $users = array_merge($users, $getUser($index, $p->policy, $domain, $m));
506 3
        return $users;
507
    }
508
509
    /**
510
     * Gets the users that has a role inside a domain. Add by Gordon.
511
     *
512
     * @param string $name
513
     * @param string $domain
514
     *
515
     * @return array
516
     */
517 3
    public function getUsersForRoleInDomain(string $name, string $domain): array
518
    {
519 3
        return $this->model['g']['g']->rm->getUsers($name, $domain);
520
    }
521
522
    /**
523
     * Gets the roles that a user has inside a domain.
524
     *
525
     * @param string $name
526
     * @param string $domain
527
     *
528
     * @return array
529
     */
530 3
    public function getRolesForUserInDomain(string $name, string $domain): array
531
    {
532 3
        return $this->model['g']['g']->rm->getRoles($name, $domain);
533
    }
534
535
    /**
536
     * Gets permissions for a user or role inside a domain.
537
     *
538
     * @param string $name
539
     * @param string $domain
540
     *
541
     * @return array
542
     */
543 6
    public function getPermissionsForUserInDomain(string $name, string $domain): array
544
    {
545 6
        return $this->getFilteredPolicy(0, $name, $domain);
546
    }
547
548
    /**
549
     * Adds a role for a user inside a domain.
550
     * returns false if the user already has the role (aka not affected).
551
     *
552
     * @param string $user
553
     * @param string $role
554
     * @param string $domain
555
     *
556
     * @return bool
557
     */
558 9
    public function addRoleForUserInDomain(string $user, string $role, string $domain): bool
559
    {
560 9
        return $this->addGroupingPolicy($user, $role, $domain);
561
    }
562
563
    /**
564
     * Deletes a role for a user inside a domain.
565
     * Returns false if the user does not have the role (aka not affected).
566
     *
567
     * @param string $user
568
     * @param string $role
569
     * @param string $domain
570
     *
571
     * @return bool
572
     */
573 6
    public function deleteRoleForUserInDomain(string $user, string $role, string $domain): bool
574
    {
575 6
        return $this->removeGroupingPolicy($user, $role, $domain);
576
    }
577
578
    /**
579
     * DeleteRolesForUserInDomain deletes all roles for a user inside a domain.
580
     * Returns false if the user does not have any roles (aka not affected).
581
     *
582
     * @param string $user
583
     * @param string $domain
584
     *
585
     * @return bool
586
     */
587 3
    public function deleteRolesForUserInDomain(string $user, string $domain): bool
588
    {
589 3
        $roles = $this->model['g']['g']->rm->getRoles($user, $domain);
590
591 3
        $rules = [];
592 3
        foreach ($roles as $role) {
593 3
            $rules[] = [$user, $role, $domain];
594
        }
595
596 3
        return $this->removeGroupingPolicies($rules);
597
    }
598
599
    /**
600
     * DeleteAllUsersByDomain would delete all users associated with the domain.
601
     *
602
     * @param string $domain
603
     * @return bool
604
     */
605 6
    public function deleteAllUsersByDomain(string $domain): bool
606
    {
607 6
        $g = $this->model['g']['g'];
608 6
        $p = $this->model['p']['p'];
609 6
        $index = $this->model->getFieldIndex('p', Constants::DOMAIN_INDEX);
610
611 2
        $getUser = function (int $index, array $policies, string $domain): array {
612 6
            if (count($policies) == 0 || count($policies[0]) <= $index) {
613
                return [];
614
            }
615 6
            $res = [];
616 6
            foreach ($policies as $policy) {
617 6
                if ($policy[$index] == $domain) {
618 6
                    $res[] = $policy;
619
                }
620
            }
621 6
            return $res;
622 6
        };
623
624 6
        $users = $getUser(2, $g->policy, $domain);
625 6
        $this->removeGroupingPolicies($users);
626 6
        $users = $getUser($index, $p->policy, $domain);
627 6
        $this->removePolicies($users);
628 6
        return true;
629
    }
630
631
    /**
632
     * DeleteDomains would delete all associated users and roles.
633
     * It would delete all domains if parameter is not provided.
634
     *
635
     * @param string ...$domains
636
     * @return bool
637
     */
638 3
    public function deleteDomains(string ...$domains): bool
639
    {
640 3
        if (count($domains) == 0) {
641 3
            $this->clearPolicy();
642 3
            return true;
643
        }
644 3
        foreach ($domains as $domain) {
645 3
            $this->deleteAllUsersByDomain($domain);
646
        }
647 3
        return true;
648
    }
649
}
650