4.4 KiB
Role-Based UI Access Control
Date: 2026-04-06 Status: Approved
Problem
The UI shows all features to all authenticated users regardless of role. VIEWER users see the Admin sidebar section, can navigate to admin pages, and encounter 403 errors from the backend. App Config is under the Admin section despite being accessible to VIEWER/OPERATOR.
Design
Role-Permission Matrix
| Feature | VIEWER | OPERATOR | ADMIN |
|---|---|---|---|
| Main tabs | |||
| Exchanges (view) | Yes | Yes | Yes |
| Dashboard | Yes | Yes | Yes |
| Runtime | Yes | Yes | Yes |
| Logs | Yes | Yes | Yes |
| Config (new tab, per-app) | Read-only | Read + Edit | Read + Edit |
| Operator actions | |||
| Route control (start/stop/suspend/resume) | Hidden | Yes | Yes |
| Replay exchange | Hidden | Yes | Yes |
| Diagram context menu | Hidden | Yes | Yes |
| Admin section (hidden entirely from non-admin) | |||
| Users & Roles | Hidden | Hidden | Full CRUD |
| Audit Log | Hidden | Hidden | Read-only |
| OIDC Config | Hidden | Hidden | Full CRUD |
| Database Admin | Hidden | Hidden | Read + Kill query |
| ClickHouse Admin | Hidden | Hidden | Read-only |
| Sidebar | |||
| Applications section | Yes | Yes | Yes |
| Starred section | Yes | Yes | Yes |
| Admin section | Hidden | Hidden | Yes |
| API Docs link | Yes | Yes | Yes |
Changes
1. Sidebar — hide Admin section for non-ADMIN
In LayoutShell.tsx, read roles from useAuthStore and conditionally render the Admin sidebar section only when the user has the ADMIN role.
2. Router — add role guard for /admin/*
In router.tsx, wrap admin routes with a RequireRole guard component that checks for ADMIN role and redirects to / if not authorized. Reuse the existing useAuthStore roles.
3. Move App Config to main application tabs
- Remove App Config from the Admin sidebar items
- Add a "Config" tab alongside Exchanges/Dashboard/Runtime/Logs in the main tab bar
- Route:
/config/:appId(scoped per-app, like other tabs) - The config page already exists (
AppConfigPage.tsx,AppConfigDetailPage.tsx) — reuse it - Hide edit/save controls for VIEWER (check
rolesfor OPERATOR+) - Backend ACL already correct:
GET /api/v1/config/*is VIEWER+,PUT /api/v1/config/*is OPERATOR+
4. Role helper
Add a small utility (e.g., hasRole(role) or useHasRole(role)) to reduce boilerplate. The existing pattern roles.some(r => r === 'OPERATOR' || r === 'ADMIN') is repeated — centralize it.
Files to modify
| File | Change |
|---|---|
ui/src/auth/auth-store.ts |
Add hasRole(role) / isAdmin / isOperator helpers |
ui/src/components/LayoutShell.tsx |
Hide Admin sidebar for non-ADMIN; remove App Config from admin items |
ui/src/router.tsx |
Add RequireRole guard on admin routes; add /config/:appId route |
ui/src/components/sidebar-utils.ts |
Remove App Config from buildAdminTreeNodes() |
ui/src/pages/Admin/AppConfigPage.tsx |
Adapt for per-app context (read appId from route params) |
ui/src/pages/Admin/AppConfigDetailPage.tsx |
Hide edit controls for VIEWER |
ui/src/pages/Exchanges/ExchangesPage.tsx |
Conditionally pass onNodeAction to diagram based on role |
5. Diagram node toolbar — hide for VIEWER
The process diagram's NodeToolbar (hover actions: inspect, toggle-trace, configure-tap, copy-id) exposes operator-level actions. Hide it for VIEWER users by not passing the onNodeAction prop to ProcessDiagram / ExecutionDiagram. When onNodeAction is undefined, the toolbar is not rendered (already handled in ProcessDiagram.tsx line 394: toolbar.hoveredNodeId && onNodeAction && ...). The inspect action (node selection) still works via onNodeSelect which is separate.
What stays the same
- Backend ACLs — already correct, no changes needed
- Route control bar — already gated on OPERATOR+ in
ExchangeHeader.tsxandExchangesPage.tsx - All admin pages — no individual page changes needed (router guard handles access)
Verification
- Log in as VIEWER: sidebar has no Admin section,
/admin/*routes redirect to/, Config tab is read-only, diagram node toolbar hidden, route control bar hidden - Log in as OPERATOR: same as VIEWER + route control buttons visible + Config tab is editable + diagram node toolbar visible
- Log in as ADMIN: full Admin sidebar visible, all admin pages accessible, all features enabled