Skip to content

Let superadmins suspend accounts from the admin panel - #1444

Merged
daveearley merged 1 commit into
developfrom
feature/admin-account-suspension
Oct 24, 2026
Merged

daveearley merged 1 commit into
developfrom
feature/admin-account-suspension

Conversation

@daveearley

Copy link
Copy Markdown
Contributor

Summary

Adds a Suspend account option to each account page in the super admin section.

Suspending an account:

  • moves its LIVE and PENDING_MANUAL_REVIEW events, and its LIVE organizer pages, to DRAFT (archived events are left alone)
  • blocks password and SSO sign-in for its members, with an ACCOUNT_SUSPENDED error the login page shows as a clear message; members of other accounts are signed in to one that isn't suspended
  • rejects existing sessions and API keys on signed-in routes with 403 ACCOUNT_SUSPENDED (the frontend sends them to the login page with the same message); public routes treat a suspended session as anonymous, so its draft previews aren't reachable
  • optionally emails the account owner, with the reason included

Unsuspending restores access but leaves events and organizer pages in draft for the owner to republish.

Other decisions:

  • Impersonation still works on a suspended account, so admins can look around before unsuspending.
  • Accounts with a superadmin member can't be suspended, matching account deletion.
  • Suspended accounts show a badge on the admin account list and detail page.

Changes

  • Migration: accounts.suspended_at, accounts.suspension_reason
  • AccountSuspensionService plus POST/DELETE /admin/accounts/{account_id}/suspension
  • EnsureAccountIsNotSuspended middleware in the api group (status cached for 60s, cleared on suspend/unsuspend)
  • LoginService excludes suspended accounts; LoginAction returns the code of any CodedAccessException
  • treatRequestAsAnonymous moved from EnsureTokenNotRevoked to AuthUserService so both middlewares share it
  • TeamInviteTest member-listing query ceiling raised from 11 to 12 for the one extra (cached) lookup per request

Testing

  • New AccountSuspensionTest (13 tests) plus full Unit and Feature suites passing locally
  • New e2e spec tests/admin/account-suspension.spec.ts passing against the dev stack
  • API smoke test against the dev stack, including the email in Mailpit
  • Checked the admin page, modal and login message in the browser

Suspending an account moves its live and pending-review events and live
organizer pages to draft, blocks password and SSO sign-in for its members,
and rejects its sessions and API keys with 403 ACCOUNT_SUSPENDED.
Public routes treat a suspended session as anonymous. Superadmins can
optionally email the account owner, with the reason included.

Unsuspending restores access but leaves everything in draft. Impersonation
still works on a suspended account, and accounts with a superadmin member
can't be suspended.
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ E2E smoke tests: Everything passed, but 1 test only passed on retry.

Mode Result ✅ Passed ❌ Failed ⚠️ Flaky ⏭️ Skipped ⏱️ Duration
Self-hosted ⚠️ Passed (some flaky) 110 0 1 0 3m 57s

⚠️ Flaky tests: failed first, then passed on retry (1)

  • Self-hosted · box-office/box-office-reconciliation.spec.ts:6 · box office reconciliation › the sales summary totals door sales by payment type and operator

Open the run

@daveearley
daveearley merged commit 5c1f9dc into develop Oct 24, 2026
9 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 24, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant