Skip to content

Admin users and RBAC

Who can use the admin, and what each role may do. The admins module owns admin users, roles and menus; the admin frontend mirrors the rules client-side.

How this page was verified

Read on 2026-09-15 from the backend admins module and guards, and the admin frontend useAccess hook and /admin/roles area.

The model

Tables: admins, roles, menus, roles_menus, departments, settings. A role links to menus through roles_menus; each link carries five abilities: view, add, update, delete, export.

Admin auth

auth resolver: login, loginWithGoogle, refreshToken, logout, requestResetPassword, verifyResetPasswordToken, resetPassword. This is the admin JWT realm (jwt / jwt-refresh strategies), separate from members. Admin login supports Google OAuth as well as email/password. See API and auth.

How rights are enforced

  • Backend@RoleCheck({ slug, action }) + RoleAbilityGuard (src/admins/guards/role-check.guard.ts) check the admin's role.menus for a menu slug and ability. The typical admin resolver stacks @UseGuards(JwtAuthGuard, LastActivityGuard, RoleAbilityGuard) — used across ~59 resolvers. @Public() bypasses the guards. LastActivityGuard enforces idle auto-logout after CMS_AUTO_LOGOUT_MAX_INACTIVE_SECONDS (default 1800s).
  • Admin frontenduseAccess(slug, action) (src/hooks/useAccess.tsx) reads session.user.me.role.menus[] and drives both the sidebar (src/components/Sidebar/sidebar-menus.tsx filters by canView) and page guards (a denied page does router.push("/404")). Permissions come from the backend me query, not hard-coded. src/middleware.ts is only a coarse "logged in?" gate — it does not check roles.

Managing it in the admin

  • /admin/admins — admin users (list, add, edit; Excel export).
  • /admin/roles — roles: add-role, edit-role, view-role. The per-menu ability grid is src/modules/roles/components/FormRoleMenuAccesses.tsx.
  • Menu slugs are catalogued in src/components/Sidebar/menu.tsx and URL constants in src/constants/menus.ts.

Gotchas

  • RBAC is client-enforced in the frontend and per-resolver in the backend. The middleware does not enforce per-action rights — the real gate for data is the backend guard.
  • A new admin page needs a menu slug and role grant, or useAccess hides and blocks it.
  • The dashboard is a stub (see Admin repo) — do not document analytics that do not exist.