Merge remote-tracking branch 'origin/master' into signature-app-master

This commit is contained in:
2024-11-14 12:18:07 +01:00
6 changed files with 349 additions and 278 deletions

View File

@@ -15,7 +15,6 @@ use Chill\MainBundle\Workflow\Helper\WorkflowRelatedEntityPermissionHelper;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Chill\MainBundle\Workflow\EntityWorkflowMarkingStore;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
@@ -23,6 +22,7 @@ use Chill\PersonBundle\Entity\Person;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Clock\MockClock;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Workflow\DefinitionBuilder;
use Symfony\Component\Workflow\Metadata\InMemoryMetadataStore;
@@ -41,67 +41,85 @@ class WorkflowRelatedEntityPermissionHelperTest extends TestCase
use ProphecyTrait;
/**
* @dataProvider provideDataNotBlockByWorkflow
* @dataProvider provideDataAllowedByWorkflowReadOperation
*
* @param list<EntityWorkflow> $entityWorkflows
*/
public function testNotBlockByWorkflow(EntityWorkflow $entityWorkflow, User $user, bool $expected, string $message): void
{
public function testAllowedByWorkflowRead(
array $entityWorkflows,
User $user,
string $expected,
?\DateTimeImmutable $atDate,
string $message,
): void {
// all entities must have this workflow name, so we are ok to set it here
$entityWorkflow->setWorkflowName('dummy');
$object = new \stdClass();
$helper = $this->buildHelper($object, $entityWorkflow, $user);
foreach ($entityWorkflows as $entityWorkflow) {
$entityWorkflow->setWorkflowName('dummy');
}
$helper = $this->buildHelper($entityWorkflows, $user, $atDate);
self::assertEquals($expected, $helper->notBlockedByWorkflow($entityWorkflow), $message);
self::assertEquals($expected, $helper->isAllowedByWorkflowForReadOperation(new \stdClass()), $message);
}
/**
* @dataProvider provideDataAllowedByWorkflow
* @dataProvider provideDataAllowedByWorkflowWriteOperation
*
* @param list<EntityWorkflow> $entityWorkflows
*/
public function testAllowedByWorkflow(EntityWorkflow $entityWorkflow, User $user, bool $expected, string $message): void
{
public function testAllowedByWorkflowWrite(
array $entityWorkflows,
User $user,
string $expected,
?\DateTimeImmutable $atDate,
string $message,
): void {
// all entities must have this workflow name, so we are ok to set it here
$entityWorkflow->setWorkflowName('dummy');
$object = new \stdClass();
$helper = $this->buildHelper($object, $entityWorkflow, $user);
foreach ($entityWorkflows as $entityWorkflow) {
$entityWorkflow->setWorkflowName('dummy');
}
$helper = $this->buildHelper($entityWorkflows, $user, $atDate);
self::assertEquals($expected, $helper->isAllowedByWorkflow($entityWorkflow), $message);
self::assertEquals($expected, $helper->isAllowedByWorkflowForWriteOperation(new \stdClass()), $message);
}
public function testNoWorkflow(): void
{
$object = new \stdClass();
$helper = $this->buildHelper($object, null, $user = new User());
self::assertTrue($helper->notBlockedByWorkflow($object), "the user is not blocked by the user, as there aren't any user inside");
$helper = $this->buildHelper([], new User(), null);
self::assertEquals(WorkflowRelatedEntityPermissionHelper::ABSTAIN, $helper->isAllowedByWorkflowForWriteOperation(new \stdClass()));
self::assertEquals(WorkflowRelatedEntityPermissionHelper::ABSTAIN, $helper->isAllowedByWorkflowForReadOperation(new \stdClass()));
}
private function buildHelper(object $relatedEntity, ?EntityWorkflow $entityWorkflow, User $user): WorkflowRelatedEntityPermissionHelper
/**
* @param list<EntityWorkflow> $entityWorkflows
*/
private function buildHelper(array $entityWorkflows, User $user, ?\DateTimeImmutable $atDateTime): WorkflowRelatedEntityPermissionHelper
{
$security = $this->prophesize(Security::class);
$security->getUser()->willReturn($user);
$entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class);
if (null !== $entityWorkflow) {
$entityWorkflowManager->findByRelatedEntity(Argument::type('object'))->willReturn([$entityWorkflow]);
} else {
$entityWorkflowManager->findByRelatedEntity(Argument::type('object'))->willReturn([]);
}
$entityWorkflowManager->findByRelatedEntity(Argument::type('object'))->willReturn($entityWorkflows);
return new WorkflowRelatedEntityPermissionHelper($security->reveal(), $entityWorkflowManager->reveal(), $this->buildRegistry());
return new WorkflowRelatedEntityPermissionHelper($security->reveal(), $entityWorkflowManager->reveal(), $this->buildRegistry(), new MockClock($atDateTime ?? new \DateTimeImmutable()));
}
public static function provideDataAllowedByWorkflow(): iterable
public static function provideDataAllowedByWorkflowReadOperation(): iterable
{
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
yield [$entityWorkflow, new User(), false, 'not allowed because the user is not present as a dest user'];
yield [[$entityWorkflow], new User(), WorkflowRelatedEntityPermissionHelper::ABSTAIN, new \DateTimeImmutable(),
'abstain because the user is not present as a dest user'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
yield [$entityWorkflow, $user, true, 'allowed because the user is a current user'];
yield [[$entityWorkflow], $user, WorkflowRelatedEntityPermissionHelper::FORCE_GRANT, new \DateTimeImmutable(),
'force grant because the user is a current user'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
@@ -112,7 +130,68 @@ class WorkflowRelatedEntityPermissionHelperTest extends TestCase
$dto->futureDestUsers[] = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
yield [$entityWorkflow, $user, true, 'allowed because the user was a previous user'];
yield [[$entityWorkflow], $user, WorkflowRelatedEntityPermissionHelper::FORCE_GRANT, new \DateTimeImmutable(),
'force grant because the user was a previous user'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futurePersonSignatures[] = new Person();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
yield [[$entityWorkflow], new User(), WorkflowRelatedEntityPermissionHelper::FORCE_GRANT, new \DateTimeImmutable(),
'force grant because there is a signature for person'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futurePersonSignatures[] = new Person();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
$signature = $entityWorkflow->getCurrentStep()->getSignatures()->first();
$signature->setState(EntityWorkflowSignatureStateEnum::SIGNED)->setStateDate(new \DateTimeImmutable('2024-01-01T12:00:00'));
yield [[$entityWorkflow], new User(), WorkflowRelatedEntityPermissionHelper::ABSTAIN, new \DateTimeImmutable('2024-01-10T12:00:00'),
'abstain because there is a signature for person, already signed, and for a long time ago'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futurePersonSignatures[] = new Person();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
$signature = $entityWorkflow->getCurrentStep()->getSignatures()->first();
$signature->setState(EntityWorkflowSignatureStateEnum::SIGNED)
->setStateDate(new \DateTimeImmutable('2024-01-01T12:00:00'));
yield [[$entityWorkflow], new User(), WorkflowRelatedEntityPermissionHelper::FORCE_GRANT,
new \DateTimeImmutable('2024-01-01T12:30:00'),
'force grant because there is a signature for person, already signed, a short time ago'];
}
public static function provideDataAllowedByWorkflowWriteOperation(): iterable
{
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
yield [[$entityWorkflow], new User(), WorkflowRelatedEntityPermissionHelper::ABSTAIN, new \DateTimeImmutable(),
'abstain because the user is not present as a dest user'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
yield [[$entityWorkflow], $user, WorkflowRelatedEntityPermissionHelper::FORCE_GRANT, new \DateTimeImmutable(),
'force grant because the user is a current user'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
yield [[$entityWorkflow], $user, WorkflowRelatedEntityPermissionHelper::FORCE_GRANT, new \DateTimeImmutable(),
'force grant because the user was a previous user'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
@@ -122,7 +201,8 @@ class WorkflowRelatedEntityPermissionHelperTest extends TestCase
$entityWorkflow->setStep('final_positive', $dto, 'to_final_positive', new \DateTimeImmutable(), new User());
$entityWorkflow->getCurrentStep()->setIsFinal(true);
yield [$entityWorkflow, $user, false, 'not allowed because: user was a previous user, but it is finalized positive'];
yield [[$entityWorkflow], $user, WorkflowRelatedEntityPermissionHelper::FORCE_DENIED, new \DateTimeImmutable(),
'force denied: user was a previous user, but it is finalized positive'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
@@ -132,80 +212,48 @@ class WorkflowRelatedEntityPermissionHelperTest extends TestCase
$entityWorkflow->setStep('final_negative', $dto, 'to_final_negative', new \DateTimeImmutable());
$entityWorkflow->getCurrentStep()->setIsFinal(true);
yield [$entityWorkflow, $user, true, 'allowed: user was a previous user, it is finalized, but finalized negative'];
}
public static function provideDataNotBlockByWorkflow(): iterable
{
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable());
yield [$entityWorkflow, new User(), false, 'blocked because the user is not present as a dest user'];
yield [[$entityWorkflow], $user, WorkflowRelatedEntityPermissionHelper::ABSTAIN, new \DateTimeImmutable(),
'abstain: user was a previous user, it is finalized, but finalized negative'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futurePersonSignatures[] = new Person();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
$signature = $entityWorkflow->getCurrentStep()->getSignatures()->first();
$signature->setState(EntityWorkflowSignatureStateEnum::SIGNED)->setStateDate(new \DateTimeImmutable());
yield [$entityWorkflow, $user, true, 'allowed because the user is present as a dest user'];
yield [[$entityWorkflow], $user, WorkflowRelatedEntityPermissionHelper::FORCE_DENIED, new \DateTimeImmutable(),
'force denied because there is a signature'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
$dto->futurePersonSignatures[] = new Person();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
yield [$entityWorkflow, $user, true, 'allowed because the user is present as a **previous** dest user'];
yield [[$entityWorkflow], $user, WorkflowRelatedEntityPermissionHelper::FORCE_GRANT, new \DateTimeImmutable(),
'force grant: there is a signature, but still pending'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('final_positive', $dto, 'to_final_positive', new \DateTimeImmutable(), $user);
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futurePersonSignatures[] = new Person();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
$signature = $entityWorkflow->getCurrentStep()->getSignatures()->first();
$signature->setState(EntityWorkflowSignatureStateEnum::SIGNED)->setStateDate(new \DateTimeImmutable());
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$entityWorkflow->setStep('final_negative', $dto, 'to_final_negative', new \DateTimeImmutable(), new User());
$entityWorkflow->getCurrentStep()->setIsFinal(true);
yield [$entityWorkflow, $user, false, 'blocked because the step is final, and final positive'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('final_negative', $dto, 'to_final_negative', new \DateTimeImmutable(), $user);
$entityWorkflow->getCurrentStep()->setIsFinal(true);
yield [$entityWorkflow, $user, true, 'allowed because the step is final, and final negative'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
$step = $entityWorkflow->getCurrentStep();
new EntityWorkflowStepSignature($step, new Person());
yield [$entityWorkflow, $user, true, 'allow, a signature is present but still pending'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
$step = $entityWorkflow->getCurrentStep();
$signature = new EntityWorkflowStepSignature($step, new Person());
$signature->setState(EntityWorkflowSignatureStateEnum::SIGNED);
yield [$entityWorkflow, $user, false, 'blocked, a signature is present and signed'];
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureDestUsers[] = $user = new User();
$entityWorkflow->setStep('final_negative', $dto, 'to_final_negative', new \DateTimeImmutable(), $user);
$step = $entityWorkflow->getCurrentStep();
$signature = new EntityWorkflowStepSignature($step, new Person());
$signature->setState(EntityWorkflowSignatureStateEnum::SIGNED);
yield [$entityWorkflow, $user, false, 'blocked, a signature is present and signed, although the workflow is final negative'];
yield [[$entityWorkflow], $user, WorkflowRelatedEntityPermissionHelper::ABSTAIN, new \DateTimeImmutable(),
'abstain: there is a signature on a canceled workflow'];
}
private static function buildRegistry(): Registry

View File

@@ -11,29 +11,100 @@ declare(strict_types=1);
namespace Chill\MainBundle\Workflow\Helper;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Workflow\Registry;
/**
* Check if an object, associated with a workflow, is blocked, or not, by this workflow.
* Helper to give supplementary permissions to a related entity.
*
* If a related entity is associated within a workflow, the logic of the workflow can give more permissions, or
* remove some permissions.
*
* The methods of this helper return either:
*
* - FORCE_GRANT, which means that a permission can be given, even if it would be denied when the related
* entity is not associated with a workflow;
* - FORCE_DENIED, which means that a permission should be denied, even if it would be granted when the related entity
* is not associated with a workflow
* - ABSTAIN, if there is no workflow logic to add or remove permission
*
* For read operations:
*
* - if the user is involved in the workflow (is part of the current step, of a step before), the user is granted read
* operation;
* - if there is a pending signature for a person, the workflow grant access to the related entity;
* - if there a signature applyied in less than 12 hours, the workflow grant access to the related entity. This allow to
* show the related entity to the person during this time frame.
*
*
* For write operation:
*
* - if the workflow is finalized "positive" (means "not canceled"), the workflow denys write operations;
* - if there isn't any finalized "positive" workflow, and if there is a signature appliyed for a running workflow (not finalized nor canceled),
* the workflow denys write operations;
* - if there is no case above and the user is involved in the workflow (is part of the current step, of a step before), the user is granted;
*/
class WorkflowRelatedEntityPermissionHelper
{
public const FORCE_GRANT = 'FORCE_GRANT';
public const FORCE_DENIED = 'FORCE_DENIED';
public const ABSTAIN = 'ABSTAIN';
public function __construct(
private readonly Security $security,
private readonly EntityWorkflowManager $entityWorkflowManager,
private readonly Registry $registry,
private readonly ClockInterface $clock,
) {}
public function isAllowedByWorkflow(object $entity): bool
/**
* @return 'FORCE_GRANT'|'FORCE_DENIED'|'ABSTAIN'
*/
public function isAllowedByWorkflowForReadOperation(object $entity): string
{
$entityWorkflows = $this->entityWorkflowManager->findByRelatedEntity($entity);
$currentUser = $this->security->getUser();
if ($this->isUserInvolvedInAWorkflow($entityWorkflows)) {
return self::FORCE_GRANT;
}
// give a view permission if there is a Person signature pending, or in the 12 hours following
// the signature last state
foreach ($entityWorkflows as $workflow) {
foreach ($workflow->getCurrentStep()->getSignatures() as $signature) {
if ('person' === $signature->getSignerKind()) {
if (EntityWorkflowSignatureStateEnum::PENDING === $signature->getState()) {
return self::FORCE_GRANT;
}
$signatureDate = $signature->getStateDate();
$visibleUntil = $signatureDate->add(new \DateInterval('PT12H'));
if ($visibleUntil > $this->clock->now()) {
return self::FORCE_GRANT;
}
}
}
}
return self::ABSTAIN;
}
/**
* @return 'FORCE_GRANT'|'FORCE_DENIED'|'ABSTAIN'
*/
public function isAllowedByWorkflowForWriteOperation(object $entity): string
{
$entityWorkflows = $this->entityWorkflowManager->findByRelatedEntity($entity);
$runningWorkflows = [];
// if a workflow is finalized positive, we are not allowed to edit to document any more
foreach ($entityWorkflows as $entityWorkflow) {
// if the user is finalized, we have to check if the workflow is finalPositive, or not
if ($entityWorkflow->isFinal()) {
$workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
$marking = $workflow->getMarkingStore()->getMarking($entityWorkflow);
@@ -41,12 +112,40 @@ class WorkflowRelatedEntityPermissionHelper
$placeMetadata = $workflow->getMetadataStore()->getPlaceMetadata($place);
if (true === ($placeMetadata['isFinalPositive'] ?? false)) {
// the workflow is final, and final positive, so we stop here.
return false;
return self::FORCE_DENIED;
}
}
} else {
$runningWorkflows[] = $entityWorkflow;
}
}
// if there is a signature on a **running workflow**, no one can edit the workflow any more
foreach ($runningWorkflows as $entityWorkflow) {
foreach ($entityWorkflow->getSteps() as $step) {
foreach ($step->getSignatures() as $signature) {
if (EntityWorkflowSignatureStateEnum::SIGNED === $signature->getState()) {
return self::FORCE_DENIED;
}
}
}
}
// allow only the users involved
if ($this->isUserInvolvedInAWorkflow($runningWorkflows)) {
return self::FORCE_GRANT;
}
return self::ABSTAIN;
}
/**
* @param list<EntityWorkflow> $entityWorkflows
*/
private function isUserInvolvedInAWorkflow(array $entityWorkflows): bool
{
$currentUser = $this->security->getUser();
foreach ($entityWorkflows as $entityWorkflow) {
// so, the workflow is running... We return true if the current user is involved
foreach ($entityWorkflow->getSteps() as $step) {
@@ -58,58 +157,4 @@ class WorkflowRelatedEntityPermissionHelper
return false;
}
/**
* Return true if the user is allowed to update the given object.
*
* Return false if some workflow block the edition of the object.
*/
public function notBlockedByWorkflow(object $entity): bool
{
$entityWorkflows = $this->entityWorkflowManager->findByRelatedEntity($entity);
$currentUser = $this->security->getUser();
$usersInvolved = [];
$entityWorkflowsNotFinalizedPositive = [];
foreach ($entityWorkflows as $entityWorkflow) {
// as soon as there is one signatured applyied, we are not able to
// edit the document any more
foreach ($entityWorkflow->getSteps() as $step) {
foreach ($step->getSignatures() as $signature) {
if (EntityWorkflowSignatureStateEnum::SIGNED === $signature->getState()) {
return false;
}
}
}
if ($entityWorkflow->isFinal()) {
$workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
$marking = $workflow->getMarkingStore()->getMarking($entityWorkflow);
foreach ($marking->getPlaces() as $place => $active) {
$metadata = $workflow->getMetadataStore()->getPlaceMetadata($place);
if ($metadata['isFinalPositive'] ?? true) {
return false;
}
}
} else {
$entityWorkflowsNotFinalizedPositive[] = $entityWorkflow;
foreach ($entityWorkflow->getSteps() as $step) {
foreach ($step->getAllDestUser()->toArray() as $user) {
$usersInvolved[] = $user;
}
}
}
}
// if there isn't any user, but a workflow, blocked
if ([] !== $entityWorkflowsNotFinalizedPositive) {
if ([] === $usersInvolved) {
return false;
}
return in_array($currentUser, $usersInvolved, true);
}
return true;
}
}