Init Git Prod Mars 2026

This commit is contained in:
Oleg Barykin committed 2026-03-05 10:25:39 +01:00
commit d81efe93b1
362 files changed
+86627

No files matched your search

+276
View File
@@ -0,0 +1,276 @@
<?php
require_once __DIR__ . '/public/includes/init_pr_cl.php';
$translations = $translations ?? [];
// Sécurité : rôle client ou praticien
require_login_or_redirect(['client', 'praticien']);
// Infos de session
$compteId = (int)($_SESSION['compte_id'] ?? 0);
$sessionRole = $_SESSION['role'] ?? null;
if ($compteId <= 0 || !in_array($sessionRole, ['client', 'praticien'], true)) {
header('Location: /connexion.php');
exit;
}
// CSRF
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(16));
}
$CSRF = $_SESSION['csrf_token'];
// Messages d’erreur
$errorMsg = null;
// --------------------------------------------------
// Traitement POST : demande de suppression
// --------------------------------------------------
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf'] ?? '')) {
$errorMsg = $translations['delete_account_error_csrf'] ?? 'Erreur de sécurité, veuillez réessayer.';
} else {
$password = (string)($_POST['password'] ?? '');
$confirm = (string)($_POST['confirm_delete'] ?? '');
if ($password === '' || $confirm !== '1') {
$errorMsg = $translations['delete_account_error_form'] ?? 'Veuillez confirmer la suppression et saisir votre mot de passe.';
} else {
try {
// Récupérer le compte
$stmt = $pdo->prepare('SELECT id, email, mot_de_passe, role, reference_id FROM compte WHERE id = ? LIMIT 1');
$stmt->execute([$compteId]);
$compte = $stmt->fetch(PDO::FETCH_ASSOC);
if (
!$compte ||
!in_array($compte['role'], ['client', 'praticien'], true)
) {
$errorMsg = $translations['delete_account_error_not_found'] ?? 'Compte introuvable.';
} elseif (!password_verify($password, (string) $compte['mot_de_passe'])) {
$errorMsg = $translations['delete_account_error_password'] ?? 'Mot de passe incorrect.';
} else {
$refId = (int)$compte['reference_id'];
$pdo->beginTransaction();
if ($compte['role'] === 'client') {
// CLIENT : la plupart des FK sont en CASCADE ou SET NULL → un seul DELETE suffit
$delClient = $pdo->prepare('DELETE FROM client WHERE id = ?');
$delClient->execute([$refId]);
} elseif ($compte['role'] === 'praticien') {
// PRATICIEN : il y a des FK SANS ON DELETE CASCADE
// On nettoie d'abord les tables dépendantes
// Tokens Google
$stmt = $pdo->prepare('DELETE FROM google_tokens WHERE praticien_id = ?');
$stmt->execute([$refId]);
// Tokens Outlook
$stmt = $pdo->prepare('DELETE FROM outlook_tokens WHERE praticien_id = ?');
$stmt->execute([$refId]);
// Paiements
$stmt = $pdo->prepare('DELETE FROM paiement WHERE praticien_id = ?');
$stmt->execute([$refId]);
// (éventuellement d’autres tables si tu ajoutes des FK plus tard)
// Enfin : supprimer le praticien lui-même
$delPrat = $pdo->prepare('DELETE FROM praticien WHERE id = ?');
$delPrat->execute([$refId]);
}
// Supprimer le compte d’authentification
$delCompte = $pdo->prepare('DELETE FROM compte WHERE id = ?');
$delCompte->execute([$compte['id']]);
$pdo->commit();
// Déconnexion propre
$_SESSION = [];
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(
session_name(),
'',
time() - 42000,
$params['path'],
$params['domain'],
$params['secure'],
$params['httponly']
);
}
session_destroy();
// Redirection vers la page de confirmation
header('Location: /confirmation_suppression.php');
exit;
}
} catch (Throwable $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
error_log('Erreur suppression compte: ' . $e->getMessage());
$errorMsg = $translations['delete_account_error_generic'] ?? 'Une erreur est survenue, veuillez réessayer plus tard.';
}
}
}
}
/** Petite fonction helper pour échapper */
$e = static fn(string $s): string => htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
// --------------------------------------------------
// Textes via $translations
// --------------------------------------------------
$title = $translations['delete_account_title'] ?? 'Supprimer mon compte';
$warningTitle = $translations['delete_account_warning_title']
?? 'Attention, cette action est irréversible.';
$warningText = $translations['delete_account_warning_text']
?? "La suppression de votre compte entraînera la suppression de vos données associées selon nos règles de confidentialité.\nCette action ne peut pas être annulée.";
$pwdLabel = $translations['delete_account_password_label']
?? 'Veuillez confirmer votre mot de passe :';
$pwdPlaceholder = $translations['delete_account_password_placeholder']
?? 'Votre mot de passe';
$checkboxLabel = $translations['delete_account_checkbox_label']
?? 'Je comprends que mon compte et mes données associées seront définitivement supprimés.';
$buttonLabel = $translations['delete_account_button_label']
?? 'Supprimer mon compte';
$saTitle = $translations['delete_account_swal_title']
?? 'Êtes-vous sûr de vouloir supprimer votre compte ?';
$saText = $translations['delete_account_swal_text']
?? 'Cette action est définitive. Vous ne pourrez plus accéder à votre espace.';
$saConfirm = $translations['delete_account_swal_confirm']
?? 'Oui, supprimer';
$saCancel = $translations['delete_account_swal_cancel']
?? 'Annuler';
?>
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title><?= $e($title) ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Montserrat + Bootstrap comme le reste du site -->
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>"> <!-- ta home -->
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
<style>
body {
background:#8CA9FF;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
</style>
</head>
<body>
<script src="/js/sweetalert2@11.js"></script>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-6">
<!-- ===================== FORMULAIRE DE SUPPRESSION ===================== -->
<div class="card shadow-sm">
<div class="card-body">
<h1 class="h4 mb-3 text-danger"><?= $e($title) ?></h1>
<div class="alert alert-warning">
<strong><?= $e($warningTitle) ?></strong><br>
<?= nl2br($e($warningText)) ?>
</div>
<?php if ($errorMsg): ?>
<div class="alert alert-danger">
<?= $e($errorMsg) ?>
</div>
<?php endif; ?>
<form method="post" id="delete-account-form" autocomplete="off">
<input type="hidden" name="csrf" value="<?= $e($CSRF) ?>">
<div class="mb-3">
<label class="form-label" for="password"><?= $e($pwdLabel) ?></label>
<input type="password"
class="form-control"
id="password"
name="password"
required
autocomplete="current-password"
placeholder="<?= $e($pwdPlaceholder) ?>">
</div>
<div class="form-check mb-3">
<input class="form-check-input"
type="checkbox"
value="1"
id="confirm_delete"
name="confirm_delete"
required>
<label class="form-check-label" for="confirm_delete">
<?= $e($checkboxLabel) ?>
</label>
</div>
<button type="submit" class="btn btn-danger w-100">
<?= $e($buttonLabel) ?>
</button>
</form>
</div>
</div>
<div class="text-center mt-3">
<a href="/" class="text-muted">&larr; <?php echo $translations['retour_avis_profil']; ?></a>
</div>
</div>
</div>
</div>
<script>
(function() {
const form = document.getElementById('delete-account-form');
if (!form) return;
form.addEventListener('submit', function(e) {
e.preventDefault();
const passwordInput = document.getElementById('password');
const checkbox = document.getElementById('confirm_delete');
if (!passwordInput.value.trim() || !checkbox.checked) {
form.reportValidity();
return;
}
Swal.fire({
title: <?= json_encode($saTitle, JSON_UNESCAPED_UNICODE) ?>,
text: <?= json_encode($saText, JSON_UNESCAPED_UNICODE) ?>,
icon: 'warning',
showCancelButton: true,
confirmButtonText: <?= json_encode($saConfirm, JSON_UNESCAPED_UNICODE) ?>,
cancelButtonText: <?= json_encode($saCancel, JSON_UNESCAPED_UNICODE) ?>,
reverseButtons: true
}).then((result) => {
if (result.isConfirmed) {
form.submit();
}
});
});
})();
</script>
</body>
</html>