Files
FabledSteward/steward/templates/auth/forgot.html
T
bvandeusenandClaude Opus 5.5 593b583d23
CI / lint (push) Failing after 3s
CI / integration (push) Successful in 1m37s
CI / unit (push) Failing after 1m43s
CI / publish (push) Skipped
feat(auth): reset a forgotten password from an emailed link (milestone 497)
Step #5429 "Reset by email: request, link and new-password page" of
milestone 497 "Passwords: change your own, and reset it by email".

- Sign-in page: "Forgot your password?" while a mail server is set.
- /forgot takes a username or email and answers the same either way; only
  an active local account with a real address gets mail. Requests count
  per address on their own throttle, so they never lock out sign-in.
- password_resets (migration 0039): a one-time key, stored as its sha256,
  working for an hour; asking again replaces it.
- /reset/<key>: the new password, then signed straight in; every other
  browser is signed out (sessions_since). Bad keys count as invite keys do.
- Email "[Steward] Reset your password", in the account's own zone.
- Audited: user.password_reset_requested, user.password_reset_by_email.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 20:17:24 -04:00

31 lines
1.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{# auth/forgot.html — ask for a password-reset email (milestone 497). It answers
the same whether or not an account matched. #}
{% extends "base.html" %}
{% block title %}Forgot your password — Steward{% endblock %}
{% block content %}
<div class="invite-page">
<div class="card">
<h1 class="invite-title">Forgot your password?</h1>
{% if error %}<div class="alert alert-error" role="alert">{{ error }}</div>{% endif %}
{% if sent %}
<div class="alert alert-success" role="status">If that names a Steward account with a password and an email address, a link to choose a new password is on its way to that address. It works for an hour.</div>
<a href="/login" class="btn btn-ghost">Back to sign in</a>
{% elif not mail_ready %}
<p class="invite-lede">Steward has no mail server set, so it can't email you a link. Ask an admin to set a new password for you in Settings › Users.</p>
<a href="/login" class="btn btn-ghost">Back to sign in</a>
{% else %}
<p class="invite-lede">Enter your username or email address. If your account has a Steward password, we'll email you a link to choose a new one.</p>
<form method="post" action="/forgot">{{ csrf_field() }}
<div class="field">
<label class="field-label" for="forgot-name">Username or email</label>
<input class="input" id="forgot-name" type="text" name="name" maxlength="255" required autofocus autocomplete="username">
<span class="field-hint">Accounts that sign in with LDAP or single sign-on change their password there.</span>
</div>
<button type="submit" class="btn invite-submit">Email me a link</button>
</form>
<p class="field-hint"><a href="/login">Back to sign in</a></p>
{% endif %}
</div>
</div>
{% endblock %}