Carry next through the password change and let requesters pick a username
A forced or voluntary password change now redirects to the validated `next` target (the page the user was heading for, or the home page) instead of landing back on the account form. Login and the must-change-password middleware pass the destination along as /account?change=1&next=... and the form carries it as a hidden field. The request-access form gains a required Username field validated with the account rules and rejected when an account or another open request already holds it (case-insensitive). Migration 0009 stores it on the request; the notification email and the Users dashboard show it, and the Approve form is prefilled with it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QVPagF6jfDv78CC5Jv2wp4
This commit is contained in:
@@ -6,12 +6,13 @@
|
||||
<p class="muted text-sm">Approve creates a user account with a temporary password and emails it; the user must choose a new password on first sign-in. Or create accounts with <code>daily-epub users add</code> and mark the request done. Change, disable, enable, or sign out users with the <code>daily-epub users</code> CLI.</p>
|
||||
<section class="card"><h2>Access requests</h2>
|
||||
{% if requests.is_empty() %}<p class="muted">No open requests.</p>{% else %}<div class="scroll-x"><table>
|
||||
<thead><tr><th>Email</th><th>Reason or comment</th><th>Requested</th><th><span class="sr-only">Action</span></th></tr></thead>
|
||||
<thead><tr><th>Email</th><th>Username</th><th>Reason or comment</th><th>Requested</th><th><span class="sr-only">Action</span></th></tr></thead>
|
||||
<tbody>{% for request in requests %}<tr>
|
||||
<td class="font-medium text-ink"><a href="mailto:{{ request.email }}">{{ request.email }}</a></td>
|
||||
<td class="font-medium text-ink">{{ request.suggested_username }}</td>
|
||||
<td class="cell-wrap">{% if request.reason.is_empty() %}<span class="text-muted">—</span>{% else %}{{ request.reason }}{% endif %}</td>
|
||||
<td class="cell-tight text-muted">{{ request.requested }}</td>
|
||||
<td><div class="flex flex-wrap gap-2"><form class="form-inline" method="post" action="/dashboard/users/requests/{{ request.id }}/approve"><input type="text" name="username" value="{{ request.suggested_username }}" required pattern="[a-z0-9_-]+" aria-label="Username for {{ request.email }}"><button class="btn-primary" type="submit"{% if !mail_configured %} disabled title="Email is not configured"{% endif %}>Approve</button></form><form method="post" action="/dashboard/users/requests/{{ request.id }}/done"><button class="btn" type="submit">Mark done</button></form></div></td>
|
||||
<td><div class="flex flex-wrap gap-2"><form class="form-inline" method="post" action="/dashboard/users/requests/{{ request.id }}/approve"><input type="text" name="username" value="{{ request.suggested_username }}" autocomplete="username" maxlength="32" required pattern="[A-Za-z0-9._-]+" aria-label="Username for {{ request.email }}"><button class="btn-primary" type="submit"{% if !mail_configured %} disabled title="Email is not configured"{% endif %}>Approve</button></form><form method="post" action="/dashboard/users/requests/{{ request.id }}/done"><button class="btn" type="submit">Mark done</button></form></div></td>
|
||||
</tr>{% endfor %}</tbody></table></div>{% endif %}
|
||||
</section>
|
||||
{% if users.len() > 1 %}<input type="search" class="table-filter" placeholder="Filter rows on this page" aria-label="Filter rows on this page" data-table-filter>{% endif %}<div class="scroll-x tall"><table data-filter>
|
||||
|
||||
Reference in New Issue
Block a user