User Roles & Permissions
The Admin UI enforces a two-tier role system: System roles for platform operators, and Organisation roles for association members.
Authentication Flow
- The user visits the login page and selects their context: Platform Admin or Organisation Member
- They submit their email + password (organisation users also provide their org identifier)
- The backend validates credentials and returns a JWT access token + refresh token
- Tokens are stored in HTTP cookies (
__auth_access_token,__auth_refresh_token) - The UI auto-refreshes the access token before it expires using the refresh token
- On logout (or a 401 response), tokens are cleared and the user is redirected to the login page
System Roles (Platform Users)
Platform users authenticate at /platform/login and access the /_platform/* route tree.
| Role | Description |
|---|---|
SUPER_ADMIN | Unrestricted access to the entire platform; can impersonate any organisation context |
PLATFORM_ADMIN | Full administrative access across all organisations |
SUPPORT_ADMIN | Read access to organisations and members for customer support |
BILLING_ADMIN | Access to billing, subscriptions, and invoices |
CONTENT_MODERATOR | Access to articles and content moderation tools |
Organisation context switching (SUPER_ADMIN)
A SUPER_ADMIN can switch into any organisation's context using the organisation switcher in the platform nav. This allows them to view and manage that organisation's data as if they were an org admin.
Organisation Roles
Organisation users authenticate at /org/:slug/login and access the /org/:slug/* route tree. Each user belongs to exactly one organisation and is assigned one role within it.
Roles are defined per-organisation by the organisation admin. The specific role names are configurable, but typically include:
| Common Role | Typical Access |
|---|---|
| Admin | Full access within the organisation |
| Manager | Manage members, events, and content; cannot change billing or org settings |
| Member | Read-only access to published events, articles, and the member directory |
The exact set of roles and their names depend on what the organisation admin has configured.
Authorities (Fine-Grained Permissions)
Each role — both system and organisation — carries a list of authorities that control specific actions. The UI uses these to conditionally render buttons, forms, and entire sections.
How authorities work
When a user logs in, their authorities array is included in the JWT payload. The frontend checks individual authorities before rendering protected UI:
// Example: only show "Create Event" button if user has this authority
const { hasAuthority } = useAuth();
if (hasAuthority('events.write')) {
// render create button
}
Common authority patterns
| Authority | Protected capability |
|---|---|
members.read | View member list and profiles |
members.write | Invite, update, or remove members |
events.read | View events list |
events.write | Create and edit events |
events.publish | Publish or unpublish events |
events.registrations.write | Approve/reject/check-in registrations |
articles.write | Create and edit articles |
documents.write | Upload and manage documents |
billing.read | View billing overview and invoices |
billing.write | Manage subscriptions and record payments |
audit-logs.read | View system audit logs |
settings.write | Update organisation or platform settings |
The authority list is defined and managed in the backend. The frontend reads and checks them but does not define them. Refer to the backend documentation for the full authority reference.
Route Protection
Routes are protected at two levels:
1. Route-level guards (TanStack Router)
Every protected route checks the user's authentication state and role before rendering. Unauthenticated users are redirected to the login page with a returnUrl parameter.
User visits /_platform/billing
→ Not authenticated → redirect to /platform/login?returnUrl=/_platform/billing
→ Authenticated as ORGANISATION user → redirect to /403
→ Authenticated as BILLING_ADMIN → render billing page
2. Backend enforcement
All API endpoints enforce permissions server-side. The UI hiding a button is a UX enhancement only — the backend will reject any unauthorised request with a 403 Forbidden response regardless.
Error Pages
| Route | Shown when |
|---|---|
/401 | User is not authenticated |
/403 | User is authenticated but lacks permission for the requested resource |
/404 | The requested page or resource does not exist |
/500 | An unexpected server error occurred |
/503 | The backend is unreachable or in maintenance mode |
Managing Organisation Roles
Organisation admins can manage roles via the platform's admin role panel (/_platform/admin-roles). From there you can:
- View all system roles and their assigned authorities
- Create custom roles
- Add or remove authorities from a role
Organisation-level role names can be customised per organisation in the organisation settings.