Skip to content

Access: admins switch between every screen; role re-read from the DB each request - #137

Merged
dominickdupuy merged 1 commit into
mainfrom
qt/admin-screens
Oct 14, 2026
Merged

dominickdupuy merged 1 commit into
mainfrom
qt/admin-screens

Conversation

@dominickdupuy

Copy link
Copy Markdown
Member

Dom (2026-10-14): admins can switch between member, QT and investor; only admins see the admin tab; make it secure.

Policy

  • An admin (exec_board, legacy admin) holds every screen, server side (GetUserScreens), so the switcher shows Member / Investor / QT / Admin. Non-admins keep exactly their granted screens; the Admin tab and every /api/admin/* route stay admin-only.

Security fixes

  • The role was trusted from the JWT claim for up to 12 h: a demoted admin kept admin (and could grant screens) until the token expired. Now access.current_role() reads auth.users.role on every request (cached per request) and is used by admin_only, /api/me/screens, current_user() and screen resolution. The JWT role claim is no longer used for access.
  • A token whose user was deleted now has no role and no screen (403 everywhere) instead of keeping access until expiry.
  • Server-side enforcement only: the frontend still just hides what the server refuses.

UI: the Admin page marks admin users ("sees every screen and the Admin tab, whatever is ticked here").

Tests: backend 374 (new: admin holds every screen, demotion/promotion take effect on the next request, deleted user keeps no access); role_for against real Postgres; vitest 153.

Known, not in this PR: logout does not revoke a stolen token (no blocklist; screens and admin are now re-checked per request, which limits it to the user's current rights).

… every request

An admin (role exec_board) switches between the member, QT and investor screens and is the
only one who sees and uses the admin tab and routes. The role is no longer taken from the
JWT claim: access.current_role reads auth.users on every request, like the screens, so a
promotion or a demotion takes effect on the next request rather than when the 12-hour token
expires, and a token whose user was deleted keeps no role and no screen.
@dominickdupuy
dominickdupuy merged commit 68445d8 into main Oct 14, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant