diff --git a/Form/Type/UserPickerType.php b/Form/Type/UserPickerType.php index b253ce393..0d0a44fdd 100644 --- a/Form/Type/UserPickerType.php +++ b/Form/Type/UserPickerType.php @@ -87,34 +87,10 @@ class UserPickerType extends AbstractType ->setDefault('choice_label', function(User $u) { return $u->getUsername(); }) - ->setNormalizer('query_builder', function(Options $options) { - $roles = $this->authorizationHelper->getParentRoles($options['role']); - $roles[] = $options['role']; + ->setNormalizer('choices', function(Options $options) { - $qb = $this->userRepository->createQueryBuilder('u'); - $qb - // add center constraint - ->join('u.groupCenters', 'ug') - ->where($qb->expr()->eq('ug.center', ':center')) - ->setParameter('center', $options['center']) - // link to permission groups - ->join('ug.permissionsGroup', 'pg') - // role constraints - ->join('pg.roleScopes', 'roleScope') - ->andWhere($qb->expr()->in('roleScope.role', ':roles')) - ->setParameter( - 'roles', - \array_map( - function(Role $role) { return $role->getRole(); }, - $roles - ) - ) - // add active constraint - ->andWhere('u.enabled = :enabled') - ->setParameter('enabled', true) - ; - - return $qb; + return $this->authorizationHelper + ->findUsersReaching($options['role'], $options['center']); }) ; } diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 6cd323c56..c60212df5 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -59,8 +59,9 @@ services: chill.main.security.authorization.helper: class: Chill\MainBundle\Security\Authorization\AuthorizationHelper arguments: - - "@security.role_hierarchy" - - "%security.role_hierarchy.roles%" + $roleHierarchy: "@security.role_hierarchy" + $hierarchy: "%security.role_hierarchy.roles%" + $em: '@Doctrine\ORM\EntityManagerInterface' Chill\MainBundle\Security\Authorization\AuthorizationHelper: '@chill.main.security.authorization.helper' chill.main.role_provider: diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index bf082188f..543031d15 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -32,7 +32,7 @@ Confirm: Confirmer Cancel: Annuler Save: Enregistrer This form contains errors: Ce formulaire contient des erreurs - +Choose an user: Choisir un utilisateur 'You are going to leave a page with unsubmitted data. Are you sure you want to leave ?': "Vous allez quitter la page alors que des données n'ont pas été enregistrées. Êtes vous sûr de vouloir partir ?" Edit: Modifier diff --git a/Security/Authorization/AuthorizationHelper.php b/Security/Authorization/AuthorizationHelper.php index 95552aa36..f786e38f3 100644 --- a/Security/Authorization/AuthorizationHelper.php +++ b/Security/Authorization/AuthorizationHelper.php @@ -27,6 +27,9 @@ use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; use Symfony\Component\Security\Core\Role\Role; use Chill\MainBundle\Entity\Scope; use Chill\MainBundle\Security\RoleProvider; +use Doctrine\ORM\EntityManagerInterface; +use Chill\MainBundle\Entity\GroupCenter; +use Chill\MainBundle\Entity\RoleScope; /** * Helper for authorizations. @@ -51,15 +54,20 @@ class AuthorizationHelper */ protected $hierarchy; - protected $existingRoles = array('CHILL_MASTER_ROLE', 'CHILL_PERSON_SEE', - 'CHILL_PERSON_UPDATE',); + /** + * + * @var EntityManagerInterface + */ + protected $em; public function __construct( RoleHierarchyInterface $roleHierarchy, - $hierarchy + $hierarchy, + EntityManagerInterface $em ) { $this->roleHierarchy = $roleHierarchy; $this->hierarchy = $hierarchy; + $this->em = $em; } /** @@ -219,7 +227,40 @@ class AuthorizationHelper return $scopes; } - + /** + * + * @param Role $role + * @param Center $center + * @param Scope $circle + * @return Users + */ + public function findUsersReaching(Role $role, Center $center, Scope $circle = null) + { + $parents = $this->getParentRoles($role); + $parents[] = $role; + $parentRolesString = \array_map(function(Role $r) { return $r->getRole(); }, $parents); + + $qb = $this->em->createQueryBuilder(); + $qb + ->select('u') + ->from(User::class, 'u') + ->join('u.groupCenters', 'gc') + ->join('gc.permissionsGroup', 'pg') + ->join('pg.roleScopes', 'rs') + ->where('gc.center = :center') + ->andWhere($qb->expr()->in('rs.role', $parentRolesString)) + ; + + $qb->setParameter('center', $center); + + if ($circle !== null) { + $qb->andWhere('rs.scope = :circle') + ->setParameter('circle', $circle) + ; + } + + return $qb->getQuery()->getResult(); + } /** * Test if a parent role may give access to a given child role diff --git a/Tests/Security/Authorization/AuthorizationHelperTest.php b/Tests/Security/Authorization/AuthorizationHelperTest.php index fb171de07..3ed9a4b6f 100644 --- a/Tests/Security/Authorization/AuthorizationHelperTest.php +++ b/Tests/Security/Authorization/AuthorizationHelperTest.php @@ -459,6 +459,20 @@ class AuthorizationHelperTest extends KernelTestCase "Assert that `CHILL_MASTER_ROLE` is a parent of `CHILL_INHERITED_ROLE_1`"); } - + public function testFindUsersReaching() + { + $centerA = static::$kernel->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository(Center::class) + ->findOneByName('Center A'); + + $users = $this->getAuthorizationHelper() + ->findUsersReaching(new Role('CHILL_PERSON_SEE'), + $centerA); + + $usernames = \array_map(function(User $u) { return $u->getUsername(); }, $users); + + $this->assertContains('center a_social', $usernames); + } }