Adjust logic for removing the hold on a workflow only by user who owns the hold and when a transition is applied on the workflow

This commit is contained in:
Julie Lenaerts 2024-08-30 12:59:08 +02:00 committed by Julien Fastré
parent 41ffc470a0
commit 745a29f742
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
5 changed files with 48 additions and 26 deletions

View File

@ -298,7 +298,7 @@ class WorkflowController extends AbstractController
$workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
$errors = [];
$signatures = $entityWorkflow->getCurrentStep()->getSignatures();
$holdOnStepByUser = $this->entityWorkflowStepHoldRepository->findOneByStepAndUser($entityWorkflow->getCurrentStep(), $this->security->getUser());
$onHoldStep = $this->entityWorkflowStepHoldRepository->findByWorkflow($entityWorkflow);
if (\count($workflow->getEnabledTransitions($entityWorkflow)) > 0) {
// possible transition
@ -343,6 +343,10 @@ class WorkflowController extends AbstractController
$this->entityManager->flush();
if ($onHoldStep) {
$this->entityManager->remove($onHoldStep);
}
return $this->redirectToRoute('chill_main_workflow_show', ['id' => $entityWorkflow->getId()]);
}
@ -361,7 +365,7 @@ class WorkflowController extends AbstractController
'entity_workflow' => $entityWorkflow,
'transition_form_errors' => $errors,
'signatures' => $signatures,
'holdOnStepByUser' => $holdOnStepByUser,
'onHoldStep' => $onHoldStep,
]
);
}

View File

@ -4,6 +4,7 @@ namespace Chill\MainBundle\Controller;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepHold;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowStepHoldRepository;
use Chill\MainBundle\Security\ChillSecurity;
use Doctrine\ORM\EntityManagerInterface;
@ -20,32 +21,23 @@ class WorkflowOnHoldController extends AbstractController
private readonly EntityManagerInterface $entityManager,
private readonly Security $security,
private readonly Registry $registry,
private readonly EntityWorkflowStepHoldRepository $entityWorkflowStepHoldRepository
private readonly EntityWorkflowStepHoldRepository $entityWorkflowStepHoldRepository,
private readonly EntityWorkflowRepository $entityWorkflowRepository
) {}
#[Route(path: '/{_locale}/main/workflow/{id}/hold', name: 'chill_main_workflow_on_hold')]
public function putOnHold(EntityWorkflow $entityWorkflow, Request $request): Response
{
$entityWorkflow = $this->entityWorkflowRepository->find($entityWorkflow);
$currentStep = $entityWorkflow->getCurrentStep();
$currentUser = $this->security->getUser();
$workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
$enabledTransitions = $workflow->getEnabledTransitions($entityWorkflow);
if (\count($enabledTransitions) === 0) {
throw $this->createAccessDeniedException('No transitions are available for the current workflow state.');
}
$isTransitionAllowed = false;
foreach ($enabledTransitions as $transition) {
if ($workflow->can($entityWorkflow, $transition->getName())) {
$isTransitionAllowed = true;
break;
}
}
if (!$isTransitionAllowed) {
throw $this->createAccessDeniedException('You are not allowed to apply any transitions to this workflow, therefore you cannot put it on hold.');
if (!count($enabledTransitions) > 0) {
throw $this->createAccessDeniedException('You are not allowed to apply any transitions to this workflow, therefore you cannot toggle the hold status.');
}
$stepHold = new EntityWorkflowStepHold($currentStep, $currentUser);
@ -61,10 +53,16 @@ class WorkflowOnHoldController extends AbstractController
{
$hold = $this->entityWorkflowStepHoldRepository->findById($holdId);
$entityWorkflow = $hold->getStep()->getEntityWorkflow();
$currentUser = $this->security->getUser();
if ($hold->getByUser() !== $currentUser) {
throw $this->createAccessDeniedException('You are not allowed to remove the hold status.');
}
$this->entityManager->remove($hold);
$this->entityManager->flush();
return $this->redirectToRoute('chill_main_workflow_show', ['id' => $entityWorkflow->getId()]);
}
}

View File

@ -12,12 +12,14 @@ declare(strict_types=1);
namespace Chill\MainBundle\Repository\Workflow;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStep;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepHold;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Workflow\Workflow;
/**
* @template-extends ServiceEntityRepository<EntityWorkflowStepHold>
@ -58,6 +60,23 @@ class EntityWorkflowStepHoldRepository extends ServiceEntityRepository
return $this->findBy(['step' => $step]);
}
/**
* @throws NonUniqueResultException
*/
public function findByWorkflow(EntityWorkflow $workflow): ?EntityWorkflowStepHold
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('h')
->from(EntityWorkflowStepHold::class, 'h')
->join('h.step', 's')
->join('s.entityWorkflow', 'w')
->where('w = :workflow')
->setParameter('workflow', $workflow);
return $qb->getQuery()->getOneOrNullResult();
}
/**
* Find a single EntityWorkflowStepHold by step and user.
*

View File

@ -68,9 +68,9 @@
<section class="step my-4">{% include '@ChillMain/Workflow/_history.html.twig' %}</section>
<ul class="record_actions sticky-form-buttons">
{% if holdOnStepByUser|length > 0 %}
{% if onHoldStep is not null %}
<li>
<a class="btn btn-misc" href="{{ path('chill_main_workflow_remove_hold', {'holdId': holdOnStepByUser.id}) }}"><i class="fa fa-hourglass"></i>
<a class="btn btn-misc" href="{{ path('chill_main_workflow_remove_hold', {'holdId': onHoldStep.id}) }}"><i class="fa fa-hourglass"></i>
{{ 'workflow.Remove hold'|trans }}
</a>
</li>

View File

@ -30,6 +30,7 @@ class WorkflowOnHoldControllerTest extends KernelTestCase
private $workflow;
private $currentStep;
private $currentUser;
private $controller;
protected function setUp(): void
{
@ -53,6 +54,13 @@ class WorkflowOnHoldControllerTest extends KernelTestCase
$this->registry->method('get')->with($this->entityWorkflow, 'workflow_name')->willReturn($this->workflow);
$this->workflow->method('getEnabledTransitions')->with($this->entityWorkflow)->willReturn([]);
$this->entityWorkflow->method('getUsersInvolved')->willReturn([]);
$this->controller = new WorkflowOnHoldController(
$this->entityManager,
$this->security,
$this->registry,
$this->entityWorkflowStepHoldRepository
);
}
public function testPutOnHoldPersistence(): void
@ -76,13 +84,6 @@ class WorkflowOnHoldControllerTest extends KernelTestCase
$this->entityManager->expects($this->once())
->method('flush');
$controller = new WorkflowOnHoldController(
$this->entityManager,
$this->security,
$this->registry,
$this->entityWorkflowStepHoldRepository
);
$request = new Request();
$controller->putOnHold($this->entityWorkflow, $request);
}