Skip to content

Commit

Permalink
Merge pull request #3544 from MTES-MCT/feature/3267-signalement-statu…
Browse files Browse the repository at this point in the history
…s-buttons

[Tech] Simplification des statuts dans le code twig de la fiche signalement
  • Loading branch information
hmeneuvrier authored Jan 22, 2025
2 parents d00784e + f7a2c5e commit 6df57f0
Show file tree
Hide file tree
Showing 13 changed files with 242 additions and 129 deletions.
7 changes: 4 additions & 3 deletions src/Controller/Back/AffectationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use App\Messenger\InterconnectionBus;
use App\Repository\AffectationRepository;
use App\Repository\PartnerRepository;
use App\Security\Voter\AffectationVoter;
use App\Service\Signalement\SearchFilterOptionDataProvider;
use App\Specification\Signalement\FirstAffectationAcceptedSpecification;
use Psr\Cache\InvalidArgumentException;
Expand Down Expand Up @@ -50,7 +51,7 @@ public function toggleAffectationSignalement(
Signalement $signalement,
TagAwareCacheInterface $cache,
): RedirectResponse|JsonResponse {
$this->denyAccessUnlessGranted('ASSIGN_TOGGLE', $signalement);
$this->denyAccessUnlessGranted(AffectationVoter::TOGGLE, $signalement);
if ($this->isCsrfTokenValid('signalement_affectation_'.$signalement->getId(), $request->get('_token'))) {
$data = $request->get('signalement-affectation');
if (isset($data['partners'])) {
Expand Down Expand Up @@ -96,7 +97,7 @@ public function removePartnerAffectation(
Signalement $signalement,
AffectationRepository $affectationRepository,
): RedirectResponse|JsonResponse {
$this->denyAccessUnlessGranted('ASSIGN_TOGGLE', $signalement);
$this->denyAccessUnlessGranted(AffectationVoter::TOGGLE, $signalement);
$idAffectation = $request->get('affectation');
$affectation = $affectationRepository->findOneBy(['id' => $idAffectation]);
if (!$affectation || $affectation->getSignalement()->getId() !== $signalement->getId()) {
Expand Down Expand Up @@ -132,7 +133,7 @@ public function affectationResponseSignalement(
DossierMessageFactory $dossierMessageFactory,
MessageBusInterface $bus,
): Response {
$this->denyAccessUnlessGranted('ASSIGN_ANSWER', $affectation);
$this->denyAccessUnlessGranted(AffectationVoter::ANSWER, $affectation);
if ($this->isCsrfTokenValid('signalement_affectation_response_'.$signalement->getId(), $request->get('_token'))
&& $response = $request->get('signalement-affectation-response')
) {
Expand Down
3 changes: 2 additions & 1 deletion src/Controller/Back/HistoryEntryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Manager\HistoryEntryManager;
use App\Repository\SignalementRepository;
use App\Security\Voter\AffectationVoter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand All @@ -22,7 +23,7 @@ public function listHistoryAffectation(
if (
!$signalement
|| !$this->isGranted('SIGN_VIEW', $signalement)
|| !$this->isGranted('ASSIGN_SEE', $signalement)
|| !$this->isGranted(AffectationVoter::SEE, $signalement)
) {
return $this->json(['response' => 'error'], Response::HTTP_FORBIDDEN);
}
Expand Down
49 changes: 33 additions & 16 deletions src/Controller/Back/SignalementController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
use App\Repository\SignalementQualificationRepository;
use App\Repository\TagRepository;
use App\Repository\ZoneRepository;
use App\Security\Voter\AffectationVoter;
use App\Security\Voter\SignalementVoter;
use App\Service\Signalement\PhotoHelper;
use App\Service\Signalement\SignalementDesordresProcessor;
use Doctrine\ORM\EntityManagerInterface;
Expand Down Expand Up @@ -73,24 +75,36 @@ public function viewSignalement(
SignalementViewedEvent::NAME
);

$isRefused = $isAccepted = $isClosedForMe = null;
$canAnswerAffectation = $canCancelRefusedAffectation = false;
$isAffectationRefused = $isAffectationAccepted = false;
$isClosedForMe = null;
$partner = $user->getPartnerInTerritoryOrFirstOne($signalement->getTerritory());
if ($isAffected = $signalement->getAffectations()->filter(function (Affectation $affectation) use ($partner) {
if ($affectation = $signalement->getAffectations()->filter(function (Affectation $affectation) use ($partner) {
return $affectation->getPartner() === $partner;
})->first()) {
switch ($isAffected->getStatut()) {
switch ($affectation->getStatut()) {
case Affectation::STATUS_ACCEPTED:
$isAccepted = $isAffected;
$isAffectationAccepted = true;
break;
case Affectation::STATUS_REFUSED:
$isRefused = $isAffected;
$isAffectationRefused = true;
$canCancelRefusedAffectation = $this->isGranted(AffectationVoter::ANSWER, $affectation);
break;
case Affectation::STATUS_CLOSED:
$isClosedForMe = true;
break;
case Affectation::STATUS_WAIT:
$canAnswerAffectation = $this->isGranted(AffectationVoter::ANSWER, $affectation);
break;
}
}

$isClosedForMe = $isClosedForMe ?? Signalement::STATUS_CLOSED === $signalement->getStatut();
$canValidateOrRefuseSignalement = $this->isGranted(SignalementVoter::VALIDATE, $signalement)
&& !$isClosedForMe
&& Signalement::STATUS_NEED_VALIDATION === $signalement->getStatut();
$canReopenAffectation = $affectation ? $this->isGranted(AffectationVoter::REOPEN, $affectation) : false;

$clotureForm = $this->createForm(ClotureType::class);
$clotureForm->handleRequest($request);
$eventParams = [];
Expand Down Expand Up @@ -118,9 +132,9 @@ public function viewSignalement(
);
$reference = $signalement->getReference();

/* @var Affectation $isAffected */
} elseif ($isAffected) {
$entity = $affectationManager->closeAffectation($isAffected, $user, $eventParams['motif_cloture'], true);
/* @var Affectation $affectation */
} elseif ($affectation) {
$entity = $affectationManager->closeAffectation($affectation, $user, $eventParams['motif_cloture'], true);
$reference = $entity->getSignalement()->getReference();
}

Expand All @@ -139,7 +153,7 @@ public function viewSignalement(
if (Signalement::STATUS_ACTIVE === $signalement->getStatut()) {
$canEditSignalement = $this->isGranted('ROLE_ADMIN')
|| $this->isGranted('ROLE_ADMIN_TERRITORY')
|| $isAccepted;
|| $isAffectationAccepted;
}

$signalementQualificationNDE = $signalementQualificationRepository->findOneBy([
Expand Down Expand Up @@ -196,13 +210,16 @@ public function viewSignalement(
'situations' => $infoDesordres['criticitesArranged'],
'photos' => $infoDesordres['photos'],
'criteres' => $infoDesordres['criteres'],
'needValidation' => Signalement::STATUS_NEED_VALIDATION === $signalement->getStatut(),
'canEditSignalement' => $canEditSignalement,
'isAffected' => $isAffected,
'isAccepted' => $isAccepted,
'isClosed' => Signalement::STATUS_CLOSED === $signalement->getStatut(),
'canAnswerAffectation' => $canAnswerAffectation,
'canCancelRefusedAffectation' => $canCancelRefusedAffectation,
'canValidateOrRefuseSignalement' => $canValidateOrRefuseSignalement,
'canReopenAffectation' => $canReopenAffectation,
'affectation' => $affectation,
'isAffectationAccepted' => $isAffectationAccepted,
'isSignalementClosed' => Signalement::STATUS_CLOSED === $signalement->getStatut(),
'isClosedForMe' => $isClosedForMe,
'isRefused' => $isRefused,
'isAffectationRefused' => $isAffectationRefused,
'isDanger' => $infoDesordres['isDanger'],
'signalement' => $signalement,
'partners' => $partners,
Expand All @@ -217,8 +234,8 @@ public function viewSignalement(
'partnersCanVisite' => $partnerVisite,
'pendingVisites' => $interventionRepository->getPendingVisitesForSignalement($signalement),
'allPhotosOrdered' => $allPhotosOrdered,
'canTogglePartnerAffectation' => $this->isGranted('ASSIGN_TOGGLE', $signalement),
'canSeePartnerAffectation' => $this->isGranted('ASSIGN_SEE', $signalement),
'canTogglePartnerAffectation' => $this->isGranted(AffectationVoter::TOGGLE, $signalement),
'canSeePartnerAffectation' => $this->isGranted(AffectationVoter::SEE, $signalement),
'zones' => $zoneRepository->findZonesBySignalement($signalement),
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\User\UserInterface;

class AssignmentVoter extends Voter
class AffectationVoter extends Voter
{
public const SEE = 'ASSIGN_SEE';
public const TOGGLE = 'ASSIGN_TOGGLE';
public const ANSWER = 'ASSIGN_ANSWER';
public const CLOSE = 'ASSIGN_CLOSE';
public const REOPEN = 'ASSIGN_REOPEN';
public const SEE = 'AFFECTATION_SEE';
public const TOGGLE = 'AFFECTATION_TOGGLE';
public const ANSWER = 'AFFECTATION_ANSWER';
public const CLOSE = 'AFFECTATION_CLOSE';
public const REOPEN = 'AFFECTATION_REOPEN';

protected function supports(string $attribute, $subject): bool
{
Expand Down Expand Up @@ -61,18 +61,18 @@ private function canToggle(Signalement $signalement, User $user)
&& Signalement::STATUS_ACTIVE === $signalement->getStatut();
}

private function canAnswer(Affectation $assignment, User $user): bool
private function canAnswer(Affectation $affectation, User $user): bool
{
return $assignment->getPartner() === $user->getPartnerInTerritory($assignment->getSignalement()->getTerritory()) && Signalement::STATUS_ACTIVE === $assignment->getSignalement()->getStatut();
return $affectation->getPartner() === $user->getPartnerInTerritory($affectation->getSignalement()->getTerritory()) && Signalement::STATUS_ACTIVE === $affectation->getSignalement()->getStatut();
}

private function canClose(Affectation $assignment, User $user): bool
private function canClose(Affectation $affectation, User $user): bool
{
return $this->canAnswer($assignment, $user) && Affectation::STATUS_ACCEPTED === $assignment->getStatut();
return $this->canAnswer($affectation, $user) && Affectation::STATUS_ACCEPTED === $affectation->getStatut();
}

private function canReopen(Affectation $assignment, User $user): bool
private function canReopen(Affectation $affectation, User $user): bool
{
return $this->canAnswer($assignment, $user) && Affectation::STATUS_CLOSED === $assignment->getStatut();
return $this->canAnswer($affectation, $user) && Affectation::STATUS_CLOSED === $affectation->getStatut();
}
}
43 changes: 29 additions & 14 deletions src/Security/Voter/SignalementVoter.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class SignalementVoter extends Voter
{
public const VALIDATE = 'SIGN_VALIDATE';
public const CLOSE = 'SIGN_CLOSE';
public const REOPEN = 'SIGN_REOPEN';
public const DELETE = 'SIGN_DELETE';
public const EDIT = 'SIGN_EDIT';
public const VIEW = 'SIGN_VIEW';
Expand All @@ -33,7 +34,7 @@ public function __construct(

protected function supports(string $attribute, $subject): bool
{
return \in_array($attribute, [self::EDIT, self::VIEW, self::DELETE, self::VALIDATE, self::CLOSE, self::ADD_VISITE, self::USAGER_EDIT, self::EDIT_NDE, self::SEE_NDE])
return \in_array($attribute, [self::EDIT, self::VIEW, self::DELETE, self::VALIDATE, self::CLOSE, self::REOPEN, self::ADD_VISITE, self::USAGER_EDIT, self::EDIT_NDE, self::SEE_NDE])
&& ($subject instanceof Signalement);
}

Expand Down Expand Up @@ -61,13 +62,10 @@ protected function voteOnAttribute(string $attribute, $subject, TokenInterface $
};
}

if ($this->security->isGranted('ROLE_ADMIN') && self::DELETE !== $attribute) {
return true;
}

return match ($attribute) {
self::VALIDATE => $this->canValidate($subject, $user),
self::CLOSE => $this->canClose($subject, $user),
self::REOPEN => $this->canReopen($subject, $user),
self::DELETE => $this->canDelete($subject, $user),
self::EDIT => $this->canEdit($subject, $user),
self::VIEW => $this->canView($subject, $user),
Expand All @@ -94,29 +92,42 @@ private function canUsagerEdit(Signalement $signalement): bool
return false;
}

private function isAdminOrTerritoryAdmin(Signalement $signalement, User $user): bool
{
return $this->security->isGranted('ROLE_ADMIN')
|| ($user->isTerritoryAdmin() && $user->hasPartnerInTerritory($signalement->getTerritory()));
}

private function canValidate(Signalement $signalement, User $user): bool
{
return Signalement::STATUS_NEED_VALIDATION === $signalement->getStatut() && $user->isTerritoryAdmin() && $user->hasPartnerInTerritory($signalement->getTerritory());
if (Signalement::STATUS_NEED_VALIDATION !== $signalement->getStatut()) {
return false;
}

return $this->isAdminOrTerritoryAdmin($signalement, $user);
}

private function canClose(Signalement $signalement, User $user): bool
{
return $signalement->getStatut() >= Signalement::STATUS_ACTIVE && $user->isTerritoryAdmin() && $user->hasPartnerInTerritory($signalement->getTerritory());
if (Signalement::STATUS_ACTIVE !== $signalement->getStatut()) {
return false;
}

return $this->isAdminOrTerritoryAdmin($signalement, $user);
}

private function canReopen(Signalement $signalement, User $user): bool
{
return $this->canDelete($signalement, $user);
}

private function canDelete(Signalement $signalement, User $user): bool
{
if (!\in_array($signalement->getStatut(), [Signalement::STATUS_CLOSED, Signalement::STATUS_REFUSED])) {
return false;
}
if ($this->security->isGranted('ROLE_ADMIN')) {
return true;
}
if ($this->security->isGranted('ROLE_ADMIN_TERRITORY') && $user->hasPartnerInTerritory($signalement->getTerritory())) {
return true;
}

return false;
return $this->isAdminOrTerritoryAdmin($signalement, $user);
}

private function canEdit(Signalement $signalement, User $user): bool
Expand All @@ -139,6 +150,10 @@ private function canEdit(Signalement $signalement, User $user): bool

private function canView(Signalement $signalement, User $user): bool
{
if ($this->security->isGranted('ROLE_ADMIN')) {
return true;
}

if (Signalement::STATUS_ARCHIVED === $signalement->getStatut()) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion templates/_partials/_modal_cloture.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
Clôturer pour tous les partenaires
</button>
</li>
{% if isAffected and isAccepted %}
{% if affectation and isAffectationAccepted %}
<li>
<button class="fr-btn fr-icon-check-line"
form="cloture_form"
Expand Down
2 changes: 1 addition & 1 deletion templates/_partials/_modal_refus_affectation.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="fr-grid-row fr-grid-row--center">
<div class="fr-col-12 fr-col-md-8 fr-col-lg-6">
<div class="fr-modal__body">
<form action="{{ path('back_signalement_affectation_response',{signalement:signalement.id,user:app.user.id,affectation:isAffected.id}) }}"
<form action="{{ path('back_signalement_affectation_response',{signalement:signalement.id,user:app.user.id,affectation:affectation.id}) }}"
class="tinyCheck fr-mb-3v" id="signalement-affectation-response-deny-form"
name="signalement-affectation-response-form" method="POST">
<div class="fr-modal__header">
Expand Down
18 changes: 8 additions & 10 deletions templates/back/signalement/view.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
{% include '_partials/_modal_historique_affectation.html.twig' %}
{% endif %}
{% include '_partials/_modal_dpe.html.twig' %}
{% if signalement.statut is not same as constant('App\\Entity\\Signalement::STATUS_NEED_VALIDATION') and not isClosed and not isClosedForMe and ((isAffected and isAccepted)) or is_granted('ROLE_ADMIN_TERRITORY') %}
{% if signalement.statut is not same as constant('App\\Entity\\Signalement::STATUS_NEED_VALIDATION') and not isSignalementClosed and not isClosedForMe and ((affectation and isAffectationAccepted)) or is_granted('ROLE_ADMIN_TERRITORY') %}
{% include '_partials/_modal_cloture.html.twig' %}
{% endif %}
{% if canEditNDE %}
{% include '_partials/_modal_edit_nde.html.twig' %}
{% include '_partials/_modal_edit_nde.html.twig' %}
{% endif %}
{% if is_granted('SIGN_EDIT', signalement) %}
{% include '_partials/_modal_upload_files.html.twig' %}
Expand All @@ -26,14 +26,12 @@
{% include '_partials/_modal_file_delete.html.twig' %}
{% include 'back/signalement/view/edit-modals/edit-file.html.twig' %}

{% if isClosedForMe or signalement.statut is same as constant('App\\Entity\\Signalement::STATUS_CLOSED') or signalement.statut is same as constant('App\\Entity\\Signalement::STATUS_REFUSED') %}
{% if isClosed and is_granted('ROLE_ADMIN_TERRITORY') %}
{% include '_partials/_modal_reopen_signalement.html.twig' with { 'all': '1' } %}
{% endif %}

{% if signalement.statut is not same as constant('App\\Entity\\Signalement::STATUS_CLOSED') and isClosedForMe %}
{% include '_partials/_modal_reopen_signalement.html.twig' with { 'all': '0' } %}
{% endif %}
{% if is_granted('SIGN_REOPEN', signalement) %}
{% include '_partials/_modal_reopen_signalement.html.twig' with { 'all': '1' } %}
{% endif %}

{% if canReopenAffectation %}
{% include '_partials/_modal_reopen_signalement.html.twig' with { 'all': '0' } %}
{% endif %}

<div class="fr-background--white
Expand Down
Loading

0 comments on commit 6df57f0

Please sign in to comment.