Ce lien de connexion est invalide.
', null)); } $pdo = db(); // ─── Rendu minimal standalone ──────────────────────────────────────────────── function renderMagicPage(string $title, string $body, ?string $token): string { $formHtml = $token !== null ? '' : ''; return '' . 'Ce lien de connexion est introuvable.
', null)); } if ($row['consumed_at'] !== null) { http_response_code(400); exit(renderMagicPage('Lien déjà utilisé', 'Ce lien de connexion a déjà été utilisé.
', null)); } if (strtotime((string)$row['expires_at']) < time()) { http_response_code(400); exit(renderMagicPage('Lien expiré', 'Ce lien de connexion a expiré.
', null)); } exit(renderMagicPage('Connexion', 'Cliquez sur le bouton ci-dessous pour vous connecter.
', $token)); } // ─── POST : consommer le token et ouvrir la session ────────────────────────── $pdo->beginTransaction(); try { $sql = 'SELECT id, email, 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é.'); } $pdo->prepare('UPDATE auth_magic_links SET consumed_at = NOW() WHERE id = :id')->execute([':id' => $row['id']]); $pdo->commit(); if (session_status() !== PHP_SESSION_ACTIVE) { session_start(); } session_regenerate_id(true); $_SESSION['user_email'] = strtolower(trim((string)$row['email'])); $dest = $row['return_to'] ?? '/'; 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); exit(renderMagicPage('Erreur', '' . htmlspecialchars($e->getMessage()) . '
', null)); }