mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Add access controls and permissions for signature steps
Implemented a Voter to enforce permissions on signature steps, ensuring only authorized users can sign steps. Updated relevant controllers and templates to reflect these permissions, and added corresponding tests to validate the changes.
This commit is contained in:
parent
1494c7ecd7
commit
9f1afb8423
@ -18,10 +18,12 @@ use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum;
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
|
||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderManagerInterface;
|
||||
use Chill\MainBundle\Security\Authorization\EntityWorkflowStepSignatureVoter;
|
||||
use Chill\MainBundle\Workflow\EntityWorkflowManager;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
@ -41,6 +43,10 @@ class SignatureRequestController
|
||||
#[Route('/api/1.0/document/workflow/{id}/signature-request', name: 'chill_docstore_signature_request')]
|
||||
public function processSignature(EntityWorkflowStepSignature $signature, Request $request): JsonResponse
|
||||
{
|
||||
if (!$this->security->isGranted(EntityWorkflowStepSignatureVoter::SIGN, $signature)) {
|
||||
throw new AccessDeniedHttpException('not authorized to sign this step');
|
||||
}
|
||||
|
||||
$entityWorkflow = $signature->getStep()->getEntityWorkflow();
|
||||
|
||||
if (EntityWorkflowSignatureStateEnum::PENDING !== $signature->getState()) {
|
||||
|
@ -14,13 +14,16 @@ namespace Chill\MainBundle\Controller;
|
||||
use Chill\DocStoreBundle\Service\Signature\PDFSignatureZoneAvailable;
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum;
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
|
||||
use Chill\MainBundle\Security\Authorization\EntityWorkflowStepSignatureVoter;
|
||||
use Chill\MainBundle\Workflow\EntityWorkflowManager;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Twig\Environment;
|
||||
|
||||
@ -32,11 +35,16 @@ final readonly class WorkflowAddSignatureController
|
||||
private NormalizerInterface $normalizer,
|
||||
private Environment $twig,
|
||||
private UrlGeneratorInterface $urlGenerator,
|
||||
private Security $security,
|
||||
) {}
|
||||
|
||||
#[Route(path: '/{_locale}/main/workflow/signature/{id}/sign', name: 'chill_main_workflow_signature_add', methods: 'GET')]
|
||||
public function __invoke(EntityWorkflowStepSignature $signature, Request $request): Response
|
||||
{
|
||||
if (!$this->security->isGranted(EntityWorkflowStepSignatureVoter::SIGN, $signature)) {
|
||||
throw new AccessDeniedHttpException('not authorized to sign this step');
|
||||
}
|
||||
|
||||
$entityWorkflow = $signature->getStep()->getEntityWorkflow();
|
||||
|
||||
if (EntityWorkflowSignatureStateEnum::PENDING !== $signature->getState()) {
|
||||
|
@ -318,7 +318,7 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
|
||||
}
|
||||
}
|
||||
|
||||
return $usersInvolved;
|
||||
return array_values($usersInvolved);
|
||||
}
|
||||
|
||||
public function getWorkflowName(): string
|
||||
@ -446,6 +446,10 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
|
||||
$newStep->addDestUser($user);
|
||||
}
|
||||
|
||||
if (null !== $transitionContextDTO->futureUserSignature) {
|
||||
$newStep->addDestUser($transitionContextDTO->futureUserSignature);
|
||||
}
|
||||
|
||||
foreach ($transitionContextDTO->futureDestEmails as $email) {
|
||||
$newStep->addDestEmail($email);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
{% if s.isSigned %}
|
||||
<span class="text-end">{{ 'workflow.signature_zone.has_signed_statement'|trans({ 'datetime' : s.stateDate }) }}</span>
|
||||
{% else %}
|
||||
{% if is_granted('CHILL_MAIN_ENTITY_WORKFLOW_SIGNATURE_SIGN', s) %}
|
||||
<ul class="record_actions slim">
|
||||
<li>
|
||||
<a class="btn btn-misc" href="{{ chill_path_add_return_path('chill_main_workflow_signature_metadata', { 'signature_id': s.id}) }}"><i class="fa fa-pencil-square-o"></i> {{ 'workflow.signature_zone.button_sign'|trans }}</a>
|
||||
@ -31,6 +32,9 @@
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<span class="text-end">{{ 'workflow.waiting_for_signature'|trans }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -0,0 +1,41 @@
|
||||
<?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\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
|
||||
final class EntityWorkflowStepSignatureVoter extends Voter
|
||||
{
|
||||
public const SIGN = 'CHILL_MAIN_ENTITY_WORKFLOW_SIGNATURE_SIGN';
|
||||
|
||||
protected function supports(string $attribute, $subject)
|
||||
{
|
||||
return $subject instanceof EntityWorkflowStepSignature && self::SIGN === $attribute;
|
||||
}
|
||||
|
||||
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token)
|
||||
{
|
||||
/** @var EntityWorkflowStepSignature $subject */
|
||||
if ($subject->getSigner() instanceof Person) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($subject->getSigner() === $token->getUser()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -18,8 +18,8 @@ final readonly class ChillEntityRenderManager implements ChillEntityRenderManage
|
||||
public function __construct(/**
|
||||
* @var iterable<ChillEntityRenderInterface>
|
||||
*/
|
||||
private iterable $renders)
|
||||
{
|
||||
private iterable $renders,
|
||||
) {
|
||||
$this->defaultRender = new ChillEntityRender();
|
||||
}
|
||||
|
||||
|
@ -18,12 +18,14 @@ use Chill\DocStoreBundle\Service\Signature\PDFSignatureZoneAvailable;
|
||||
use Chill\MainBundle\Controller\WorkflowAddSignatureController;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||
use Chill\MainBundle\Security\Authorization\EntityWorkflowStepSignatureVoter;
|
||||
use Chill\MainBundle\Workflow\EntityWorkflowManager;
|
||||
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Twig\Environment;
|
||||
|
||||
@ -65,7 +67,11 @@ class WorkflowAddSignatureControllerTest extends TestCase
|
||||
|
||||
$urlGenerator = $this->createMock(UrlGeneratorInterface::class);
|
||||
|
||||
$controller = new WorkflowAddSignatureController($entityWorkflowManager, $pdfSignatureZoneAvailable, $normalizer, $twig, $urlGenerator);
|
||||
$security = $this->createMock(Security::class);
|
||||
$security->expects($this->once())->method('isGranted')->with(EntityWorkflowStepSignatureVoter::SIGN, $signature)
|
||||
->willReturn(true);
|
||||
|
||||
$controller = new WorkflowAddSignatureController($entityWorkflowManager, $pdfSignatureZoneAvailable, $normalizer, $twig, $urlGenerator, $security);
|
||||
|
||||
$actual = $controller($signature, new Request());
|
||||
|
||||
|
@ -531,9 +531,10 @@ workflow:
|
||||
Remove hold: Enlever la mise en attente
|
||||
On hold: En attente
|
||||
Automated transition: Transition automatique
|
||||
waiting_for_signature: En attente de signature
|
||||
|
||||
signature_zone:
|
||||
title: Appliquer les signatures électroniques
|
||||
title: Signatures électroniques
|
||||
button_sign: Signer
|
||||
metadata:
|
||||
sign_by: 'Signature pour %name%'
|
||||
|
Loading…
x
Reference in New Issue
Block a user