Repository navigation
adopt v-permission where the UI doesn't gate an admin-only action #16494
Description
Activity
Closure evidence — each criterion checked against merged code in
origin/main(f72de7e)Severity first, because it decides how to read the rest: the backend already refuses all three actions, verified before any UI was touched —
api/feature_flags.pycarriesDepends(require_admin)on 8 of 8 routes,POST /api/settings/telemetrytakes_: None = Depends(check_admin_permission)(the GET is public by design), andapi/themes.py:28,34gates install and uninstall the same way. So these were confusing dead-ends, not privilege escalation: nothing was reachable, only 403s were.-
FeatureFlagsSettingsPanel's tab/panel gated onisAdmin.views/SettingsView.vue:74—v-if="userStore.isAdmin"on the tab button, and:280—<section v-if="activeTab === 'featureflags' && userStore.isAdmin">. Both halves, so the section cannot be reached even ifactiveTabis set another way. -
TelemetrySettingsPanel's admin-only toggle gated, the public GET half still visible.components/settings/TelemetrySettingsPanel.vue:34—<label v-if="userStore.isAdmin" class="toggle-switch">. Only the control is gated; the state it displays comes from the public GET and still renders for everyone. -
ThemeManagerView's install/uninstall gated, listing open.views/slm/ThemeManagerView.vue:69—<template v-if="userStore.isAdmin">around the upload prompt and file input, and:81—v-if="userStore.isAdmin"on the Uninstall button. The theme list itself stays visible, matching the open listing GETs. - SecretsManager's infrastructure-hosts category: confirmed, no change needed. security(secrets): admin-gate infrastructure hosts, fix vault-backed template names (#16426, #16427) #16442 is MERGED and security(secrets): any logged-in user can list and delete infrastructure hosts through /api/infrastructure/hosts #16426 CLOSED, and
components/security/SecretsManager.vuealready gates both the category and its quick-add button onuserStore.isAdmin.
v-ifwith the existinguserStore.isAdminpattern rather thanv-permission, since each of these is a plain admin/non-admin binary — the finer-grained directive is for a gate that needs a specificPermission, which none of these do. No new UI strings, so no locale changes.Covered by tests, which the gate did not have before:
views/slm/__tests__/ThemeManagerView.test.tsnow asserts a non-admin sees the list but neither the file input nor the Uninstall button, and an admin sees both.-
Follow-up from #16243
#16243 wired up a real
v-permissiondirective andusePermissions()composable, but adopting it anywhere is a separate decision -- this issue
names the actual gaps rather than guessing.
Existing gates (for reference -- the right pattern already in use)
router/index.ts(/admin/users,/admin/sandbox,/admin/advanced-control,/admin/budget-policies,/admin/system-health,/admin/provider-fallback,/secrets/llm-keys)meta.admin: true, enforced by the nav guardviews/AgentRegistryView.vue:166,354v-if="isAdmin"App.vue:159,307v-if="userStore.isAdmin"views/UsageView.vue:21,51v-if="isAdmin"views/BudgetPolicies.vue:115,views/SecretsView.vue:28,components/knowledge/KnowledgeScopeSelector.vue:48v-if="isAdmin"None of these currently use
v-permissionorusePermissions()-- theypredate it and use
userStore.isAdmindirectly, which is fine for a pureadmin/non-admin binary.
v-permissionmatters once a gate needs to befiner than "admin or not" (a specific
Permission), which is a separatecall for whoever picks up one of the items below.
Candidate gaps -- frontend doesn't gate, but the backend action does
components/security/SecretsManager.vue+composables/security/useSecretsInfraApi.tsGET/DELETE /api/infrastructure/hostsautobot-backend/api/infrastructure.py-- already being fixed by open PR #16442/#16426 (admin-gates both routes AND hides the category from non-admins in this same component). No action needed here once that merges.components/settings/FeatureFlagsSettingsPanel.vue(tab + panel inviews/SettingsView.vue)autobot-backend/api/feature_flags.py-- every route depends onrequire_admincomponents/settings/TelemetrySettingsPanel.vue(inviews/SettingsView.vue)autobot-backend/api/settings.py--POST /api/settings/telemetryrequirescheck_admin_permission(GET is intentionally public)views/slm/ThemeManagerView.vue(route has nometa.admin)autobot-backend/api/themes.py-- install/uninstall depend oncheck_admin_permission; list/asset GETs are openEach of these lets a non-admin see and attempt an action that already 403s
server-side -- a confusing dead-end rather than a hidden control, not a
privilege-escalation bug (the backend still refuses it), but still the
wrong UX and worth fixing with the same
v-if="isAdmin"pattern alreadyused elsewhere (or
v-permissionif a finer-grained gate turns out to beneeded for one of them).
Acceptance criteria
FeatureFlagsSettingsPanel's tab/panel gated onisAdminTelemetrySettingsPanel's admin-only toggle gated onisAdmin(thepublic GET half stays visible to everyone)
ThemeManagerView's install/uninstall controls gated onisAdmin(list/asset viewing can stay open, matching the backend)
landed and covers this; if not, gate it here too
Refs #16243.