92 lines
3.9 KiB
PHP
92 lines
3.9 KiB
PHP
<?php
|
|
/*
|
|
* Reflector Dashboard — web front-end for SvxReflector
|
|
* Copyright (C) 2026 SA7AUX (Björn)
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify it under
|
|
* the terms of the GNU Affero General Public License as published by the Free
|
|
* Software Foundation, either version 3 of the License, or (at your option) any
|
|
* later version. See the LICENSE file for details.
|
|
*/
|
|
declare(strict_types=1);
|
|
require __DIR__ . '/lib.php';
|
|
|
|
$tid = trim((string)($_GET['tid'] ?? ''));
|
|
$token = trim((string)($_GET['token'] ?? ''));
|
|
$error = '';
|
|
$done = false;
|
|
|
|
if ($tid === '' || $token === '') {
|
|
$error = 'Invalid or missing reset link.';
|
|
} else {
|
|
$k = rkey("token:reset:$tid");
|
|
$h = redis()->hGetAll($k);
|
|
if (!is_array($h) || empty($h['uid']) || empty($h['hash'])) {
|
|
$error = 'Reset link has expired or is invalid.';
|
|
} elseif (!hash_equals((string)$h['hash'], token_hash($token))) {
|
|
$error = 'Invalid reset token.';
|
|
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$pass1 = (string)($_POST['password'] ?? '');
|
|
$pass2 = (string)($_POST['password2'] ?? '');
|
|
if ($pass1 === '' || strlen($pass1) < 6) {
|
|
$error = 'Password must be at least 6 characters.';
|
|
} elseif ($pass1 !== $pass2) {
|
|
$error = 'Passwords do not match.';
|
|
} else {
|
|
$uid = (string)$h['uid'];
|
|
redis()->hSet(acct_key($uid), 'password_hash', password_hash($pass1, PASSWORD_DEFAULT));
|
|
redis()->del($k);
|
|
$done = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
function he(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); }
|
|
?>
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>Reset Password — Reflector Dashboard</title>
|
|
<style>
|
|
:root{ color-scheme:dark; --bg:#000; --fg:#00ffff; --fg2:rgba(0,255,255,.75); --line:rgba(0,255,255,.35); }
|
|
html, body{ height:100%; background:var(--bg); color:var(--fg); margin:0; font-family:system-ui,sans-serif; }
|
|
.box{ max-width:400px; margin:60px auto; padding:24px; border:1px solid var(--line); border-radius:10px; }
|
|
input{ background:var(--bg); color:var(--fg); border:1px solid rgba(0,255,255,.5); border-radius:4px; padding:6px 10px; width:100%; margin-bottom:10px; box-sizing:border-box; }
|
|
input:focus{ outline:none; box-shadow:0 0 0 2px rgba(0,255,255,.25); }
|
|
button{ background:rgba(0,255,255,.15); color:var(--fg); border:1px solid rgba(0,255,255,.7); border-radius:4px; padding:6px 16px; cursor:pointer; }
|
|
button:hover{ background:rgba(0,255,255,.25); }
|
|
.err{ color:#ff8080; font-size:.9rem; margin-bottom:10px; }
|
|
.ok{ color:#00ff80; font-size:.9rem; }
|
|
a{ color:var(--fg); }
|
|
label{ display:block; font-size:.85rem; color:var(--fg2); margin-bottom:4px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="box">
|
|
<h3 style="margin-top:0;">Reset Password</h3>
|
|
<?php if ($done): ?>
|
|
<div class="ok">Password changed successfully!</div>
|
|
<p><a href="/">Back to Reflector Dashboard</a></p>
|
|
<?php elseif ($error && ($_SERVER['REQUEST_METHOD'] !== 'POST' || $tid === '' || $token === '')): ?>
|
|
<div class="err"><?=he($error)?></div>
|
|
<p><a href="/">Back to Reflector Dashboard</a></p>
|
|
<?php else: ?>
|
|
<?php if ($error): ?><div class="err"><?=he($error)?></div><?php endif; ?>
|
|
<form method="post">
|
|
<label>New password</label>
|
|
<input type="password" name="password" autocomplete="new-password" required minlength="6">
|
|
<label>Confirm password</label>
|
|
<input type="password" name="password2" autocomplete="new-password" required>
|
|
<button type="submit">Set New Password</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
<footer style="text-align:center; padding:16px; color:rgba(0,255,255,.4); font-size:.75rem; border-top:1px solid rgba(0,255,255,.15);">
|
|
© 2026 SA7AUX. All rights reserved.
|
|
</footer>
|
|
</body>
|
|
</html>
|