Init Git Prod Mars 2026
This commit is contained in:
commit
d81efe93b1
362 files changed
+86627
No files matched your search
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../public/includes/init_admin.php';
|
||||
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
@session_start();
|
||||
}
|
||||
|
||||
// Lang (pour $translations)
|
||||
|
||||
|
||||
function e($s): string {
|
||||
return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
const ADMIN_PRACTICIEN_ID = 88888888;
|
||||
|
||||
$me = (int)($_SESSION['reference_id'] ?? 0);
|
||||
if ($me !== ADMIN_PRACTICIEN_ID) {
|
||||
http_response_code(403);
|
||||
echo '<div class="container py-5"><div class="alert alert-danger">'
|
||||
. e($translations['admin_access_denied'] ?? 'Доступ запрещён.')
|
||||
. '</div></div>';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Reauth (10 min)
|
||||
$mustReauth = function (int $ttl = 600) {
|
||||
$t = (int)($_SESSION['admin_reauth_at'] ?? 0);
|
||||
return ($t === 0 || (time() - $t) > $ttl);
|
||||
};
|
||||
if ($mustReauth()) {
|
||||
$qs = http_build_query(['page' => 'reauth', 'redir' => ($_SERVER['REQUEST_URI'] ?? 'index.php?page=maintenance')]);
|
||||
header('Location:?' . $qs);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
// CSRF
|
||||
if (empty($_SESSION['csrf_token'])) {
|
||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
$CSRF = $_SESSION['csrf_token'];
|
||||
|
||||
// Récupération des comptes non validés depuis >6h
|
||||
$sql = "SELECT * FROM compte WHERE email_valide = 0 AND TIMESTAMPDIFF(HOUR, cree_le, NOW()) > 6";
|
||||
$stmt = $pdo->query($sql);
|
||||
$comptes = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Ajouter nom, prénom et âge du compte
|
||||
foreach ($comptes as &$c) {
|
||||
$nom = $prenom = ($translations['label_unknown'] ?? '(inconnu)');
|
||||
|
||||
if ($c['role'] === 'client') {
|
||||
$stmt2 = $pdo->prepare("SELECT nom, prenom FROM client WHERE id = :id");
|
||||
$stmt2->execute(['id' => $c['reference_id']]);
|
||||
$info = $stmt2->fetch(PDO::FETCH_ASSOC);
|
||||
if ($info) { $nom = $info['nom']; $prenom = $info['prenom']; }
|
||||
} elseif ($c['role'] === 'praticien') {
|
||||
$stmt2 = $pdo->prepare("SELECT nom, prenom FROM praticien WHERE id = :id");
|
||||
$stmt2->execute(['id' => $c['reference_id']]);
|
||||
$info = $stmt2->fetch(PDO::FETCH_ASSOC);
|
||||
if ($info) { $nom = $info['nom']; $prenom = $info['prenom']; }
|
||||
}
|
||||
|
||||
$c['nom'] = $nom;
|
||||
$c['prenom'] = $prenom;
|
||||
|
||||
// Calculer la durée depuis création
|
||||
$diff = time() - strtotime($c['cree_le']);
|
||||
$heures = floor($diff / 3600);
|
||||
$minutes = floor(($diff % 3600) / 60);
|
||||
$c['age_humain'] = sprintf("%dh %02dmin", $heures, $minutes);
|
||||
}
|
||||
unset($c);
|
||||
|
||||
// --- Suppression sur POST ---
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST'
|
||||
&& isset($_POST['csrf_token'])
|
||||
&& hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])
|
||||
&& !empty($_POST['ids'])) {
|
||||
|
||||
$idsToDelete = array_map('intval', $_POST['ids']);
|
||||
$deleted = 0;
|
||||
|
||||
foreach ($comptes as $compte) {
|
||||
if (!in_array($compte['id'], $idsToDelete, true)) continue;
|
||||
|
||||
$id = $compte['id'];
|
||||
$role = $compte['role'];
|
||||
$ref_id = $compte['reference_id'];
|
||||
|
||||
// Supprimer fiche associée
|
||||
if ($role === 'client') {
|
||||
$pdo->prepare("DELETE FROM client WHERE id = :id")->execute(['id' => $ref_id]);
|
||||
} elseif ($role === 'praticien') {
|
||||
$pdo->prepare("DELETE FROM praticien WHERE id = :id")->execute(['id' => $ref_id]);
|
||||
}
|
||||
|
||||
// Supprimer le compte
|
||||
$pdo->prepare("DELETE FROM compte WHERE id = :id")->execute(['id' => $id]);
|
||||
$deleted++;
|
||||
}
|
||||
|
||||
$msgTpl = ($translations['flash_unverified_deleted'] ?? '✅ {N} compte(s) non validé(s) supprimé(s).');
|
||||
$msg = str_replace('{N}', (string)$deleted, $msgTpl);
|
||||
|
||||
echo '<div class="alert alert-success text-center p-4">'
|
||||
. e($msg)
|
||||
. '</div>';
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="shadow p-4 rounded bg-light">
|
||||
<h2 class="mb-3 text-center">
|
||||
<?= e($translations['h2_unverified_accounts_6h'] ?? '🕒 Comptes non validés depuis plus de 6h') ?>
|
||||
</h2>
|
||||
|
||||
<?php if (empty($comptes)): ?>
|
||||
<div class="alert alert-success text-center">
|
||||
<?= e($translations['alert_no_unverified_accounts'] ?? 'Aucun compte non validé à supprimer 🎉') ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<form method="post" onsubmit="return confirm('<?= e($translations['confirm_delete_checked_accounts'] ?? '⚠️ Supprimer les comptes cochés ?') ?>');">
|
||||
<input type="hidden" name="csrf_token" value="<?= e($CSRF) ?>">
|
||||
|
||||
<table class="table table-bordered table-sm align-middle text-center">
|
||||
<thead class="table-secondary">
|
||||
<tr>
|
||||
<th><input type="checkbox" id="checkAll" aria-label="<?= e($translations['aria_check_all'] ?? 'Tout cocher') ?>"></th>
|
||||
<th><?= e($translations['th_id'] ?? 'ID') ?></th>
|
||||
<th><?= e($translations['th_email'] ?? 'Email') ?></th>
|
||||
<th><?= e($translations['th_nom'] ?? 'Nom') ?></th>
|
||||
<th><?= e($translations['th_prenom'] ?? 'Prénom') ?></th>
|
||||
<th><?= e($translations['th_role'] ?? 'Rôle') ?></th>
|
||||
<th><?= e($translations['th_created_at'] ?? 'Créé le') ?></th>
|
||||
<th><?= e($translations['th_account_age'] ?? 'Âge du compte') ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($comptes as $compte): ?>
|
||||
<tr>
|
||||
<td><input type="checkbox" name="ids[]" value="<?= (int)$compte['id'] ?>"></td>
|
||||
<td><?= e($compte['id']) ?></td>
|
||||
<td><?= e($compte['email']) ?></td>
|
||||
<td><?= e($compte['nom']) ?></td>
|
||||
<td><?= e($compte['prenom']) ?></td>
|
||||
<td><?= e($compte['role']) ?></td>
|
||||
<td><?= e($compte['cree_le']) ?></td>
|
||||
<td><?= e($compte['age_humain']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-3">
|
||||
<small class="text-muted">
|
||||
<?php
|
||||
$tpl = ($translations['label_accounts_listed'] ?? 'Comptes listés : {N}');
|
||||
echo e(str_replace('{N}', (string)count($comptes), $tpl));
|
||||
?>
|
||||
</small>
|
||||
|
||||
<button type="submit" class="btn btn-danger">
|
||||
<?= e($translations['btn_delete_checked_accounts'] ?? '🗑️ Supprimer les comptes cochés') ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
// Cocher / décocher tout
|
||||
document.getElementById('checkAll').addEventListener('change', function() {
|
||||
const boxes = document.querySelectorAll('input[name="ids[]"]');
|
||||
boxes.forEach(b => b.checked = this.checked);
|
||||
});
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
Reference in new issue
Block a user