fxGetResults("SHOW COLUMNS FROM inscriptions_eve_roles LIKE 'role_delegable'"); $blnHas = ($tab != null && count($tab) > 0); 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( 'api' => 'API mobile', 'inscriptions' => 'Inscriptions', 'dossards' => 'Dossards', 'epreuves' => 'Épreuves', 'rabais' => 'Rabais', 'emails' => 'Courriels', 'reports' => 'Rapports', 'team' => 'Équipe', 'tools' => 'Outils', 'action' => 'Actions mobile', 'general' => 'Général', ); } function fxEveAccesAdminNormalizeRoleCode($strCode) { $strCode = strtolower(trim((string)$strCode)); $strCode = preg_replace('/[^a-z0-9_]+/', '_', $strCode); $strCode = preg_replace('/_+/', '_', $strCode); $strCode = trim($strCode, '_'); return substr($strCode, 0, 32); } function fxEveAccesAdminRoleCodeExists($strCode, $intExcludeRoleId = 0) { global $objDatabase; $sql = "SELECT COUNT(*) FROM inscriptions_eve_roles WHERE role_code = '" . $objDatabase->fxEscape($strCode) . "'"; if (intval($intExcludeRoleId) > 0) { $sql .= ' AND role_id <> ' . intval($intExcludeRoleId); } return intval($objDatabase->fxGetVar($sql)) > 0; } function fxEveAccesAdminGetRolesForList($blnActifOnly = false) { global $objDatabase; if (!fxEveAccesIsEnabled()) { return array(); } $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}{$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, (SELECT COUNT(*) FROM inscriptions_eve_acces ea WHERE ea.role_id = r.role_id AND ea.ea_statut <> 'actif') AS history_assign_count FROM inscriptions_eve_roles r"; if ($blnActifOnly) { $sql .= ' WHERE r.role_actif = 1'; } $sql .= ' ORDER BY r.role_tri ASC, r.role_label_fr ASC'; return $objDatabase->fxGetResults($sql); } function fxEveAccesAdminGetRoleById($intRoleId) { global $objDatabase; if (!fxEveAccesIsEnabled() || intval($intRoleId) <= 0) { return null; } $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}{$strGrantsAll} FROM inscriptions_eve_roles WHERE role_id = " . intval($intRoleId) . " LIMIT 1"; return $objDatabase->fxGetRow($sql); } function fxEveAccesAdminGetRolePermKeys($intRoleId) { global $objDatabase; if (!fxEveAccesIsEnabled() || intval($intRoleId) <= 0) { return array(); } $sql = "SELECT perm_key FROM inscriptions_eve_role_permissions WHERE role_id = " . intval($intRoleId) . " ORDER BY perm_key ASC"; $tab = $objDatabase->fxGetResults($sql); $arrKeys = array(); if ($tab != null) { foreach ($tab as $row) { $arrKeys[] = $row['perm_key']; } } return $arrKeys; } function fxEveAccesAdminCountActiveAssignments($intRoleId) { global $objDatabase; $sql = "SELECT COUNT(*) FROM inscriptions_eve_acces WHERE role_id = " . intval($intRoleId) . " AND ea_statut = 'actif'"; return intval($objDatabase->fxGetVar($sql)); } function fxEveAccesAdminCountAllAssignments($intRoleId) { global $objDatabase; $sql = "SELECT COUNT(*) FROM inscriptions_eve_acces WHERE role_id = " . intval($intRoleId); return intval($objDatabase->fxGetVar($sql)); } function fxEveAccesAdminCanDeleteRole($intRoleId) { $row = fxEveAccesAdminGetRoleById($intRoleId); if ($row === null) { return array('can' => false, 'message' => 'Kit introuvable.'); } $intActive = fxEveAccesAdminCountActiveAssignments($intRoleId); if ($intActive > 0) { return array( 'can' => false, 'message' => 'Ce kit est assigné à ' . $intActive . ' compte(s). Retirez les assignations sur la fiche compte avant de supprimer.', ); } return array('can' => true, 'message' => ''); } function fxEveAccesAdminDeleteRole($intRoleId) { global $objDatabase; $arrCheck = fxEveAccesAdminCanDeleteRole($intRoleId); if (!$arrCheck['can']) { return array('state' => 'error', 'message' => $arrCheck['message']); } $intRoleId = intval($intRoleId); $objDatabase->fxQuery('DELETE FROM inscriptions_eve_acces WHERE role_id = ' . $intRoleId); $objDatabase->fxQuery('DELETE FROM inscriptions_eve_role_permissions WHERE role_id = ' . $intRoleId); $objDatabase->fxQuery('DELETE FROM inscriptions_eve_roles WHERE role_id = ' . $intRoleId); return array('state' => 'ok', 'message' => 'Kit supprimé.'); } /** * Assignations d'un kit (actives et historique). * * @return array> */ function fxEveAccesAdminGetRoleAssignments($intRoleId, $strStatut = null) { global $objDatabase; if (!fxEveAccesIsEnabled() || intval($intRoleId) <= 0) { return array(); } $sql = "SELECT ea.ea_id, ea.com_id, ea.eve_id, ea.ea_statut, ea.ea_created_at, ea.ea_revoked_at, c.com_nom, c.com_prenom, c.com_courriel, c.com_lastvisit, e.eve_nom_fr, e.eve_date_fin FROM inscriptions_eve_acces ea INNER JOIN inscriptions_comptes c ON c.com_id = ea.com_id INNER JOIN inscriptions_evenements e ON e.eve_id = ea.eve_id WHERE ea.role_id = " . intval($intRoleId); if ($strStatut === 'actif') { $sql .= " AND ea.ea_statut = 'actif'"; } elseif ($strStatut !== null && $strStatut !== '') { $sql .= " AND ea.ea_statut = '" . $objDatabase->fxEscape($strStatut) . "'"; } $sql .= " ORDER BY FIELD(ea.ea_statut, 'actif', 'invite', 'revoke'), e.eve_date_fin DESC, c.com_nom ASC, c.com_prenom ASC"; $tab = $objDatabase->fxGetResults($sql); return ($tab != null) ? $tab : array(); } /** * Tableau des comptes assignés à un kit (réutilisé fiche kit + page dédiée). */ function fxEveAccesAdminRenderRoleAssignmentsBlock($intRoleId, $arrOpts = array()) { $blnShowFilters = !empty($arrOpts['filters']); $strAnchorId = isset($arrOpts['anchor_id']) ? (string)$arrOpts['anchor_id'] : ''; $strFilter = $arrOpts['statut'] ?? 'actif'; if (!in_array($strFilter, array('actif', 'all', 'revoke', 'invite'), true)) { $strFilter = 'actif'; } $intActive = fxEveAccesAdminCountActiveAssignments($intRoleId); $intTotal = fxEveAccesAdminCountAllAssignments($intRoleId); $strStatutSql = ($strFilter === 'all') ? null : $strFilter; $arrRows = fxEveAccesAdminGetRoleAssignments($intRoleId, $strStatutSql); ?>
>
Personnes assignées actif(s) $intActive) { ?> — dans l'historique

Pour ajouter ou retirer un kit, utilisez la fiche compte (section Accès événement v2).

'Actifs (' . intval($intActive) . ')', 'all' => 'Tous (' . intval($intTotal) . ')', 'revoke' => 'Révoqués', 'invite' => 'Invitations', ); foreach ($arrFilters as $strKey => $strLabel) { $blnOn = ($strFilter === $strKey); echo '' . htmlspecialchars($strLabel, ENT_QUOTES, 'UTF-8') . ''; } ?>

$intActive) { ?>

Voir l'historique complet

'; } else { foreach ($arrRows as $arrAssign) { $strCompte = trim($arrAssign['com_prenom'] . ' ' . $arrAssign['com_nom']); $strStatut = (string)$arrAssign['ea_statut']; $strBadge = 'secondary'; if ($strStatut === 'actif') { $strBadge = 'success'; } elseif ($strStatut === 'invite') { $strBadge = 'info'; } elseif ($strStatut === 'revoke') { $strBadge = 'warning'; } $strCompteUrl = fxEveAccesCompteAdminUrl(intval($arrAssign['com_id']), intval($arrAssign['eve_id'])); ?>
Compte Événement Statut Assigné le Dernière connexion
Aucune assignation.
#
Fiche compte
Tables acces v2 non installees.'; return; } $row = fxEveAccesAdminGetRoleById($intRoleId); if ($row === null) { echo '
Kit introuvable.
'; return; } $strFilter = $_GET['statut'] ?? 'actif'; if (!in_array($strFilter, array('actif', 'all', 'revoke', 'invite'), true)) { $strFilter = 'actif'; } if ($strFlash !== '') { echo '
' . htmlspecialchars($strFlash, ENT_QUOTES, 'UTF-8') . '
'; } ?>
Retour aux kits Modifier le kit

Assignations —

Code . Retour à la fiche kit

true, 'statut' => $strFilter, )); } function fxEveAccesAdminSaveRole($arrData, $arrPermKeys) { global $objDatabase; if (!fxEveAccesIsEnabled()) { return array('state' => 'error', 'message' => 'Tables acces v2 non installees.'); } $intRoleId = intval($arrData['role_id'] ?? 0); $rowExisting = ($intRoleId > 0) ? fxEveAccesAdminGetRoleById($intRoleId) : null; $strLabelFr = trim((string)($arrData['role_label_fr'] ?? '')); $strLabelEn = trim((string)($arrData['role_label_en'] ?? '')); if ($strLabelFr === '') { return array('state' => 'error', 'message' => 'Le libelle FR est obligatoire.'); } if ($strLabelEn === '') { $strLabelEn = $strLabelFr; } $strCode = fxEveAccesAdminNormalizeRoleCode($arrData['role_code'] ?? ''); if ($strCode === '' || !preg_match('/^[a-z][a-z0-9_]{0,31}$/', $strCode)) { return array('state' => 'error', 'message' => 'Code invalide (a-z, 0-9, _, min. 2 caracteres).'); } $blnCodeLocked = ($rowExisting !== null && ($rowExisting['role_code'] ?? '') === 'migration_legacy'); if ($blnCodeLocked) { $strCode = $rowExisting['role_code']; } elseif (fxEveAccesAdminRoleCodeExists($strCode, $intRoleId)) { return array('state' => 'error', 'message' => 'Ce code de kit existe deja.'); } $strDescFr = trim((string)($arrData['role_description_fr'] ?? '')); $strDescEn = trim((string)($arrData['role_description_en'] ?? '')); $strIcone = trim((string)($arrData['role_icone'] ?? '')); if ($strIcone !== '' && !preg_match('/^fa-[a-z0-9-]+$/', $strIcone)) { $strIcone = ''; } $intTri = intval($arrData['role_tri'] ?? 0); $blnActif = !empty($arrData['role_actif']) ? 1 : 0; $blnDelegable = !empty($arrData['role_delegable']) ? 1 : 0; $blnGrantsAll = !empty($arrData['role_grants_all']) ? 1 : 0; if ($blnCodeLocked) { $blnGrantsAll = 1; } if ($blnGrantsAll) { $blnDelegable = 0; } if ($blnCodeLocked || in_array($strCode, array('owner', 'qr_debug'), true)) { $blnDelegable = 0; } $arrValidKeys = array(); if (!$blnGrantsAll && !empty($arrPermKeys)) { $arrCatalog = fxEveAccesGetCatalogPermissions(null, true); $arrCatalogKeys = array(); if ($arrCatalog != null) { foreach ($arrCatalog as $rowPerm) { $arrCatalogKeys[$rowPerm['perm_key']] = true; } } foreach ($arrPermKeys as $strKey) { $strKey = trim((string)$strKey); if ($strKey !== '' && isset($arrCatalogKeys[$strKey])) { $arrValidKeys[$strKey] = true; } } } if ($intRoleId > 0 && $rowExisting === null) { return array('state' => 'error', 'message' => 'Kit introuvable.'); } if ($intRoleId <= 0) { $sqlInsert = "INSERT INTO inscriptions_eve_roles SET role_code = '" . $objDatabase->fxEscape($strCode) . "', role_label_fr = '" . $objDatabase->fxEscape($strLabelFr) . "', role_label_en = '" . $objDatabase->fxEscape($strLabelEn) . "', role_description_fr = " . ($strDescFr !== '' ? "'" . $objDatabase->fxEscape($strDescFr) . "'" : 'NULL') . ", role_description_en = " . ($strDescEn !== '' ? "'" . $objDatabase->fxEscape($strDescEn) . "'" : 'NULL') . ", role_icone = " . ($strIcone !== '' ? "'" . $objDatabase->fxEscape($strIcone) . "'" : 'NULL') . ", role_systeme = 0, role_actif = " . intval($blnActif) . ", role_tri = " . intval($intTri); 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 { $sqlUpdate = "UPDATE inscriptions_eve_roles SET role_code = '" . $objDatabase->fxEscape($strCode) . "', role_label_fr = '" . $objDatabase->fxEscape($strLabelFr) . "', role_label_en = '" . $objDatabase->fxEscape($strLabelEn) . "', role_description_fr = " . ($strDescFr !== '' ? "'" . $objDatabase->fxEscape($strDescFr) . "'" : 'NULL') . ", role_description_en = " . ($strDescEn !== '' ? "'" . $objDatabase->fxEscape($strDescEn) . "'" : 'NULL') . ", role_icone = " . ($strIcone !== '' ? "'" . $objDatabase->fxEscape($strIcone) . "'" : 'NULL') . ", role_actif = " . intval($blnActif) . ", role_tri = " . intval($intTri); 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)); 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( 'state' => 'ok', 'message' => 'Kit enregistre.', 'role_id' => $intRoleId, ); } function fxEveAccesAdminDuplicateRole($intRoleId) { global $objDatabase; $row = fxEveAccesAdminGetRoleById($intRoleId); if ($row === null) { return array('state' => 'error', 'message' => 'Kit introuvable.'); } $strBase = fxEveAccesAdminNormalizeRoleCode($row['role_code'] . '_copy'); $strCode = $strBase; $intSuffix = 2; while (fxEveAccesAdminRoleCodeExists($strCode)) { $strCode = substr($strBase, 0, 28) . '_' . $intSuffix; $intSuffix++; } $arrSave = array( 'role_id' => 0, 'role_code' => $strCode, 'role_label_fr' => $row['role_label_fr'] . ' (copie)', 'role_label_en' => ($row['role_label_en'] !== '' ? $row['role_label_en'] : $row['role_label_fr']) . ' (copy)', 'role_description_fr' => $row['role_description_fr'] ?? '', 'role_description_en' => $row['role_description_en'] ?? '', 'role_icone' => $row['role_icone'] ?? '', '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, !empty($row['role_grants_all']) ? array() : fxEveAccesAdminGetRolePermKeys($intRoleId) ); } function fxEveAccesAdminToggleRoleActif($intRoleId) { global $objDatabase; $row = fxEveAccesAdminGetRoleById($intRoleId); if ($row === null) { return array('state' => 'error', 'message' => 'Kit introuvable.'); } $blnNew = intval($row['role_actif']) === 1 ? 0 : 1; $objDatabase->fxQuery( 'UPDATE inscriptions_eve_roles SET role_actif = ' . intval($blnNew) . ' WHERE role_id = ' . intval($intRoleId) ); return array( 'state' => 'ok', 'message' => $blnNew ? 'Kit reactive.' : 'Kit desactive.', ); } function fxEveAccesAdminRenderKitsList($strFlash = '') { if (!fxEveAccesIsEnabled()) { echo '
Tables acces v2 non installees. Executer les SQL MSIN-eve-acces-v2-phase1.
'; return; } if (!fxEveAccesAdminHasDelegableColumn()) { 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); if ($strFlash !== '') { echo '
' . htmlspecialchars($strFlash, ENT_QUOTES, 'UTF-8') . '
'; } ?>

Kits d'accès

Nouveau kit
Comment ça marche ?

Un kit accorde des droits à un compte sur un événement. Deux modes :

  • Droits à la pièce — cochez les permissions dans la matrice.
  • Tous les droits — switch « Kit total » (toutes les permissions actives, présentes et futures).
  • Assigner → fiche compte, section Accès événement v2.
  • Supprimer un kit → possible dès qu'aucun compte ne l'a actuellement (colonne Assign. = 0).
  • Qui a ce kit ? → ouvrez le kit : section « Personnes assignées » en bas de fiche.

Les kits « délégables » pourront plus tard être proposés par un promoteur à son équipe.

Tous Actifs seulement

'; } else { foreach ($arrRoles as $row) { $strIcon = trim((string)($row['role_icone'] ?? '')); $arrDelete = fxEveAccesAdminCanDeleteRole(intval($row['role_id'])); ?>
Kit Perms Assign. Délég. Statut
Aucun kit.
Tous les droits
∞'; } else { echo intval($row['perm_count']); } ?> 0) { echo '' . $intAssign . ''; } else { echo '0'; } ?> oui' : '' ?> actif inactif
Tables acces v2 non installees.'; return; } $row = null; $arrSelected = array(); if ($intRoleId > 0) { $row = fxEveAccesAdminGetRoleById($intRoleId); if ($row === null) { echo '
Kit introuvable.
'; return; } foreach (fxEveAccesAdminGetRolePermKeys($intRoleId) as $strKey) { $arrSelected[$strKey] = true; } } $blnCodeLocked = ($row !== null && ($row['role_code'] ?? '') === 'migration_legacy'); $arrDelete = ($intRoleId > 0) ? fxEveAccesAdminCanDeleteRole($intRoleId) : array('can' => false, 'message' => ''); $arrCatalog = fxEveAccesGetCatalogPermissions(null, true); $arrByGroup = array(); if ($arrCatalog != null) { foreach ($arrCatalog as $rowPerm) { $strGroup = $rowPerm['perm_group'] ?? 'general'; if (!isset($arrByGroup[$strGroup])) { $arrByGroup[$strGroup] = array(); } $arrByGroup[$strGroup][] = $rowPerm; } } $arrGroupLabels = fxEveAccesAdminPermGroupLabels(); ksort($arrByGroup); if ($strError !== '') { echo '
' . htmlspecialchars($strError, ENT_QUOTES, 'UTF-8') . '
'; } ?>
Retour à la liste

0 ? 'Modifier le kit' : 'Nouveau kit' ?>

Identité
placeholder="ex. gestion_statut"> Code verrouillé (kit migration legacy).
>
>
Le promoteur pourra assigner ce kit à un membre invité, dans les limites définies par l'admin.
>
Si coché : aucune matrice à maintenir. Sinon : choisissez les droits un par un ci-dessous.
Supprimer 0 && $arrDelete['message'] !== '') { ?>
0) { fxEveAccesAdminRenderRoleAssignmentsBlock($intRoleId, array( 'anchor_id' => 'kit-assignations', 'statut' => 'actif', )); } ?> Tables acces v2 non installees.'; return; } $intRoleId = fxEveAccesGetMigrationLegacyRoleId(); $arrStats = fxEveAccesMigrationGetStats(); $intTotal = intval($arrStats['total_legacy']); $intPendingEvents = intval($arrStats['pending_events']); if ($strFlash !== '') { echo '
' . htmlspecialchars($strFlash, ENT_QUOTES, 'UTF-8') . '
'; } if (!empty($_GET['err'])) { echo '
' . htmlspecialchars((string)$_GET['err'], ENT_QUOTES, 'UTF-8') . '
'; } ?>

Migration promoteur legacy → v2

Action unique et globale : parcourt tous les comptes avec com_eve_promoteur, assigne le kit migration_legacy une fois par événement (tampon journal), puis ne redemande plus. Le champ legacy n'est pas modifié. Gérer les kits ensuite sur chaque fiche compte.

Comptes promoteur legacy
Événements sans tampon migration
Kit migration_legacy introuvable — exécuter sql/MSIN-eve-acces-v2-phase4-role-grants-all.sql.
0) { ?>

Migrer tous les promoteurs legacy

Migration terminée — aucun événement legacy en attente.