diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx index f3f1e79ac2a..50cee215eb9 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx @@ -4,9 +4,9 @@ import GuardrailsPanel from "@/components/guardrails"; import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; const GuardrailsPage = () => { - const { accessToken, userRole } = useAuthorized(); + const { accessToken } = useAuthorized(); - return ; + return ; }; export default GuardrailsPage; diff --git a/ui/litellm-dashboard/src/components/guardrails.tsx b/ui/litellm-dashboard/src/components/guardrails.tsx index c2bc4a903a9..f171bbc3e56 100644 --- a/ui/litellm-dashboard/src/components/guardrails.tsx +++ b/ui/litellm-dashboard/src/components/guardrails.tsx @@ -5,6 +5,7 @@ import { getGuardrailsList, deleteGuardrailCall } from "./networking"; import AddGuardrailForm from "./guardrails/add_guardrail_form"; import GuardrailTable from "./guardrails/guardrail_table"; import { isAdminRole } from "@/utils/roles"; +import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; import GuardrailInfoView from "./guardrails/guardrail_info"; import GuardrailTestPlayground from "./guardrails/GuardrailTestPlayground"; import NotificationsManager from "./molecules/notifications_manager"; @@ -17,7 +18,6 @@ import { TeamGuardrailsTab } from "./guardrails/TeamGuardrailsTab"; interface GuardrailsPanelProps { accessToken: string | null; - userRole?: string; } interface GuardrailItem { @@ -38,7 +38,8 @@ interface GuardrailsResponse { guardrails: Guardrail[]; } -const GuardrailsPanel: React.FC = ({ accessToken, userRole }) => { +const GuardrailsPanel: React.FC = ({ accessToken }) => { + const { userRole } = useAuthorized(); const [guardrailsList, setGuardrailsList] = useState([]); const [isAddModalVisible, setIsAddModalVisible] = useState(false); const [isCustomCodeModalVisible, setIsCustomCodeModalVisible] = useState(false); @@ -252,7 +253,7 @@ const GuardrailsPanel: React.FC = ({ accessToken, userRole { key: "submitted", label: "Submitted Guardrails", - children: , + children: , }, ]} /> diff --git a/ui/litellm-dashboard/src/components/guardrails/TeamGuardrailsTab.tsx b/ui/litellm-dashboard/src/components/guardrails/TeamGuardrailsTab.tsx index 8ba26553c42..1be00b2a357 100644 --- a/ui/litellm-dashboard/src/components/guardrails/TeamGuardrailsTab.tsx +++ b/ui/litellm-dashboard/src/components/guardrails/TeamGuardrailsTab.tsx @@ -25,6 +25,7 @@ import { import NotificationsManager from "@/components/molecules/notifications_manager"; import TeamDropdown from "@/components/common_components/team_dropdown"; import { useRegisterGuardrail } from "@/app/(dashboard)/hooks/guardrails/useRegisterGuardrail"; +import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; import { isAdminRole } from "@/utils/roles"; type GuardrailStatus = "active" | "pending" | "rejected"; @@ -805,10 +806,10 @@ function ConfirmDialog({ interface TeamGuardrailsTabProps { accessToken: string | null; - userRole?: string; } -export function TeamGuardrailsTab({ accessToken, userRole }: TeamGuardrailsTabProps) { +export function TeamGuardrailsTab({ accessToken }: TeamGuardrailsTabProps) { + const { userRole } = useAuthorized(); const isAdmin = userRole ? isAdminRole(userRole) : false; const [guardrails, setGuardrails] = useState([]); const [summary, setSummary] = useState({ diff --git a/ui/litellm-dashboard/tests/team_guardrails_tab.test.tsx b/ui/litellm-dashboard/tests/team_guardrails_tab.test.tsx index fe18b6e3009..d499e64e3da 100644 --- a/ui/litellm-dashboard/tests/team_guardrails_tab.test.tsx +++ b/ui/litellm-dashboard/tests/team_guardrails_tab.test.tsx @@ -1,6 +1,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { renderWithProviders, screen } from "./test-utils"; import { TeamGuardrailsTab } from "../src/components/guardrails/TeamGuardrailsTab"; +import useAuthorized from "../src/app/(dashboard)/hooks/useAuthorized"; vi.mock("../src/components/networking", () => ({ listGuardrailSubmissions: vi.fn(), @@ -20,6 +21,10 @@ vi.mock("../src/components/common_components/team_dropdown", () => ({ default: () => null, })); +vi.mock("../src/app/(dashboard)/hooks/useAuthorized", () => ({ + default: vi.fn(), +})); + import { listGuardrailSubmissions } from "../src/components/networking"; const pendingSubmission = { @@ -37,7 +42,19 @@ const pendingSubmission = { submitted_at: "2026-05-09T00:00:00Z", }; +const baseAuth = { + token: "test-token", + accessToken: "test-token", + userId: "user-1", + userEmail: "user@example.com", + premiumUser: false, + disabledPersonalKeyCreation: null, + showSSOBanner: false, +}; + describe("TeamGuardrailsTab — approve/reject role gate", () => { + const mockUseAuthorized = vi.mocked(useAuthorized); + beforeEach(() => { vi.clearAllMocks(); vi.mocked(listGuardrailSubmissions).mockResolvedValue({ @@ -47,11 +64,9 @@ describe("TeamGuardrailsTab — approve/reject role gate", () => { }); it("hides Approve and Reject buttons for an internal user on a pending submission", async () => { - renderWithProviders( - - ); + mockUseAuthorized.mockReturnValue({ ...baseAuth, userRole: "Internal User" }); + renderWithProviders(); - // Wait for the submission row to render await screen.findByText("test-pending-guardrail"); expect(screen.queryByRole("button", { name: /approve/i })).not.toBeInTheDocument(); @@ -59,9 +74,8 @@ describe("TeamGuardrailsTab — approve/reject role gate", () => { }); it("shows Approve and Reject buttons for an admin on a pending submission", async () => { - renderWithProviders( - - ); + mockUseAuthorized.mockReturnValue({ ...baseAuth, userRole: "Admin" }); + renderWithProviders(); await screen.findByText("test-pending-guardrail"); @@ -70,6 +84,7 @@ describe("TeamGuardrailsTab — approve/reject role gate", () => { }); it("hides Approve and Reject buttons when userRole is undefined (defaults to non-admin)", async () => { + mockUseAuthorized.mockReturnValue({ ...baseAuth, userRole: undefined }); renderWithProviders(); await screen.findByText("test-pending-guardrail");