Files
ms1inscription-v5/php/inc_fx_eve_acces.php
stephan e9ad3d8a92 Enhance event access control and integrate new permission checks
This commit introduces the `fxEveAccesCanManageBibV4` and `fxEveAccesCanQrTest` functions to improve event access management. It updates various files to utilize these new permission checks, ensuring that only authorized users can manage event registrations and access QR testing features. Additionally, redundant session checks are removed, and redirection logic is refined for better user experience across the application.
2026-06-19 12:49:19 -04:00

530 lines
18 KiB
PHP

<?php
/**
* Acces evenement v2 — parallele au legacy com_eve_promoteur.
* Ne modifie jamais les champs legacy.
*/
function fxEveAccesIsEnabled()
{
static $blnEnabled = null;
if ($blnEnabled !== null) {
return $blnEnabled;
}
global $objDatabase;
if (!isset($objDatabase)) {
$blnEnabled = false;
return $blnEnabled;
}
$tab = $objDatabase->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 fxEveAccesHasAnyPermission($intComId, $intEveId, $arrPermKeys)
{
global $objDatabase;
if (!fxEveAccesIsEnabled() || empty($arrPermKeys)) {
return false;
}
$arrEsc = array();
foreach ($arrPermKeys as $strKey) {
$arrEsc[] = "'" . $objDatabase->fxEscape($strKey) . "'";
}
$sql = "SELECT COUNT(*) FROM v_eve_acces_permissions
WHERE com_id = " . intval($intComId) . "
AND eve_id = " . intval($intEveId) . "
AND perm_key IN (" . implode(',', $arrEsc) . ")";
$intNb = $objDatabase->fxGetVar($sql);
return ($intNb != null && intval($intNb) > 0);
}
function fxEveAccesGetEventIdsWithAnyPermission($intComId, $arrPermKeys)
{
global $objDatabase;
if (!fxEveAccesIsEnabled() || empty($arrPermKeys)) {
return array();
}
$arrEsc = array();
foreach ($arrPermKeys as $strKey) {
$arrEsc[] = "'" . $objDatabase->fxEscape($strKey) . "'";
}
$sql = "SELECT DISTINCT eve_id FROM v_eve_acces_permissions
WHERE com_id = " . intval($intComId) . "
AND perm_key IN (" . implode(',', $arrEsc) . ")
ORDER BY eve_id ASC";
$tab = $objDatabase->fxGetResults($sql);
$arrIds = array();
if ($tab != null) {
foreach ($tab as $row) {
$arrIds[] = intval($row['eve_id']);
}
}
return $arrIds;
}
function fxEveAccesIsSuperAdminSession()
{
return !empty($_SESSION['usa_id']);
}
/** Permissions gestion bib v4 (quantites + dossards). */
function fxEveAccesBibV4PermKeys()
{
return array('dossards.manage', 'epreuves.edit_qte');
}
function fxEveAccesCanManageBibV4($intComId, $intEveId)
{
if (fxEveAccesIsSuperAdminSession()) {
return true;
}
return fxEveAccesHasAnyPermission(intval($intComId), intval($intEveId), fxEveAccesBibV4PermKeys());
}
/** Outil debug QR — acces v2 actif avec tools.qr_test (pas de bypass super admin). */
function fxEveAccesCanQrTest($intComId)
{
if (!fxEveAccesIsEnabled() || intval($intComId) <= 0) {
return false;
}
global $objDatabase;
$sql = "SELECT COUNT(*) FROM v_eve_acces_permissions
WHERE com_id = " . intval($intComId) . "
AND perm_key = 'tools.qr_test'";
$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 '<div class="alert alert-warning">Tables acces v2 non installees. Executer les SQL MSIN-eve-acces-v2-phase1.</div>';
return;
}
$arrAcces = fxEveAccesListByComId($intComId);
$arrRoles = fxEveAccesGetRoles(true);
$strT = urlencode($_GET['t'] ?? '');
$intComId = intval($intComId);
?>
<h1 id="eve-acces-v2">Acces v2 (pilote mobile)</h1>
<p class="text-muted">
Systeme parallele au legacy <code>com_eve_promoteur</code>.
Seuls les comptes listes ici utilisent les permissions v2 pour l'API mobile.
</p>
<div class="card mb-3">
<div class="card-header">Ajouter un acces</div>
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-5">
<label>Evenement</label>
<div id="pick-eve-acces-v2">
<input id="pp-eve-acces-v2" type="text" class="form-control" placeholder="Rechercher un evenement...">
<input type="hidden" id="pp-eve-acces-v2-id" value="">
<div id="pp-results-eve-acces-v2" class="list-group d-none"></div>
</div>
</div>
<div class="form-group col-md-3">
<label>Role</label>
<select id="pp-eve-acces-v2-role" class="form-control">
<option value="">— Choisir —</option>
<?php
if ($arrRoles != null) {
foreach ($arrRoles as $row) {
echo '<option value="' . intval($row['role_id']) . '">'
. htmlspecialchars($row['role_label_fr']) . ' (' . htmlspecialchars($row['role_code']) . ')</option>';
}
}
?>
</select>
</div>
<div class="form-group col-md-2">
<label>Expiration (jours)</label>
<input type="number" id="pp-eve-acces-v2-days" class="form-control" min="0" placeholder="0 = aucune">
</div>
<div class="form-group col-md-2 d-flex align-items-end">
<button type="button" class="btn btn-success btn-block" id="btn-eve-acces-v2-add">
<i class="fa fa-plus"></i> Ajouter
</button>
</div>
</div>
</div>
</div>
<table class="table table-striped table-sm">
<thead>
<tr>
<th>Evenement</th>
<th>Role</th>
<th>Statut</th>
<th>Expire</th>
<th>Cree</th>
<th></th>
</tr>
</thead>
<tbody>
<?php
if ($arrAcces == null || count($arrAcces) === 0) {
echo '<tr><td colspan="6" class="text-muted">Aucun acces v2 pour ce compte.</td></tr>';
} else {
foreach ($arrAcces as $row) {
$blnActif = ($row['ea_statut'] === 'actif'
&& (empty($row['ea_expires_at']) || strtotime($row['ea_expires_at']) > time()));
$strStatut = $blnActif ? '<span class="badge badge-success">actif</span>' : '<span class="badge badge-secondary">' . htmlspecialchars($row['ea_statut']) . '</span>';
$strExpire = !empty($row['ea_expires_at']) ? htmlspecialchars($row['ea_expires_at']) : '—';
?>
<tr>
<td>
<strong><?= htmlspecialchars($row['eve_nom_fr'] ?? ('eve_id ' . $row['eve_id'])) ?></strong>
<small class="text-muted">(#<?= intval($row['eve_id']) ?>)</small>
</td>
<td><?= htmlspecialchars($row['role_label_fr']) ?> <small class="text-muted">(<?= htmlspecialchars($row['role_code']) ?>)</small></td>
<td><?= $strStatut ?></td>
<td><?= $strExpire ?></td>
<td><small><?= htmlspecialchars($row['ea_created_at']) ?></small></td>
<td class="text-right">
<?php if ($row['ea_statut'] === 'actif') { ?>
<a href="index.php?t=<?= $strT ?>&amp;a=mod&amp;id=<?= $intComId ?>&amp;action=revokeveacces&amp;ea_id=<?= intval($row['ea_id']) ?>"
class="btn btn-sm btn-danger"
onclick="return confirm('Revoquer cet acces v2 ?');">
<i class="fa fa-ban"></i>
</a>
<?php } ?>
</td>
</tr>
<?php
if ($blnActif) {
$arrPerms = fxEveAccesGetPermissionsForComEvent($intComId, $row['eve_id']);
if ($arrPerms != null && count($arrPerms) > 0) {
$arrKeys = array();
foreach ($arrPerms as $p) {
$arrKeys[] = $p['perm_key'];
}
echo '<tr><td colspan="6"><small class="text-muted">Permissions : ' . htmlspecialchars(implode(', ', $arrKeys)) . '</small></td></tr>';
}
}
}
}
?>
</tbody>
</table>
<script>
(function($){
var timerV2 = null, xhrV2 = null;
function renderEveAccesV2(items){
var $box = $('#pp-results-eve-acces-v2').empty();
if (!items || !items.length){
$box.addClass('d-none');
return;
}
items.forEach(function(it){
var id = it.eve_id || it.eveId || it.id;
var label = it.eve_nom_fr || it.nom || ('#' + id);
$('<a href="#" class="list-group-item list-group-item-action"></a>')
.text(label + ' (#' + id + ')')
.data('item', it)
.appendTo($box);
});
$box.removeClass('d-none');
}
$('#pp-eve-acces-v2').on('input', function(){
var q = $(this).val().trim();
if (q.length < 2) {
$('#pp-results-eve-acces-v2').addClass('d-none').empty();
return;
}
clearTimeout(timerV2);
timerV2 = setTimeout(function(){
if (xhrV2) xhrV2.abort();
xhrV2 = $.getJSON('ajax_newpromoteur.php', { action: 'search_evenement', q: q }, renderEveAccesV2)
.fail(function(){ renderEveAccesV2([]); });
}, 200);
});
$('#pp-results-eve-acces-v2').on('click', '.list-group-item', function(e){
e.preventDefault();
var item = $(this).data('item') || {};
var id = item.eve_id || item.eveId || item.id;
var label = item.eve_nom_fr || $(this).text();
$('#pp-eve-acces-v2-id').val(id);
$('#pp-eve-acces-v2').val(label);
$('#pp-results-eve-acces-v2').addClass('d-none').empty();
});
$('#btn-eve-acces-v2-add').on('click', function(){
var eveId = $('#pp-eve-acces-v2-id').val();
var roleId = $('#pp-eve-acces-v2-role').val();
var days = $('#pp-eve-acces-v2-days').val() || 0;
if (!eveId || !roleId) {
alert('Choisir un evenement et un role.');
return;
}
var p = new URLSearchParams(window.location.search);
var url = 'index.php'
+ '?t=' + encodeURIComponent(p.get('t') || '')
+ '&a=mod'
+ '&id=' + encodeURIComponent(p.get('id') || '0')
+ '&action=addeveacces'
+ '&evenement_id=' + encodeURIComponent(eveId)
+ '&role_id=' + encodeURIComponent(roleId)
+ '&expire_days=' + encodeURIComponent(days);
window.location.href = url;
});
})(jQuery);
</script>
<?php
}