improve userPicker: delegate query to authorization helper

This commit is contained in:
Julien Fastré 2018-06-05 09:45:22 +02:00
parent 514b619f8a
commit 13dbaa0b78
5 changed files with 67 additions and 35 deletions

View File

@ -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']);
})
;
}

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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);
}
}