apply new role on accompanying period

This commit is contained in:
2021-09-17 13:57:45 +02:00
parent cf40f38463
commit 74598ee926
19 changed files with 281 additions and 195 deletions

View File

@@ -146,14 +146,7 @@ class ScopePickerType extends AbstractType
->setParameter('center', $center->getId())
// role constraints
->andWhere($qb->expr()->in('rs.role', ':roles'))
->setParameter(
'roles', \array_map(
function (Role $role) {
return $role->getRole();
},
$roles
)
)
->setParameter('roles', $roles)
// user contraint
->andWhere(':user MEMBER OF gc.users')
->setParameter('user', $this->tokenStorage->getToken()->getUser());

View File

@@ -269,16 +269,12 @@ class AuthorizationHelper
/**
*
* @param Role $role
* @param Center $center
* @param Scope $circle
* @return Users
* @return User[]
*/
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[] = $role;
$parentRolesString = \array_map(function(Role $r) { return $r->getRole(); }, $parents);
$qb = $this->em->createQueryBuilder();
$qb
@@ -288,7 +284,7 @@ class AuthorizationHelper
->join('gc.permissionsGroup', 'pg')
->join('pg.roleScopes', 'rs')
->where('gc.center = :center')
->andWhere($qb->expr()->in('rs.role', $parentRolesString))
->andWhere($qb->expr()->in('rs.role', $parents))
;
$qb->setParameter('center', $center);
@@ -322,21 +318,16 @@ class AuthorizationHelper
* which are registered into Chill are taken into account.
*
* @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 = [];
// transform the roles from role hierarchy from string to Role
$roles = \array_map(
function($string) {
return new Role($string);
},
\array_keys($this->hierarchy)
);
$roles = \array_keys($this->hierarchy);
foreach ($roles as $r) {
$childRoles = $this->roleHierarchy->getReachableRoleNames([$r->getRole()]);
$childRoles = $this->roleHierarchy->getReachableRoleNames([$r]);
if (\in_array($role, $childRoles)) {
$parentRoles[] = $r;

View File

@@ -5,7 +5,7 @@ namespace Chill\MainBundle\Security\Authorization;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
class DefaultVoterHelper implements VoterHelperInterface
final class DefaultVoterHelper implements VoterHelperInterface
{
protected AuthorizationHelper $authorizationHelper;

View File

@@ -18,7 +18,7 @@ final class DefaultVoterHelperGenerator implements VoterGeneratorInterface
$this->centerResolverDispatcher = $centerResolverDispatcher;
}
public function addCheckFor($subject, $attributes): self
public function addCheckFor(?string $subject, array $attributes): self
{
$this->configuration[] = [$attributes, $subject];

View File

@@ -9,7 +9,7 @@ interface VoterGeneratorInterface
* @param array $attributes an array of attributes
* @return $this
*/
public function addCheckFor(string $class, array $attributes): self;
public function addCheckFor(?string $class, array $attributes): self;
public function build(): VoterHelperInterface;
}

View File

@@ -30,22 +30,22 @@ use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\Center;
/**
*
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class AuthorizationHelperTest extends KernelTestCase
{
use PrepareUserTrait, PrepareCenterTrait, PrepareScopeTrait, ProphecyTrait;
public function setUp()
public function setUp()
{
static::bootKernel();
}
/**
*
*
* @return \Chill\MainBundle\Security\Authorization\AuthorizationHelper
*/
private function getAuthorizationHelper()
@@ -54,13 +54,13 @@ class AuthorizationHelperTest extends KernelTestCase
->get('chill.main.security.authorization.helper')
;
}
/**
* Test function userCanReach of helper.
*
*
* A user can reach center => the function should return true.
*/
public function testUserCanReachCenter_UserShouldReach()
public function testUserCanReachCenter_UserShouldReach()
{
$center = $this->prepareCenter(1, 'center');
$scope = $this->prepareScope(1, 'default');
@@ -72,16 +72,16 @@ class AuthorizationHelperTest extends KernelTestCase
)
));
$helper = $this->getAuthorizationHelper();
$this->assertTrue($helper->userCanReachCenter($user, $center));
}
/**
* Test function userCanReach of helper
*
*
* A user can not reachcenter =>W the function should return false
*/
public function testUserCanReachCenter_UserShouldNotReach()
public function testUserCanReachCenter_UserShouldNotReach()
{
$centerA = $this->prepareCenter(1, 'center');
$centerB = $this->prepareCenter(2, 'centerB');
@@ -94,11 +94,11 @@ class AuthorizationHelperTest extends KernelTestCase
)
));
$helper = $this->getAuthorizationHelper();
$this->assertFalse($helper->userCanReachCenter($user, $centerB));
}
public function testUserHasAccess_shouldHaveAccess_EntityWithoutScope()
{
$center = $this->prepareCenter(1, 'center');
@@ -114,11 +114,11 @@ class AuthorizationHelperTest extends KernelTestCase
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$entity->getCenter()->willReturn($center);
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(),
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(),
'CHILL_ROLE'));
}
public function testUserHasAccess_ShouldHaveAccessWithInheritance_EntityWithoutScope()
{
$center = $this->prepareCenter(1, 'center');
@@ -130,17 +130,17 @@ class AuthorizationHelperTest extends KernelTestCase
)
)
));
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$entity->getCenter()->willReturn($center);
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(),
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(),
'CHILL_INHERITED_ROLE_1'));
}
public function testuserHasAccess_UserHasNoRole_EntityWithoutScope()
{
$center = $this->prepareCenter(1, 'center');
@@ -156,10 +156,10 @@ class AuthorizationHelperTest extends KernelTestCase
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$entity->getCenter()->willReturn($center);
$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
* on another center
@@ -186,10 +186,10 @@ class AuthorizationHelperTest extends KernelTestCase
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$entity->getCenter()->willReturn($centerA);
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
public function testtestUserHasAccess_UserShouldHaveAccess_EntityWithScope()
{
$center = $this->prepareCenter(1, 'center');
@@ -207,10 +207,10 @@ class AuthorizationHelperTest extends KernelTestCase
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
$entity->getCenter()->willReturn($center);
$entity->getScope()->willReturn($scope);
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
public function testUserHasAccess_UserHasNoRole_EntityWithScope()
{
$center = $this->prepareCenter(1, 'center');
@@ -228,10 +228,10 @@ class AuthorizationHelperTest extends KernelTestCase
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
$entity->getCenter()->willReturn($center);
$entity->getScope()->willReturn($scope);
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'ANOTHER_ROLE'));
}
public function testUserHasAccess_UserHasNoCenter_EntityWithScope()
{
$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->getCenter()->willReturn($centerB);
$entity->getScope()->willReturn($scope);
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
public function testUserHasAccess_UserHasNoScope_EntityWithScope()
{
$center = $this->prepareCenter(1, 'center');
@@ -272,12 +272,12 @@ class AuthorizationHelperTest extends KernelTestCase
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
$entity->getCenter()->willReturn($center);
$entity->getScope()->willReturn($scopeA);
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
/**
*
*
* @dataProvider dataProvider_getReachableCenters
* @param Center $shouldHaveCenter
* @param User $user
@@ -288,7 +288,7 @@ class AuthorizationHelperTest extends KernelTestCase
{
$this->assertEquals($test, $result, $msg);
}
public function dataProvider_getReachableCenters()
{
$this->setUp();
@@ -297,10 +297,10 @@ class AuthorizationHelperTest extends KernelTestCase
$scopeA = $this->prepareScope(1, 'scope default');
$scopeB = $this->prepareScope(2, 'scope B');
$scopeC = $this->prepareScope(3, 'scope C');
$userA = $this->prepareUser(array(
array(
'center' => $centerA,
'center' => $centerA,
'permissionsGroup' => array(
['scope' => $scopeB, 'role' => 'CHILL_ROLE_1'],
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2']
@@ -313,62 +313,62 @@ class AuthorizationHelperTest extends KernelTestCase
['scope' => $scopeC, 'role' => 'CHILL_ROLE_2']
)
)
));
$ah = $this->getAuthorizationHelper();
return array(
// without scopes
array(
true,
in_array($centerA, $ah->getReachableCenters($userA,
true,
in_array($centerA, $ah->getReachableCenters($userA,
new Role('CHILL_ROLE_1'), null)),
'center A should be available for userA, with role 1 '
),
array(
true,
in_array($centerA, $ah->getReachableCenters($userA,
true,
in_array($centerA, $ah->getReachableCenters($userA,
new Role('CHILL_ROLE_2'), null)),
'center A should be available for userA, with role 2 '
),
array(
true,
in_array($centerB, $ah->getReachableCenters($userA,
true,
in_array($centerB, $ah->getReachableCenters($userA,
new Role('CHILL_ROLE_2'), null)),
'center A should be available for userA, with role 2 '
),
array(
false,
false,
in_array($centerB, $ah->getReachableCenters($userA,
new Role('CHILL_ROLE_1'), null)),
'center B should NOT be available for userA, with role 1 '
),
// with scope
array(
true,
in_array($centerA, $ah->getReachableCenters($userA,
true,
in_array($centerA, $ah->getReachableCenters($userA,
new Role('CHILL_ROLE_1'), $scopeB)),
'center A should be available for userA, with role 1, scopeC '
),
array(
false,
in_array($centerA, $ah->getReachableCenters($userA,
false,
in_array($centerA, $ah->getReachableCenters($userA,
new Role('CHILL_ROLE_2'), $scopeC)),
'center A should NOT be available for userA, with role 2, scopeA '
),
array(
true,
in_array($centerB, $ah->getReachableCenters($userA,
true,
in_array($centerB, $ah->getReachableCenters($userA,
new Role('CHILL_ROLE_2'), $scopeA)),
'center B should be available for userA, with role 2, scopeA '
),
);
}
/**
*
*
* @dataProvider dataProvider_getReachableScopes
* @param boolean $expectedResult
* @param Scope $testedScope
@@ -382,11 +382,11 @@ class AuthorizationHelperTest extends KernelTestCase
{
$reachableScopes = $this->getAuthorizationHelper()
->getReachableScopes($user, $role, $center);
$this->assertEquals($expectedResult, in_array($testedScope, $reachableScopes),
$message);
}
public function dataProvider_getReachableScopes()
{
$centerA = $this->prepareCenter(1, 'center A');
@@ -394,10 +394,10 @@ class AuthorizationHelperTest extends KernelTestCase
$scopeA = $this->prepareScope(1, 'scope default');
$scopeB = $this->prepareScope(2, 'scope B');
$scopeC = $this->prepareScope(3, 'scope C');
$userA = $this->prepareUser(array(
array(
'center' => $centerA,
'center' => $centerA,
'permissionsGroup' => array(
['scope' => $scopeB, 'role' => 'CHILL_ROLE_1'],
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2']
@@ -411,9 +411,9 @@ class AuthorizationHelperTest extends KernelTestCase
['scope' => $scopeB, 'role' => 'CHILL_ROLE_2']
)
)
));
return array(
array(
true,
@@ -442,37 +442,30 @@ 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
),
->getParentRoles('CHILL_INHERITED_ROLE_1');
$this->assertContains('CHILL_MASTER_ROLE', $parentRoles,
"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'),
->findUsersReaching(new Role('CHILL_PERSON_SEE'),
$centerA);
$usernames = \array_map(function(User $u) { return $u->getUsername(); }, $users);
$this->assertContains('center a_social', $usernames);
}
}

View File

@@ -19,11 +19,11 @@ services:
autowire: true
# do not autowire the directory Security/Resolver
Chill\MainBundle\Security\Authorization\DefaultVoterFactory:
Chill\MainBundle\Security\Authorization\DefaultVoterHelperFactory:
autowire: true
# 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:
class: Chill\MainBundle\Security\Authorization\AuthorizationHelper