feat(admin): delete a whitelist entry, and stop hiding a broken mail setup

Three operator gaps, all found the same way — a person could not sign up and the
app showed nobody anything.

- DELETE /api/admin/invites/{id} with a delete control on both the pending
  requests and the previously-decided list. Deny keeps the row so the person
  cannot immediately re-ask; delete forgets the address. Refused with 409 while
  a User row exists for it, because is_allowed reads that row and removing it
  would revoke a live user's access with no other sign — the list ships
  has_account so the UI withholds the button instead of offering one that fails.
- Email is fail-soft by design, which had come to mean invisible. _send() now
  records an email_undelivered notification for every admin when a message is
  skipped or rejected, naming the message that was lost, throttled to one an
  hour. /api/me carries email_configured, driving a standing warning on
  Configuration → Email / SMTP and above the access-request list.
- The sign-in card's Create account / Forgot password / Didn't get the email
  views are history entries (useHistorySubview), so Back returns to the previous
  view instead of only moving the address bar.

Also: the per-test rate-limiter reset sweeps every loaded app.* module rather
than a hand-kept list of three — this change added a limiter outside it.
This commit is contained in:
2026-09-01 23:09:25 +02:00
parent 24c93cbb83
commit 44f626f732
25 changed files with 636 additions and 23 deletions
+10 -1
View File
@@ -164,6 +164,15 @@
"deny": "Deny",
"denied": "Request denied",
"denyTitle": "Deny access request?",
"denyConfirm": "Deny the access request from {{email}}?"
"denyConfirm": "Deny the access request from {{email}}?",
"delete": "Delete",
"deleteLabel": "Delete {{email}} from the whitelist",
"deleteHint": "Remove this address entirely. A later request from it starts over.",
"deleteTitle": "Delete whitelist entry?",
"deleteConfirm": "Remove {{email}} from the whitelist? If they were approved, they lose access until you add them again.",
"deleteHasAccount": "This address has an account — delete the user instead.",
"deleted": "Whitelist entry removed.",
"deleteFailed": "Could not remove the entry.",
"emailOff": "Email sending is not configured, so nobody gets a verification link and you get no notice when someone signs up. Fix it under Configuration → Email / SMTP."
}
}