This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | /* |
||
6 | * This file is part of the zibios/sharep. |
||
7 | * |
||
8 | * (c) Zbigniew Ślązak |
||
9 | */ |
||
10 | |||
11 | namespace App\Voter\Configuration; |
||
12 | |||
13 | use App\Entity\Access\User; |
||
14 | use App\Entity\GetMemberInterface; |
||
15 | use App\Entity\GetRoleInterface; |
||
16 | use App\Entity\Parking\Availability; |
||
17 | use App\Entity\Parking\AvailabilityBreak; |
||
18 | use App\Entity\Parking\Member; |
||
19 | use App\Entity\Parking\MemberNeed; |
||
20 | use App\Entity\Parking\Membership; |
||
21 | use App\Entity\Parking\Reservation; |
||
22 | use App\Enum\Functional\PermissionEnum; |
||
23 | use App\Service\Functional\ConfigurationService; |
||
24 | use Psr\Log\LoggerInterface; |
||
25 | use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; |
||
26 | use Symfony\Component\Security\Core\Authorization\Voter\Voter; |
||
27 | |||
28 | class PermissionVoter extends Voter |
||
29 | { |
||
30 | private const TYPE_BOOLEAN = 'TYPE_BOOLEAN'; |
||
31 | private const TYPE_ROLE = 'TYPE_ROLE'; |
||
32 | private const TYPE_MEMBER_ROLE = 'TYPE_MEMBER_ROLE'; |
||
33 | |||
34 | private $attributeMap = [ |
||
35 | PermissionEnum::PARKING_AVAILABILITY_CREATE => [self::TYPE_BOOLEAN, Availability::class, false], |
||
36 | PermissionEnum::PARKING_AVAILABILITY_READ => [self::TYPE_BOOLEAN, Availability::class, true], |
||
37 | PermissionEnum::PARKING_AVAILABILITY_UPDATE => [self::TYPE_BOOLEAN, Availability::class, false], |
||
38 | PermissionEnum::PARKING_AVAILABILITY_DELETE => [self::TYPE_BOOLEAN, Availability::class, false], |
||
39 | |||
40 | PermissionEnum::PARKING_AVAILABILITY_BREAK_CREATE => [self::TYPE_BOOLEAN, AvailabilityBreak::class, false], |
||
41 | PermissionEnum::PARKING_AVAILABILITY_BREAK_READ => [self::TYPE_BOOLEAN, AvailabilityBreak::class, true], |
||
42 | PermissionEnum::PARKING_AVAILABILITY_BREAK_UPDATE => [self::TYPE_BOOLEAN, AvailabilityBreak::class, false], |
||
43 | PermissionEnum::PARKING_AVAILABILITY_BREAK_DELETE => [self::TYPE_BOOLEAN, AvailabilityBreak::class, false], |
||
44 | |||
45 | PermissionEnum::PARKING_MEMBER_CREATE => [self::TYPE_ROLE, Member::class, false], |
||
46 | PermissionEnum::PARKING_MEMBER_READ => [self::TYPE_BOOLEAN, Member::class, true], |
||
47 | PermissionEnum::PARKING_MEMBER_UPDATE => [self::TYPE_ROLE, Member::class, false], |
||
48 | PermissionEnum::PARKING_MEMBER_DELETE => [self::TYPE_ROLE, Member::class, false], |
||
49 | |||
50 | PermissionEnum::PARKING_MEMBER_NEED_CREATE => [self::TYPE_MEMBER_ROLE, MemberNeed::class, false], |
||
51 | PermissionEnum::PARKING_MEMBER_NEED_READ => [self::TYPE_BOOLEAN, MemberNeed::class, true], |
||
52 | PermissionEnum::PARKING_MEMBER_NEED_UPDATE => [self::TYPE_MEMBER_ROLE, MemberNeed::class, false], |
||
53 | PermissionEnum::PARKING_MEMBER_NEED_DELETE => [self::TYPE_MEMBER_ROLE, MemberNeed::class, false], |
||
54 | |||
55 | PermissionEnum::PARKING_MEMBERSHIP_CREATE => [self::TYPE_MEMBER_ROLE, Membership::class, false], |
||
56 | PermissionEnum::PARKING_MEMBERSHIP_READ => [self::TYPE_BOOLEAN, Membership::class, true], |
||
57 | PermissionEnum::PARKING_MEMBERSHIP_UPDATE => [self::TYPE_MEMBER_ROLE, Membership::class, false], |
||
58 | PermissionEnum::PARKING_MEMBERSHIP_DELETE => [self::TYPE_MEMBER_ROLE, Membership::class, false], |
||
59 | |||
60 | PermissionEnum::PARKING_RESERVATION_CREATE => [self::TYPE_MEMBER_ROLE, Reservation::class, false], |
||
61 | PermissionEnum::PARKING_RESERVATION_READ => [self::TYPE_BOOLEAN, Reservation::class, true], |
||
62 | PermissionEnum::PARKING_RESERVATION_UPDATE => [self::TYPE_MEMBER_ROLE, Reservation::class, false], |
||
63 | PermissionEnum::PARKING_RESERVATION_DELETE => [self::TYPE_MEMBER_ROLE, Reservation::class, false], |
||
64 | ]; |
||
65 | |||
66 | /** @var ConfigurationService */ |
||
67 | private $configurationService; |
||
68 | /** @var LoggerInterface */ |
||
69 | private $logger; |
||
70 | |||
71 | //------------------------------------------------------------------------------------------------------------------ |
||
72 | |||
73 | 20 | public function __construct(ConfigurationService $configurationService, LoggerInterface $logger) |
|
74 | { |
||
75 | 20 | $this->configurationService = $configurationService; |
|
76 | 20 | $this->logger = $logger; |
|
77 | 20 | } |
|
78 | |||
79 | //------------------------------------------------------------------------------------------------------------------ |
||
80 | |||
81 | /** |
||
82 | * @param string $attribute |
||
83 | * @param object|mixed $subject |
||
84 | */ |
||
85 | 20 | protected function supports($attribute, $subject): bool |
|
86 | { |
||
87 | 20 | $this->logger->debug(sprintf( |
|
88 | 20 | 'ConfigurationPermissionVoter Supports %s - %s', |
|
89 | $attribute, |
||
90 | 20 | $subject ? \get_class($subject) : 'null' |
|
91 | )); |
||
92 | 20 | if (!$this->isAttributeSupported($attribute)) { |
|
93 | 7 | return false; |
|
94 | } |
||
95 | 16 | $configuration = $this->getAttributeConfiguration($attribute); |
|
96 | |||
97 | 16 | if (null === $subject && $configuration->isNullable()) { |
|
98 | 4 | return true; |
|
99 | } |
||
100 | |||
101 | 15 | $class = $configuration->getClass(); |
|
102 | 15 | if (!$subject instanceof $class) { |
|
103 | return false; |
||
104 | } |
||
105 | |||
106 | 15 | return true; |
|
107 | } |
||
108 | |||
109 | /** |
||
110 | * @param string|mixed $attribute |
||
111 | * @param object|mixed $subject |
||
112 | */ |
||
113 | 16 | protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool |
|
114 | { |
||
115 | 16 | $this->assertAttributeAndSubject($attribute, $subject); |
|
116 | 16 | $loggedInMember = $this->getLoggedInMember($token); |
|
117 | 16 | if (!$loggedInMember instanceof Member) { |
|
118 | return false; |
||
119 | } |
||
120 | 16 | $configuration = $this->getAttributeConfiguration($attribute); |
|
121 | |||
122 | 16 | switch ($configuration->getType()) { |
|
123 | 16 | case self::TYPE_BOOLEAN: |
|
124 | 8 | $subjectRole = 'null'; |
|
125 | 8 | $isValid = $this->voteOnAttributeBoolean($attribute, $loggedInMember); |
|
126 | 8 | break; |
|
127 | 11 | case self::TYPE_ROLE: |
|
128 | 10 | $this->assertSubjectHasRole($subject); |
|
129 | /** @var GetRoleInterface $subject */ |
||
130 | 10 | $subjectRole = $subject->getRole()->getValue(); |
|
131 | 10 | $isValid = $this->voteOnAttributeRole($attribute, $subject, $loggedInMember); |
|
132 | 10 | break; |
|
133 | 1 | case self::TYPE_MEMBER_ROLE: |
|
134 | 1 | $this->assertSubjectHasMember($subject); |
|
135 | /** @var GetMemberInterface $subject */ |
||
136 | 1 | $subjectRole = $subject->getmember()->getRole()->getValue(); |
|
137 | 1 | $isValid = $this->voteOnAttributeMemberRole($attribute, $subject, $loggedInMember); |
|
138 | 1 | break; |
|
139 | default: |
||
140 | throw new \LogicException('Unexpected type'); |
||
141 | } |
||
142 | |||
143 | 16 | $this->logger->debug(sprintf( |
|
144 | 16 | 'ConfigurationPermissionVoter Result a:%s - c:%s - r:%s - sr:%s - v:%s', |
|
145 | $attribute, |
||
146 | 16 | $subject ? \get_class($subject) : 'null', |
|
147 | 16 | $loggedInMember->getRole()->getValue(), |
|
148 | $subjectRole, |
||
149 | 16 | (int) $isValid |
|
150 | )); |
||
151 | |||
152 | 16 | return $isValid; |
|
153 | } |
||
154 | |||
155 | //------------------------------------------------------------------------------------------------------------------ |
||
156 | |||
157 | 20 | private function isAttributeSupported(string $attribute): bool |
|
158 | { |
||
159 | 20 | return \array_key_exists($attribute, $this->attributeMap); |
|
160 | } |
||
161 | |||
162 | 16 | private function getAttributeConfiguration(string $attribute): PermissionData |
|
163 | { |
||
164 | 16 | if ($this->isAttributeSupported($attribute)) { |
|
165 | 16 | $configuration = $this->attributeMap[$attribute]; |
|
166 | |||
167 | 16 | return new PermissionData(...$configuration); |
|
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
168 | } |
||
169 | |||
170 | throw new \InvalidArgumentException('Attribute not supported'); |
||
171 | } |
||
172 | |||
173 | 16 | private function getLoggedInMember(TokenInterface $token): ?Member |
|
174 | { |
||
175 | 16 | $loggedInUser = $token->getUser(); |
|
176 | 16 | if (!$loggedInUser instanceof User) { |
|
177 | return null; |
||
178 | } |
||
179 | 16 | $loggedInMember = $loggedInUser->getMember(); |
|
180 | 16 | if (!$loggedInMember instanceof Member) { |
|
181 | return null; |
||
182 | } |
||
183 | |||
184 | 16 | return $loggedInMember; |
|
185 | } |
||
186 | |||
187 | /** |
||
188 | * @param string|mixed $attribute |
||
189 | * @param object|mixed $subject |
||
190 | */ |
||
191 | 16 | private function assertAttributeAndSubject($attribute, $subject): void |
|
192 | { |
||
193 | 16 | if (!$this->supports($attribute, $subject)) { |
|
194 | throw new \LogicException('Invalid attribute or subject'); |
||
195 | } |
||
196 | 16 | } |
|
197 | |||
198 | 8 | protected function voteOnAttributeBoolean(string $attribute, Member $loggedInMember): bool |
|
0 ignored issues
–
show
function voteOnAttributeBoolean() does not seem to conform to the naming convention (^(?:is|has|should|may|supports) ).
This check examines a number of code elements and verifies that they conform to the given naming conventions. You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods. ![]() |
|||
199 | { |
||
200 | 8 | return $this->configurationService |
|
201 | 8 | ->hasPermissionBoolean( |
|
202 | 8 | new PermissionEnum($attribute), |
|
203 | 8 | $loggedInMember->getRole() |
|
204 | ); |
||
205 | } |
||
206 | |||
207 | 10 | protected function voteOnAttributeRole(string $attribute, GetRoleInterface $subject, Member $loggedInMember): bool |
|
0 ignored issues
–
show
function voteOnAttributeRole() does not seem to conform to the naming convention (^(?:is|has|should|may|supports) ).
This check examines a number of code elements and verifies that they conform to the given naming conventions. You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods. ![]() |
|||
208 | { |
||
209 | 10 | return $this->configurationService |
|
210 | 10 | ->hasPermissionRole( |
|
211 | 10 | new PermissionEnum($attribute), |
|
212 | 10 | $loggedInMember->getRole(), |
|
213 | 10 | $subject->getRole() |
|
214 | ); |
||
215 | } |
||
216 | |||
217 | 1 | protected function voteOnAttributeMemberRole(string $attribute, GetMemberInterface $subject, Member $loggedInMember): bool |
|
0 ignored issues
–
show
function voteOnAttributeMemberRole() does not seem to conform to the naming convention (^(?:is|has|should|may|supports) ).
This check examines a number of code elements and verifies that they conform to the given naming conventions. You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods. ![]() |
|||
218 | { |
||
219 | 1 | $hasPermissionRole = $this->configurationService |
|
220 | 1 | ->hasPermissionRole( |
|
221 | 1 | new PermissionEnum($attribute), |
|
222 | 1 | $loggedInMember->getRole(), |
|
223 | 1 | $subject->getMember()->getRole() |
|
224 | ); |
||
225 | 1 | $hasPermissionSelfOnly = $this->configurationService |
|
226 | 1 | ->hasPermissionSelfOnly( |
|
227 | 1 | new PermissionEnum($attribute), |
|
228 | 1 | $loggedInMember->getRole() |
|
229 | ); |
||
230 | 1 | $hasSubjectOwnership = ($loggedInMember->getId() === $subject->getMember()->getId()); |
|
231 | |||
232 | 1 | return $hasPermissionRole || ($hasPermissionSelfOnly && $hasSubjectOwnership); |
|
233 | } |
||
234 | |||
235 | /** |
||
236 | * @param object|mixed $subject |
||
237 | */ |
||
238 | 10 | private function assertSubjectHasRole($subject): void |
|
239 | { |
||
240 | 10 | if (!$subject instanceof GetRoleInterface) { |
|
241 | throw new \LogicException('Subject should implement GetRoleInterface'); |
||
242 | } |
||
243 | 10 | } |
|
244 | |||
245 | /** |
||
246 | * @param object|mixed $subject |
||
247 | */ |
||
248 | 1 | private function assertSubjectHasMember($subject): void |
|
249 | { |
||
250 | 1 | if (!$subject instanceof GetMemberInterface) { |
|
251 | throw new \LogicException('Subject should implement GetMemberInterface'); |
||
252 | } |
||
253 | 1 | } |
|
254 | } |
||
255 |