mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-09-25 18:03:05 +02:00
51 lines
1.6 KiB
PHP
51 lines
1.6 KiB
PHP
<?php
|
|
/**
|
|
* Request a password reset (unauthenticated).
|
|
*
|
|
* Issues a single-use reset token (shared OneTimeToken model, purpose
|
|
* 'password_reset') and emails the link to the admin notification address.
|
|
* Always returns a neutral message so an attacker cannot learn whether a
|
|
* password hash is configured.
|
|
*/
|
|
require_once __DIR__ . '/../../bootstrap.php';
|
|
require_once APP_ROOT . '/src/AdminAuth.php';
|
|
require_once APP_ROOT . '/src/App.php';
|
|
require_once APP_ROOT . '/src/RateLimit.php';
|
|
|
|
// Only meaningful when a password actually exists (dev mode has none).
|
|
if (!AdminAuth::hasPassword()) {
|
|
header('Location: /admin/');
|
|
exit;
|
|
}
|
|
|
|
App::boot();
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
http_response_code(405);
|
|
header('Allow: POST');
|
|
exit;
|
|
}
|
|
|
|
// CSRF
|
|
if (empty($_POST['csrf_token']) || empty($_SESSION['csrf_token'])
|
|
|| !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
|
|
App::flash('error', 'Erreur de sécurité : token invalide.');
|
|
header('Location: /admin/login.php');
|
|
exit;
|
|
}
|
|
|
|
// Rate-limit reset requests (3 per 10 min per IP) to prevent inbox flooding.
|
|
$key = 'password_reset_' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown');
|
|
if (!(new RateLimit(3, 600))->checkKey($key)) {
|
|
App::flash('error', 'Trop de demandes. Réessayez dans quelques minutes.');
|
|
header('Location: /admin/login.php');
|
|
exit;
|
|
}
|
|
|
|
$sent = AdminAuth::requestPasswordReset();
|
|
|
|
// Neutral message regardless of outcome (no information leak).
|
|
App::flash('success', 'Si une adresse de notification est configurée, un lien de réinitialisation a été envoyé.');
|
|
header('Location: /admin/login.php');
|
|
exit;
|