2022-01-27 17:08:00 +01:00

589 lines
20 KiB
PHP

<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Tests\Security\Authorization;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\HasCenterInterface;
use Chill\MainBundle\Entity\HasCentersInterface;
use Chill\MainBundle\Entity\HasScopeInterface;
use Chill\MainBundle\Entity\HasScopesInterface;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Test\PrepareCenterTrait;
use Chill\MainBundle\Test\PrepareScopeTrait;
use Chill\MainBundle\Test\PrepareUserTrait;
use Chill\MainBundle\Test\ProphecyTrait;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Security\Core\Role\Role;
use function array_map;
use function in_array;
/**
* @internal
* @coversNothing
*/
final class AuthorizationHelperTest extends KernelTestCase
{
use PrepareCenterTrait;
use PrepareScopeTrait;
use PrepareUserTrait;
use ProphecyTrait;
protected function setUp(): void
{
self::bootKernel();
}
public function dataProvider_getReachableCenters()
{
$this->setUp();
$centerA = $this->prepareCenter(1, 'center A');
$centerB = $this->prepareCenter(2, 'center B');
$scopeA = $this->prepareScope(1, 'scope default');
$scopeB = $this->prepareScope(2, 'scope B');
$scopeC = $this->prepareScope(3, 'scope C');
$userA = $this->prepareUser([
[
'center' => $centerA,
'permissionsGroup' => [
['scope' => $scopeB, 'role' => 'CHILL_ROLE_1'],
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2'],
],
],
[
'center' => $centerB,
'permissionsGroup' => [
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2'],
['scope' => $scopeC, 'role' => 'CHILL_ROLE_2'],
],
],
]);
$ah = $this->getAuthorizationHelper();
return [
// without scopes
[
true,
in_array($centerA, $ah->getReachableCenters(
$userA,
'CHILL_ROLE_1',
null
), true),
'center A should be available for userA, with role 1 ',
],
[
true,
in_array($centerA, $ah->getReachableCenters(
$userA,
'CHILL_ROLE_2',
null
), true),
'center A should be available for userA, with role 2 ',
],
[
true,
in_array($centerB, $ah->getReachableCenters(
$userA,
'CHILL_ROLE_2',
null
), true),
'center A should be available for userA, with role 2 ',
],
[
false,
in_array($centerB, $ah->getReachableCenters(
$userA,
'CHILL_ROLE_1',
null
), true),
'center B should NOT be available for userA, with role 1 ',
],
// with scope
[
true,
in_array($centerA, $ah->getReachableCenters(
$userA,
'CHILL_ROLE_1',
$scopeB
), true),
'center A should be available for userA, with role 1, scopeC ',
],
[
false,
in_array($centerA, $ah->getReachableCenters(
$userA,
'CHILL_ROLE_2',
$scopeC
), true),
'center A should NOT be available for userA, with role 2, scopeA ',
],
[
true,
in_array($centerB, $ah->getReachableCenters(
$userA,
'CHILL_ROLE_2',
$scopeA
), true),
'center B should be available for userA, with role 2, scopeA ',
],
];
}
public function dataProvider_getReachableScopes()
{
$centerA = $this->prepareCenter(1, 'center A');
$centerB = $this->prepareCenter(2, 'center B');
$scopeA = $this->prepareScope(1, 'scope default');
$scopeB = $this->prepareScope(2, 'scope B');
$scopeC = $this->prepareScope(3, 'scope C');
$userA = $this->prepareUser([
[
'center' => $centerA,
'permissionsGroup' => [
['scope' => $scopeB, 'role' => 'CHILL_ROLE_1'],
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2'],
],
],
[
'center' => $centerB,
'permissionsGroup' => [
['scope' => $scopeA, 'role' => 'CHILL_ROLE_2'],
['scope' => $scopeC, 'role' => 'CHILL_ROLE_2'],
['scope' => $scopeB, 'role' => 'CHILL_ROLE_2'],
],
],
]);
return [
[
true,
$scopeA,
$userA,
'CHILL_ROLE_2',
$centerA,
'Assert that a scope is found within accessible scopes',
],
[
false,
$scopeB,
$userA,
'CHILL_ROLE_2',
$centerA,
'Assert that a scope not reachable is NOT found within accessible scopes',
],
[
false,
$scopeB,
$userA,
'CHILL_ROLE_1',
$centerB,
'Assert that a scope not reachable is not found within accessible scopes.'
. ' Trying on filter centering',
],
];
}
public function testFindUsersReaching()
{
$centerA = self::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository(Center::class)
->findOneByName('Center A');
$users = $this->getAuthorizationHelper()
->findUsersReaching(
'CHILL_PERSON_SEE',
$centerA
);
$usernames = array_map(static function (User $u) { return $u->getUsername(); }, $users);
$this->assertContains('center a_social', $usernames);
}
public function testGetParentRoles()
{
$parentRoles = $this->getAuthorizationHelper()
->getParentRoles('CHILL_INHERITED_ROLE_1');
$this->assertContains(
'CHILL_MASTER_ROLE',
$parentRoles,
'Assert that `CHILL_MASTER_ROLE` is a parent of `CHILL_INHERITED_ROLE_1`'
);
}
/**
* @dataProvider dataProvider_getReachableCenters
*
* @param mixed $test
* @param mixed $result
* @param mixed $msg
*/
public function testGetReachableCenters($test, $result, $msg)
{
$this->assertEquals($test, $result, $msg);
}
/**
* @dataProvider dataProvider_getReachableScopes
*
* @param bool $expectedResult
* @param string $message
*/
public function testGetReachableScopes(
$expectedResult,
Scope $testedScope,
User $user,
string $role,
Center $center,
$message
) {
$reachableScopes = $this->getAuthorizationHelper()
->getReachableScopes($user, $role, $center);
$this->assertEquals(
$expectedResult,
in_array($testedScope, $reachableScopes, true),
$message
);
}
public function testtestUserHasAccessUserShouldHaveAccessEntityWithScope()
{
$center = $this->prepareCenter(1, 'center');
$scope = $this->prepareScope(1, 'default');
$user = $this->prepareUser([
[
'center' => $center, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'CHILL_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
$entity->getCenter()->willReturn($center);
$entity->getScope()->willReturn($scope);
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
/**
* Test function userCanReach of helper.
*
* A user can not reachcenter =>W the function should return false
*/
public function testUserCanReachCenterUserShouldNotReach()
{
$centerA = $this->prepareCenter(1, 'center');
$centerB = $this->prepareCenter(2, 'centerB');
$scope = $this->prepareScope(1, 'default');
$user = $this->prepareUser([
[
'center' => $centerA, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'ANY_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$this->assertFalse($helper->userCanReachCenter($user, $centerB));
}
/**
* Test function userCanReach of helper.
*
* A user can reach center => the function should return true.
*/
public function testUserCanReachCenterUserShouldReach()
{
$center = $this->prepareCenter(1, 'center');
$scope = $this->prepareScope(1, 'default');
$user = $this->prepareUser([
[
'center' => $center, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'ANY_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$this->assertTrue($helper->userCanReachCenter($user, $center));
}
public function testUserHasAccessEntityMultiScope()
{
$centerA = $this->prepareCenter(1, 'center');
$centerB = $this->prepareCenter(1, 'centerB');
$scopeA = $this->prepareScope(2, 'other'); //the user will be granted this scope
$scopeB = $this->prepareScope(2, 'other'); //the user will be granted this scope
$user = $this->prepareUser([
[
'center' => $centerA, 'permissionsGroup' => [
['scope' => $scopeA, 'role' => 'CHILL_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement(HasCentersInterface::class);
$entity->willImplement(HasScopesInterface::class);
$entity->getCenters()->willReturn([$centerA, $centerB]);
$entity->getScopes()->willReturn([$scopeA, $scopeB]);
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
public function testUserHasAccessMultiCenterEntityWithoutScope()
{
$center = $this->prepareCenter(1, 'center');
$centerB = $this->prepareCenter(1, 'centerB');
$scopeB = $this->prepareScope(2, 'other'); //the user will be granted this scope
$user = $this->prepareUser([
[
'center' => $center, 'permissionsGroup' => [
['scope' => $scopeB, 'role' => 'CHILL_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement(HasCentersInterface::class);
$entity->getCenters()->willReturn([$center, $centerB]);
$this->assertTrue($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
public function testUserHasAccessShouldHaveAccessEntityWithoutScope()
{
$center = $this->prepareCenter(1, 'center');
$scope = $this->prepareScope(1, 'default');
$user = $this->prepareUser([
[
'center' => $center, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'CHILL_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$entity->getCenter()->willReturn($center);
$this->assertTrue($helper->userHasAccess(
$user,
$entity->reveal(),
'CHILL_ROLE'
));
}
public function testUserHasAccessShouldHaveAccessWithInheritanceEntityWithoutScope()
{
$center = $this->prepareCenter(1, 'center');
$scope = $this->prepareScope(1, 'default');
$user = $this->prepareUser([
[
'center' => $center, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'CHILL_MASTER_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$entity->getCenter()->willReturn($center);
$this->assertTrue($helper->userHasAccess(
$user,
$entity->reveal(),
'CHILL_INHERITED_ROLE_1'
));
}
public function testUserHasAccessUserHasNoCenterEntityWithScope()
{
$centerA = $this->prepareCenter(1, 'center'); //the user will have this center
$centerB = $this->prepareCenter(2, 'centerB'); //the entity will have another center
$scope = $this->prepareScope(1, 'default');
$user = $this->prepareUser([
[
'center' => $centerA, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'CHILL_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$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 testuserHasAccessUserHasNoRoleEntityWithoutScope()
{
$center = $this->prepareCenter(1, 'center');
$scope = $this->prepareScope(1, 'default');
$user = $this->prepareUser([
[
'center' => $center, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'ANY_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$entity->getCenter()->willReturn($center);
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
public function testUserHasAccessUserHasNoRoleEntityWithScope()
{
$center = $this->prepareCenter(1, 'center');
$scope = $this->prepareScope(1, 'default');
$user = $this->prepareUser([
[
'center' => $center, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'CHILL_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement('\Chill\MainBundle\Entity\HasCenterInterface');
$entity->willImplement('\Chill\MainBundle\Entity\HasScopeInterface');
$entity->getCenter()->willReturn($center);
$entity->getScope()->willReturn($scope);
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'ANOTHER_ROLE'));
}
/**
* test that a user has no access on a entity, but is granted on the same role
* on another center.
*/
public function testUserHasAccessUserHasNoRoleUserHasRoleOnAnotherCenterEntityWithoutScope()
{
$centerA = $this->prepareCenter(1, 'center');
$centerB = $this->prepareCenter(2, 'centerB');
$scope = $this->prepareScope(1, 'default');
$user = $this->prepareUser([
[
'center' => $centerA, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'ANY_ROLE'],
],
[
'centerB' => $centerB, 'permissionsGroup' => [
['scope' => $scope, 'role' => 'ANY_ROLE'],
['scope' => $scope, 'role' => 'CHILL_ROLE'],
],
],
],
]);
$helper = $this->getAuthorizationHelper();
$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 testUserHasAccessUserHasNoScopeEntityWithScope()
{
$center = $this->prepareCenter(1, 'center');
$scopeA = $this->prepareScope(1, 'default'); //the entity will have this scope
$scopeB = $this->prepareScope(2, 'other'); //the user will be granted this scope
$user = $this->prepareUser([
[
'center' => $center, 'permissionsGroup' => [
['scope' => $scopeB, 'role' => 'CHILL_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement(HasCenterInterface::class);
$entity->willImplement(HasScopeInterface::class);
$entity->getCenter()->willReturn($center);
$entity->getScope()->willReturn($scopeA);
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
public function testUserHasNoAccessEntityMultiScope()
{
$centerA = $this->prepareCenter(1, 'center');
$centerB = $this->prepareCenter(1, 'centerB');
$scopeA = $this->prepareScope(2, 'other'); //the user will be granted this scope
$scopeB = $this->prepareScope(2, 'other'); //the user will be granted this scope
$scopeC = $this->prepareScope(2, 'other'); //the user will be granted this scope
$user = $this->prepareUser([
[
'center' => $centerA, 'permissionsGroup' => [
['scope' => $scopeA, 'role' => 'CHILL_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement(HasCentersInterface::class);
$entity->willImplement(HasScopesInterface::class);
$entity->getCenters()->willReturn([$centerA, $centerB]);
$entity->getScopes()->willReturn([$scopeB, $scopeC]);
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
public function testUserHasNoAccessMultiCenterEntityWithoutScope()
{
$center = $this->prepareCenter(1, 'center');
$centerB = $this->prepareCenter(1, 'centerB');
$centerC = $this->prepareCenter(1, 'centerC');
$scopeB = $this->prepareScope(2, 'other'); //the user will be granted this scope
$user = $this->prepareUser([
[
'center' => $center, 'permissionsGroup' => [
['scope' => $scopeB, 'role' => 'CHILL_ROLE'],
],
],
]);
$helper = $this->getAuthorizationHelper();
$entity = $this->getProphet()->prophesize();
$entity->willImplement(HasCentersInterface::class);
$entity->getCenters()->willReturn([$centerB, $centerC]);
$this->assertFalse($helper->userHasAccess($user, $entity->reveal(), 'CHILL_ROLE'));
}
/**
* @return \Chill\MainBundle\Security\Authorization\AuthorizationHelper
*/
private function getAuthorizationHelper()
{
return self::$container
->get('chill.main.security.authorization.helper');
}
}