Files
retoor 9fb4d65787 Member invites, gallery resync, content and operator docs
- Invite flow: admin issue/revoke on join requests, public single-use
  claim links (hash-only tokens, 7-day expiry, no state reveal), claim
  creates the Member account and marks the request accepted
- Gallery: admin status page plus resync endpoint; sync refreshes
  thumbnails whose content changed; tools/gallery contract and checker
- Docs: public content page, admin-only operator runbook, api.md
  invite/gallery sections, all routes in the live API docs, docs
  reachability gate test
- Screenshots cover the new pages; version 1.0.18
2026-10-06 02:56:08 +02:00

25 lines
1.8 KiB
HTML

<!-- retoor <retoor@molodetz.nl> -->
{% extends "base.html" %}
{% block content %}
<header class="article-header">
<span class="label">Invite</span>
<h1>Accept your invite</h1>
</header>
{% if not valid %}
<div class="notice error" role="alert"><ul>{% for error in errors %}<li>{{ error }}</li>{% endfor %}</ul></div>
<p><a class="button ghost" href="/">Back home</a></p>
{% else %}
{% if errors %}
<div class="notice error" role="alert"><ul>{% for error in errors %}<li>{{ error }}</li>{% endfor %}</ul></div>
{% endif %}
<form class="form" method="post">
<div class="field"><label for="username">Name</label><input id="username" type="text" name="username" required minlength="3" maxlength="32" pattern="[A-Za-z0-9_-]{3,32}" value="{{ (form or {}).username or '' }}" autocomplete="username"><p class="hint">3 to 32 letters, digits, _ or -.</p></div>
<div class="field"><label for="email">Email</label><input id="email" type="email" name="email" required maxlength="255" value="{{ (form or {}).email or '' }}" autocomplete="email"{% if email_locked %} readonly{% endif %}>{% if email_locked %}<p class="hint">This invite was issued for this address.</p>{% endif %}</div>
<div class="field"><label for="password">Password</label><input id="password" type="password" name="password" required minlength="6" maxlength="128" autocomplete="new-password"></div>
<div class="field"><label for="password_confirm">Password again</label><input id="password_confirm" type="password" name="password_confirm" required minlength="6" maxlength="128" autocomplete="new-password"></div>
<label class="check"><input type="checkbox" name="terms" value="true"> I accept the <a href="/terms" target="_blank" rel="noopener">house rules</a></label>
<div class="actions"><button class="button" type="submit" data-loading>Create my account</button></div>
</form>
{% endif %}
{% endblock %}