diff --git a/php/inc_fx_eve_acces.php b/php/inc_fx_eve_acces.php new file mode 100644 index 0000000..8614d55 --- /dev/null +++ b/php/inc_fx_eve_acces.php @@ -0,0 +1,441 @@ +fxGetResults("SHOW TABLES LIKE 'inscriptions_eve_acces'"); + $blnEnabled = ($tab != null && count($tab) > 0); + + return $blnEnabled; +} + +function fxEveAccesGetRoles($blnActifOnly = true) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return array(); + } + + $sql = "SELECT role_id, role_code, role_label_fr, role_label_en, role_description_fr + FROM inscriptions_eve_roles"; + + if ($blnActifOnly) { + $sql .= " WHERE role_actif = 1"; + } + + $sql .= " ORDER BY role_tri ASC, role_label_fr ASC"; + + return $objDatabase->fxGetResults($sql); +} + +function fxEveAccesListByComId($intComId) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return array(); + } + + $sql = "SELECT ea.ea_id, ea.com_id, ea.eve_id, ea.role_id, ea.ea_statut, + ea.ea_expires_at, ea.ea_expire_days, ea.ea_granted_by, ea.ea_note, + ea.ea_created_at, ea.ea_revoked_at, + r.role_code, r.role_label_fr, + e.eve_nom_fr, e.eve_date_fin + FROM inscriptions_eve_acces ea + INNER JOIN inscriptions_eve_roles r ON r.role_id = ea.role_id + LEFT JOIN inscriptions_evenements e ON e.eve_id = ea.eve_id + WHERE ea.com_id = " . intval($intComId) . " + ORDER BY ea.ea_statut ASC, e.eve_date_fin DESC, ea.ea_created_at DESC"; + + return $objDatabase->fxGetResults($sql); +} + +function fxEveAccesComHasV2($intComId) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return false; + } + + $sql = "SELECT COUNT(*) FROM v_eve_acces_actif WHERE com_id = " . intval($intComId); + $intNb = $objDatabase->fxGetVar($sql); + + return ($intNb != null && intval($intNb) > 0); +} + +function fxEveAccesGetEventIds($intComId) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return array(); + } + + $sql = "SELECT eve_id FROM v_eve_acces_actif WHERE com_id = " . intval($intComId); + $tab = $objDatabase->fxGetResults($sql); + $arrIds = array(); + + if ($tab != null) { + foreach ($tab as $row) { + $arrIds[] = (string) intval($row['eve_id']); + } + } + + return $arrIds; +} + +function fxEveAccesHasPermission($intComId, $intEveId, $strPermKey) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return false; + } + + $sql = "SELECT COUNT(*) FROM v_eve_acces_permissions + WHERE com_id = " . intval($intComId) . " + AND eve_id = " . intval($intEveId) . " + AND perm_key = '" . $objDatabase->fxEscape($strPermKey) . "'"; + $intNb = $objDatabase->fxGetVar($sql); + + return ($intNb != null && intval($intNb) > 0); +} + +function fxEveAccesGrant($intComId, $intEveId, $intRoleId, $intExpireDays, $intGrantedBy, $strNote = '') +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return array('state' => 'error', 'message' => 'Tables v2 non installees'); + } + + $intComId = intval($intComId); + $intEveId = intval($intEveId); + $intRoleId = intval($intRoleId); + $intGrantedBy = intval($intGrantedBy); + + if ($intComId <= 0 || $intEveId <= 0 || $intRoleId <= 0) { + return array('state' => 'error', 'message' => 'Parametres invalides'); + } + + $tabRole = $objDatabase->fxGetRow("SELECT role_id FROM inscriptions_eve_roles WHERE role_id = " . $intRoleId . " AND role_actif = 1 LIMIT 1"); + if ($tabRole == null) { + return array('state' => 'error', 'message' => 'Role invalide'); + } + + $tabCom = $objDatabase->fxGetRow("SELECT com_id FROM inscriptions_comptes WHERE com_id = " . $intComId . " LIMIT 1"); + if ($tabCom == null) { + return array('state' => 'error', 'message' => 'Compte introuvable'); + } + + $tabEve = $objDatabase->fxGetRow("SELECT eve_id FROM inscriptions_evenements WHERE eve_id = " . $intEveId . " LIMIT 1"); + if ($tabEve == null) { + return array('state' => 'error', 'message' => 'Evenement introuvable'); + } + + $strExpires = 'NULL'; + $intExpireDaysStore = 'NULL'; + + if ($intExpireDays > 0) { + $strExpires = "'" . $objDatabase->fxEscape(date('Y-m-d H:i:s', strtotime('+' . intval($intExpireDays) . ' days'))) . "'"; + $intExpireDaysStore = intval($intExpireDays); + } + + $strNote = $objDatabase->fxEscape(trim($strNote)); + $strGrantedBy = ($intGrantedBy > 0) ? $intGrantedBy : 'NULL'; + + $sql = "INSERT INTO inscriptions_eve_acces + (com_id, eve_id, role_id, ea_statut, ea_expires_at, ea_expire_days, ea_granted_by, ea_note) + VALUES + ($intComId, $intEveId, $intRoleId, 'actif', $strExpires, $intExpireDaysStore, $strGrantedBy, '$strNote') + ON DUPLICATE KEY UPDATE + role_id = VALUES(role_id), + ea_statut = 'actif', + ea_expires_at = VALUES(ea_expires_at), + ea_expire_days = VALUES(ea_expire_days), + ea_granted_by = VALUES(ea_granted_by), + ea_note = VALUES(ea_note), + ea_revoked_at = NULL, + ea_revoked_by = NULL, + ea_updated_at = NOW()"; + + $objDatabase->fxQuery($sql); + + $intEaId = intval($objDatabase->fxGetVar("SELECT ea_id FROM inscriptions_eve_acces WHERE com_id = $intComId AND eve_id = $intEveId LIMIT 1")); + + fxEveAccesWriteLog($intEaId, $intComId, $intEveId, $intRoleId, 'create', 'Grant / mise a jour acces v2', $intGrantedBy); + + return array('state' => 'success', 'ea_id' => $intEaId); +} + +function fxEveAccesRevoke($intEaId, $intRevokedBy) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return array('state' => 'error', 'message' => 'Tables v2 non installees'); + } + + $intEaId = intval($intEaId); + $tab = $objDatabase->fxGetRow("SELECT * FROM inscriptions_eve_acces WHERE ea_id = " . $intEaId . " LIMIT 1"); + + if ($tab == null) { + return array('state' => 'error', 'message' => 'Acces introuvable'); + } + + $sql = "UPDATE inscriptions_eve_acces + SET ea_statut = 'revoke', + ea_revoked_at = NOW(), + ea_revoked_by = " . intval($intRevokedBy) . ", + ea_updated_at = NOW() + WHERE ea_id = " . $intEaId; + $objDatabase->fxQuery($sql); + + fxEveAccesWriteLog($intEaId, $tab['com_id'], $tab['eve_id'], $tab['role_id'], 'revoke', 'Revoke manuel super admin', $intRevokedBy); + + return array('state' => 'success'); +} + +function fxEveAccesWriteLog($intEaId, $intComId, $intEveId, $intRoleId, $strAction, $strDetail, $intByComId) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return; + } + + $intEaId = ($intEaId > 0) ? intval($intEaId) : 'NULL'; + $intRoleId = ($intRoleId > 0) ? intval($intRoleId) : 'NULL'; + $intByComId = ($intByComId > 0) ? intval($intByComId) : 'NULL'; + + $sql = "INSERT INTO inscriptions_eve_acces_log + (ea_id, com_id, eve_id, role_id, log_action, log_detail, log_by_com_id) + VALUES + ($intEaId, " . intval($intComId) . ", " . intval($intEveId) . ", $intRoleId, + '" . $objDatabase->fxEscape($strAction) . "', + '" . $objDatabase->fxEscape($strDetail) . "', + $intByComId)"; + $objDatabase->fxQuery($sql); +} + +function fxEveAccesGetPermissionsForComEvent($intComId, $intEveId) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + return array(); + } + + $sql = "SELECT perm_key, perm_group, perm_label_fr + FROM v_eve_acces_permissions + WHERE com_id = " . intval($intComId) . " + AND eve_id = " . intval($intEveId) . " + ORDER BY perm_group, perm_key"; + + return $objDatabase->fxGetResults($sql); +} + +function fxEveAccesShowCompteForm($intComId) +{ + global $objDatabase; + + if (!fxEveAccesIsEnabled()) { + echo '
Tables acces v2 non installees. Executer les SQL MSIN-eve-acces-v2-phase1.
'; + return; + } + + $arrAcces = fxEveAccesListByComId($intComId); + $arrRoles = fxEveAccesGetRoles(true); + $strT = urlencode($_GET['t'] ?? ''); + $intComId = intval($intComId); + ?> +

Acces v2 (pilote mobile)

+

+ Systeme parallele au legacy com_eve_promoteur. + Seuls les comptes listes ici utilisent les permissions v2 pour l'API mobile. +

+ +
+
Ajouter un acces
+
+
+
+ +
+ + +
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+ + + + + + + + + + + + + + '; + } else { + foreach ($arrAcces as $row) { + $blnActif = ($row['ea_statut'] === 'actif' + && (empty($row['ea_expires_at']) || strtotime($row['ea_expires_at']) > time())); + $strStatut = $blnActif ? 'actif' : '' . htmlspecialchars($row['ea_statut']) . ''; + $strExpire = !empty($row['ea_expires_at']) ? htmlspecialchars($row['ea_expires_at']) : '—'; + ?> + + + + + + + + + 0) { + $arrKeys = array(); + foreach ($arrPerms as $p) { + $arrKeys[] = $p['perm_key']; + } + echo ''; + } + } + } + } + ?> + +
EvenementRoleStatutExpireCree
Aucun acces v2 pour ce compte.
+ + (#) + () + + + + + +
Permissions : ' . htmlspecialchars(implode(', ', $arrKeys)) . '
+ + + diff --git a/v3_ci4/app/Controllers/Api/V1/Events.php b/v3_ci4/app/Controllers/Api/V1/Events.php index 69149b5..8f6943b 100644 --- a/v3_ci4/app/Controllers/Api/V1/Events.php +++ b/v3_ci4/app/Controllers/Api/V1/Events.php @@ -2,34 +2,33 @@ namespace App\Controllers\Api\V1; +use App\Libraries\EventAccess; use CodeIgniter\RESTful\ResourceController; class Events extends ResourceController { protected $helpers = ['text']; + protected function eventAccess(): EventAccess + { + return new EventAccess(); + } public function index() { $db = \Config\Database::connect(); + $comId = (int) $this->request->com_id; + $access = $this->eventAccess(); - $comId = $this->request->com_id; + $eventIds = $access->getAuthorizedEventIds($comId); - // récupérer la liste d'événements du promoteur - $compte = $db->table('inscriptions_comptes') - ->select('com_eve_promoteur') - ->where('com_id', $comId) - ->get() - ->getRow(); - - if (!$compte) { + if (empty($eventIds)) { return $this->respond([ - 'events' => [] + 'events' => [], + 'access_mode' => $access->hasV2Access($comId) ? 'v2' : 'legacy', ]); } - $eventIds = explode(',', $compte->com_eve_promoteur); - $startDate = $this->request->getGet('start_date'); $endDate = $this->request->getGet('end_date'); $updatedSince = $this->request->getGet('updated_since'); @@ -50,12 +49,9 @@ class Events extends ResourceController $builder->where('last_update >', $updatedSince); } - $events = $builder - ->get() - ->getResultArray(); + $events = $builder->get()->getResultArray(); foreach ($events as &$event) { - $categories = $db->table('api_v1_categories') ->where('eve_id', $event['eve_id']) ->get() @@ -64,37 +60,35 @@ class Events extends ResourceController $event['categories'] = $categories; } + unset($event); + + if ($access->hasV2Access($comId)) { + $events = array_values(array_filter($events, function ($e) use ($access, $comId) { + return $access->hasPermission($comId, (int) $e['eve_id'], 'events.list'); + })); + } + $events = clean_text_fields($events); return $this->respond([ 'events' => $events, - 'total' => count($events) + 'total' => count($events), + 'access_mode' => $access->hasV2Access($comId) ? 'v2' : 'legacy', ]); } + public function show($id = null) { $db = \Config\Database::connect(); + $comId = (int) $this->request->com_id; + $access = $this->eventAccess(); + $id = (string) $id; - $comId = $this->request->com_id; - - // récupérer les événements autorisés - $compte = $db->table('inscriptions_comptes') - ->select('com_eve_promoteur') - ->where('com_id', $comId) - ->get() - ->getRow(); - - if (!$compte) { - return $this->respond(['error' => 'account_not_found'], 404); - } - - $eventIds = explode(',', $compte->com_eve_promoteur); - - // sécurité - if (!in_array($id, $eventIds)) { + if (!$access->assertEventPermission($comId, (int) $id, 'events.view')) { return $this->respond([ 'error' => 'event_not_allowed', - 'requested_event' => $id + 'requested_event' => $id, + 'access_mode' => $access->hasV2Access($comId) ? 'v2' : 'legacy', ], 403); } @@ -111,48 +105,46 @@ class Events extends ResourceController $event['categories'] = $categories; $event = clean_text_fields($event); + return $this->respond([ - 'event' => $event + 'event' => $event, + 'access_mode' => $access->hasV2Access($comId) ? 'v2' : 'legacy', ]); } + public function categories($event_id) { $db = \Config\Database::connect(); + $comId = (int) $this->request->com_id; + $access = $this->eventAccess(); + + if (!$access->assertEventPermission($comId, (int) $event_id, 'events.view')) { + return $this->respond(['error' => 'event_not_allowed'], 403); + } $rows = $db->table('api_v1_categories') ->where('eve_id', $event_id) ->get() ->getResultArray(); $rows = clean_text_fields($rows); + return $this->response->setJSON([ 'event_id' => (int)$event_id, - 'categories' => $rows + 'categories' => $rows, ]); } public function registrations($event_id) { $db = \Config\Database::connect(); + $comId = (int) $this->request->com_id; + $access = $this->eventAccess(); - $comId = $this->request->com_id; - - // vérifier que l'événement appartient au promoteur - $compte = $db->table('inscriptions_comptes') - ->select('com_eve_promoteur') - ->where('com_id', $comId) - ->get() - ->getRow(); - - if (!$compte) { - return $this->respond(['error' => 'account_not_found'], 404); - } - - $eventIds = explode(',', $compte->com_eve_promoteur); - - if (!in_array($event_id, $eventIds)) { + if (!$access->assertEventPermission($comId, (int) $event_id, 'registrations.view')) { return $this->respond([ 'error' => 'event_not_allowed', - 'requested_event' => $event_id + 'requested_event' => $event_id, + 'access_mode' => $access->hasV2Access($comId) ? 'v2' : 'legacy', ], 403); } @@ -178,16 +170,12 @@ class Events extends ResourceController $registrations = []; foreach ($rows as $row) { - - // clé unique pour 1 participant inscrit à 1 épreuve $key = $row['pec_id'].'_'.$row['par_id']; if (!isset($registrations[$key])) { - $registrations[$key] = $row; $registrations[$key]['custom_questions'] = []; - // enlever les champs techniques des questions unset( $registrations[$key]['que_id'], $registrations[$key]['que_question_fr'], @@ -198,15 +186,13 @@ class Events extends ResourceController ); } - // ajouter la réponse dans custom_questions if (!empty($row['que_id'])) { - $registrations[$key]['custom_questions'][] = [ 'que_id' => $row['que_id'], 'que_question_fr' => $row['que_question_fr'], 'que_question_en' => $row['que_question_en'], 'que_choix_fr' => $row['que_choix_fr'], - 'que_choix_en' => $row['que_choix_en'] + 'que_choix_en' => $row['que_choix_en'], ]; } } @@ -215,7 +201,8 @@ class Events extends ResourceController return $this->respond([ 'registrations' => $registrations, - 'total' => count($registrations) + 'total' => count($registrations), + 'access_mode' => $access->hasV2Access($comId) ? 'v2' : 'legacy', ]); } -} \ No newline at end of file +} diff --git a/v3_ci4/app/Libraries/EventAccess.php b/v3_ci4/app/Libraries/EventAccess.php new file mode 100644 index 0000000..e66ee3b --- /dev/null +++ b/v3_ci4/app/Libraries/EventAccess.php @@ -0,0 +1,135 @@ +db = Database::connect(); + } + + public function isEnabled(): bool + { + static $enabled = null; + + if ($enabled !== null) { + return $enabled; + } + + try { + $row = $this->db->query("SHOW TABLES LIKE 'inscriptions_eve_acces'")->getRow(); + $enabled = ($row !== null); + } catch (\Throwable $e) { + $enabled = false; + } + + return $enabled; + } + + public function hasV2Access(int $comId): bool + { + if (!$this->isEnabled()) { + return false; + } + + $count = $this->db->table('v_eve_acces_actif') + ->where('com_id', $comId) + ->countAllResults(); + + return $count > 0; + } + + public function getEventIds(int $comId): array + { + if (!$this->isEnabled()) { + return []; + } + + $rows = $this->db->table('v_eve_acces_actif') + ->select('eve_id') + ->where('com_id', $comId) + ->get() + ->getResultArray(); + + return array_map(static fn($r) => (string) $r['eve_id'], $rows); + } + + public function hasPermission(int $comId, int $eveId, string $permKey): bool + { + if (!$this->isEnabled()) { + return false; + } + + $count = $this->db->table('v_eve_acces_permissions') + ->where('com_id', $comId) + ->where('eve_id', $eveId) + ->where('perm_key', $permKey) + ->countAllResults(); + + return $count > 0; + } + + public function canAccessEvent(int $comId, int $eveId): bool + { + if (!$this->isEnabled()) { + return false; + } + + $count = $this->db->table('v_eve_acces_actif') + ->where('com_id', $comId) + ->where('eve_id', $eveId) + ->countAllResults(); + + return $count > 0; + } + + /** + * Legacy : com_eve_promoteur CSV + */ + public function getLegacyEventIds(int $comId): array + { + $compte = $this->db->table('inscriptions_comptes') + ->select('com_eve_promoteur') + ->where('com_id', $comId) + ->get() + ->getRow(); + + if (!$compte || empty(trim($compte->com_eve_promoteur ?? ''))) { + return []; + } + + $ids = array_filter(array_map('trim', explode(',', $compte->com_eve_promoteur))); + + return array_values($ids); + } + + public function getAuthorizedEventIds(int $comId): array + { + if ($this->hasV2Access($comId)) { + return $this->getEventIds($comId); + } + + return $this->getLegacyEventIds($comId); + } + + public function assertEventPermission(int $comId, int $eveId, ?string $permKey = null): bool + { + if ($this->hasV2Access($comId)) { + if ($permKey !== null) { + return $this->hasPermission($comId, $eveId, $permKey); + } + + return $this->canAccessEvent($comId, $eveId); + } + + return in_array((string) $eveId, $this->getLegacyEventIds($comId), true); + } +}