Create a voter for applying all transitions on all workflow's steps

This voter checks that the related entity's centers is reachable by the user.
This commit is contained in:
2024-09-16 14:16:42 +02:00
parent 0d54637d35
commit 4696332a46
3 changed files with 235 additions and 0 deletions

View File

@@ -0,0 +1,144 @@
<?php
declare(strict_types=1);
/*
* 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.
*/
namespace Chill\MainBundle\Tests\Authorization;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
use Chill\MainBundle\Security\Authorization\EntityWorkflowTransitionVoter;
use Chill\MainBundle\Security\Authorization\EntityWorkflowVoter;
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
/**
* @internal
*
* @coversNothing
*/
class EntityWorkflowTransitionVoterTest extends TestCase
{
use ProphecyTrait;
public function testVoteOnAttributeHappyScenario(): void
{
$entityWorkflow = new EntityWorkflow();
$object = new \stdClass();
$center = new Center();
$user = new User();
$handler = $this->prophesize(EntityWorkflowHandlerInterface::class);
$handler->getRelatedEntity($entityWorkflow)->willReturn($object);
$entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class);
$entityWorkflowManager->getHandler($entityWorkflow)->willReturn($handler);
$centerResolver = $this->prophesize(CenterResolverManagerInterface::class);
$centerResolver->resolveCenters($object)->willReturn([$center, new Center()]);
$autorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class);
$autorizationHelper->getReachableCenters('CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION')
->willReturn([$center, new Center()]);
$token = new UsernamePasswordToken($user, 'default', $user->getRoles());
$accessDecision = $this->prophesize(AccessDecisionManagerInterface::class);
$accessDecision->decide($token, [EntityWorkflowVoter::SEE], $entityWorkflow)
->willReturn(true)->shouldBeCalled();
$voter = new EntityWorkflowTransitionVoter(
$entityWorkflowManager->reveal(),
$autorizationHelper->reveal(),
$centerResolver->reveal(),
$accessDecision->reveal(),
);
self::assertEquals(Voter::ACCESS_GRANTED, $voter->vote($token, $entityWorkflow->getCurrentStep(), ['CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION']));
}
public function testVoteOnAttributeCenterNotReachable(): void
{
$entityWorkflow = new EntityWorkflow();
$object = new \stdClass();
$user = new User();
$handler = $this->prophesize(EntityWorkflowHandlerInterface::class);
$handler->getRelatedEntity($entityWorkflow)->willReturn($object);
$entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class);
$entityWorkflowManager->getHandler($entityWorkflow)->willReturn($handler);
$centerResolver = $this->prophesize(CenterResolverManagerInterface::class);
$centerResolver->resolveCenters($object)->willReturn([new Center()]);
$autorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class);
$autorizationHelper->getReachableCenters('CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION')
->willReturn([new Center()]);
$token = new UsernamePasswordToken($user, 'default', $user->getRoles());
$accessDecision = $this->prophesize(AccessDecisionManagerInterface::class);
$accessDecision->decide($token, [EntityWorkflowVoter::SEE], $entityWorkflow)
->willReturn(true)->shouldBeCalled();
$voter = new EntityWorkflowTransitionVoter(
$entityWorkflowManager->reveal(),
$autorizationHelper->reveal(),
$centerResolver->reveal(),
$accessDecision->reveal(),
);
self::assertEquals(Voter::ACCESS_DENIED, $voter->vote($token, $entityWorkflow->getCurrentStep(), ['CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION']));
}
public function testVoteNotOnSupportedAttribute(): void
{
$entityWorkflow = new EntityWorkflow();
$object = new \stdClass();
$user = new User();
$handler = $this->prophesize(EntityWorkflowHandlerInterface::class);
$handler->getRelatedEntity($entityWorkflow)->willReturn($object);
$entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class);
$entityWorkflowManager->getHandler($entityWorkflow)->willReturn($handler);
$centerResolver = $this->prophesize(CenterResolverManagerInterface::class);
$centerResolver->resolveCenters($object)->willReturn([new Center()]);
$autorizationHelper = $this->prophesize(AuthorizationHelperForCurrentUserInterface::class);
$autorizationHelper->getReachableCenters('CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION')
->willReturn([new Center()]);
$token = new UsernamePasswordToken($user, 'default', $user->getRoles());
$accessDecision = $this->prophesize(AccessDecisionManagerInterface::class);
$accessDecision->decide($token, [EntityWorkflowVoter::SEE], $entityWorkflow)
->willReturn(true);
$voter = new EntityWorkflowTransitionVoter(
$entityWorkflowManager->reveal(),
$autorizationHelper->reveal(),
$centerResolver->reveal(),
$accessDecision->reveal(),
);
self::assertEquals(Voter::ACCESS_ABSTAIN, $voter->vote($token, new \stdClass(), ['CHILL_MAIN_WORKFLOW_APPLY_ALL_TRANSITION']));
self::assertEquals(Voter::ACCESS_ABSTAIN, $voter->vote($token, $entityWorkflow->getCurrentStep(), ['SOMETHING_ELSE']));
}
}