diff --git a/css/style.css b/css/style.css index 24c2158..08593f3 100644 --- a/css/style.css +++ b/css/style.css @@ -1046,6 +1046,29 @@ ul.ms1-menu-compte li a:hover, ul.ms1-menu-compte li a:active { box-shadow:0 0 0 2px rgba(114,28,36,.35); } +.ms1-perm-inspect-badge{ + display:inline-block; + font-size:11px; + line-height:1.3; + padding:2px 6px; + margin:2px 4px 2px 0; + border-radius:3px; + background:#fff3cd; + border:1px solid #e0a800; + color:#856404; + vertical-align:middle; +} +.ms1-perm-inspect-badge code{ + font-size:10px; + color:inherit; + background:transparent; + padding:0; +} +.ms1-perm-inspect-zone{ + outline:2px dashed rgba(224,168,0,.55); + outline-offset:4px; +} + .epr-wrapper{ display:flex; flex-direction:column; diff --git a/inc_header.php b/inc_header.php index 03493a4..0d238f5 100644 --- a/inc_header.php +++ b/inc_header.php @@ -3,6 +3,7 @@ global $vPaypal_devise,$vblnEnvironementDev,$vDomaine, $vClient, $strCode, $strLangue, $vRepertoireFichiers,$vPaypaladv_SANDBOX,$favicon; fxAdminTextEditModeHandleRequest(); +fxAdminPermInspectModeHandleRequest(); $strQueryString = ""; diff --git a/inc_tableau_gestion_epreuves.php b/inc_tableau_gestion_epreuves.php index 935f2d7..171ad95 100644 --- a/inc_tableau_gestion_epreuves.php +++ b/inc_tableau_gestion_epreuves.php @@ -64,6 +64,9 @@ if (isset($_POST['btn_cancel_event_promo'])) { diff --git a/php/inc_fonctions_sl.php b/php/inc_fonctions_sl.php index 6becb81..6a51829 100644 --- a/php/inc_fonctions_sl.php +++ b/php/inc_fonctions_sl.php @@ -177,6 +177,62 @@ function fxAdminTextEditModeActive() { return fxAdminCanUseTextEditTools() && !empty($_SESSION['ms1_text_edit_mode']); } +/** Mode inspecteur droits v2 (cadenas) — super admin connecte uniquement. */ +function fxAdminCanUsePermInspectTools() { + return !empty($_SESSION['usa_id']); +} + +function fxAdminPermInspectModeActive() { + return fxAdminCanUsePermInspectTools() && !empty($_SESSION['ms1_perm_inspect_mode']); +} + +function fxAdminPermInspectModeHandleRequest() { + if (!fxAdminCanUsePermInspectTools() || !isset($_GET['ms1_perm_inspect'])) { + return; + } + + $_SESSION['ms1_perm_inspect_mode'] = ($_GET['ms1_perm_inspect'] === '1') ? 1 : 0; + + $strPath = strtok($_SERVER['REQUEST_URI'], '?'); + $tabParams = $_GET; + unset($tabParams['ms1_perm_inspect']); + $strQuery = http_build_query($tabParams); + + header('Location: ' . $strPath . ($strQuery !== '' ? '?' . $strQuery : '')); + exit; +} + +function fxAdminPermInspectSwitchHtml() { + $blnOn = fxAdminPermInspectModeActive(); + + return ' + + + + '; +} + /** Échappement HTML — outils admin traduction. */ function fxAdminEsc($str) { return htmlspecialchars((string)$str, ENT_QUOTES, 'UTF-8'); @@ -424,16 +480,27 @@ function fxAdminTextEditSwitchHtml() { function fxRenderEnvNoticeBar() { global $vEnvNotice; + $strExtraSwitches = ''; + if (function_exists('fxAdminCanUsePermInspectTools') && fxAdminCanUsePermInspectTools()) { + $strExtraSwitches .= fxAdminPermInspectSwitchHtml(); + } + if (trim($vEnvNotice) === '') { + if ($strExtraSwitches !== '') { + echo '
' . $strExtraSwitches . '
'; + } return; } if (!fxAdminCanUseTextEditTools()) { echo $vEnvNotice; + if ($strExtraSwitches !== '') { + echo '
' . $strExtraSwitches . '
'; + } return; } - $strSwitch = fxAdminTextEditSwitchHtml(); + $strSwitch = fxAdminTextEditSwitchHtml() . $strExtraSwitches; $strHtml = preg_replace('/<\/strong>/', ' ' . $strSwitch, trim($vEnvNotice), 1); if ($strHtml === null || $strHtml === trim($vEnvNotice)) { diff --git a/php/inc_fx_eve_acces.php b/php/inc_fx_eve_acces.php index 0fcedd2..1487861 100644 --- a/php/inc_fx_eve_acces.php +++ b/php/inc_fx_eve_acces.php @@ -164,6 +164,10 @@ function fxEveAccesGetEventIds($intComId) /** Acces web gestion inscriptions : vue API/page OU au moins une permission action inscriptions_gestion.* */ function fxEveAccesHasInscrGestionWebAccess($intComId, $intEveId) { + if (fxEveAccesComEventHasGrantsAllKit(intval($intComId), intval($intEveId))) { + return true; + } + if (fxEveAccesHasAnyPermission(intval($intComId), intval($intEveId), array('registrations.view', 'inscriptions_gestion.view'))) { return true; } @@ -191,6 +195,24 @@ function fxEveAccesGetEventIdsWithInscrGestionAccess($intComId) return array(); } + $arrIds = array(); + + if (fxEveAccesHasGrantsAllColumn()) { + $sqlAll = "SELECT DISTINCT ea.eve_id FROM inscriptions_eve_acces ea + INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id AND r.role_actif = 1 + WHERE ea.com_id = " . intval($intComId) . " + AND ea.ea_statut = 'actif' + AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW()) + AND r.role_grants_all = 1 + ORDER BY ea.eve_id ASC"; + $tabAll = $objDatabase->fxGetResults($sqlAll); + if ($tabAll != null) { + foreach ($tabAll as $row) { + $arrIds[intval($row['eve_id'])] = intval($row['eve_id']); + } + } + } + $sql = "SELECT DISTINCT eve_id FROM " . fxEveAccesPermSql() . " WHERE com_id = " . intval($intComId) . " AND ( @@ -199,17 +221,77 @@ function fxEveAccesGetEventIdsWithInscrGestionAccess($intComId) ) ORDER BY eve_id ASC"; $tab = $objDatabase->fxGetResults($sql); - $arrIds = array(); if ($tab != null) { foreach ($tab as $row) { - $arrIds[] = intval($row['eve_id']); + $arrIds[intval($row['eve_id'])] = intval($row['eve_id']); } } + $arrIds = array_values($arrIds); + sort($arrIds, SORT_NUMERIC); + return $arrIds; } +function fxEveAccesHasGrantsAllColumn() +{ + global $objDatabase; + + static $blnHas = null; + + if ($blnHas !== null) { + return $blnHas; + } + + if (!fxEveAccesIsEnabled()) { + $blnHas = false; + return $blnHas; + } + + $tab = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_eve_roles LIKE 'role_grants_all'"); + $blnHas = ($tab != null && count($tab) > 0); + + return $blnHas; +} + +function fxEveAccesCatalogPermIsActive($strPermKey) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled() || trim((string)$strPermKey) === '') { + return false; + } + + $sql = "SELECT COUNT(*) FROM inscriptions_eve_permissions + WHERE perm_key = '" . $objDatabase->fxEscape($strPermKey) . "' + AND perm_actif = 1"; + $intNb = $objDatabase->fxGetVar($sql); + + return ($intNb != null && intval($intNb) > 0); +} + +/** Compte avec au moins un kit role_grants_all actif sur cet evenement. */ +function fxEveAccesComEventHasGrantsAllKit($intComId, $intEveId) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled() || !fxEveAccesHasGrantsAllColumn()) { + return false; + } + + $sql = "SELECT COUNT(*) FROM inscriptions_eve_acces ea + INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id AND r.role_actif = 1 + WHERE ea.com_id = " . intval($intComId) . " + AND ea.eve_id = " . intval($intEveId) . " + AND ea.ea_statut = 'actif' + AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW()) + AND r.role_grants_all = 1"; + $intNb = $objDatabase->fxGetVar($sql); + + return ($intNb != null && intval($intNb) > 0); +} + function fxEveAccesHasPermission($intComId, $intEveId, $strPermKey) { global $objDatabase; @@ -218,6 +300,10 @@ function fxEveAccesHasPermission($intComId, $intEveId, $strPermKey) return false; } + if (fxEveAccesComEventHasGrantsAllKit($intComId, $intEveId)) { + return fxEveAccesCatalogPermIsActive($strPermKey); + } + $sql = "SELECT COUNT(*) FROM " . fxEveAccesPermSql() . " WHERE com_id = " . intval($intComId) . " AND eve_id = " . intval($intEveId) . " @@ -235,6 +321,16 @@ function fxEveAccesHasAnyPermission($intComId, $intEveId, $arrPermKeys) return false; } + if (fxEveAccesComEventHasGrantsAllKit($intComId, $intEveId)) { + foreach ($arrPermKeys as $strKey) { + if (fxEveAccesCatalogPermIsActive($strKey)) { + return true; + } + } + + return false; + } + $arrEsc = array(); foreach ($arrPermKeys as $strKey) { $arrEsc[] = "'" . $objDatabase->fxEscape($strKey) . "'"; @@ -973,6 +1069,331 @@ function fxEveAccesShowEventAccessPanel($intEveId) 0) { + $arrIds[$intId] = $intId; + } + } + + return array_values($arrIds); +} + +function fxEveAccesGetMigrationLegacyRoleId() +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return 0; + } + + $intRoleId = intval($objDatabase->fxGetVar( + "SELECT role_id FROM inscriptions_eve_roles + WHERE role_code = 'migration_legacy' AND role_actif = 1 + LIMIT 1" + )); + + return ($intRoleId > 0) ? $intRoleId : 0; +} + +/** Le compte a-t-il deja le kit migration_legacy actif sur cet evenement ? */ +function fxEveAccesComEventHasMigrationKit($intComId, $intEveId) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return false; + } + + $sql = "SELECT COUNT(*) FROM inscriptions_eve_acces ea + INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id + WHERE ea.com_id = " . intval($intComId) . " + AND ea.eve_id = " . intval($intEveId) . " + AND ea.ea_statut = 'actif' + AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW()) + AND r.role_code = 'migration_legacy'"; + $intNb = $objDatabase->fxGetVar($sql); + + return ($intNb != null && intval($intNb) > 0); +} + +/** + * Etat migration legacy → v2 pour un compte (lecture inscriptions_comptes.com_eve_promoteur). + * + * @return array{com_id:int,legacy_csv:string,role_id:int,events:array,pending_count:int,migrated_count:int} + */ +function fxEveAccesMigrationStatusForCom($intComId) +{ + global $objDatabase; + + $intComId = intval($intComId); + $arrOut = array( + 'com_id' => $intComId, + 'legacy_csv' => '', + 'role_id' => fxEveAccesGetMigrationLegacyRoleId(), + 'events' => array(), + 'pending_count' => 0, + 'migrated_count' => 0, + ); + + if (!fxEveAccesIsEnabled() || $intComId <= 0) { + return $arrOut; + } + + $row = $objDatabase->fxGetRow( + "SELECT com_id, com_eve_promoteur FROM inscriptions_comptes WHERE com_id = $intComId LIMIT 1" + ); + if ($row === null) { + return $arrOut; + } + + $arrOut['legacy_csv'] = trim((string)($row['com_eve_promoteur'] ?? '')); + $arrEveIds = fxEveAccesParseLegacyPromoteurCsv($arrOut['legacy_csv']); + + if (empty($arrEveIds)) { + return $arrOut; + } + + $sql = "SELECT eve_id, eve_nom_fr FROM inscriptions_evenements + WHERE eve_id IN (" . implode(',', array_map('intval', $arrEveIds)) . ")"; + $tabEve = $objDatabase->fxGetResults($sql); + $arrEveNames = array(); + if ($tabEve != null) { + foreach ($tabEve as $rowEve) { + $arrEveNames[intval($rowEve['eve_id'])] = $rowEve['eve_nom_fr']; + } + } + + foreach ($arrEveIds as $intEveId) { + $blnMigrated = fxEveAccesComEventHasMigrationKit($intComId, $intEveId); + $arrOut['events'][] = array( + 'eve_id' => $intEveId, + 'eve_nom_fr' => $arrEveNames[$intEveId] ?? ('Événement #' . $intEveId), + 'migrated' => $blnMigrated, + ); + if ($blnMigrated) { + $arrOut['migrated_count']++; + } else { + $arrOut['pending_count']++; + } + } + + return $arrOut; +} + +/** + * Cree les acces v2 (kit migration_legacy) pour chaque evenement du promoteur legacy. + * + * @return array{state:string,message:string,granted:int,skipped:int,errors:array} + */ +function fxEveAccesMigrateCompteFromLegacy($intComId, $intGrantedBy = 0) +{ + $arrStatus = fxEveAccesMigrationStatusForCom($intComId); + $intRoleId = intval($arrStatus['role_id']); + + if ($intRoleId <= 0) { + return array( + 'state' => 'error', + 'message' => 'Kit migration_legacy introuvable. Executer sql/MSIN-eve-acces-v2-phase4-role-grants-all.sql', + 'granted' => 0, + 'skipped' => 0, + 'errors' => array(), + ); + } + + if ($arrStatus['legacy_csv'] === '') { + return array( + 'state' => 'error', + 'message' => 'Aucun evenement dans com_eve_promoteur (inscriptions_comptes).', + 'granted' => 0, + 'skipped' => 0, + 'errors' => array(), + ); + } + + $intGranted = 0; + $intSkipped = 0; + $arrErrors = array(); + + foreach ($arrStatus['events'] as $arrEvent) { + $intEveId = intval($arrEvent['eve_id']); + if (!empty($arrEvent['migrated'])) { + $intSkipped++; + continue; + } + + $arrResult = fxEveAccesGrant( + $intComId, + $intEveId, + $intRoleId, + 0, + $intGrantedBy, + 'Migration depuis com_eve_promoteur' + ); + + if (($arrResult['state'] ?? '') === 'success') { + $intGranted++; + } else { + $arrErrors[] = '#' . $intEveId . ': ' . ($arrResult['message'] ?? 'erreur'); + } + } + + if (!empty($arrErrors)) { + return array( + 'state' => 'error', + 'message' => $intGranted . ' migre(s), ' . count($arrErrors) . ' erreur(s).', + 'granted' => $intGranted, + 'skipped' => $intSkipped, + 'errors' => $arrErrors, + ); + } + + if ($intGranted === 0 && $intSkipped > 0) { + return array( + 'state' => 'success', + 'message' => 'Deja migre : tous les evenements legacy ont le kit migration.', + 'granted' => 0, + 'skipped' => $intSkipped, + 'errors' => array(), + ); + } + + return array( + 'state' => 'success', + 'message' => $intGranted . ' evenement(s) migre(s)' + . ($intSkipped > 0 ? ', ' . $intSkipped . ' deja en place' : '') . '.', + 'granted' => $intGranted, + 'skipped' => $intSkipped, + 'errors' => array(), + ); +} + +/** Liste comptes avec com_eve_promoteur non vide (migration globale). */ +function fxEveAccesMigrationListComptesPending() +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return array(); + } + + $sql = "SELECT com_id, com_nom, com_prenom, com_courriel, com_eve_promoteur + FROM inscriptions_comptes + WHERE com_eve_promoteur IS NOT NULL + AND TRIM(com_eve_promoteur) <> '' + ORDER BY com_nom ASC, com_prenom ASC"; + $tab = $objDatabase->fxGetResults($sql); + $arrRows = array(); + + if ($tab == null) { + return $arrRows; + } + + foreach ($tab as $row) { + $arrStatus = fxEveAccesMigrationStatusForCom(intval($row['com_id'])); + if ($arrStatus['pending_count'] <= 0) { + continue; + } + $arrRows[] = array( + 'com_id' => intval($row['com_id']), + 'com_nom' => $row['com_nom'], + 'com_prenom' => $row['com_prenom'], + 'com_courriel' => $row['com_courriel'], + 'legacy_csv' => $arrStatus['legacy_csv'], + 'pending_count' => $arrStatus['pending_count'], + 'migrated_count' => $arrStatus['migrated_count'], + 'event_count' => count($arrStatus['events']), + ); + } + + return $arrRows; +} + +function fxEveAccesShowCompteMigrationPanel($intComId) +{ + $arrStatus = fxEveAccesMigrationStatusForCom($intComId); + $strT = urlencode($_GET['t'] ?? ''); + $intComId = intval($intComId); + + if (!empty($_GET['mig_msg'])) { + $strClass = (!empty($_GET['mig_err'])) ? 'alert-danger' : 'alert-success'; + echo '
' + . htmlspecialchars((string)$_GET['mig_msg'], ENT_QUOTES, 'UTF-8') . '
'; + } + ?> +
+

Migration promoteur legacy → accès v2

+

+ Source : champ inscriptions_comptes.com_eve_promoteur — + kit migration_legacy (tous les droits). + Migration globale +

+ + +

Ce compte n'a aucun événement promoteur legacy.

+ +

+ com_eve_promoteur : + +

+ + +
+ Kit migration_legacy absent — exécuter + sql/MSIN-eve-acces-v2-phase4-role-grants-all.sql. +
+ + + + + + + + + + + + + + + + +
Événementv2 migration
+ + (#) + + + OK + + À migrer + +
+ + 0) { ?> + + + Migrer événement(s) vers v2 + + + Tous les événements legacy sont migrés en v2. + + + +
+ Accès aux événements

Gérer les kits + · + Migration legacy

+ + @@ -1334,3 +1759,77 @@ function fxEveAccesShowCompteForm($intComId) ' + . ' ' + . '' . htmlspecialchars($strPermKey, ENT_QUOTES, 'UTF-8') . ''; +} + +/** Attributs HTML zone inspectee (data-ms1-perm). */ +function fxEveAccesPermInspectZoneAttr($strPermKey) +{ + if (!function_exists('fxAdminPermInspectModeActive') || !fxAdminPermInspectModeActive()) { + return ''; + } + + $strPermKey = trim((string)$strPermKey); + if ($strPermKey === '') { + return ''; + } + + return ' class="ms1-perm-inspect-zone" data-ms1-perm="' + . htmlspecialchars($strPermKey, ENT_QUOTES, 'UTF-8') . '"'; +} + +/** + * Badge cadenas droits v2 (visible si super admin + mode inspecteur actif). + */ +function fxEveAccesPermInspectBadge($strPermKey, $strContext = 'v2') +{ + if (!function_exists('fxAdminPermInspectModeActive') || !fxAdminPermInspectModeActive()) { + return ''; + } + + $strPermKey = trim((string)$strPermKey); + if ($strPermKey === '') { + return ''; + } + + $strTitle = ($strContext !== '' ? $strContext . ' — ' : '') . $strPermKey; + + return '' + . ' ' + . '' . htmlspecialchars($strPermKey, ENT_QUOTES, 'UTF-8') . ''; +} + +/** Attributs HTML zone inspectee (data-ms1-perm). */ +function fxEveAccesPermInspectZoneAttr($strPermKey) +{ + if (!function_exists('fxAdminPermInspectModeActive') || !fxAdminPermInspectModeActive()) { + return ''; + } + + $strPermKey = trim((string)$strPermKey); + if ($strPermKey === '') { + return ''; + } + + return ' class="ms1-perm-inspect-zone" data-ms1-perm="' + . htmlspecialchars($strPermKey, ENT_QUOTES, 'UTF-8') . '"'; +} diff --git a/sql/MSIN-eve-acces-v2-phase4-role-grants-all.sql b/sql/MSIN-eve-acces-v2-phase4-role-grants-all.sql new file mode 100644 index 0000000..cffc67f --- /dev/null +++ b/sql/MSIN-eve-acces-v2-phase4-role-grants-all.sql @@ -0,0 +1,38 @@ +/* + MSIN - Acces evenement v2 (phase 4) - Kit « tous les droits » + Executer APRES MSIN-eve-acces-v2-phase3-role-delegable.sql + + role_grants_all = 1 : le kit accorde toute permission active du catalogue, + presentes et futures, sans maintenir la matrice role_permissions. +*/ + +SET NAMES utf8mb4; + +ALTER TABLE `inscriptions_eve_roles` + ADD COLUMN `role_grants_all` tinyint(1) unsigned NOT NULL DEFAULT 0 + COMMENT '1 = tous les droits actifs du catalogue (presents et futurs)' + AFTER `role_delegable`; + +UPDATE `inscriptions_eve_roles` +SET `role_grants_all` = 1 +WHERE `role_code` = 'owner'; + +INSERT INTO `inscriptions_eve_roles` + (`role_code`, `role_label_fr`, `role_label_en`, `role_description_fr`, `role_description_en`, + `role_icone`, `role_systeme`, `role_actif`, `role_tri`, `role_delegable`, `role_grants_all`) +VALUES + ('migration_legacy', 'Migration promoteur', 'Legacy promoter migration', + 'Acces total equivalent promoteur legacy — migration uniquement', + 'Full legacy promoter equivalent access — migration only', + 'fa-exchange', 1, 1, 5, 0, 1) +ON DUPLICATE KEY UPDATE + `role_label_fr` = VALUES(`role_label_fr`), + `role_label_en` = VALUES(`role_label_en`), + `role_description_fr` = VALUES(`role_description_fr`), + `role_description_en` = VALUES(`role_description_en`), + `role_icone` = VALUES(`role_icone`), + `role_systeme` = VALUES(`role_systeme`), + `role_actif` = VALUES(`role_actif`), + `role_tri` = VALUES(`role_tri`), + `role_delegable` = VALUES(`role_delegable`), + `role_grants_all` = VALUES(`role_grants_all`); diff --git a/superadm/css/style_blue.css b/superadm/css/style_blue.css index b9f79a0..ee677bc 100644 --- a/superadm/css/style_blue.css +++ b/superadm/css/style_blue.css @@ -156,4 +156,51 @@ table.rapport tr {background-color: #190d7394;}*/ } .superadm-sidebar-subtitle + .nav { margin-bottom: 0.25rem; +} + +/* Toggle Aperçu / Droits (super admin) */ +.navbar .ms1-env-text-edit-label{ + display:inline-flex; + align-items:center; + gap:6px; + color:#fff; + font-size:12px; + cursor:pointer; + margin:0; +} +.navbar .ms1-env-text-edit-opt{ + opacity:.65; +} +.navbar .ms1-env-text-edit-opt.is-active{ + opacity:1; + font-weight:600; +} +.navbar .ms1-env-text-edit-switch{ + appearance:none; + width:36px; + height:18px; + border-radius:9px; + background:#6c757d; + border:1px solid #495057; + position:relative; + cursor:pointer; + vertical-align:middle; +} +.navbar .ms1-env-text-edit-switch::after{ + content:''; + position:absolute; + top:2px; + left:2px; + width:12px; + height:12px; + border-radius:50%; + background:#fff; + transition:transform .15s ease; +} +.navbar .ms1-env-text-edit-switch:checked{ + background:#e67e22; + border-color:#a04000; +} +.navbar .ms1-env-text-edit-switch:checked::after{ + transform:translateX(18px); } \ No newline at end of file diff --git a/superadm/eve_acces.php b/superadm/eve_acces.php index dbfdf3f..613b810 100644 --- a/superadm/eve_acces.php +++ b/superadm/eve_acces.php @@ -74,6 +74,12 @@ include('inc_header.php');
' . htmlspecialchars($strError, ENT_QUOTES, 'UTF-8') . '
'; + } + fxEveAccesAdminRenderMigrationPage($strFlash); + break; case 'kit': if ($strFlash !== '' && $strError === '') { echo '
' . htmlspecialchars($strFlash, ENT_QUOTES, 'UTF-8') . '
'; diff --git a/superadm/inc_droite.php b/superadm/inc_droite.php index 25ae37b..a720c67 100644 --- a/superadm/inc_droite.php +++ b/superadm/inc_droite.php @@ -73,6 +73,12 @@ global $db, $objDatabase, $vblnEnvironementDev, $vDomaine, $vblnEnvironementPreP  Kits d'accès +
Gestion de la documentation et Aide
diff --git a/superadm/inc_header.php b/superadm/inc_header.php index 8025c2f..e66033a 100644 --- a/superadm/inc_header.php +++ b/superadm/inc_header.php @@ -3,6 +3,9 @@ if (function_exists('fxAdminTextEditModeHandleRequest')) { fxAdminTextEditModeHandleRequest(); } +if (function_exists('fxAdminPermInspectModeHandleRequest')) { + fxAdminPermInspectModeHandleRequest(); +} ?> @@ -119,6 +122,11 @@ if ($strPage != 'popup.php') {  Sync BD + + + diff --git a/superadm/index.php b/superadm/index.php index 2b50133..2ffa4cd 100644 --- a/superadm/index.php +++ b/superadm/index.php @@ -161,6 +161,48 @@ if (isset($_GET['action']) && $_GET['action'] == 'reactivateveaccesextra') { header('Location: index.php?t=' . urlencode($_GET['t']) . '&a=mod&id=' . intval($_GET['id']) . '#eve-acces-v2'); exit; } + +if (isset($_GET['action']) && $_GET['action'] == 'migrateveacceslegacy') { + if (session_status() === PHP_SESSION_NONE) { + session_start(); + } + require_once(dirname(__FILE__) . '/../php/inc_fx_eve_acces.php'); + $intGrantedBy = isset($_SESSION['usa_id']) ? intval($_SESSION['usa_id']) : 0; + $arrResult = fxEveAccesMigrateCompteFromLegacy(intval($_GET['id']), $intGrantedBy); + $strQ = 'index.php?t=' . urlencode($_GET['t']) . '&a=mod&id=' . intval($_GET['id']) + . '#eve-acces-migration' + . '&mig_msg=' . urlencode($arrResult['message']); + if (($arrResult['state'] ?? '') !== 'success') { + $strQ .= '&mig_err=1'; + } + header('Location: ' . $strQ); + exit; +} + +if (isset($_GET['action']) && $_GET['action'] == 'migrateveacceslegacyall') { + if (session_status() === PHP_SESSION_NONE) { + session_start(); + } + require_once(dirname(__FILE__) . '/../php/inc_fx_eve_acces.php'); + $intGrantedBy = isset($_SESSION['usa_id']) ? intval($_SESSION['usa_id']) : 0; + $intTotalGranted = 0; + $intTotalSkipped = 0; + $intComptes = 0; + foreach (fxEveAccesMigrationListComptesPending() as $arrRow) { + $arrResult = fxEveAccesMigrateCompteFromLegacy(intval($arrRow['com_id']), $intGrantedBy); + if (($arrResult['state'] ?? '') === 'success' || ($arrResult['granted'] ?? 0) > 0) { + $intTotalGranted += intval($arrResult['granted'] ?? 0); + $intTotalSkipped += intval($arrResult['skipped'] ?? 0); + $intComptes++; + } + } + header('Location: eve_acces.php?p=migrate&ok=' . urlencode( + $intTotalGranted . ' acces cree(s) sur ' . $intComptes . ' compte(s)' + . ($intTotalSkipped > 0 ? ', ' . $intTotalSkipped . ' deja en place' : '') + )); + exit; +} + if ($strAction != 'report') { require_once('php/inc_start_time.php'); $blnLogged = true; diff --git a/superadm/php/inc_fx_eve_acces_admin.php b/superadm/php/inc_fx_eve_acces_admin.php index 28af990..8a51231 100644 --- a/superadm/php/inc_fx_eve_acces_admin.php +++ b/superadm/php/inc_fx_eve_acces_admin.php @@ -26,6 +26,26 @@ function fxEveAccesAdminHasDelegableColumn() return $blnHas; } +function fxEveAccesAdminHasGrantsAllColumn() +{ + global $objDatabase; + + static $blnHas = null; + if ($blnHas !== null) { + return $blnHas; + } + + if (!fxEveAccesIsEnabled()) { + $blnHas = false; + return $blnHas; + } + + $tab = $objDatabase->fxGetResults("SHOW COLUMNS FROM inscriptions_eve_roles LIKE 'role_grants_all'"); + $blnHas = ($tab != null && count($tab) > 0); + + return $blnHas; +} + function fxEveAccesAdminPermGroupLabels() { return array( @@ -75,10 +95,11 @@ function fxEveAccesAdminGetRolesForList($blnActifOnly = false) } $strDelegable = fxEveAccesAdminHasDelegableColumn() ? ', r.role_delegable' : ', 0 AS role_delegable'; + $strGrantsAll = fxEveAccesAdminHasGrantsAllColumn() ? ', r.role_grants_all' : ', 0 AS role_grants_all'; $sql = "SELECT r.role_id, r.role_code, r.role_label_fr, r.role_label_en, r.role_description_fr, r.role_icone, r.role_systeme, r.role_actif, r.role_tri - {$strDelegable}, + {$strDelegable}{$strGrantsAll}, (SELECT COUNT(*) FROM inscriptions_eve_role_permissions erp WHERE erp.role_id = r.role_id) AS perm_count, (SELECT COUNT(*) FROM inscriptions_eve_acces ea WHERE ea.role_id = r.role_id AND ea.ea_statut = 'actif') AS assign_count @@ -102,10 +123,11 @@ function fxEveAccesAdminGetRoleById($intRoleId) } $strDelegable = fxEveAccesAdminHasDelegableColumn() ? ', role_delegable' : ', 0 AS role_delegable'; + $strGrantsAll = fxEveAccesAdminHasGrantsAllColumn() ? ', role_grants_all' : ', 0 AS role_grants_all'; $sql = "SELECT role_id, role_code, role_label_fr, role_label_en, role_description_fr, role_description_en, role_icone, - role_systeme, role_actif, role_tri {$strDelegable} + role_systeme, role_actif, role_tri {$strDelegable}{$strGrantsAll} FROM inscriptions_eve_roles WHERE role_id = " . intval($intRoleId) . " LIMIT 1"; @@ -189,12 +211,19 @@ function fxEveAccesAdminSaveRole($arrData, $arrPermKeys) $intTri = intval($arrData['role_tri'] ?? 0); $blnActif = !empty($arrData['role_actif']) ? 1 : 0; $blnDelegable = !empty($arrData['role_delegable']) ? 1 : 0; - if ($blnSysteme && in_array($strCode, array('owner', 'qr_debug'), true)) { + $blnGrantsAll = !empty($arrData['role_grants_all']) ? 1 : 0; + if ($blnSysteme && $rowExisting !== null && ($rowExisting['role_code'] ?? '') === 'migration_legacy') { + $blnGrantsAll = 1; + } + if ($blnGrantsAll) { + $blnDelegable = 0; + } + if ($blnSysteme && in_array($strCode, array('owner', 'qr_debug', 'migration_legacy'), true)) { $blnDelegable = 0; } $arrValidKeys = array(); - if (!empty($arrPermKeys)) { + if (!$blnGrantsAll && !empty($arrPermKeys)) { $arrCatalog = fxEveAccesGetCatalogPermissions(null, true); $arrCatalogKeys = array(); if ($arrCatalog != null) { @@ -228,6 +257,9 @@ function fxEveAccesAdminSaveRole($arrData, $arrPermKeys) if (fxEveAccesAdminHasDelegableColumn()) { $sqlInsert .= ', role_delegable = ' . intval($blnDelegable); } + if (fxEveAccesAdminHasGrantsAllColumn()) { + $sqlInsert .= ', role_grants_all = ' . intval($blnGrantsAll); + } $objDatabase->fxQuery($sqlInsert); $intRoleId = intval($objDatabase->fxGetVar('SELECT LAST_INSERT_ID()')); } else { @@ -243,16 +275,21 @@ function fxEveAccesAdminSaveRole($arrData, $arrPermKeys) if (fxEveAccesAdminHasDelegableColumn()) { $sqlUpdate .= ', role_delegable = ' . intval($blnDelegable); } + if (fxEveAccesAdminHasGrantsAllColumn()) { + $sqlUpdate .= ', role_grants_all = ' . intval($blnGrantsAll); + } $sqlUpdate .= ' WHERE role_id = ' . intval($intRoleId); $objDatabase->fxQuery($sqlUpdate); } $objDatabase->fxQuery('DELETE FROM inscriptions_eve_role_permissions WHERE role_id = ' . intval($intRoleId)); - foreach (array_keys($arrValidKeys) as $strKey) { - $objDatabase->fxQuery( - "INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key) - VALUES (" . intval($intRoleId) . ", '" . $objDatabase->fxEscape($strKey) . "')" - ); + if (!$blnGrantsAll) { + foreach (array_keys($arrValidKeys) as $strKey) { + $objDatabase->fxQuery( + "INSERT INTO inscriptions_eve_role_permissions (role_id, perm_key) + VALUES (" . intval($intRoleId) . ", '" . $objDatabase->fxEscape($strKey) . "')" + ); + } } return array( @@ -290,9 +327,13 @@ function fxEveAccesAdminDuplicateRole($intRoleId) 'role_tri' => intval($row['role_tri']) + 1, 'role_actif' => 1, 'role_delegable' => !empty($row['role_delegable']) ? 1 : 0, + 'role_grants_all' => !empty($row['role_grants_all']) ? 1 : 0, ); - return fxEveAccesAdminSaveRole($arrSave, fxEveAccesAdminGetRolePermKeys($intRoleId)); + return fxEveAccesAdminSaveRole( + $arrSave, + !empty($row['role_grants_all']) ? array() : fxEveAccesAdminGetRolePermKeys($intRoleId) + ); } function fxEveAccesAdminToggleRoleActif($intRoleId) @@ -327,6 +368,10 @@ function fxEveAccesAdminRenderKitsList($strFlash = '') echo '
Executer sql/MSIN-eve-acces-v2-phase3-role-delegable.sql pour activer le flag « delegable par promoteur ».
'; } + if (!fxEveAccesAdminHasGrantsAllColumn()) { + echo '
Executer sql/MSIN-eve-acces-v2-phase4-role-grants-all.sql pour activer les kits « tous les droits ».
'; + } + $blnActifOnly = isset($_GET['actif']) && $_GET['actif'] === '1'; $arrRoles = fxEveAccesAdminGetRolesForList($blnActifOnly); @@ -380,8 +425,17 @@ function fxEveAccesAdminRenderKitsList($strFlash = '') - +
+ + Tous les droits +
∞'; + } else { + echo intval($row['perm_count']); + } + ?> oui' : '' ?> @@ -533,11 +587,30 @@ function fxEveAccesAdminRenderKitForm($intRoleId, $strError = '') Le promoteur pourra assigner ce kit à un membre invité, dans les limites définies par l'admin. + +
+
+ + > + + + + +
+ + Aucune matrice à maintenir : toute permission active du catalogue est accordée automatiquement. + Incompatible avec « délégable promoteur ». + +
+ -
+