1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | namespace Ecodev\Felix\Acl; |
||
6 | |||
7 | use Doctrine\Common\Util\ClassUtils; |
||
8 | use Ecodev\Felix\Model\CurrentUser; |
||
9 | use Ecodev\Felix\Model\Model; |
||
10 | |||
11 | class Acl extends \Laminas\Permissions\Acl\Acl |
||
12 | { |
||
13 | /** |
||
14 | * The message explaining the last denial. |
||
15 | */ |
||
16 | private ?string $message = null; |
||
17 | |||
18 | /** |
||
19 | * @var string[] |
||
20 | */ |
||
21 | private array $reasons = []; |
||
22 | |||
23 | 2 | protected function createModelResource(string $class): ModelResource |
|
1 ignored issue
–
show
|
|||
24 | { |
||
25 | 2 | $resource = new ModelResource($class); |
|
26 | 2 | $this->addResource($resource); |
|
27 | |||
28 | 2 | return $resource; |
|
29 | } |
||
30 | |||
31 | /** |
||
32 | * Return whether the current user is allowed to do something. |
||
33 | * |
||
34 | * This should be the main method to do all ACL checks. |
||
35 | */ |
||
36 | 2 | public function isCurrentUserAllowed(Model $model, string $privilege): bool |
|
37 | { |
||
38 | 2 | $resource = new ModelResource($this->getClass($model), $model); |
|
39 | 2 | $role = $this->getCurrentRole(); |
|
40 | 2 | $this->reasons = []; |
|
41 | |||
42 | 2 | $isAllowed = $this->isAllowed($role, $resource, $privilege); |
|
43 | |||
44 | 2 | $this->message = $this->buildMessage($resource, $privilege, $role, $isAllowed); |
|
45 | |||
46 | 2 | return $isAllowed; |
|
47 | } |
||
48 | |||
49 | /** |
||
50 | * Set the reason for rejection that will be shown to end-user. |
||
51 | * |
||
52 | * This method always return false for usage convenience and should be used by all assertions, |
||
53 | * instead of only return false themselves. |
||
54 | * |
||
55 | * @return false |
||
56 | */ |
||
57 | 2 | public function reject(string $reason): bool |
|
58 | { |
||
59 | 2 | $this->reasons[] = $reason; |
|
60 | |||
61 | 2 | return false; |
|
62 | } |
||
63 | |||
64 | 2 | private function getClass(Model $resource): string |
|
65 | { |
||
66 | 2 | return ClassUtils::getRealClass($resource::class); |
|
67 | } |
||
68 | |||
69 | 2 | private function getCurrentRole(): string |
|
70 | { |
||
71 | 2 | $user = CurrentUser::get(); |
|
72 | 2 | if (!$user) { |
|
73 | 1 | return 'anonymous'; |
|
74 | } |
||
75 | |||
76 | 2 | return $user->getRole(); |
|
77 | } |
||
78 | |||
79 | 2 | private function buildMessage(ModelResource $resource, ?string $privilege, string $role, bool $isAllowed): ?string |
|
80 | { |
||
81 | 2 | if ($isAllowed) { |
|
82 | return null; |
||
83 | } |
||
84 | |||
85 | 2 | $resource = $resource->getName(); |
|
86 | |||
87 | 2 | $user = CurrentUser::get(); |
|
88 | 2 | $userName = $user ? 'User "' . $user->getLogin() . '"' : 'Non-logged user'; |
|
89 | 2 | $privilege ??= 'NULL'; |
|
90 | |||
91 | 2 | $message = "$userName with role $role is not allowed on resource \"$resource\" with privilege \"$privilege\""; |
|
92 | |||
93 | 2 | $count = count($this->reasons); |
|
94 | 2 | if ($count === 1) { |
|
95 | 1 | $message .= ' because ' . $this->reasons[0]; |
|
96 | 2 | } elseif ($count) { |
|
97 | 1 | $list = array_map(fn ($reason) => '- ' . $reason, $this->reasons); |
|
98 | 1 | $message .= ' because:' . PHP_EOL . PHP_EOL . implode(PHP_EOL, $list); |
|
99 | } |
||
100 | |||
101 | 2 | return $message; |
|
102 | } |
||
103 | |||
104 | /** |
||
105 | * Returns the message explaining the last denial, if any. |
||
106 | */ |
||
107 | 2 | public function getLastDenialMessage(): ?string |
|
108 | { |
||
109 | 2 | return $this->message; |
|
110 | } |
||
111 | } |
||
112 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths