Files
varlog/public/login/magic.php
T
Cedric Abonnel 700329f156 Initial commit
2026-05-08 12:55:46 +02:00

69 lines
2.4 KiB
PHP

<?php
// projet : mug.a5l.fr
// fichier : pages/login/magic.php
// version : 20251011
declare(strict_types=1);
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__DIR__, 2) . '/app/bootstrap.php';
require_once dirname(__DIR__, 2) . '/config/config.php';
use App\Service\AuthService; // si tu as un service pour ouvrir une session
if (!function_exists('db')) {
function db(): PDO { return \App\Infrastructure\Database::get(); }
}
if (!function_exists('url')) {
function url(string $path = '/'): string {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
return $scheme . '://' . $host . $path;
}
}
$token = (string)($_GET['token'] ?? '');
if ($token === '' || preg_match('/[^A-Za-z0-9\-\_]/', $token)) {
http_response_code(400);
exit('Lien invalide.');
}
$pdo = db();
$pdo->beginTransaction();
try {
// récupère lien non consommé et non expiré
$sql = "SELECT id, email, token, created_at, expires_at, consumed_at, return_to
FROM auth_magic_links
WHERE token = :t
FOR UPDATE";
$stmt = $pdo->prepare($sql);
$stmt->execute([':t' => $token]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$row) throw new RuntimeException('Lien inconnu.');
if ($row['consumed_at'] !== null) throw new RuntimeException('Lien déjà utilisé.');
if (strtotime((string)$row['expires_at']) < time()) throw new RuntimeException('Lien expiré.');
// consomme le lien
$pdo->prepare("UPDATE auth_magic_links SET consumed_at = NOW() WHERE id = :id")->execute([':id' => $row['id']]);
$pdo->commit();
// ouvre une session applicative « anonyme authentifiée par email »
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
$_SESSION['auth'] = [
'method' => 'magic',
'email' => (string)$row['email'],
'ts' => time(),
];
// Aucun create user ici, conforme à la demande
$dest = $row['return_to'] ?? '/';
// sécurité: ne renvoyer que des chemins relatifs
if (!is_string($dest) || !str_starts_with($dest, '/')) $dest = '/';
header('Location: ' . $dest, true, 303);
exit;
} catch (\Throwable $e) {
if ($pdo->inTransaction()) $pdo->rollBack();
http_response_code(400);
echo htmlspecialchars($e->getMessage(), ENT_QUOTES);
}