Roles and Admin access
How Mithril Forge's role model works and how to grant or revoke admin access.
Roles and Admin access
Section titled “Roles and Admin access”Mithril Forge uses a simple role-based access control stored in the users.role column. Two roles are recognised today:
ROLE_USER(default for every signup)ROLE_ADMIN(grants access to the/admininterface and/api/admin/**endpoints)
The value is stored with the ROLE_ prefix in the database (Spring Security convention).
How access is enforced
Section titled “How access is enforced”Two layers defend admin-only endpoints:
- Backend filter chain —
SecurityConfigrequireshasRole("ADMIN")for/api/admin/**. A request without a validsession_tokencookie, with an unknown user, or withROLE_USERreceives403 Forbidden. - Frontend guard —
<AdminGuard>probes/api/admin/users/statson mount. If the response is not2xx, the user is redirected to/login?redirect=/admin.
Only the app owner (or a delegated operator) should carry ROLE_ADMIN.
How to grant admin access
Section titled “How to grant admin access”The intended workflow is a one-off SQL update against the production database. Use the Postgres console of your environment (Railway, local Docker, etc.).
UPDATE usersSET role = 'ROLE_ADMIN', updated_at = NOW()WHERE email = '[email protected]' AND role <> 'ROLE_ADMIN';The AND role <> 'ROLE_ADMIN' guard keeps the statement idempotent — re-running it is safe.
Locally (development stack)
Section titled “Locally (development stack)”docker compose exec postgres psql -U myuser -d mydatabase \ -c "UPDATE users SET role = 'ROLE_ADMIN', updated_at = NOW() \ WHERE email = '[email protected]' AND role <> 'ROLE_ADMIN';"Railway (production)
Section titled “Railway (production)”- Open the project on Railway.
- Open the Postgres service → Data → Query.
- Paste the SQL above, replace the email.
- Run once. The change is immediate; the affected user can refresh
/adminafter reloading the page (the existing session already carries the new role becauseSessionTokenAuthFilterreads roles fresh from the DB on every request).
How to revoke admin access
Section titled “How to revoke admin access”UPDATE usersSET role = 'ROLE_USER', updated_at = NOW()WHERE email = '[email protected]' AND role <> 'ROLE_USER';The next request from that user will be rejected with 403.
Auditing who is admin
Section titled “Auditing who is admin”SELECT id, email, role, created_at, last_login_atFROM usersWHERE role = 'ROLE_ADMIN'ORDER BY created_at DESC;Run this periodically to verify only intended operators have elevated privileges.
Future work
Section titled “Future work”- Self-service role changes via the admin UI
- Audit log of admin actions
- Multi-role support (e.g.
ROLE_SUPPORTwith limited privileges)