1
0
Fork 0
app.sixfold.org/www/forgot-password.php

182 lines
5.9 KiB
PHP

<?php
if (LOGGED_IN) {
// http_response_code(303);
// header("Location: /");
// die();
}
$title = "Reset Password";
$description = "Request a password reset email.";
if (isset($_GET["hash"])) {
$stmt = $db["data"]->prepare(
"SELECT member_id FROM password_resets WHERE hash = :hash"
);
$stmt->execute([
"hash" => $_GET["hash"] ?? null,
]);
$is_valid_hash = $stmt->fetch(PDO::FETCH_COLUMN) ? true : false;
if (!$is_valid_hash) {
$_SESSION["alert_message"] =
"This password reset link is expired or invalid.";
}
}
if ($_SERVER["REQUEST_METHOD"] === "POST"):
define(
"IS_RESET_REQUEST",
$_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["email"])
);
define(
"IS_NEW_PASSWORD",
$_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["new-password"])
);
$errors = [];
if (IS_NEW_PASSWORD) {
if (mb_strlen(trim($_POST["new-password"])) === 0) {
$errors["new-password"] = "You can't have an empty password.";
}
if ($_POST["new-password"] !== $_POST["new-password-confirm"]) {
$errors["new-password"] =
"The newly-entered passwords do not match.";
}
if (count($errors) === 0) {
// get id from has lookup
$stmt = $db["data"]->prepare(
"SELECT member_id FROM password_resets WHERE hash = :hash"
);
$stmt->execute([
"hash" => $_POST["hash"],
]);
$member_id = $stmt->fetch(PDO::FETCH_COLUMN);
// update password
$stmt = $db["data"]->prepare(
"UPDATE members SET password = :password WHERE id = :id;"
);
$stmt->execute([
"id" => $member_id,
"password" => password_hash(
$_POST["new-password"],
PASSWORD_ARGON2ID
),
]);
$stmt = $db["data"]->prepare(
"DELETE FROM password_resets WHERE hash = :hash;"
);
$stmt->execute([
"hash" => $_POST["hash"],
]);
$_SESSION["alert_message"] =
"Your password has been successfully reset.";
http_response_code(303);
header("Location: /login");
die();
}
}
if (IS_RESET_REQUEST) {
if (mb_strlen(trim($_POST["email"])) === 0) {
$errors["email"] = "Please enter an email address.";
} else {
$stmt = $db["data"]->prepare(
"SELECT id FROM members WHERE LOWER(email) = LOWER(:email)"
);
$stmt->execute([
"email" => $_POST["email"],
]);
$member_id = $stmt->fetch(PDO::FETCH_COLUMN);
if ($member_id) {
$stmt = $db["data"]->prepare(
"INSERT OR REPLACE INTO password_resets (hash, member_id) VALUES (:hash, :member_id)"
);
$stmt->execute([
"hash" => bin2hex(random_bytes(32)),
"member_id" => $member_id,
]);
// send password reset
// $_SESSION["alert_message"] =
// "A password reset email will be sent if an account with the provided email exists.";
http_response_code(303);
header("Location: /forgot-password");
die();
}
}
}
endif;
include "partials/head.php";
?>
<body>
<?php include "partials/header.php"; ?>
<main id="main" class="flow">
<header>
<h1><?= $title ?></h1>
</header>
<?php if (isset($_SESSION["alert_message"])) { ?>
<aside class="alert">
<p><?= $_SESSION["alert_message"] ?></p>
<?php unset($_SESSION["alert_message"]); ?>
</aside>
<?php } ?>
<form action="<?= $_SERVER[
"REQUEST_URI"
] ?>" method="post" class="flow">
<?php if (isset($is_valid_hash) && $is_valid_hash): ?>
<?php if (
isset($errors) &&
isset($errors["new-password"])
) { ?><p><mark><?= $errors[
"new-password"
] ?></mark></p><?php } ?>
<label>
<span>New password</span>
<input type="password" name="new-password" value='<?= $_POST[
"new-password"
] ?? "" ?>'/>
</label>
<label>
<span>Confirm new password</span>
<input type="password" name="new-password-confirm" value='<?= $_POST[
"new-password-confirm"
] ?? "" ?>'/>
</label>
<input type='hidden' name='hash' value='<?= $_GET[
"hash"
] ?>'/>
<button type="submit">Reset password</button>
<?php else: ?>
<aside class="alert">
<p><b>This form doesn't work yet.</b> Please mail <code>sixfold [at] sixfold.org</code> to request a reset link.</p>
</aside>
<label>
<span>Email address <small>(email@example.com)</small></span>
<?php if (
isset($errors) &&
isset($errors["email"])
) { ?><span><mark><?= $errors[
"email"
] ?></mark></span><?php } ?>
<input type="email" name="email"/>
</label>
<button type="submit">Send reset email</button>
<?php endif; ?>
</form>
</main>
<?php include "partials/footer.php"; ?>