From e52c3b7b4560fec9cf87a06fd54c8a3a36b15dfc Mon Sep 17 00:00:00 2001 From: stephan Date: Mon, 13 Jul 2026 17:53:55 -0400 Subject: [PATCH] Refactor inscription management access control to implement granular permissions for transaction actions. Update CSS for improved button layout and alignment, ensuring consistent styling across action items. Increment version code to 4.72.816 to reflect these changes. --- ajax_inscr_gestion.php | 5 +- css/style.css | 19 +++ php/inc_fx_inscriptions_gestion.php | 145 +++++++++++++------ php/inc_settings.php | 2 +- sql/MSIN-4401-inscr-gestion-actions-perm.sql | 59 ++++++++ 5 files changed, 183 insertions(+), 47 deletions(-) create mode 100644 sql/MSIN-4401-inscr-gestion-actions-perm.sql diff --git a/ajax_inscr_gestion.php b/ajax_inscr_gestion.php index ef098dc..561ca1b 100644 --- a/ajax_inscr_gestion.php +++ b/ajax_inscr_gestion.php @@ -243,10 +243,9 @@ switch ($strAction) { break; } - // L'eve_id fait foi cote serveur (jamais le client). Acces = acces a la fiche : - // qui peut voir la transaction peut voir ses remboursements (decision produit). + // L'eve_id fait foi cote serveur (jamais le client). Droit granulaire transaction. $intEveId = intval($recCommandes['eve_id']); - if ($intEveId <= 0 || !fxInscrGestionCanAccess($intComId, $intEveId)) { + if ($intEveId <= 0 || !fxInscrGestionCanDo($intComId, $intEveId, 'inscriptions_gestion.transaction')) { $tabRetour = array('state' => 'error', 'message' => 'unauthorized'); break; } diff --git a/css/style.css b/css/style.css index 4ecccb2..748f10d 100644 --- a/css/style.css +++ b/css/style.css @@ -4137,12 +4137,31 @@ a.ms1-trad-link.btn-aide-trad{ flex-wrap:wrap; gap:8px; padding:0; + align-items:center; } .inscr-gestion-gestion-actions .btn{ margin:0; } +/* MSIN-4401 — Bouton + cadenas colle a droite (jamais orphelin a gauche). */ +.inscr-gestion-action-item{ + display:inline-flex; + flex-wrap:wrap; + align-items:center; + gap:4px 6px; + max-width:100%; +} + +.inscr-gestion-action-item .ms1-perm-inspect-badge, +.inscr-gestion-action-item .ms1-perm-inspect-slot{ + margin:0; +} + +.inscr-gestion-action-item--inspect-only{ + opacity:.92; +} + /* Remboursement PayPal — fiche gestion promoteur (formulaire + panneau doc) */ .ms1-refund-wrap{ width:100%; diff --git a/php/inc_fx_inscriptions_gestion.php b/php/inc_fx_inscriptions_gestion.php index 894e388..d974399 100644 --- a/php/inc_fx_inscriptions_gestion.php +++ b/php/inc_fx_inscriptions_gestion.php @@ -100,7 +100,7 @@ function fxInscrGestionPermInspectEcho($strPermKey) { return; } fxInscrGestionLoadEveAcces(); - echo ' ' . fxEveAccesPermInspectBadge($strPermKey, 'inscr_gestion'); + echo fxEveAccesPermInspectBadge($strPermKey, 'inscr_gestion'); } /** Badge + libelle pour un controle masque par les droits (mode inspecteur). */ @@ -112,7 +112,19 @@ function fxInscrGestionPermInspectEchoHidden($strPermKey, $strLabel) { echo ''; echo fxEveAccesPermInspectBadge($strPermKey, 'inscr_gestion'); echo ' ' . fxInscrGestionEsc($strLabel) . ''; - echo ' '; + echo ''; +} + +/** MSIN-4401 — Enveloppe action + cadenas (toujours a droite du controle). */ +function fxInscrGestionActionItemOpen($strExtraClass = '') { + $strExtra = trim((string)$strExtraClass); + echo ''; +} + +function fxInscrGestionActionItemClose() { + echo ''; } function fxInscrGestionLoadEveAcces() { @@ -2099,8 +2111,13 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq, $blnCanRestore = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.restore'); // Droit de remboursement PayPal (etape remboursement) : controle l'affichage du bouton + panneau. $blnCanRefund = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.refund'); + // MSIN-4401 — granularite facture / transaction / renvoi (plus d'acces implicite sans droit). + $blnCanInvoice = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.invoice'); + $blnCanTransaction = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.transaction'); + $blnCanRenvoi = fxInscrGestionCanDo($intComId, $intRowEveId, 'inscriptions_gestion.renvoi'); $blnHasEditable = ($blnCanStatut || $blnCanBib || $blnCanRemis); - $blnHasGestion = ($blnCanEdit || $blnCanCancel || $blnCanRestore || $blnCanRefund); + $blnHasGestion = ($blnCanEdit || $blnCanCancel || $blnCanRestore || $blnCanRefund + || $blnCanInvoice || $blnCanTransaction || $blnCanRenvoi); $blnInspect = function_exists('fxAdminPermInspectModeActive') && fxAdminPermInspectModeActive(); $strBackUrl = fxInscrGestionResolveBackUrl($strBaseUrl, $intEveId, $arrReq); @@ -2183,61 +2200,101 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq, $blnForceSectionsOpen ); echo '
'; - // Libelle devant le bouton facture (numero de commande) — invite a afficher la facture. - echo '' . fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_show_invoice')) . ''; - echo '' . fxInscrGestionEsc($arrRow['no_commande']) . ''; - // Bascule "Afficher la transaction" (MSIN) : place entre le numero de transaction et Modifier. - // Charge le resume de la commande en AJAX (action transaction_resume) dans le panneau ci-dessous. - echo ''; - if ($blnCanEdit) { - echo ''; - fxInscrGestionPermInspectEcho('inscriptions_gestion.edit'); + // MSIN-4401 — Chaque action = wrap [controle][cadenas a droite] (evite badge orphelin a gauche). + if ($blnCanInvoice) { + fxInscrGestionActionItemOpen(); + echo '' . fxInscrGestionEsc(fxInscrGestionT('inscr_gestion_show_invoice')) . ''; + echo '' . fxInscrGestionEsc($arrRow['no_commande']) . ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.invoice'); + fxInscrGestionActionItemClose(); } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); + fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.invoice', fxInscrGestionT('inscr_gestion_show_invoice')); + fxInscrGestionActionItemClose(); + } + if ($blnCanTransaction) { + fxInscrGestionActionItemOpen(); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.transaction'); + fxInscrGestionActionItemClose(); + } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); + fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.transaction', fxInscrGestionT('inscr_gestion_show_transaction')); + fxInscrGestionActionItemClose(); + } + if ($blnCanEdit) { + // d-none sur le wrap entier (pas seulement le bouton) pour ne pas laisser le cadenas orphelin. + fxInscrGestionActionItemOpen(trim($strStyleEdit)); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.edit'); + fxInscrGestionActionItemClose(); + } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.edit', fxInscrGestionT('inscr_gestion_modifier_participant')); + fxInscrGestionActionItemClose(); } if ($blnCanRefund) { - // Bouton bascule : ouvre/ferme le panneau de remboursement et declenche le chargement AJAX du formulaire. - echo ''; - fxInscrGestionPermInspectEcho('inscriptions_gestion.refund'); + fxInscrGestionActionItemOpen(); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.refund'); + fxInscrGestionActionItemClose(); } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.refund', fxInscrGestionT('inscr_gestion_remboursement')); + fxInscrGestionActionItemClose(); } if ($blnCanCancel) { - echo ''; - fxInscrGestionPermInspectEcho('inscriptions_gestion.cancel'); + fxInscrGestionActionItemOpen(trim($strStyleCancel)); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.cancel'); + fxInscrGestionActionItemClose(); } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.cancel', fxInscrGestionT('btn_annulerinscriptions')); + fxInscrGestionActionItemClose(); } if ($blnCanRestore) { - echo ''; - fxInscrGestionPermInspectEcho('inscriptions_gestion.restore'); + fxInscrGestionActionItemOpen(trim($strStyleRetablir)); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.restore'); + fxInscrGestionActionItemClose(); } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.restore', fxInscrGestionT('btn_retablirinscriptions')); + fxInscrGestionActionItemClose(); + } + if ($blnCanRenvoi) { + fxInscrGestionActionItemOpen(); + echo ''; + fxInscrGestionPermInspectEcho('inscriptions_gestion.renvoi'); + fxInscrGestionActionItemClose(); + } elseif ($blnInspect) { + fxInscrGestionActionItemOpen('inscr-gestion-action-item--inspect-only'); + fxInscrGestionPermInspectEchoHidden('inscriptions_gestion.renvoi', $strRenvoi); + fxInscrGestionActionItemClose(); } - // RENVOI place en dernier (MSIN-4403) : retourne la confirmation au participant. - echo ''; echo '
'; if ($blnCanRefund) { // Panneau de remboursement : vide au depart, rempli en AJAX a la 1ere ouverture (action=refund_form). @@ -2249,9 +2306,11 @@ function fxInscrGestionRenderFiche($intEveId, $strLangue, $strBaseUrl, $arrReq, } // Panneau de transaction : vide au depart, rempli en AJAX a la 1ere ouverture (action=transaction_resume). // Sous les boutons, repliable, accessible a tout moment (independant du remboursement). + if ($blnCanTransaction) { echo ''; + } fxInscrGestionRenderFicheSectionEnd(); } diff --git a/php/inc_settings.php b/php/inc_settings.php index 76055a2..038fd55 100644 --- a/php/inc_settings.php +++ b/php/inc_settings.php @@ -7,7 +7,7 @@ * Constantes * * **************/ -define('_VERSION_CODE', '4.72.815'); +define('_VERSION_CODE', '4.72.816'); define('_DATE_CODE', '2026-07-13'); //MSIN-4290 define('QR_SECRET_KEY', 'ms1_qr_2026_cle_secrete_longue_et_fixe'); diff --git a/sql/MSIN-4401-inscr-gestion-actions-perm.sql b/sql/MSIN-4401-inscr-gestion-actions-perm.sql new file mode 100644 index 0000000..6c14c0d --- /dev/null +++ b/sql/MSIN-4401-inscr-gestion-actions-perm.sql @@ -0,0 +1,59 @@ +-- MSIN-4401 — Droits granulaires fiche Gestion : facture, transaction, renvoi +-- Prérequis : MSIN-eve-acces-v2-phase2-multi-granular.sql (perms base) +-- Idempotent. Safe pilote. +-- +-- Note : kit propriétaire (role_grants_all) n'a PAS besoin de ces lignes. + +SET NAMES utf8mb4; + +INSERT INTO `inscriptions_eve_permissions` + (`perm_key`, `perm_group`, `perm_scope`, `perm_label_fr`, `perm_label_en`, + `perm_description_fr`, `perm_description_en`, `perm_phase`, `perm_actif`, `perm_tri`) +VALUES + ('inscriptions_gestion.invoice', 'inscriptions', 'action', + 'Gestion inscription : facture', 'Registration mgmt: invoice', + 'Afficher la facture (numero de commande) depuis la fiche', + 'Show invoice (order number) from the sheet', + 2, 1, 138), + ('inscriptions_gestion.transaction', 'inscriptions', 'action', + 'Gestion inscription : transaction', 'Registration mgmt: transaction', + 'Afficher le resume de transaction depuis la fiche', + 'Show transaction summary from the sheet', + 2, 1, 139), + ('inscriptions_gestion.renvoi', 'inscriptions', 'action', + 'Gestion inscription : renvoyer confirmation', 'Registration mgmt: resend confirmation', + 'Renvoyer la confirmation au participant depuis la fiche', + 'Resend confirmation to the participant from the sheet', + 2, 1, 140) +ON DUPLICATE KEY UPDATE + `perm_group` = VALUES(`perm_group`), + `perm_scope` = VALUES(`perm_scope`), + `perm_label_fr` = VALUES(`perm_label_fr`), + `perm_label_en` = VALUES(`perm_label_en`), + `perm_description_fr` = VALUES(`perm_description_fr`), + `perm_description_en` = VALUES(`perm_description_en`), + `perm_phase` = VALUES(`perm_phase`), + `perm_actif` = 1, + `perm_tri` = VALUES(`perm_tri`); + +/* Kits terrain : ops = les 3 ; readonly = lecture facture+transaction */ +INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key) +SELECT r.role_id, p.perm_key +FROM inscriptions_eve_roles r +CROSS JOIN ( + SELECT 'inscriptions_gestion.invoice' AS perm_key + UNION ALL SELECT 'inscriptions_gestion.transaction' + UNION ALL SELECT 'inscriptions_gestion.renvoi' +) p +WHERE r.role_code = 'gestion_ops' +ON DUPLICATE KEY UPDATE perm_key = VALUES(perm_key); + +INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key) +SELECT r.role_id, p.perm_key +FROM inscriptions_eve_roles r +CROSS JOIN ( + SELECT 'inscriptions_gestion.invoice' AS perm_key + UNION ALL SELECT 'inscriptions_gestion.transaction' +) p +WHERE r.role_code IN ('gestion_readonly', 'gestion_statut') +ON DUPLICATE KEY UPDATE perm_key = VALUES(perm_key);