From f5039cc36f325347ce39377862639a7e764285e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Apr 2018 12:03:47 +0200 Subject: [PATCH] add UserPickerType --- Form/Type/UserPickerType.php | 12 ++++- Resources/config/services.yml | 1 + .../Authorization/AuthorizationHelper.php | 45 ++++++++++++++++++- .../Authorization/AuthorizationHelperTest.php | 16 +++++++ 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/Form/Type/UserPickerType.php b/Form/Type/UserPickerType.php index 9cade1ad2..fd7600bf9 100644 --- a/Form/Type/UserPickerType.php +++ b/Form/Type/UserPickerType.php @@ -25,6 +25,8 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Chill\MainBundle\Entity\User; +use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; +use Symfony\Component\Security\Core\Role\Role; /** @@ -96,8 +98,14 @@ class UserPickerType extends AbstractType ->join('ug.permissionsGroup', 'pg') // role constraints ->join('pg.roleScopes', 'roleScope') - ->andWhere($qb->expr()->eq('roleScope.role', ':role')) - ->setParameter('role', $options['role']) + ->andWhere($qb->expr()->in('roleScope.role', ':roles')) + ->setParameter( + 'roles', + \array_map( + function(Role $role) { return $role->getRole(); }, + $this->authorizationHelper->getParentRoles($options['role']) + ) + ) // add active constraint ->andWhere('u.enabled = :enabled') ->setParameter('enabled', true) diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 33b64df34..c0364f3cd 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -80,6 +80,7 @@ services: class: Chill\MainBundle\Security\Authorization\AuthorizationHelper arguments: - "@security.role_hierarchy" + - "%security.role_hierarchy.roles%" chill.main.role_provider: class: Chill\MainBundle\Security\RoleProvider diff --git a/Security/Authorization/AuthorizationHelper.php b/Security/Authorization/AuthorizationHelper.php index 4c749ad62..95552aa36 100644 --- a/Security/Authorization/AuthorizationHelper.php +++ b/Security/Authorization/AuthorizationHelper.php @@ -26,6 +26,7 @@ use Chill\MainBundle\Entity\HasScopeInterface; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; use Symfony\Component\Security\Core\Role\Role; use Chill\MainBundle\Entity\Scope; +use Chill\MainBundle\Security\RoleProvider; /** * Helper for authorizations. @@ -42,12 +43,23 @@ class AuthorizationHelper */ protected $roleHierarchy; + /** + * The role in a hierarchy, given by the parameter + * `security.role_hierarchy.roles` from the container. + * + * @var string[] + */ + protected $hierarchy; + protected $existingRoles = array('CHILL_MASTER_ROLE', 'CHILL_PERSON_SEE', 'CHILL_PERSON_UPDATE',); - public function __construct(RoleHierarchyInterface $roleHierarchy) - { + public function __construct( + RoleHierarchyInterface $roleHierarchy, + $hierarchy + ) { $this->roleHierarchy = $roleHierarchy; + $this->hierarchy = $hierarchy; } /** @@ -223,4 +235,33 @@ class AuthorizationHelper return in_array($childRole, $reachableRoles); } + + /** + * Return all the role which give access to the given role. Only the role + * which are registered into Chill are taken into account. + * + * @param Role $role + * @return Role[] the role which give access to the given $role + */ + public function getParentRoles(Role $role) + { + $parentRoles = []; + // transform the roles from role hierarchy from string to Role + $roles = \array_map( + function($string) { + return new Role($string); + }, + \array_keys($this->hierarchy) + ); + + foreach ($roles as $r) { + $childRoles = $this->roleHierarchy->getReachableRoles([$r]); + + if (\in_array($role, $childRoles)) { + $parentRoles[] = $r; + } + } + + return $parentRoles; + } } diff --git a/Tests/Security/Authorization/AuthorizationHelperTest.php b/Tests/Security/Authorization/AuthorizationHelperTest.php index abfc3c754..fb171de07 100644 --- a/Tests/Security/Authorization/AuthorizationHelperTest.php +++ b/Tests/Security/Authorization/AuthorizationHelperTest.php @@ -443,6 +443,22 @@ class AuthorizationHelperTest extends KernelTestCase ); } + public function testGetParentRoles() + { + $parentRoles = $this->getAuthorizationHelper() + ->getParentRoles(new Role('CHILL_INHERITED_ROLE_1')); + + $this->assertContains( + 'CHILL_MASTER_ROLE', + \array_map( + function(Role $role) { + return $role->getRole(); + }, + $parentRoles + ), + "Assert that `CHILL_MASTER_ROLE` is a parent of `CHILL_INHERITED_ROLE_1`"); + } + }