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>
This commit is contained in:
@@ -451,11 +451,13 @@ a.stat-tile:hover { border-color: var(--border-mid); background: var(--bg-elevat
|
||||
.form-section > .section-title { margin-bottom: 0.9rem; }
|
||||
.form-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr)); gap: 0 1rem; }
|
||||
.form-pair[hidden] { display: none; }
|
||||
/* The invite page (milestone 496): the login page's centred card, with labelled fields. */
|
||||
/* The invite, forgot-password and reset pages (milestones 496, 497): the login
|
||||
page's centred card, with labelled fields. */
|
||||
.invite-page { max-width: 420px; margin: 4rem auto; }
|
||||
.invite-title { font-family: var(--font-serif); font-size: 1.5rem; font-weight: 500; margin: 0 0 0.5rem; }
|
||||
.invite-lede { color: var(--text-muted); margin: 0 0 1.25rem; }
|
||||
.invite-submit { width: 100%; margin-top: 0.25rem; }
|
||||
.login-forgot { text-align: center; margin: 1rem 0 0; font-size: 0.85rem; }
|
||||
/* A link shown once to copy (an invite without mail): the value and its Copy button. */
|
||||
.copy-once { display: flex; gap: 0.5rem; align-items: center; }
|
||||
.copy-once .input { flex: 1; font-family: ui-monospace, monospace; font-size: 0.8rem; }
|
||||
|
||||
Reference in New Issue
Block a user