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
This commit is contained in:
@@ -36,6 +36,7 @@ from molodetz.routers import (
|
||||
flyers,
|
||||
health,
|
||||
home,
|
||||
invite,
|
||||
join,
|
||||
legacy,
|
||||
memes,
|
||||
@@ -145,6 +146,7 @@ app.include_router(flyers.router, prefix="/flyers")
|
||||
app.include_router(memes.router, prefix="/memes")
|
||||
app.include_router(people.router, prefix="/people")
|
||||
app.include_router(join.router, prefix="/join")
|
||||
app.include_router(invite.router, prefix="/invite")
|
||||
app.include_router(terms.router, prefix="/terms")
|
||||
app.include_router(privacy.router, prefix="/privacy")
|
||||
app.include_router(health.router, prefix="/health")
|
||||
@@ -439,4 +441,22 @@ async def validation_handler(request: Request, exc: RequestValidationError):
|
||||
{"errors": messages, "form": echoed, "submitted": False, "seo": {"title": "Join", "robots": "index,follow"}},
|
||||
status_code=400,
|
||||
)
|
||||
if request.url.path.startswith("/invite/"):
|
||||
from molodetz.database import get_invite_by_token
|
||||
|
||||
form = await request.form()
|
||||
echoed = {key: value for key, value in form.items() if isinstance(value, str) and not key.startswith("password")}
|
||||
invite = get_invite_by_token(request.url.path.rsplit("/", 1)[-1])
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"invite.html",
|
||||
{
|
||||
"valid": True,
|
||||
"errors": messages,
|
||||
"form": echoed,
|
||||
"email_locked": bool(invite and invite.get("email")),
|
||||
"seo": {"title": "Accept invite", "robots": "noindex,nofollow"},
|
||||
},
|
||||
status_code=400,
|
||||
)
|
||||
return RedirectResponse(safe_next(request.headers.get("referer", "").replace(str(request.base_url).rstrip("/"), ""), "/"), status_code=303)
|
||||
|
||||
Reference in New Issue
Block a user