mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
apply new role on accompanying period
This commit is contained in:
parent
cf40f38463
commit
74598ee926
@ -146,14 +146,7 @@ class ScopePickerType extends AbstractType
|
|||||||
->setParameter('center', $center->getId())
|
->setParameter('center', $center->getId())
|
||||||
// role constraints
|
// role constraints
|
||||||
->andWhere($qb->expr()->in('rs.role', ':roles'))
|
->andWhere($qb->expr()->in('rs.role', ':roles'))
|
||||||
->setParameter(
|
->setParameter('roles', $roles)
|
||||||
'roles', \array_map(
|
|
||||||
function (Role $role) {
|
|
||||||
return $role->getRole();
|
|
||||||
},
|
|
||||||
$roles
|
|
||||||
)
|
|
||||||
)
|
|
||||||
// user contraint
|
// user contraint
|
||||||
->andWhere(':user MEMBER OF gc.users')
|
->andWhere(':user MEMBER OF gc.users')
|
||||||
->setParameter('user', $this->tokenStorage->getToken()->getUser());
|
->setParameter('user', $this->tokenStorage->getToken()->getUser());
|
||||||
|
@ -269,16 +269,12 @@ class AuthorizationHelper
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param Role $role
|
* @return User[]
|
||||||
* @param Center $center
|
|
||||||
* @param Scope $circle
|
|
||||||
* @return Users
|
|
||||||
*/
|
*/
|
||||||
public function findUsersReaching(Role $role, Center $center, Scope $circle = null)
|
public function findUsersReaching(string $role, Center $center, Scope $circle = null): array
|
||||||
{
|
{
|
||||||
$parents = $this->getParentRoles($role);
|
$parents = $this->getParentRoles($role);
|
||||||
$parents[] = $role;
|
$parents[] = $role;
|
||||||
$parentRolesString = \array_map(function(Role $r) { return $r->getRole(); }, $parents);
|
|
||||||
|
|
||||||
$qb = $this->em->createQueryBuilder();
|
$qb = $this->em->createQueryBuilder();
|
||||||
$qb
|
$qb
|
||||||
@ -288,7 +284,7 @@ class AuthorizationHelper
|
|||||||
->join('gc.permissionsGroup', 'pg')
|
->join('gc.permissionsGroup', 'pg')
|
||||||
->join('pg.roleScopes', 'rs')
|
->join('pg.roleScopes', 'rs')
|
||||||
->where('gc.center = :center')
|
->where('gc.center = :center')
|
||||||
->andWhere($qb->expr()->in('rs.role', $parentRolesString))
|
->andWhere($qb->expr()->in('rs.role', $parents))
|
||||||
;
|
;
|
||||||
|
|
||||||
$qb->setParameter('center', $center);
|
$qb->setParameter('center', $center);
|
||||||
@ -322,21 +318,16 @@ class AuthorizationHelper
|
|||||||
* which are registered into Chill are taken into account.
|
* which are registered into Chill are taken into account.
|
||||||
*
|
*
|
||||||
* @param Role $role
|
* @param Role $role
|
||||||
* @return Role[] the role which give access to the given $role
|
* @return string[] the role which give access to the given $role
|
||||||
*/
|
*/
|
||||||
public function getParentRoles(Role $role)
|
public function getParentRoles($role): array
|
||||||
{
|
{
|
||||||
$parentRoles = [];
|
$parentRoles = [];
|
||||||
// transform the roles from role hierarchy from string to Role
|
// transform the roles from role hierarchy from string to Role
|
||||||
$roles = \array_map(
|
$roles = \array_keys($this->hierarchy);
|
||||||
function($string) {
|
|
||||||
return new Role($string);
|
|
||||||
},
|
|
||||||
\array_keys($this->hierarchy)
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($roles as $r) {
|
foreach ($roles as $r) {
|
||||||
$childRoles = $this->roleHierarchy->getReachableRoleNames([$r->getRole()]);
|
$childRoles = $this->roleHierarchy->getReachableRoleNames([$r]);
|
||||||
|
|
||||||
if (\in_array($role, $childRoles)) {
|
if (\in_array($role, $childRoles)) {
|
||||||
$parentRoles[] = $r;
|
$parentRoles[] = $r;
|
||||||
|
@ -5,7 +5,7 @@ namespace Chill\MainBundle\Security\Authorization;
|
|||||||
use Chill\MainBundle\Entity\User;
|
use Chill\MainBundle\Entity\User;
|
||||||
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
||||||
|
|
||||||
class DefaultVoterHelper implements VoterHelperInterface
|
final class DefaultVoterHelper implements VoterHelperInterface
|
||||||
{
|
{
|
||||||
protected AuthorizationHelper $authorizationHelper;
|
protected AuthorizationHelper $authorizationHelper;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ final class DefaultVoterHelperGenerator implements VoterGeneratorInterface
|
|||||||
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addCheckFor($subject, $attributes): self
|
public function addCheckFor(?string $subject, array $attributes): self
|
||||||
{
|
{
|
||||||
$this->configuration[] = [$attributes, $subject];
|
$this->configuration[] = [$attributes, $subject];
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ interface VoterGeneratorInterface
|
|||||||
* @param array $attributes an array of attributes
|
* @param array $attributes an array of attributes
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function addCheckFor(string $class, array $attributes): self;
|
public function addCheckFor(?string $class, array $attributes): self;
|
||||||
|
|
||||||
public function build(): VoterHelperInterface;
|
public function build(): VoterHelperInterface;
|
||||||
}
|
}
|
||||||
|
@ -30,22 +30,22 @@ use Chill\MainBundle\Entity\Scope;
|
|||||||
use Chill\MainBundle\Entity\Center;
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||||
*/
|
*/
|
||||||
class AuthorizationHelperTest extends KernelTestCase
|
class AuthorizationHelperTest extends KernelTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
use PrepareUserTrait, PrepareCenterTrait, PrepareScopeTrait, ProphecyTrait;
|
use PrepareUserTrait, PrepareCenterTrait, PrepareScopeTrait, ProphecyTrait;
|
||||||
|
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
static::bootKernel();
|
static::bootKernel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return \Chill\MainBundle\Security\Authorization\AuthorizationHelper
|
* @return \Chill\MainBundle\Security\Authorization\AuthorizationHelper
|
||||||
*/
|
*/
|
||||||
private function getAuthorizationHelper()
|
private function getAuthorizationHelper()
|
||||||
@ -54,13 +54,13 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
->get('chill.main.security.authorization.helper')
|
->get('chill.main.security.authorization.helper')
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test function userCanReach of helper.
|
* Test function userCanReach of helper.
|
||||||
*
|
*
|
||||||
* A user can reach center => the function should return true.
|
* A user can reach center => the function should return true.
|
||||||
*/
|
*/
|
||||||
public function testUserCanReachCenter_UserShouldReach()
|
public function testUserCanReachCenter_UserShouldReach()
|
||||||
{
|
{
|
||||||
$center = $this->prepareCenter(1, 'center');
|
$center = $this->prepareCenter(1, 'center');
|
||||||
$scope = $this->prepareScope(1, 'default');
|
$scope = $this->prepareScope(1, 'default');
|
||||||
@ -72,16 +72,16 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
)
|
)
|
||||||
));
|
));
|
||||||
$helper = $this->getAuthorizationHelper();
|
$helper = $this->getAuthorizationHelper();
|
||||||
|
|
||||||
$this->assertTrue($helper->userCanReachCenter($user, $center));
|
$this->assertTrue($helper->userCanReachCenter($user, $center));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test function userCanReach of helper
|
* Test function userCanReach of helper
|
||||||
*
|
*
|
||||||
* A user can not reachcenter =>W the function should return false
|
* A user can not reachcenter =>W the function should return false
|
||||||
*/
|
*/
|
||||||
public function testUserCanReachCenter_UserShouldNotReach()
|
public function testUserCanReachCenter_UserShouldNotReach()
|
||||||
{
|
{
|
||||||
$centerA = $this->prepareCenter(1, 'center');
|
$centerA = $this->prepareCenter(1, 'center');
|
||||||
$centerB = $this->prepareCenter(2, 'centerB');
|
$centerB = $this->prepareCenter(2, 'centerB');
|
||||||
@ -94,11 +94,11 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
)
|
)
|
||||||
));
|
));
|
||||||
$helper = $this->getAuthorizationHelper();
|
$helper = $this->getAuthorizationHelper();
|
||||||
|
|
||||||
$this->assertFalse($helper->userCanReachCenter($user, $centerB));
|
$this->assertFalse($helper->userCanReachCenter($user, $centerB));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUserHasAccess_shouldHaveAccess_EntityWithoutScope()
|
public function testUserHasAccess_shouldHaveAccess_EntityWithoutScope()
|
||||||
{
|
{
|
||||||
$center = $this->prepareCenter(1, 'center');
|
$center = $this->prepareCenter(1, 'center');
|
||||||
@ -114,11 +114,11 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
$entity = $this->getProphet()->prophesize();
|
$entity = $this->getProphet()->prophesize();
|
||||||
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
|
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
|
||||||
$entity->getCenter()->willReturn($center);
|
$entity->getCenter()->willReturn($center);
|
||||||
|
|
||||||
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(),
|
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(),
|
||||||
'CHILL_ROLE'));
|
'CHILL_ROLE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUserHasAccess_ShouldHaveAccessWithInheritance_EntityWithoutScope()
|
public function testUserHasAccess_ShouldHaveAccessWithInheritance_EntityWithoutScope()
|
||||||
{
|
{
|
||||||
$center = $this->prepareCenter(1, 'center');
|
$center = $this->prepareCenter(1, 'center');
|
||||||
@ -130,17 +130,17 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|
||||||
$helper = $this->getAuthorizationHelper();
|
$helper = $this->getAuthorizationHelper();
|
||||||
$entity = $this->getProphet()->prophesize();
|
$entity = $this->getProphet()->prophesize();
|
||||||
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
|
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
|
||||||
$entity->getCenter()->willReturn($center);
|
$entity->getCenter()->willReturn($center);
|
||||||
|
|
||||||
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(),
|
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(),
|
||||||
'CHILL_INHERITED_ROLE_1'));
|
'CHILL_INHERITED_ROLE_1'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testuserHasAccess_UserHasNoRole_EntityWithoutScope()
|
public function testuserHasAccess_UserHasNoRole_EntityWithoutScope()
|
||||||
{
|
{
|
||||||
$center = $this->prepareCenter(1, 'center');
|
$center = $this->prepareCenter(1, 'center');
|
||||||
@ -156,10 +156,10 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
$entity = $this->getProphet()->prophesize();
|
$entity = $this->getProphet()->prophesize();
|
||||||
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
|
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
|
||||||
$entity->getCenter()->willReturn($center);
|
$entity->getCenter()->willReturn($center);
|
||||||
|
|
||||||
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test that a user has no access on a entity, but is granted on the same role
|
* test that a user has no access on a entity, but is granted on the same role
|
||||||
* on another center
|
* on another center
|
||||||
@ -186,10 +186,10 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
$entity = $this->getProphet()->prophesize();
|
$entity = $this->getProphet()->prophesize();
|
||||||
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
|
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
|
||||||
$entity->getCenter()->willReturn($centerA);
|
$entity->getCenter()->willReturn($centerA);
|
||||||
|
|
||||||
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testtestUserHasAccess_UserShouldHaveAccess_EntityWithScope()
|
public function testtestUserHasAccess_UserShouldHaveAccess_EntityWithScope()
|
||||||
{
|
{
|
||||||
$center = $this->prepareCenter(1, 'center');
|
$center = $this->prepareCenter(1, 'center');
|
||||||
@ -207,10 +207,10 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
|
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
|
||||||
$entity->getCenter()->willReturn($center);
|
$entity->getCenter()->willReturn($center);
|
||||||
$entity->getScope()->willReturn($scope);
|
$entity->getScope()->willReturn($scope);
|
||||||
|
|
||||||
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUserHasAccess_UserHasNoRole_EntityWithScope()
|
public function testUserHasAccess_UserHasNoRole_EntityWithScope()
|
||||||
{
|
{
|
||||||
$center = $this->prepareCenter(1, 'center');
|
$center = $this->prepareCenter(1, 'center');
|
||||||
@ -228,10 +228,10 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
|
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
|
||||||
$entity->getCenter()->willReturn($center);
|
$entity->getCenter()->willReturn($center);
|
||||||
$entity->getScope()->willReturn($scope);
|
$entity->getScope()->willReturn($scope);
|
||||||
|
|
||||||
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'ANOTHER_ROLE'));
|
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'ANOTHER_ROLE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUserHasAccess_UserHasNoCenter_EntityWithScope()
|
public function testUserHasAccess_UserHasNoCenter_EntityWithScope()
|
||||||
{
|
{
|
||||||
$centerA = $this->prepareCenter(1, 'center'); //the user will have this center
|
$centerA = $this->prepareCenter(1, 'center'); //the user will have this center
|
||||||
@ -250,10 +250,10 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
|
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
|
||||||
$entity->getCenter()->willReturn($centerB);
|
$entity->getCenter()->willReturn($centerB);
|
||||||
$entity->getScope()->willReturn($scope);
|
$entity->getScope()->willReturn($scope);
|
||||||
|
|
||||||
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUserHasAccess_UserHasNoScope_EntityWithScope()
|
public function testUserHasAccess_UserHasNoScope_EntityWithScope()
|
||||||
{
|
{
|
||||||
$center = $this->prepareCenter(1, 'center');
|
$center = $this->prepareCenter(1, 'center');
|
||||||
@ -272,12 +272,12 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
|
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
|
||||||
$entity->getCenter()->willReturn($center);
|
$entity->getCenter()->willReturn($center);
|
||||||
$entity->getScope()->willReturn($scopeA);
|
$entity->getScope()->willReturn($scopeA);
|
||||||
|
|
||||||
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @dataProvider dataProvider_getReachableCenters
|
* @dataProvider dataProvider_getReachableCenters
|
||||||
* @param Center $shouldHaveCenter
|
* @param Center $shouldHaveCenter
|
||||||
* @param User $user
|
* @param User $user
|
||||||
@ -288,7 +288,7 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
{
|
{
|
||||||
$this->assertEquals($test, $result, $msg);
|
$this->assertEquals($test, $result, $msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dataProvider_getReachableCenters()
|
public function dataProvider_getReachableCenters()
|
||||||
{
|
{
|
||||||
$this->setUp();
|
$this->setUp();
|
||||||
@ -297,10 +297,10 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
$scopeA = $this->prepareScope(1, 'scope default');
|
$scopeA = $this->prepareScope(1, 'scope default');
|
||||||
$scopeB = $this->prepareScope(2, 'scope B');
|
$scopeB = $this->prepareScope(2, 'scope B');
|
||||||
$scopeC = $this->prepareScope(3, 'scope C');
|
$scopeC = $this->prepareScope(3, 'scope C');
|
||||||
|
|
||||||
$userA = $this->prepareUser(array(
|
$userA = $this->prepareUser(array(
|
||||||
array(
|
array(
|
||||||
'center' => $centerA,
|
'center' => $centerA,
|
||||||
'permissionsGroup' => array(
|
'permissionsGroup' => array(
|
||||||
['scope' => $scopeB, 'role' => 'CHILL_ROLE_1'],
|
['scope' => $scopeB, 'role' => 'CHILL_ROLE_1'],
|
||||||
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2']
|
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2']
|
||||||
@ -313,62 +313,62 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
['scope' => $scopeC, 'role' => 'CHILL_ROLE_2']
|
['scope' => $scopeC, 'role' => 'CHILL_ROLE_2']
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
));
|
));
|
||||||
|
|
||||||
$ah = $this->getAuthorizationHelper();
|
$ah = $this->getAuthorizationHelper();
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
// without scopes
|
// without scopes
|
||||||
array(
|
array(
|
||||||
true,
|
true,
|
||||||
in_array($centerA, $ah->getReachableCenters($userA,
|
in_array($centerA, $ah->getReachableCenters($userA,
|
||||||
new Role('CHILL_ROLE_1'), null)),
|
new Role('CHILL_ROLE_1'), null)),
|
||||||
'center A should be available for userA, with role 1 '
|
'center A should be available for userA, with role 1 '
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
true,
|
true,
|
||||||
in_array($centerA, $ah->getReachableCenters($userA,
|
in_array($centerA, $ah->getReachableCenters($userA,
|
||||||
new Role('CHILL_ROLE_2'), null)),
|
new Role('CHILL_ROLE_2'), null)),
|
||||||
'center A should be available for userA, with role 2 '
|
'center A should be available for userA, with role 2 '
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
true,
|
true,
|
||||||
in_array($centerB, $ah->getReachableCenters($userA,
|
in_array($centerB, $ah->getReachableCenters($userA,
|
||||||
new Role('CHILL_ROLE_2'), null)),
|
new Role('CHILL_ROLE_2'), null)),
|
||||||
'center A should be available for userA, with role 2 '
|
'center A should be available for userA, with role 2 '
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
false,
|
false,
|
||||||
in_array($centerB, $ah->getReachableCenters($userA,
|
in_array($centerB, $ah->getReachableCenters($userA,
|
||||||
new Role('CHILL_ROLE_1'), null)),
|
new Role('CHILL_ROLE_1'), null)),
|
||||||
'center B should NOT be available for userA, with role 1 '
|
'center B should NOT be available for userA, with role 1 '
|
||||||
),
|
),
|
||||||
// with scope
|
// with scope
|
||||||
array(
|
array(
|
||||||
true,
|
true,
|
||||||
in_array($centerA, $ah->getReachableCenters($userA,
|
in_array($centerA, $ah->getReachableCenters($userA,
|
||||||
new Role('CHILL_ROLE_1'), $scopeB)),
|
new Role('CHILL_ROLE_1'), $scopeB)),
|
||||||
'center A should be available for userA, with role 1, scopeC '
|
'center A should be available for userA, with role 1, scopeC '
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
false,
|
false,
|
||||||
in_array($centerA, $ah->getReachableCenters($userA,
|
in_array($centerA, $ah->getReachableCenters($userA,
|
||||||
new Role('CHILL_ROLE_2'), $scopeC)),
|
new Role('CHILL_ROLE_2'), $scopeC)),
|
||||||
'center A should NOT be available for userA, with role 2, scopeA '
|
'center A should NOT be available for userA, with role 2, scopeA '
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
true,
|
true,
|
||||||
in_array($centerB, $ah->getReachableCenters($userA,
|
in_array($centerB, $ah->getReachableCenters($userA,
|
||||||
new Role('CHILL_ROLE_2'), $scopeA)),
|
new Role('CHILL_ROLE_2'), $scopeA)),
|
||||||
'center B should be available for userA, with role 2, scopeA '
|
'center B should be available for userA, with role 2, scopeA '
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @dataProvider dataProvider_getReachableScopes
|
* @dataProvider dataProvider_getReachableScopes
|
||||||
* @param boolean $expectedResult
|
* @param boolean $expectedResult
|
||||||
* @param Scope $testedScope
|
* @param Scope $testedScope
|
||||||
@ -382,11 +382,11 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
{
|
{
|
||||||
$reachableScopes = $this->getAuthorizationHelper()
|
$reachableScopes = $this->getAuthorizationHelper()
|
||||||
->getReachableScopes($user, $role, $center);
|
->getReachableScopes($user, $role, $center);
|
||||||
|
|
||||||
$this->assertEquals($expectedResult, in_array($testedScope, $reachableScopes),
|
$this->assertEquals($expectedResult, in_array($testedScope, $reachableScopes),
|
||||||
$message);
|
$message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function dataProvider_getReachableScopes()
|
public function dataProvider_getReachableScopes()
|
||||||
{
|
{
|
||||||
$centerA = $this->prepareCenter(1, 'center A');
|
$centerA = $this->prepareCenter(1, 'center A');
|
||||||
@ -394,10 +394,10 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
$scopeA = $this->prepareScope(1, 'scope default');
|
$scopeA = $this->prepareScope(1, 'scope default');
|
||||||
$scopeB = $this->prepareScope(2, 'scope B');
|
$scopeB = $this->prepareScope(2, 'scope B');
|
||||||
$scopeC = $this->prepareScope(3, 'scope C');
|
$scopeC = $this->prepareScope(3, 'scope C');
|
||||||
|
|
||||||
$userA = $this->prepareUser(array(
|
$userA = $this->prepareUser(array(
|
||||||
array(
|
array(
|
||||||
'center' => $centerA,
|
'center' => $centerA,
|
||||||
'permissionsGroup' => array(
|
'permissionsGroup' => array(
|
||||||
['scope' => $scopeB, 'role' => 'CHILL_ROLE_1'],
|
['scope' => $scopeB, 'role' => 'CHILL_ROLE_1'],
|
||||||
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2']
|
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2']
|
||||||
@ -411,9 +411,9 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
['scope' => $scopeB, 'role' => 'CHILL_ROLE_2']
|
['scope' => $scopeB, 'role' => 'CHILL_ROLE_2']
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
));
|
));
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
array(
|
array(
|
||||||
true,
|
true,
|
||||||
@ -442,37 +442,30 @@ class AuthorizationHelperTest extends KernelTestCase
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetParentRoles()
|
public function testGetParentRoles()
|
||||||
{
|
{
|
||||||
$parentRoles = $this->getAuthorizationHelper()
|
$parentRoles = $this->getAuthorizationHelper()
|
||||||
->getParentRoles(new Role('CHILL_INHERITED_ROLE_1'));
|
->getParentRoles('CHILL_INHERITED_ROLE_1');
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains('CHILL_MASTER_ROLE', $parentRoles,
|
||||||
'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`");
|
"Assert that `CHILL_MASTER_ROLE` is a parent of `CHILL_INHERITED_ROLE_1`");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFindUsersReaching()
|
public function testFindUsersReaching()
|
||||||
{
|
{
|
||||||
$centerA = static::$kernel->getContainer()
|
$centerA = static::$kernel->getContainer()
|
||||||
->get('doctrine.orm.entity_manager')
|
->get('doctrine.orm.entity_manager')
|
||||||
->getRepository(Center::class)
|
->getRepository(Center::class)
|
||||||
->findOneByName('Center A');
|
->findOneByName('Center A');
|
||||||
|
|
||||||
$users = $this->getAuthorizationHelper()
|
$users = $this->getAuthorizationHelper()
|
||||||
->findUsersReaching(new Role('CHILL_PERSON_SEE'),
|
->findUsersReaching(new Role('CHILL_PERSON_SEE'),
|
||||||
$centerA);
|
$centerA);
|
||||||
|
|
||||||
$usernames = \array_map(function(User $u) { return $u->getUsername(); }, $users);
|
$usernames = \array_map(function(User $u) { return $u->getUsername(); }, $users);
|
||||||
|
|
||||||
$this->assertContains('center a_social', $usernames);
|
$this->assertContains('center a_social', $usernames);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ services:
|
|||||||
autowire: true
|
autowire: true
|
||||||
|
|
||||||
# do not autowire the directory Security/Resolver
|
# do not autowire the directory Security/Resolver
|
||||||
Chill\MainBundle\Security\Authorization\DefaultVoterFactory:
|
Chill\MainBundle\Security\Authorization\DefaultVoterHelperFactory:
|
||||||
autowire: true
|
autowire: true
|
||||||
|
|
||||||
# do not autowire the directory Security/Resolver
|
# do not autowire the directory Security/Resolver
|
||||||
Chill\MainBundle\Security\Authorization\VoterFactoryInterface: '@Chill\MainBundle\Security\Authorization\DefaultVoterFactory'
|
Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface: '@Chill\MainBundle\Security\Authorization\DefaultVoterHelperFactory'
|
||||||
|
|
||||||
chill.main.security.authorization.helper:
|
chill.main.security.authorization.helper:
|
||||||
class: Chill\MainBundle\Security\Authorization\AuthorizationHelper
|
class: Chill\MainBundle\Security\Authorization\AuthorizationHelper
|
||||||
|
@ -73,7 +73,7 @@ class AccompanyingCourseController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $period);
|
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::CREATE, $period);
|
||||||
|
|
||||||
$em->persist($period);
|
$em->persist($period);
|
||||||
$em->flush();
|
$em->flush();
|
||||||
@ -92,6 +92,8 @@ class AccompanyingCourseController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function indexAction(AccompanyingPeriod $accompanyingCourse): Response
|
public function indexAction(AccompanyingPeriod $accompanyingCourse): Response
|
||||||
{
|
{
|
||||||
|
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingCourse);
|
||||||
|
|
||||||
// compute some warnings
|
// compute some warnings
|
||||||
// get persons without household
|
// get persons without household
|
||||||
$withoutHousehold = [];
|
$withoutHousehold = [];
|
||||||
@ -131,6 +133,8 @@ class AccompanyingCourseController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function editAction(AccompanyingPeriod $accompanyingCourse): Response
|
public function editAction(AccompanyingPeriod $accompanyingCourse): Response
|
||||||
{
|
{
|
||||||
|
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingCourse);
|
||||||
|
|
||||||
return $this->render('@ChillPerson/AccompanyingCourse/edit.html.twig', [
|
return $this->render('@ChillPerson/AccompanyingCourse/edit.html.twig', [
|
||||||
'accompanyingCourse' => $accompanyingCourse
|
'accompanyingCourse' => $accompanyingCourse
|
||||||
]);
|
]);
|
||||||
@ -146,6 +150,8 @@ class AccompanyingCourseController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function historyAction(AccompanyingPeriod $accompanyingCourse): Response
|
public function historyAction(AccompanyingPeriod $accompanyingCourse): Response
|
||||||
{
|
{
|
||||||
|
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingCourse);
|
||||||
|
|
||||||
return $this->render('@ChillPerson/AccompanyingCourse/history.html.twig', [
|
return $this->render('@ChillPerson/AccompanyingCourse/history.html.twig', [
|
||||||
'accompanyingCourse' => $accompanyingCourse
|
'accompanyingCourse' => $accompanyingCourse
|
||||||
]);
|
]);
|
||||||
|
@ -23,7 +23,10 @@
|
|||||||
namespace Chill\PersonBundle\Controller;
|
namespace Chill\PersonBundle\Controller;
|
||||||
|
|
||||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||||
|
use Chill\PersonBundle\Repository\AccompanyingPeriodACLAwareRepository;
|
||||||
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||||
use Doctrine\DBAL\Exception;
|
use Doctrine\DBAL\Exception;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Chill\PersonBundle\Form\AccompanyingPeriodType;
|
use Chill\PersonBundle\Form\AccompanyingPeriodType;
|
||||||
@ -53,21 +56,24 @@ class AccompanyingPeriodController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
protected $validator;
|
protected $validator;
|
||||||
|
|
||||||
/**
|
protected AccompanyingPeriodACLAwareRepository $accompanyingPeriodACLAwareRepository;
|
||||||
* AccompanyingPeriodController constructor.
|
|
||||||
*
|
public function __construct(
|
||||||
* @param EventDispatcherInterface $eventDispatcher
|
AccompanyingPeriodACLAwareRepository $accompanyingPeriodACLAwareRepository,
|
||||||
* @param ValidatorInterface $validator
|
EventDispatcherInterface $eventDispatcher,
|
||||||
*/
|
ValidatorInterface $validator
|
||||||
public function __construct(EventDispatcherInterface $eventDispatcher, ValidatorInterface $validator)
|
) {
|
||||||
{
|
$this->accompanyingPeriodACLAwareRepository = $accompanyingPeriodACLAwareRepository;
|
||||||
$this->eventDispatcher = $eventDispatcher;
|
$this->eventDispatcher = $eventDispatcher;
|
||||||
$this->validator = $validator;
|
$this->validator = $validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function listAction(int $person_id): Response
|
/**
|
||||||
|
* @ParamConverter("person", options={"id"="person_id"})
|
||||||
|
*/
|
||||||
|
public function listAction(Person $person): Response
|
||||||
{
|
{
|
||||||
$person = $this->_getPerson($person_id);
|
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $person);
|
||||||
|
|
||||||
$event = new PrivacyEvent($person, [
|
$event = new PrivacyEvent($person, [
|
||||||
'element_class' => AccompanyingPeriod::class,
|
'element_class' => AccompanyingPeriod::class,
|
||||||
@ -75,9 +81,10 @@ class AccompanyingPeriodController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
|
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
|
||||||
|
|
||||||
$accompanyingPeriods = $person->getAccompanyingPeriodsOrdered();
|
$accompanyingPeriods = $this->accompanyingPeriodACLAwareRepository
|
||||||
|
->findByPerson($person, AccompanyingPeriodVoter::SEE);
|
||||||
|
|
||||||
return $this->render('ChillPersonBundle:AccompanyingPeriod:list.html.twig', [
|
return $this->render('@ChillPerson/AccompanyingPeriod/list.html.twig', [
|
||||||
'accompanying_periods' => $accompanyingPeriods,
|
'accompanying_periods' => $accompanyingPeriods,
|
||||||
'person' => $person
|
'person' => $person
|
||||||
]);
|
]);
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
namespace Chill\PersonBundle\DependencyInjection;
|
namespace Chill\PersonBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\Config\FileLocator;
|
use Symfony\Component\Config\FileLocator;
|
||||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||||
@ -258,14 +259,26 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
*/
|
*/
|
||||||
protected function prependRoleHierarchy(ContainerBuilder $container)
|
protected function prependRoleHierarchy(ContainerBuilder $container)
|
||||||
{
|
{
|
||||||
$container->prependExtensionConfig('security', array(
|
$container->prependExtensionConfig('security', [
|
||||||
'role_hierarchy' => array(
|
'role_hierarchy' => [
|
||||||
'CHILL_PERSON_UPDATE' => array('CHILL_PERSON_SEE'),
|
PersonVoter::UPDATE => [PersonVoter::SEE],
|
||||||
'CHILL_PERSON_CREATE' => array('CHILL_PERSON_SEE'),
|
PersonVoter::CREATE => [PersonVoter::SEE],
|
||||||
PersonVoter::LISTS => [ ChillExportVoter::EXPORT ],
|
PersonVoter::LISTS => [ChillExportVoter::EXPORT],
|
||||||
PersonVoter::STATS => [ ChillExportVoter::EXPORT ]
|
PersonVoter::STATS => [ChillExportVoter::EXPORT],
|
||||||
)
|
// accompanying period
|
||||||
));
|
AccompanyingPeriodVoter::SEE_DETAILS => [AccompanyingPeriodVoter::SEE],
|
||||||
|
AccompanyingPeriodVoter::CREATE => [AccompanyingPeriodVoter::SEE_DETAILS],
|
||||||
|
AccompanyingPeriodVoter::DELETE => [AccompanyingPeriodVoter::SEE_DETAILS],
|
||||||
|
AccompanyingPeriodVoter::EDIT => [AccompanyingPeriodVoter::SEE_DETAILS],
|
||||||
|
// give all ACL for FULL
|
||||||
|
AccompanyingPeriodVoter::FULL => [
|
||||||
|
AccompanyingPeriodVoter::SEE_DETAILS,
|
||||||
|
AccompanyingPeriodVoter::CREATE,
|
||||||
|
AccompanyingPeriodVoter::EDIT,
|
||||||
|
AccompanyingPeriodVoter::DELETE
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,14 +18,17 @@
|
|||||||
namespace Chill\PersonBundle\Menu;
|
namespace Chill\PersonBundle\Menu;
|
||||||
|
|
||||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||||
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||||
use Knp\Menu\MenuItem;
|
use Knp\Menu\MenuItem;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add menu entrie to person menu.
|
* Add menu entrie to person menu.
|
||||||
*
|
*
|
||||||
* Menu entries added :
|
* Menu entries added :
|
||||||
*
|
*
|
||||||
* - person details ;
|
* - person details ;
|
||||||
* - accompanying period (if `visible`)
|
* - accompanying period (if `visible`)
|
||||||
*
|
*
|
||||||
@ -37,21 +40,25 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
* @var string 'visible' or 'hidden'
|
* @var string 'visible' or 'hidden'
|
||||||
*/
|
*/
|
||||||
protected $showAccompanyingPeriod;
|
protected $showAccompanyingPeriod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @var TranslatorInterface
|
* @var TranslatorInterface
|
||||||
*/
|
*/
|
||||||
protected $translator;
|
protected $translator;
|
||||||
|
|
||||||
|
private Security $security;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
$showAccompanyingPeriod,
|
ParameterBagInterface $parameterBag,
|
||||||
|
Security $security,
|
||||||
TranslatorInterface $translator
|
TranslatorInterface $translator
|
||||||
) {
|
) {
|
||||||
$this->showAccompanyingPeriod = $showAccompanyingPeriod;
|
$this->showAccompanyingPeriod = $parameterBag->get('chill_person.accompanying_period');
|
||||||
|
$this->security = $security;
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||||
{
|
{
|
||||||
$menu->addChild($this->translator->trans('Person details'), [
|
$menu->addChild($this->translator->trans('Person details'), [
|
||||||
@ -83,8 +90,10 @@ class PersonMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
->setExtras([
|
->setExtras([
|
||||||
'order' => 99999
|
'order' => 99999
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($this->showAccompanyingPeriod === 'visible') {
|
if ($this->showAccompanyingPeriod === 'visible'
|
||||||
|
&& $this->security->isGranted(AccompanyingPeriodVoter::SEE, $parameters['person'])
|
||||||
|
) {
|
||||||
$menu->addChild($this->translator->trans('Accompanying period list'), [
|
$menu->addChild($this->translator->trans('Accompanying period list'), [
|
||||||
'route' => 'chill_person_accompanying_period_list',
|
'route' => 'chill_person_accompanying_period_list',
|
||||||
'routeParameters' => [
|
'routeParameters' => [
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||||
|
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
||||||
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
|
final class AccompanyingPeriodACLAwareRepository
|
||||||
|
{
|
||||||
|
private AccompanyingPeriodRepository $accompanyingPeriodRepository;
|
||||||
|
private Security $security;
|
||||||
|
private AuthorizationHelper $authorizationHelper;
|
||||||
|
private CenterResolverDispatcher $centerResolverDispatcher;
|
||||||
|
|
||||||
|
public function __construct(AccompanyingPeriodRepository $accompanyingPeriodRepository, Security $security, AuthorizationHelper $authorizationHelper, CenterResolverDispatcher $centerResolverDispatcher)
|
||||||
|
{
|
||||||
|
$this->accompanyingPeriodRepository = $accompanyingPeriodRepository;
|
||||||
|
$this->security = $security;
|
||||||
|
$this->authorizationHelper = $authorizationHelper;
|
||||||
|
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findByPerson(
|
||||||
|
Person $person,
|
||||||
|
string $role,
|
||||||
|
?array $orderBy = [],
|
||||||
|
int $limit = null,
|
||||||
|
int $offset = null
|
||||||
|
): array {
|
||||||
|
dump(__METHOD__);
|
||||||
|
$qb = $this->accompanyingPeriodRepository->createQueryBuilder('ap');
|
||||||
|
$scopes = $this->authorizationHelper
|
||||||
|
->getReachableCircles($this->security->getUser(), $role,
|
||||||
|
$this->centerResolverDispatcher->resolveCenter($person));
|
||||||
|
|
||||||
|
if (0 === count($scopes)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->join('ap.participations', 'participation')
|
||||||
|
->where($qb->expr()->eq('participation.person', ':person'))
|
||||||
|
->setParameter('person', $person)
|
||||||
|
;
|
||||||
|
// add join condition for scopes
|
||||||
|
$orx = $qb->expr()->orX();
|
||||||
|
foreach ($scopes as $key => $scope) {
|
||||||
|
$orx->add($qb->expr()->in('ap.scopes', ':scope_'.$key));
|
||||||
|
$qb->setParameter('scope_'.$key, $scope);
|
||||||
|
}
|
||||||
|
$qb->andWhere($orx);
|
||||||
|
|
||||||
|
return $qb->getQuery()->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -59,6 +59,11 @@ final class AccompanyingPeriodRepository implements ObjectRepository
|
|||||||
return $this->findOneBy($criteria);
|
return $this->findOneBy($criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function createQueryBuilder(string $alias, ?string $indexBy = null): QueryBuilder
|
||||||
|
{
|
||||||
|
return $this->repository->createQueryBuilder($alias, $indexBy);
|
||||||
|
}
|
||||||
|
|
||||||
public function getClassName()
|
public function getClassName()
|
||||||
{
|
{
|
||||||
return AccompanyingPeriod::class;
|
return AccompanyingPeriod::class;
|
||||||
|
@ -60,7 +60,7 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
|||||||
$countryCode);
|
$countryCode);
|
||||||
$this->addACLClauses($qb, 'p');
|
$this->addACLClauses($qb, 'p');
|
||||||
|
|
||||||
return $this->getQueryResult($qb, $simplify, $limit, $start);
|
return $this->getQueryResult($qb, 'p', $simplify, $limit, $start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,7 +119,7 @@ final class PersonACLAwareRepository implements PersonACLAwareRepositoryInterfac
|
|||||||
$countryCode);
|
$countryCode);
|
||||||
$this->addACLClauses($qb, 'p');
|
$this->addACLClauses($qb, 'p');
|
||||||
|
|
||||||
return $this->getCountQueryResult($qb);
|
return $this->getCountQueryResult($qb,'p');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,73 +4,101 @@ namespace Chill\PersonBundle\Security\Authorization;
|
|||||||
|
|
||||||
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
|
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
|
||||||
use Chill\MainBundle\Entity\User;
|
use Chill\MainBundle\Entity\User;
|
||||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
use Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface;
|
||||||
|
use Chill\MainBundle\Security\Authorization\VoterHelperInterface;
|
||||||
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
|
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
use Chill\MainBundle\Entity\Center;
|
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
use Symfony\Component\Security\Core\Role\Role;
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
||||||
{
|
{
|
||||||
protected AuthorizationHelper $helper;
|
|
||||||
|
|
||||||
public const SEE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_SEE';
|
public const SEE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_SEE';
|
||||||
|
/**
|
||||||
|
* details are for seeing:
|
||||||
|
*
|
||||||
|
* * SocialIssues
|
||||||
|
*/
|
||||||
|
public const SEE_DETAILS = 'CHILL_PERSON_ACCOMPANYING_PERIOD_SEE_DETAILS';
|
||||||
|
public const CREATE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_CREATE';
|
||||||
|
public const EDIT = 'CHILL_PERSON_ACCOMPANYING_PERIOD_UPDATE';
|
||||||
|
public const DELETE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_DELETE';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param AuthorizationHelper $helper
|
* Give all the right above
|
||||||
*/
|
*/
|
||||||
public function __construct(AuthorizationHelper $helper)
|
public const FULL = 'CHILL_PERSON_ACCOMPANYING_PERIOD_FULL';
|
||||||
{
|
|
||||||
$this->helper = $helper;
|
public const ALL = [
|
||||||
|
self::SEE,
|
||||||
|
self::SEE_DETAILS,
|
||||||
|
self::CREATE,
|
||||||
|
self::EDIT,
|
||||||
|
self::DELETE,
|
||||||
|
self::FULL,
|
||||||
|
];
|
||||||
|
|
||||||
|
private VoterHelperInterface $voterHelper;
|
||||||
|
|
||||||
|
private Security $security;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Security $security,
|
||||||
|
VoterHelperFactoryInterface $voterHelperFactory
|
||||||
|
) {
|
||||||
|
$this->security = $security;
|
||||||
|
$this->voterHelper = $voterHelperFactory
|
||||||
|
->generate(self::class)
|
||||||
|
->addCheckFor(null, [self::CREATE])
|
||||||
|
->addCheckFor(AccompanyingPeriod::class, self::ALL)
|
||||||
|
->addCheckFor(Person::class, [self::SEE])
|
||||||
|
->build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function supports($attribute, $subject)
|
protected function supports($attribute, $subject)
|
||||||
{
|
{
|
||||||
return $subject instanceof AccompanyingPeriod;
|
return $this->voterHelper->supports($attribute, $subject);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
|
||||||
{
|
{
|
||||||
if (!$token->getUser() instanceof User) {
|
if (!$token->getUser() instanceof User) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO take scopes into account
|
if ($subject instanceof AccompanyingPeriod) {
|
||||||
if (count($subject->getPersons()) === 0) {
|
if (AccompanyingPeriod::STEP_DRAFT === $subject->getStep()) {
|
||||||
return true;
|
// only creator can see, edit, delete, etc.
|
||||||
}
|
if ($subject->getCreatedBy() === $token->getUser()
|
||||||
foreach ($subject->getPersons() as $person) {
|
|| NULL === $subject->getCreatedBy()) {
|
||||||
// give access as soon as on center is reachable
|
return true;
|
||||||
if ($this->helper->userHasAccess($token->getUser(), $person->getCenter(), $attribute)) {
|
}
|
||||||
return true;
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
// if confidential, only the referent can see it
|
||||||
|
if ($subject->isConfidential()) {
|
||||||
|
return $token->getUser() === $subject->getUser();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private function getAttributes()
|
return $this->voterHelper->voteOnAttribute($attribute, $subject, $token);
|
||||||
{
|
|
||||||
return [
|
|
||||||
self::SEE
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRoles()
|
public function getRoles()
|
||||||
{
|
{
|
||||||
return $this->getAttributes();
|
return self::ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRolesWithoutScope()
|
public function getRolesWithoutScope()
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRolesWithHierarchy()
|
public function getRolesWithHierarchy()
|
||||||
{
|
{
|
||||||
return [ 'Person' => $this->getRoles() ];
|
return [ 'Accompanying period' => $this->getRoles() ];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,19 +40,11 @@ class PersonVoter extends AbstractChillVoter implements ProvideRoleHierarchyInte
|
|||||||
const LISTS = 'CHILL_PERSON_LISTS';
|
const LISTS = 'CHILL_PERSON_LISTS';
|
||||||
const DUPLICATE = 'CHILL_PERSON_DUPLICATE';
|
const DUPLICATE = 'CHILL_PERSON_DUPLICATE';
|
||||||
|
|
||||||
protected AuthorizationHelper $helper;
|
|
||||||
|
|
||||||
protected CenterResolverDispatcher $centerResolverDispatcher;
|
|
||||||
|
|
||||||
protected VoterHelperInterface $voter;
|
protected VoterHelperInterface $voter;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
AuthorizationHelper $helper,
|
|
||||||
CenterResolverDispatcher $centerResolverDispatcher,
|
|
||||||
VoterHelperFactoryInterface $voterFactory
|
VoterHelperFactoryInterface $voterFactory
|
||||||
) {
|
) {
|
||||||
$this->helper = $helper;
|
|
||||||
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
|
||||||
$this->voter = $voterFactory
|
$this->voter = $voterFactory
|
||||||
->generate(self::class)
|
->generate(self::class)
|
||||||
->addCheckFor(Center::class, [self::STATS, self::LISTS, self::DUPLICATE])
|
->addCheckFor(Center::class, [self::STATS, self::LISTS, self::DUPLICATE])
|
||||||
|
@ -12,9 +12,8 @@ services:
|
|||||||
tags: ['controller.service_arguments']
|
tags: ['controller.service_arguments']
|
||||||
|
|
||||||
Chill\PersonBundle\Controller\AccompanyingPeriodController:
|
Chill\PersonBundle\Controller\AccompanyingPeriodController:
|
||||||
arguments:
|
autowire: true
|
||||||
$eventDispatcher: '@Symfony\Component\EventDispatcher\EventDispatcherInterface'
|
autoconfigure: true
|
||||||
$validator: '@Symfony\Component\Validator\Validator\ValidatorInterface'
|
|
||||||
tags: ['controller.service_arguments']
|
tags: ['controller.service_arguments']
|
||||||
|
|
||||||
Chill\PersonBundle\Controller\PersonAddressController:
|
Chill\PersonBundle\Controller\PersonAddressController:
|
||||||
|
@ -19,14 +19,7 @@ services:
|
|||||||
# - { name: 'chill.menu_builder' }
|
# - { name: 'chill.menu_builder' }
|
||||||
#
|
#
|
||||||
Chill\PersonBundle\Menu\PersonMenuBuilder:
|
Chill\PersonBundle\Menu\PersonMenuBuilder:
|
||||||
arguments:
|
autowire: true
|
||||||
$showAccompanyingPeriod: '%chill_person.accompanying_period%'
|
autoconfigure: true
|
||||||
$translator: '@Symfony\Contracts\Translation\TranslatorInterface'
|
|
||||||
tags:
|
tags:
|
||||||
- { name: 'chill.menu_builder' }
|
- { name: 'chill.menu_builder' }
|
||||||
|
|
||||||
# Chill\PersonBundle\Menu\AccompanyingCourseMenuBuilder:
|
|
||||||
# arguments:
|
|
||||||
# $translator: '@Symfony\Contracts\Translation\TranslatorInterface'
|
|
||||||
# tags:
|
|
||||||
# - { name: 'chill.menu_builder' }
|
|
||||||
|
@ -7,8 +7,7 @@ services:
|
|||||||
- { name: chill.role }
|
- { name: chill.role }
|
||||||
|
|
||||||
Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter:
|
Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter:
|
||||||
arguments:
|
autowire: true
|
||||||
- "@chill.main.security.authorization.helper"
|
|
||||||
tags:
|
tags:
|
||||||
- { name: security.voter }
|
- { name: security.voter }
|
||||||
- { name: chill.role }
|
- { name: chill.role }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user