These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Kunstmaan\AdminBundle\Helper\Security\Acl\Permission; |
||
4 | |||
5 | use Doctrine\ORM\EntityManager; |
||
6 | use Kunstmaan\AdminBundle\Entity\AbstractEntity; |
||
7 | use Kunstmaan\AdminBundle\Entity\AclChangeset; |
||
8 | use Kunstmaan\AdminBundle\Entity\Role; |
||
9 | use Kunstmaan\UtilitiesBundle\Helper\Shell\Shell; |
||
10 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
||
11 | use Symfony\Component\HttpFoundation\Request; |
||
12 | use Symfony\Component\HttpKernel\KernelInterface; |
||
13 | use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; |
||
14 | use Symfony\Component\Security\Acl\Exception\AclNotFoundException; |
||
15 | use Symfony\Component\Security\Acl\Model\AclInterface; |
||
16 | use Symfony\Component\Security\Acl\Model\AclProviderInterface; |
||
17 | use Symfony\Component\Security\Acl\Model\AuditableEntryInterface; |
||
18 | use Symfony\Component\Security\Acl\Model\MutableAclInterface; |
||
19 | use Symfony\Component\Security\Acl\Model\MutableAclProviderInterface; |
||
20 | use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface; |
||
21 | use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; |
||
22 | use Symfony\Component\Security\Core\Role\RoleInterface; |
||
23 | use Symfony\Component\Security\Core\User\UserInterface; |
||
24 | |||
25 | /** |
||
26 | * Helper to manage the permissions on a certain entity |
||
27 | */ |
||
28 | class PermissionAdmin |
||
29 | { |
||
30 | const ADD = 'ADD'; |
||
31 | const DELETE = 'DEL'; |
||
32 | |||
33 | /** |
||
34 | * @var AbstractEntity |
||
35 | */ |
||
36 | protected $resource = null; |
||
37 | |||
38 | /** |
||
39 | * @var EntityManager |
||
40 | */ |
||
41 | protected $em = null; |
||
42 | |||
43 | /** |
||
44 | * @var TokenStorageInterface |
||
45 | */ |
||
46 | protected $tokenStorage = null; |
||
47 | |||
48 | /** |
||
49 | * @var MutableAclProviderInterface |
||
50 | */ |
||
51 | protected $aclProvider = null; |
||
52 | |||
53 | /** |
||
54 | * @var ObjectIdentityRetrievalStrategyInterface |
||
55 | */ |
||
56 | protected $oidRetrievalStrategy = null; |
||
57 | |||
58 | /** |
||
59 | * @var PermissionMap |
||
60 | */ |
||
61 | protected $permissionMap = null; |
||
62 | |||
63 | /** |
||
64 | * @var array |
||
65 | */ |
||
66 | protected $permissions = null; |
||
67 | |||
68 | /** |
||
69 | * @var EventDispatcherInterface |
||
70 | */ |
||
71 | protected $eventDispatcher = null; |
||
72 | |||
73 | /** |
||
74 | * @var KernelInterface |
||
75 | */ |
||
76 | protected $kernel; |
||
77 | |||
78 | /** |
||
79 | * @var Shell |
||
80 | */ |
||
81 | protected $shellHelper; |
||
82 | |||
83 | /** |
||
84 | * Constructor |
||
85 | * |
||
86 | * @param EntityManager $em The EntityManager |
||
87 | * @param TokenStorageInterface $tokenStorage The token storage |
||
88 | * @param AclProviderInterface $aclProvider The ACL provider |
||
89 | * @param ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy The object retrieval strategy |
||
90 | * @param EventDispatcherInterface $eventDispatcher The event dispatcher |
||
91 | * @param Shell $shellHelper The shell helper |
||
92 | * @param KernelInterface $kernel The kernel |
||
93 | */ |
||
94 | public function __construct( |
||
95 | EntityManager $em, |
||
96 | TokenStorageInterface $tokenStorage, |
||
97 | AclProviderInterface $aclProvider, |
||
98 | ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, |
||
99 | EventDispatcherInterface $eventDispatcher, |
||
100 | Shell $shellHelper, |
||
101 | KernelInterface $kernel |
||
102 | ) { |
||
103 | $this->em = $em; |
||
104 | $this->tokenStorage = $tokenStorage; |
||
105 | $this->aclProvider = $aclProvider; |
||
106 | $this->oidRetrievalStrategy = $oidRetrievalStrategy; |
||
107 | $this->eventDispatcher = $eventDispatcher; |
||
108 | $this->shellHelper = $shellHelper; |
||
109 | $this->kernel = $kernel; |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * Initialize permission admin with specified entity. |
||
114 | * |
||
115 | * @param AbstractEntity $resource The object which has the permissions |
||
116 | * @param PermissionMapInterface $permissionMap The permission map to use |
||
117 | */ |
||
118 | public function initialize(AbstractEntity $resource, PermissionMapInterface $permissionMap) |
||
119 | { |
||
120 | $this->resource = $resource; |
||
121 | $this->permissionMap = $permissionMap; |
||
122 | $this->permissions = array(); |
||
123 | |||
124 | // Init permissions |
||
125 | try { |
||
126 | $objectIdentity = $this->oidRetrievalStrategy->getObjectIdentity($this->resource); |
||
127 | /* @var $acl AclInterface */ |
||
128 | $acl = $this->aclProvider->findAcl($objectIdentity); |
||
129 | $objectAces = $acl->getObjectAces(); |
||
130 | /* @var $ace AuditableEntryInterface */ |
||
131 | View Code Duplication | foreach ($objectAces as $ace) { |
|
132 | $securityIdentity = $ace->getSecurityIdentity(); |
||
133 | if ($securityIdentity instanceof RoleSecurityIdentity) { |
||
134 | $this->permissions[$securityIdentity->getRole()] = new MaskBuilder($ace->getMask()); |
||
135 | } |
||
136 | } |
||
137 | } catch (AclNotFoundException $e) { |
||
138 | // No Acl found - do nothing (or should we initialize with default values here?) |
||
139 | } |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * Get permissions. |
||
144 | * |
||
145 | * @return MaskBuilder[] |
||
146 | */ |
||
147 | public function getPermissions() |
||
148 | { |
||
149 | return $this->permissions; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Get permission for specified role. |
||
154 | * |
||
155 | * @param RoleInterface|string $role |
||
156 | * |
||
157 | * @return MaskBuilder|null |
||
158 | */ |
||
159 | public function getPermission($role) |
||
160 | { |
||
161 | if ($role instanceof RoleInterface || $role instanceof \Symfony\Component\Security\Core\Role\Role) { |
||
0 ignored issues
–
show
|
|||
162 | $role = $role->getRole(); |
||
163 | } |
||
164 | if (isset($this->permissions[$role])) { |
||
165 | return $this->permissions[$role]; |
||
166 | } |
||
167 | |||
168 | return null; |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * Get all roles. |
||
173 | * |
||
174 | * @return Role[] |
||
175 | */ |
||
176 | public function getAllRoles() |
||
177 | { |
||
178 | return $this->em->getRepository('KunstmaanAdminBundle:Role')->findAll(); |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Get all manageable roles for pages |
||
183 | * |
||
184 | * @return Role[] |
||
185 | */ |
||
186 | public function getManageableRolesForPages() |
||
187 | { |
||
188 | $roles = $this->em->getRepository('KunstmaanAdminBundle:Role')->findAll(); |
||
189 | |||
190 | if (($token = $this->tokenStorage->getToken()) && ($user = $token->getUser())) { |
||
191 | if ($user && !$user->isSuperAdmin() && ($superAdminRole = array_keys($roles, 'ROLE_SUPER_ADMIN'))) { |
||
192 | $superAdminRole = current($superAdminRole); |
||
193 | unset($roles[$superAdminRole]); |
||
194 | } |
||
195 | } |
||
196 | |||
197 | return $roles; |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * Get possible permissions. |
||
202 | * |
||
203 | * @return array |
||
204 | */ |
||
205 | public function getPossiblePermissions() |
||
206 | { |
||
207 | return $this->permissionMap->getPossiblePermissions(); |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * Handle form entry of permission changes. |
||
212 | * |
||
213 | * @param Request $request |
||
214 | * |
||
215 | * @return bool |
||
216 | */ |
||
217 | public function bindRequest(Request $request) |
||
218 | { |
||
219 | $changes = $request->request->get('permission-hidden-fields'); |
||
220 | |||
221 | if (empty($changes)) { |
||
222 | return true; |
||
223 | } |
||
224 | |||
225 | // Just apply the changes to the current node (non recursively) |
||
226 | $this->applyAclChangeset($this->resource, $changes, false); |
||
227 | |||
228 | // Apply recursively (on request) |
||
229 | $applyRecursive = $request->request->get('applyRecursive'); |
||
230 | if ($applyRecursive) { |
||
231 | // Serialize changes & store them in DB |
||
232 | $user = $this->tokenStorage->getToken()->getUser(); |
||
233 | $this->createAclChangeSet($this->resource, $changes, $user); |
||
234 | |||
235 | $cmd = 'php ' . $this->kernel->getRootDir() . '/../bin/console kuma:acl:apply'; |
||
0 ignored issues
–
show
The method
Symfony\Component\HttpKe...Interface::getRootDir() has been deprecated with message: since Symfony 4.2
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.
Loading history...
|
|||
236 | $cmd .= ' --env=' . $this->kernel->getEnvironment(); |
||
237 | |||
238 | $this->shellHelper->runInBackground($cmd); |
||
239 | } |
||
240 | |||
241 | return true; |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * Create a new ACL changeset. |
||
246 | * |
||
247 | * @param AbstractEntity $entity The entity |
||
248 | * @param array $changes The changes |
||
249 | * @param UserInterface $user The user |
||
250 | * |
||
251 | * @return AclChangeset |
||
252 | */ |
||
253 | public function createAclChangeSet(AbstractEntity $entity, $changes, UserInterface $user) |
||
254 | { |
||
255 | $aclChangeset = new AclChangeset(); |
||
256 | $aclChangeset->setRef($entity); |
||
257 | $aclChangeset->setChangeset($changes); |
||
258 | /* @var $user BaseUser */ |
||
259 | $aclChangeset->setUser($user); |
||
260 | $this->em->persist($aclChangeset); |
||
261 | $this->em->flush(); |
||
262 | |||
263 | return $aclChangeset; |
||
264 | } |
||
265 | |||
266 | /** |
||
267 | * Apply the specified ACL changeset. |
||
268 | * |
||
269 | * @param AbstractEntity $entity The entity |
||
270 | * @param array $changeset The changeset |
||
271 | * @param bool $recursive The recursive |
||
272 | */ |
||
273 | public function applyAclChangeset(AbstractEntity $entity, $changeset, $recursive = true) |
||
274 | { |
||
275 | if ($recursive) { |
||
276 | if (!method_exists($entity, 'getChildren')) { |
||
277 | return; |
||
278 | } |
||
279 | |||
280 | // Iterate over children and apply recursively |
||
281 | /* @noinspection PhpUndefinedMethodInspection */ |
||
282 | foreach ($entity->getChildren() as $child) { |
||
283 | $this->applyAclChangeset($child, $changeset); |
||
284 | } |
||
285 | } |
||
286 | |||
287 | // Apply ACL modifications to node |
||
288 | $objectIdentity = $this->oidRetrievalStrategy->getObjectIdentity($entity); |
||
289 | |||
290 | try { |
||
291 | /* @var $acl MutableAclInterface */ |
||
292 | $acl = $this->aclProvider->findAcl($objectIdentity); |
||
293 | } catch (AclNotFoundException $e) { |
||
294 | /* @var $acl MutableAclInterface */ |
||
295 | $acl = $this->aclProvider->createAcl($objectIdentity); |
||
296 | } |
||
297 | |||
298 | // Process permissions in changeset |
||
299 | foreach ($changeset as $role => $roleChanges) { |
||
300 | $index = $this->getObjectAceIndex($acl, $role); |
||
301 | $mask = 0; |
||
302 | if (false !== $index) { |
||
303 | $mask = $this->getMaskAtIndex($acl, $index); |
||
304 | } |
||
305 | foreach ($roleChanges as $type => $permissions) { |
||
306 | $maskChange = new MaskBuilder(); |
||
307 | foreach ($permissions as $permission) { |
||
308 | $maskChange->add($permission); |
||
309 | } |
||
310 | switch ($type) { |
||
311 | case self::ADD: |
||
312 | $mask = $mask | $maskChange->get(); |
||
313 | |||
314 | break; |
||
315 | case self::DELETE: |
||
316 | $mask = $mask & ~$maskChange->get(); |
||
317 | |||
318 | break; |
||
319 | } |
||
320 | } |
||
321 | if (false !== $index) { |
||
322 | $acl->updateObjectAce($index, $mask); |
||
323 | } else { |
||
324 | $securityIdentity = new RoleSecurityIdentity($role); |
||
325 | $acl->insertObjectAce($securityIdentity, $mask); |
||
326 | } |
||
327 | } |
||
328 | $this->aclProvider->updateAcl($acl); |
||
329 | } |
||
330 | |||
331 | /** |
||
332 | * Get current object ACE index for specified role. |
||
333 | * |
||
334 | * @param AclInterface $acl The AclInterface |
||
335 | * @param string $role The role |
||
336 | * |
||
337 | * @return bool|int |
||
338 | */ |
||
339 | View Code Duplication | private function getObjectAceIndex(AclInterface $acl, $role) |
|
340 | { |
||
341 | $objectAces = $acl->getObjectAces(); |
||
342 | /* @var $ace AuditableEntryInterface */ |
||
343 | foreach ($objectAces as $index => $ace) { |
||
344 | $securityIdentity = $ace->getSecurityIdentity(); |
||
345 | if ($securityIdentity instanceof RoleSecurityIdentity) { |
||
346 | if ($securityIdentity->getRole() == $role) { |
||
347 | return $index; |
||
348 | } |
||
349 | } |
||
350 | } |
||
351 | |||
352 | return false; |
||
353 | } |
||
354 | |||
355 | /** |
||
356 | * Get object ACE mask at specified index. |
||
357 | * |
||
358 | * @param AclInterface $acl The acl interface |
||
359 | * @param int $index The index |
||
360 | * |
||
361 | * @return bool|int |
||
362 | */ |
||
363 | View Code Duplication | private function getMaskAtIndex(AclInterface $acl, $index) |
|
364 | { |
||
365 | $objectAces = $acl->getObjectAces(); |
||
366 | /* @var $ace AuditableEntryInterface */ |
||
367 | $ace = $objectAces[$index]; |
||
368 | $securityIdentity = $ace->getSecurityIdentity(); |
||
369 | if ($securityIdentity instanceof RoleSecurityIdentity) { |
||
370 | return $ace->getMask(); |
||
371 | } |
||
372 | |||
373 | return false; |
||
374 | } |
||
375 | } |
||
376 |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.