feat(webui): add missing permission scopes (models:register, logs:list, monitor:view) to UI - #5254
Conversation
…t, monitor:view) to UI - Add models:register, logs:list, monitor:view to ALL_PERMISSIONS array - Add logs and monitor permission groups to PERMISSION_GROUPS - Add hasLogsList and hasMonitorView to useMenuAuth hook - Gate log center sidebar visibility on hasLogsList scope - Gate monitor center sidebar visibility on hasMonitorView scope - Add i18n labels for new scopes and groups (en, zh, ja, ko) These three scopes are already defined in the backend (INITIAL_ADMIN_PERMISSIONS) but were never exposed in the UI, making it impossible to grant them to non-admin users. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces new permissions (models:register, logs:list, and monitor:view) and updates the sidebar navigation to conditionally display the log and monitor centers based on these permissions. The review feedback correctly identifies a critical bug where the new permission flags are omitted from the useMemo dependency array in the sidebar, which prevents the UI from updating when permissions load asynchronously. Additionally, the feedback recommends implementing and applying the canRegisterModel permission check to properly gate the model registration menu item.
- Add hasLogsList, hasMonitorView, canRegisterModel to navGroups useMemo dependency array to fix stale UI after async token load - Add canRegisterModel to useMenuAuth hook - Gate /register-model sidebar item on canRegisterModel scope Without the dependency array fix, non-admin users with logs:list or monitor:view scopes would never see the log/monitor center menu items because navGroups is not recomputed after the token loads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Backend scope_aliases.py normalizes models:add and models:unregister to models:register. Users with legacy scopes in their JWT token pass API authorization but should also see the Register Model sidebar item. Add both legacy scope names to the hasScope check.
… pages Sidebar show gating alone does not prevent direct URL navigation to /monitor-center or /log-center. Add a reusable PermissionGuard client component that checks the required scope against useMenuAuth and renders an access-denied page when auth_advanced is enabled and the user lacks the scoped permission. - Create PermissionGuard component (monitor:view, logs:list, models:register scopes) - Wrap /monitor-center page with monitor:view guard - Wrap /log-center page with logs:list guard - Add accessDenied i18n keys (en, zh, ja, ko) The /register-model page uses server-side redirect() so its guard is handled at the sidebar level for now.
qinxuye
left a comment
There was a problem hiding this comment.
One route-level permission gap remains.
The server-side redirect at /register-model does not protect direct URLs such as /register-model/LLM or /register-model/LLM/<name>. Both client pages rendered the registration form for users without the models:register scope, relying only on backend 403 errors. Wrap both dynamic page clients with PermissionGuard scope="models:register" so the UI permission is enforced consistently with monitor-center and log-center.
qinxuye
left a comment
There was a problem hiding this comment.
One initialization gap remains in the route guard.
clusterUIConfig starts as {} so auth_advanced is temporarily falsy
before the global APIs resolve. This creates a brief window where
unauthorized users see protected pages on direct-route refresh.
Read globalReady from useGlobal() and render a Loading spinner
until the configuration is loaded.
qinxuye
left a comment
There was a problem hiding this comment.
The two Windows failures are deterministic: Python 3.10 and 3.13 both fail test_build_subpool_envs_for_virtual_env_enabled because os.path.join() produces backslash-separated paths on Windows while the expected value hard-codes forward slashes. This is a baseline failure introduced by 7c772e1d1a, not by this frontend-only PR; the latest main run fails the same two Windows jobs. Please rebase/rerun after the baseline test is fixed so this PR can return to green.
Withdrawing approval until the two reproducible Windows CI failures are cleared. They are baseline failures rather than changes introduced by this PR.
Summary
Add three permission scopes that exist in the backend but were never exposed in the frontend UI:
models:register— Register/unregister modelslogs:list— View logsmonitor:view— View monitoringThese scopes are already defined in
xinference/api/oauth2/advanced/auth_service.py(INITIAL_ADMIN_PERMISSIONS) but were missing fromALL_PERMISSIONSin the frontend, making it impossible to grant them to non-admin users via the UI.Changes
permissions.tsx: Add 3 missing scopes toALL_PERMISSIONSand addlogs/monitorgroups toPERMISSION_GROUPSuse-menu-auth.ts: AddhasLogsList,hasMonitorView, andcanRegisterModelcomputed properties (with legacy scope alias support formodels:addandmodels:unregister)sidebar.tsx: Gate log center onhasLogsListscope; gate monitor center onhasMonitorViewscope; gate register model oncanRegisterModelscope (all gated behindauth_advancedflag)en/zh/ja/ko.ts: Add i18n labels and group names for new scopesBackward Compatibility
auth_advancedis enabled)models:addandmodels:unregisterscopes recognized via frontend alias check (matching backendscope_aliases.pynormalization)