diff --git a/php/inc_fx_eve_acces.php b/php/inc_fx_eve_acces.php index da82d9b..71efcaa 100644 --- a/php/inc_fx_eve_acces.php +++ b/php/inc_fx_eve_acces.php @@ -26,6 +26,48 @@ function fxEveAccesIsEnabled() return $blnEnabled; } +/** + * Corps SELECT des acces actifs (remplace l'ancienne vue v_eve_acces_actif). + * Pas de vue stockee : evite le DEFINER non copiable par Navicat / releve. + */ +function fxEveAccesActifBody() +{ + return "SELECT ea.ea_id, ea.com_id, ea.eve_id, ea.role_id, + r.role_code, r.role_label_fr, r.role_label_en, + ea.ea_statut, ea.ea_expires_at, ea.ea_expire_days, + ea.ea_granted_by, ea.ea_created_at + 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.ea_statut = 'actif' + AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW())"; +} + +/** Sous-requete aliasee, equivalente a l'ancienne vue v_eve_acces_actif. */ +function fxEveAccesActifSql() +{ + return "(" . fxEveAccesActifBody() . ") v_eve_acces_actif"; +} + +/** + * Sous-requete aliasee, equivalente a l'ancienne vue v_eve_acces_permissions + * (kits via roles + permissions extra individuelles). + */ +function fxEveAccesPermSql() +{ + return "((SELECT v.ea_id, v.com_id, v.eve_id, v.role_id, v.role_code, + erp.perm_key, p.perm_group, p.perm_scope, p.perm_label_fr, p.perm_phase + FROM (" . fxEveAccesActifBody() . ") v + INNER JOIN inscriptions_eve_role_permissions erp ON erp.role_id = v.role_id + INNER JOIN inscriptions_eve_permissions p ON p.perm_key = erp.perm_key AND p.perm_actif = 1) + UNION + (SELECT NULL AS ea_id, ae.com_id, ae.eve_id, NULL AS role_id, 'extra' AS role_code, + ae.perm_key, p.perm_group, p.perm_scope, p.perm_label_fr, p.perm_phase + FROM inscriptions_eve_acces_extra ae + INNER JOIN inscriptions_eve_permissions p ON p.perm_key = ae.perm_key AND p.perm_actif = 1 + WHERE ae.ae_statut = 'actif')) v_eve_acces_permissions"; +} + function fxEveAccesGetRoles($blnActifOnly = true) { global $objDatabase; @@ -76,7 +118,7 @@ function fxEveAccesComHasV2($intComId) return false; } - $sql = "SELECT COUNT(*) FROM v_eve_acces_actif WHERE com_id = " . intval($intComId); + $sql = "SELECT COUNT(*) FROM " . fxEveAccesActifSql() . " WHERE com_id = " . intval($intComId); $intNb = $objDatabase->fxGetVar($sql); return ($intNb != null && intval($intNb) > 0); @@ -90,7 +132,7 @@ function fxEveAccesComHasV2ForEvent($intComId, $intEveId) return false; } - $sql = "SELECT COUNT(*) FROM v_eve_acces_actif + $sql = "SELECT COUNT(*) FROM " . fxEveAccesActifSql() . " WHERE com_id = " . intval($intComId) . " AND eve_id = " . intval($intEveId); $intNb = $objDatabase->fxGetVar($sql); @@ -106,7 +148,7 @@ function fxEveAccesGetEventIds($intComId) return array(); } - $sql = "SELECT eve_id FROM v_eve_acces_actif WHERE com_id = " . intval($intComId); + $sql = "SELECT eve_id FROM " . fxEveAccesActifSql() . " WHERE com_id = " . intval($intComId); $tab = $objDatabase->fxGetResults($sql); $arrIds = array(); @@ -132,7 +174,7 @@ function fxEveAccesHasInscrMobileWebAccess($intComId, $intEveId) return false; } - $sql = "SELECT COUNT(*) FROM v_eve_acces_permissions + $sql = "SELECT COUNT(*) FROM " . fxEveAccesPermSql() . " WHERE com_id = " . intval($intComId) . " AND eve_id = " . intval($intEveId) . " AND perm_key LIKE 'inscriptions_mobile.%'"; @@ -149,7 +191,7 @@ function fxEveAccesGetEventIdsWithInscrMobileAccess($intComId) return array(); } - $sql = "SELECT DISTINCT eve_id FROM v_eve_acces_permissions + $sql = "SELECT DISTINCT eve_id FROM " . fxEveAccesPermSql() . " WHERE com_id = " . intval($intComId) . " AND ( perm_key IN ('registrations.view', 'inscriptions_mobile.view') @@ -176,7 +218,7 @@ function fxEveAccesHasPermission($intComId, $intEveId, $strPermKey) return false; } - $sql = "SELECT COUNT(*) FROM v_eve_acces_permissions + $sql = "SELECT COUNT(*) FROM " . fxEveAccesPermSql() . " WHERE com_id = " . intval($intComId) . " AND eve_id = " . intval($intEveId) . " AND perm_key = '" . $objDatabase->fxEscape($strPermKey) . "'"; @@ -198,7 +240,7 @@ function fxEveAccesHasAnyPermission($intComId, $intEveId, $arrPermKeys) $arrEsc[] = "'" . $objDatabase->fxEscape($strKey) . "'"; } - $sql = "SELECT COUNT(*) FROM v_eve_acces_permissions + $sql = "SELECT COUNT(*) FROM " . fxEveAccesPermSql() . " WHERE com_id = " . intval($intComId) . " AND eve_id = " . intval($intEveId) . " AND perm_key IN (" . implode(',', $arrEsc) . ")"; @@ -220,10 +262,10 @@ function fxEveAccesGetEventIdsWithAnyPermission($intComId, $arrPermKeys) $arrEsc[] = "'" . $objDatabase->fxEscape($strKey) . "'"; } - $sql = "SELECT DISTINCT eve_id FROM v_eve_acces_permissions + $sql = "SELECT DISTINCT eve_id FROM " . fxEveAccesPermSql() . " WHERE com_id = " . intval($intComId) . " AND perm_key IN (" . implode(',', $arrEsc) . ") - ORDER BY eve_id ASC"; + ORDER BY eve_id ASC"; $tab = $objDatabase->fxGetResults($sql); $arrIds = array(); @@ -245,7 +287,7 @@ function fxEveAccesCanQrTest($intComId) global $objDatabase; - $sql = "SELECT COUNT(*) FROM v_eve_acces_permissions + $sql = "SELECT COUNT(*) FROM " . fxEveAccesPermSql() . " WHERE com_id = " . intval($intComId) . " AND perm_key = 'tools.qr_test'"; $intNb = $objDatabase->fxGetVar($sql); @@ -609,10 +651,10 @@ function fxEveAccesGetPermissionsForComEvent($intComId, $intEveId) } $sql = "SELECT perm_key, perm_group, perm_label_fr - FROM v_eve_acces_permissions + FROM " . fxEveAccesPermSql() . " WHERE com_id = " . intval($intComId) . " AND eve_id = " . intval($intEveId) . " - ORDER BY perm_group, perm_key"; + ORDER BY perm_group, perm_key"; return $objDatabase->fxGetResults($sql); } diff --git a/sql/MSIN-eve-acces-v2-drop-views.sql b/sql/MSIN-eve-acces-v2-drop-views.sql new file mode 100644 index 0000000..5f0ade4 --- /dev/null +++ b/sql/MSIN-eve-acces-v2-drop-views.sql @@ -0,0 +1,26 @@ +/* ------------------------------------------------------------------ + MSIN — Suppression des vues acces v2 + ------------------------------------------------------------------ + Les vues v_eve_acces_actif / v_eve_acces_permissions portaient un DEFINER + (compte@IP) que Navicat recopie tel quel et que MySQL refuse de recreer + sur un autre serveur / compte sans privilege SUPER (erreur 1227). + Resultat : la copie Navicat et la restauration sur la releve plantaient. + + La logique de ces vues est desormais integree en sous-requetes dans le + code PHP (php/inc_fx_eve_acces.php et v3_ci4/app/Libraries/EventAccess.php). + On peut donc supprimer les vues sans rien casser : le module acces v2 + continue de fonctionner a l'identique. + + A executer sur CHAQUE base concernee (prod, preprod, releve, dev) : + - selectionner la base, puis lancer ce script. + Aucune donnee n'est touchee : seules 2 vues sont supprimees. + ------------------------------------------------------------------ */ + +DROP VIEW IF EXISTS `v_eve_acces_permissions`; +DROP VIEW IF EXISTS `v_eve_acces_actif`; + +/* Verification : doit retourner 0 ligne. */ +SELECT TABLE_NAME +FROM information_schema.VIEWS +WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME IN ('v_eve_acces_actif', 'v_eve_acces_permissions'); diff --git a/sql/MSIN-eve-acces-v2-phase1-tables.sql b/sql/MSIN-eve-acces-v2-phase1-tables.sql index 9bf601d..dbec961 100644 --- a/sql/MSIN-eve-acces-v2-phase1-tables.sql +++ b/sql/MSIN-eve-acces-v2-phase1-tables.sql @@ -116,46 +116,10 @@ CREATE TABLE IF NOT EXISTS `inscriptions_eve_acces_log` ( COMMENT='Audit acces v2'; -/* 6. Vue acces actifs */ -DROP VIEW IF EXISTS `v_eve_acces_actif`; -CREATE VIEW `v_eve_acces_actif` AS -SELECT - ea.ea_id, - ea.com_id, - ea.eve_id, - ea.role_id, - r.role_code, - r.role_label_fr, - r.role_label_en, - ea.ea_statut, - ea.ea_expires_at, - ea.ea_expire_days, - ea.ea_granted_by, - ea.ea_created_at -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.ea_statut = 'actif' - AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW()); - - -/* 7. Vue permissions effectives */ +/* 6-7. Plus de vues SQL. + Les anciennes vues v_eve_acces_actif / v_eve_acces_permissions portaient un + DEFINER non copiable par Navicat / la releve. La logique est desormais en + sous-requetes directement dans le code PHP (php/inc_fx_eve_acces.php et + v3_ci4/app/Libraries/EventAccess.php). On supprime les vues si elles existent. */ DROP VIEW IF EXISTS `v_eve_acces_permissions`; -CREATE VIEW `v_eve_acces_permissions` AS -SELECT - v.ea_id, - v.com_id, - v.eve_id, - v.role_id, - v.role_code, - erp.perm_key, - p.perm_group, - p.perm_label_fr, - p.perm_phase -FROM v_eve_acces_actif v -INNER JOIN inscriptions_eve_role_permissions erp - ON erp.role_id = v.role_id -INNER JOIN inscriptions_eve_permissions p - ON p.perm_key = erp.perm_key - AND p.perm_actif = 1; +DROP VIEW IF EXISTS `v_eve_acces_actif`; diff --git a/sql/MSIN-eve-acces-v2-phase2-multi-granular.sql b/sql/MSIN-eve-acces-v2-phase2-multi-granular.sql index 85fb6e7..198ceb0 100644 --- a/sql/MSIN-eve-acces-v2-phase2-multi-granular.sql +++ b/sql/MSIN-eve-acces-v2-phase2-multi-granular.sql @@ -16,9 +16,20 @@ SET NAMES utf8mb4; /* ------------------------------------------------------------------ 1. Niveau permission : page | action | api | report ------------------------------------------------------------------ */ -ALTER TABLE `inscriptions_eve_permissions` - ADD COLUMN `perm_scope` enum('page','action','api','report') NOT NULL DEFAULT 'api' - AFTER `perm_group`; +/* Ajout idempotent : n'ajoute la colonne que si elle n'existe pas deja + (evite l'erreur 1060 - Duplicate column name si le script est relance). */ +SET @col_exists := ( + SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'inscriptions_eve_permissions' + AND COLUMN_NAME = 'perm_scope' +); +SET @ddl := IF(@col_exists = 0, + 'ALTER TABLE `inscriptions_eve_permissions` ADD COLUMN `perm_scope` enum(''page'',''action'',''api'',''report'') NOT NULL DEFAULT ''api'' AFTER `perm_group`', + 'DO 0'); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; UPDATE `inscriptions_eve_permissions` SET `perm_scope` = 'api' WHERE `perm_group` = 'api'; @@ -43,11 +54,33 @@ UPDATE `inscriptions_eve_permissions` SET `perm_scope` = 'action' /* ------------------------------------------------------------------ 2. Multi-kits : plusieurs roles par compte x evenement ------------------------------------------------------------------ */ -ALTER TABLE `inscriptions_eve_acces` - DROP INDEX `uk_com_eve`; +/* Retrait idempotent de l'ancien index unique (evite 1091 si deja retire). */ +SET @idx_old := ( + SELECT COUNT(*) FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'inscriptions_eve_acces' + AND INDEX_NAME = 'uk_com_eve' +); +SET @ddl := IF(@idx_old > 0, + 'ALTER TABLE `inscriptions_eve_acces` DROP INDEX `uk_com_eve`', + 'DO 0'); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; -ALTER TABLE `inscriptions_eve_acces` - ADD UNIQUE KEY `uk_com_eve_role` (`com_id`, `eve_id`, `role_id`); +/* Ajout idempotent du nouvel index unique (evite 1061 si deja present). */ +SET @idx_new := ( + SELECT COUNT(*) FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'inscriptions_eve_acces' + AND INDEX_NAME = 'uk_com_eve_role' +); +SET @ddl := IF(@idx_new = 0, + 'ALTER TABLE `inscriptions_eve_acces` ADD UNIQUE KEY `uk_com_eve_role` (`com_id`, `eve_id`, `role_id`)', + 'DO 0'); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; /* ------------------------------------------------------------------ @@ -198,67 +231,12 @@ WHERE r.role_code = 'mobile_statut'; /* ------------------------------------------------------------------ - 6. Vues : union kits multiples + extras + 6. Plus de vues SQL. + Les vues v_eve_acces_actif / v_eve_acces_permissions portaient un DEFINER + non copiable par Navicat / la releve. La logique (union kits multiples + + extras) est desormais en sous-requetes directement dans le code PHP + (php/inc_fx_eve_acces.php et v3_ci4/app/Libraries/EventAccess.php). + On supprime les vues si elles existent. ------------------------------------------------------------------ */ DROP VIEW IF EXISTS `v_eve_acces_permissions`; DROP VIEW IF EXISTS `v_eve_acces_actif`; - -CREATE VIEW `v_eve_acces_actif` AS -SELECT - ea.ea_id, - ea.com_id, - ea.eve_id, - ea.role_id, - r.role_code, - r.role_label_fr, - r.role_label_en, - ea.ea_statut, - ea.ea_expires_at, - ea.ea_expire_days, - ea.ea_granted_by, - ea.ea_created_at -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.ea_statut = 'actif' - AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW()); - - -CREATE VIEW `v_eve_acces_permissions` AS -SELECT - v.ea_id, - v.com_id, - v.eve_id, - v.role_id, - v.role_code, - erp.perm_key, - p.perm_group, - p.perm_scope, - p.perm_label_fr, - p.perm_phase -FROM v_eve_acces_actif v -INNER JOIN inscriptions_eve_role_permissions erp - ON erp.role_id = v.role_id -INNER JOIN inscriptions_eve_permissions p - ON p.perm_key = erp.perm_key - AND p.perm_actif = 1 - -UNION - -SELECT - NULL AS ea_id, - ae.com_id, - ae.eve_id, - NULL AS role_id, - 'extra' AS role_code, - ae.perm_key, - p.perm_group, - p.perm_scope, - p.perm_label_fr, - p.perm_phase -FROM inscriptions_eve_acces_extra ae -INNER JOIN inscriptions_eve_permissions p - ON p.perm_key = ae.perm_key - AND p.perm_actif = 1 -WHERE ae.ae_statut = 'actif'; diff --git a/v3_ci4/app/Libraries/EventAccess.php b/v3_ci4/app/Libraries/EventAccess.php index e66ee3b..74a8d13 100644 --- a/v3_ci4/app/Libraries/EventAccess.php +++ b/v3_ci4/app/Libraries/EventAccess.php @@ -16,6 +16,45 @@ class EventAccess $this->db = Database::connect(); } + /** + * Corps SELECT des acces actifs (remplace l'ancienne vue v_eve_acces_actif). + * Pas de vue stockee : evite le DEFINER non copiable par Navicat / releve. + */ + protected function actifBody(): string + { + return "SELECT ea.ea_id, ea.com_id, ea.eve_id, ea.role_id, + r.role_code, r.role_label_fr, r.role_label_en, + ea.ea_statut, ea.ea_expires_at, ea.ea_expire_days, + ea.ea_granted_by, ea.ea_created_at + 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.ea_statut = 'actif' + AND (ea.ea_expires_at IS NULL OR ea.ea_expires_at > NOW())"; + } + + /** Sous-requete aliasee, equivalente a l'ancienne vue v_eve_acces_actif. */ + protected function actifSql(): string + { + return "(" . $this->actifBody() . ") v_eve_acces_actif"; + } + + /** Sous-requete aliasee, equivalente a l'ancienne vue v_eve_acces_permissions. */ + protected function permSql(): string + { + return "((SELECT v.ea_id, v.com_id, v.eve_id, v.role_id, v.role_code, + erp.perm_key, p.perm_group, p.perm_scope, p.perm_label_fr, p.perm_phase + FROM (" . $this->actifBody() . ") v + INNER JOIN inscriptions_eve_role_permissions erp ON erp.role_id = v.role_id + INNER JOIN inscriptions_eve_permissions p ON p.perm_key = erp.perm_key AND p.perm_actif = 1) + UNION + (SELECT NULL AS ea_id, ae.com_id, ae.eve_id, NULL AS role_id, 'extra' AS role_code, + ae.perm_key, p.perm_group, p.perm_scope, p.perm_label_fr, p.perm_phase + FROM inscriptions_eve_acces_extra ae + INNER JOIN inscriptions_eve_permissions p ON p.perm_key = ae.perm_key AND p.perm_actif = 1 + WHERE ae.ae_statut = 'actif')) v_eve_acces_permissions"; + } + public function isEnabled(): bool { static $enabled = null; @@ -40,11 +79,10 @@ class EventAccess return false; } - $count = $this->db->table('v_eve_acces_actif') - ->where('com_id', $comId) - ->countAllResults(); + $sql = "SELECT COUNT(*) AS n FROM " . $this->actifSql() . " WHERE com_id = ?"; + $row = $this->db->query($sql, [$comId])->getRow(); - return $count > 0; + return $row !== null && (int) $row->n > 0; } public function getEventIds(int $comId): array @@ -53,11 +91,8 @@ class EventAccess return []; } - $rows = $this->db->table('v_eve_acces_actif') - ->select('eve_id') - ->where('com_id', $comId) - ->get() - ->getResultArray(); + $sql = "SELECT eve_id FROM " . $this->actifSql() . " WHERE com_id = ?"; + $rows = $this->db->query($sql, [$comId])->getResultArray(); return array_map(static fn($r) => (string) $r['eve_id'], $rows); } @@ -68,13 +103,11 @@ class EventAccess return false; } - $count = $this->db->table('v_eve_acces_permissions') - ->where('com_id', $comId) - ->where('eve_id', $eveId) - ->where('perm_key', $permKey) - ->countAllResults(); + $sql = "SELECT COUNT(*) AS n FROM " . $this->permSql() . " + WHERE com_id = ? AND eve_id = ? AND perm_key = ?"; + $row = $this->db->query($sql, [$comId, $eveId, $permKey])->getRow(); - return $count > 0; + return $row !== null && (int) $row->n > 0; } public function canAccessEvent(int $comId, int $eveId): bool @@ -83,12 +116,11 @@ class EventAccess return false; } - $count = $this->db->table('v_eve_acces_actif') - ->where('com_id', $comId) - ->where('eve_id', $eveId) - ->countAllResults(); + $sql = "SELECT COUNT(*) AS n FROM " . $this->actifSql() . " + WHERE com_id = ? AND eve_id = ?"; + $row = $this->db->query($sql, [$comId, $eveId])->getRow(); - return $count > 0; + return $row !== null && (int) $row->n > 0; } /**