<?php
/**
* PassGram v3.0 - Password Reset Entry Point
*
* Users arrive here via a link generated by an admin.
* Token is validated; on success the user sets a new password.
*/
require_once __DIR__ . '/autoload.php';
use PassGram\Core\Config;
use PassGram\Core\Session;
use PassGram\Core\Database;
use PassGram\Security\CSRF;
use PassGram\Security\Encryption;
use PassGram\Models\User;
use PassGram\Models\PasswordReset;
use PassGram\Helpers\Validator;
use PassGram\Helpers\Logger;
use PassGram\Helpers\Sanitizer;
// Check if installed
$config = Config::getInstance(__DIR__ . '/config');
if (!$config->isInstalled() || !file_exists(__DIR__ . '/data/users.json.enc')) {
header('Location: /setup.php');
exit;
}
Session::start();
$masterKey = hex2bin($config->get('security.master_application_key'));
$encryption = new Encryption($masterKey, $config->get('security.encryption'));
$db = new Database($encryption, $config->database());
$csrf = new CSRF();
$validator = new Validator($config);
$logger = new Logger($config->get('database.activity_log'));
$userModel = new User($db, $config, $validator);
$resetModel = new PasswordReset($db);
$token = Sanitizer::trim($_GET['token'] ?? $_POST['token'] ?? '');
$reset = $token ? $resetModel->validate($token) : null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!$csrf->validatePost()) {
Session::flash('error', 'Invalid security token. Please try again.');
header('Location: /reset-password.php?token=' . urlencode($token));
exit;
}
if (!$reset) {
Session::flash('error', 'Invalid or expired reset link.');
header('Location: /reset-password.php');
exit;
}
$password = $_POST['password'] ?? '';
$confirmPassword = $_POST['confirm_password'] ?? '';
if ($password !== $confirmPassword) {
Session::flash('error', 'Passwords do not match.');
header('Location: /reset-password.php?token=' . urlencode($token));
exit;
}
try {
$userModel->updatePassword($reset['user_id'], $password);
$resetModel->consume($token);
$logger->info("Password reset completed for user ID {$reset['user_id']}");
Session::flash('success', 'Password updated successfully. You can now log in.');
header('Location: /login.php');
exit;
} catch (\Exception $e) {
$logger->error('Password reset error: ' . $e->getMessage());
Session::flash('error', $e->getMessage());
header('Location: /reset-password.php?token=' . urlencode($token));
exit;
}
} else {
// GET — display form
$user = $reset ? $userModel->findById($reset['user_id']) : null;
$data = [
'csrf_token' => $csrf->getToken(),
'token' => $token,
'valid_token' => (bool) $reset,
'username' => $user['username'] ?? '',
'error' => Session::flash('error'),
'success' => Session::flash('success'),
];
extract($data);
require __DIR__ . '/src/Views/auth/reset_password.php';
}