From b00c5d19c16c90fc19e9c5b4bc448b94ed35a88c Mon Sep 17 00:00:00 2001
From: Jean-Philippe Metivier <jean-philippe.metivier@unicaen.fr>
Date: Mon, 31 Mar 2025 10:13:29 +0200
Subject: [PATCH] =?UTF-8?q?Blocage=20de=20l'action=20d'annulation=20d'insc?=
 =?UTF-8?q?ription=20via=20un=20privil=C3=A8ge/assertion?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 documentation/SQL/release_1.1.0.sql                   |  7 +++++++
 module/Formation/config/merged/inscription.config.php | 11 ++++++++++-
 .../src/Formation/Assertion/InscriptionAssertion.php  |  8 ++++++++
 .../src/Formation/Provider/Etat/SessionEtats.php      |  6 ++++++
 .../Provider/Privilege/InscriptionPrivileges.php      |  1 +
 .../formation-instance-inscrit/inscriptions.phtml     |  5 ++++-
 6 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/documentation/SQL/release_1.1.0.sql b/documentation/SQL/release_1.1.0.sql
index 94196494..ac835934 100644
--- a/documentation/SQL/release_1.1.0.sql
+++ b/documentation/SQL/release_1.1.0.sql
@@ -32,3 +32,10 @@ FROM d
          JOIN unicaen_parametre_categorie cp ON cp.CODE = 'GLOBAL';
 
 
+INSERT INTO unicaen_privilege_privilege(CATEGORIE_ID, CODE, LIBELLE, ORDRE)
+WITH d(code, lib, ordre) AS (
+    select 'inscription_annuler', 'Annuler l''inscription', 60
+)
+SELECT cp.id, d.code, d.lib, d.ordre
+FROM d
+JOIN unicaen_privilege_categorie cp ON cp.CODE = 'inscription';
\ No newline at end of file
diff --git a/module/Formation/config/merged/inscription.config.php b/module/Formation/config/merged/inscription.config.php
index 3c266aac..54236453 100644
--- a/module/Formation/config/merged/inscription.config.php
+++ b/module/Formation/config/merged/inscription.config.php
@@ -46,6 +46,7 @@ return [
                     [
                         'privileges' => [
                             InscriptionPrivileges::INSCRIPTION_AFFICHER,
+                            InscriptionPrivileges::INSCRIPTION_ANNULER,
                         ],
                         'resources' => ['Inscription'],
                         'assertion' => InscriptionAssertion::class
@@ -140,13 +141,21 @@ return [
                     'controller' => InscriptionController::class,
                     'action' => [
                         'inscription',
-                        'desinscription',
                     ],
                     'roles' => [
                         'Agent',
                         'Stagiaire externe',
                     ],
                 ],
+                [
+                    'controller' => InscriptionController::class,
+                    'action' => [
+                        'desinscription',
+                    ],
+                    'privileges' => [
+                        InscriptionPrivileges::INSCRIPTION_ANNULER,
+                    ],
+                ],
                 [
                     'controller' => InscriptionController::class,
                     'action' => [
diff --git a/module/Formation/src/Formation/Assertion/InscriptionAssertion.php b/module/Formation/src/Formation/Assertion/InscriptionAssertion.php
index 478d46b8..dde38523 100644
--- a/module/Formation/src/Formation/Assertion/InscriptionAssertion.php
+++ b/module/Formation/src/Formation/Assertion/InscriptionAssertion.php
@@ -9,6 +9,8 @@ use Agent\Service\Agent\AgentServiceAwareTrait;
 use Agent\Service\AgentValidateur\AgentValidateurServiceAwareTrait;
 use Agent\Provider\Privilege\AgentPrivileges;
 use Formation\Entity\Db\Inscription;
+use Formation\Provider\Etat\InscriptionEtats;
+use Formation\Provider\Etat\SessionEtats;
 use Formation\Provider\Privilege\InscriptionPrivileges;
 use Formation\Provider\Role\FormationRoles;
 use Formation\Service\Inscription\InscriptionServiceAwareTrait;
@@ -64,10 +66,16 @@ class InscriptionAssertion extends AbstractAssertion
 
         if (!$this->getPrivilegeService()->checkPrivilege($privilege, $role)) return false;
 
+        $session = $entity->getSession();
+        $sessionEtat = $session->getEtatActif()?->getType()->getCode();
 
         switch ($privilege) {
             case InscriptionPrivileges::INSCRIPTION_AFFICHER:
                 return $this->isScopeCompatible($entity, $user, $role);
+            case InscriptionPrivileges::INSCRIPTION_ANNULER:
+                if (!$this->isScopeCompatible($entity, $user, $role)) return false;
+                if (!in_array($role->getRoleId(), [RolesProvider::ROLE_AGENT, FormationRoles::STAGIAIRE_EXTERNE])) return true;
+                return ($sessionEtat AND in_array($sessionEtat, SessionEtats::ETATS_INSCRIPTION_ANNULABLE));
         }
 
         return true;
diff --git a/module/Formation/src/Formation/Provider/Etat/SessionEtats.php b/module/Formation/src/Formation/Provider/Etat/SessionEtats.php
index 34b3187f..4fc070c8 100644
--- a/module/Formation/src/Formation/Provider/Etat/SessionEtats.php
+++ b/module/Formation/src/Formation/Provider/Etat/SessionEtats.php
@@ -32,4 +32,10 @@ class SessionEtats {
         SessionEtats::ETAT_SESSION_ANNULEE,
         SessionEtats::ETAT_CLOTURE_INSTANCE,
     ];
+
+    const ETATS_INSCRIPTION_ANNULABLE = [
+        SessionEtats::ETAT_CREATION_EN_COURS,
+        SessionEtats::ETAT_INSCRIPTION_OUVERTE,
+        SessionEtats::ETAT_INSCRIPTION_FERMEE,
+    ];
 }
\ No newline at end of file
diff --git a/module/Formation/src/Formation/Provider/Privilege/InscriptionPrivileges.php b/module/Formation/src/Formation/Provider/Privilege/InscriptionPrivileges.php
index 298106ff..b26efecf 100644
--- a/module/Formation/src/Formation/Provider/Privilege/InscriptionPrivileges.php
+++ b/module/Formation/src/Formation/Provider/Privilege/InscriptionPrivileges.php
@@ -7,5 +7,6 @@ use UnicaenPrivilege\Provider\Privilege\Privileges;
 class InscriptionPrivileges extends Privileges
 {
     const INSCRIPTION_AFFICHER = 'inscription-inscription_afficher';
+    const INSCRIPTION_ANNULER = 'inscription-inscription_annuler';
     const INSCRIPTION_ENQUETE = 'inscription-inscription_enquete';
 }
diff --git a/module/Formation/view/formation/formation-instance-inscrit/inscriptions.phtml b/module/Formation/view/formation/formation-instance-inscrit/inscriptions.phtml
index 124ddf90..09f8b1b8 100644
--- a/module/Formation/view/formation/formation-instance-inscrit/inscriptions.phtml
+++ b/module/Formation/view/formation/formation-instance-inscrit/inscriptions.phtml
@@ -18,6 +18,7 @@ use Agent\Entity\Db\Agent;
 use DemandeExterne\Entity\Db\DemandeExterne;
 use Formation\Entity\Db\Inscription;
 use Formation\Provider\Etat\SessionEtats;
+use Formation\Provider\Privilege\InscriptionPrivileges;
 
 ?>
 
@@ -64,13 +65,15 @@ use Formation\Provider\Etat\SessionEtats;
                         <strong>Inscrit en liste <?php echo $inscription->getListe(); ?></strong>
                     </div>
                     <div class="col-md-4">
+                        <?php if ($this->isAllowed($inscription, InscriptionPrivileges::INSCRIPTION_ANNULER)) : ?>
                         <a
-                            <?php /** @see \Formation\Controller\FormationInstanceInscritController::desinscriptionAction() */ ?>
+                            <?php /** @see \Formation\Controller\InscriptionController::desinscriptionAction() */ ?>
                                 href="<?php echo $this->url('inscription/annuler-inscription', ['inscription' => $inscription->getId()], [], true); ?>"
                                 class="btn btn-danger ajax-modal" data-event="modification"
                         >
                             <span class="icon icon-unchecked"> J'annule mon inscription </span>
                         </a>
+                        <?php endif; ?>
                         <?php if ($instance->isEtatActif(SessionEtats::ETAT_FORMATION_CONVOCATION) && $inscription->getListe() === Inscription::PRINCIPALE) : ?>
                             <br/>
                             <a
-- 
GitLab