From 705af3aeb2ba2f9515650472481d9a2764dcbdf6 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 26 Aug 2026 20:40:15 +0200 Subject: [PATCH] fix(frontend): restrict management controls to admins --- .../AppShell.database-management.test.tsx | 14 ++++--- frontend/src/shell/AppShell.tsx | 41 +++++++++++-------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/frontend/src/shell/AppShell.database-management.test.tsx b/frontend/src/shell/AppShell.database-management.test.tsx index 7177213b..84eb3786 100644 --- a/frontend/src/shell/AppShell.database-management.test.tsx +++ b/frontend/src/shell/AppShell.database-management.test.tsx @@ -22,9 +22,9 @@ beforeEach(() => { setAuthState({ issuer: "test", subject: "test", - roles: ["user"], - permissions: ["session.use", "workspace.manage"], - isAdmin: false, + roles: ["admin"], + permissions: ["session.use", "workspace.manage", "workspace.secrets.manage", "pi.manage"], + isAdmin: true, csrfToken: null, session: null, }); @@ -37,7 +37,7 @@ beforeEach(() => { issuer: "test", subject: "test", displayName: "Test", - isAdmin: false, + isAdmin: true, })), http.get("/api/sessions", () => HttpResponse.json([])), http.get("/api/settings", () => HttpResponse.json({ @@ -122,7 +122,7 @@ test("keeps a live core session connected and returns when that session is opene expect(FakeEventSource.instances).toHaveLength(1); }); -test("shows database management entry to authenticated users without workspace management permission", () => { +test("hides all management entries from non-admin users", () => { clearAuthState(); setAuthState({ issuer: "test", @@ -136,5 +136,7 @@ test("shows database management entry to authenticated users without workspace m renderShell(); - expect(screen.getByRole("button", { name: "Database management" })).toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Workspace management" })).not.toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Database management" })).not.toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Pi management" })).not.toBeInTheDocument(); }); diff --git a/frontend/src/shell/AppShell.tsx b/frontend/src/shell/AppShell.tsx index 3b7ee55c..ba3644ff 100644 --- a/frontend/src/shell/AppShell.tsx +++ b/frontend/src/shell/AppShell.tsx @@ -105,6 +105,7 @@ export function AppShell({ canLogout }: AppShellProps) { const canManageWorkspace = permissions.includes("workspace.manage"); const canManageWorkspaceSecrets = permissions.includes("workspace.secrets.manage"); const canManagePi = permissions.includes("pi.manage"); + const isAdmin = authenticatedUser?.isAdmin === true; const authGeneration = useAuthGeneration(); const { data: sessions = [] } = useQuery({ queryKey: ["sessions", sessionScope], @@ -737,24 +738,28 @@ export function AppShell({ canLogout }: AppShellProps) { > New session - - - {canManagePi && ( + {isAdmin && ( + <> + + + + )} + {isAdmin && canManagePi && (