mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
fix(ui): hide admin write-form tabs on the models page from view-only admins
This commit is contained in:
parent
d44d281d1d
commit
3eb48c1fba
2 changed files with 51 additions and 14 deletions
|
|
@ -14,6 +14,7 @@ vi.mock("./panels/HealthStatusPanel", () => ({ default: () => <div data-testid="
|
|||
vi.mock("./panels/ModelRetrySettingsPanel", () => ({ default: () => <div data-testid="panel-retry" /> }));
|
||||
vi.mock("./panels/ModelGroupAliasPanel", () => ({ default: () => <div data-testid="panel-alias" /> }));
|
||||
vi.mock("./panels/PriceDataPanel", () => ({ default: () => <div data-testid="panel-price" /> }));
|
||||
vi.mock("./panels/AccessGroupBudgetsPanel", () => ({ default: () => <div data-testid="panel-budgets" /> }));
|
||||
|
||||
const detailState = { modelId: null as string | null, teamId: null as string | null };
|
||||
vi.mock("./detailNavigation", () => ({
|
||||
|
|
@ -38,8 +39,18 @@ vi.mock("./useModelDashboardData", () => ({
|
|||
useModelDashboardData: () => ({ availableModelAccessGroups: [], allModelsOnProxy: [], availableModelGroups: [] }),
|
||||
}));
|
||||
|
||||
const ADMIN = { accessToken: "at", token: "t", userRole: "Admin", userId: "u1", premiumUser: false };
|
||||
const NON_ADMIN = { accessToken: "at", token: "t", userRole: "Internal User", userId: "u1", premiumUser: false };
|
||||
const ADMIN = { accessToken: "at", token: "t", userRole: "Admin", userId: "u1", premiumUser: false, isViewOnly: false };
|
||||
const NON_ADMIN = {
|
||||
accessToken: "at",
|
||||
token: "t",
|
||||
userRole: "Internal User",
|
||||
userId: "u1",
|
||||
premiumUser: false,
|
||||
isViewOnly: false,
|
||||
};
|
||||
// What useAuthorized returns for a proxy_admin_viewer session: effectiveSessionRole masquerades
|
||||
// the role as "Admin" for read parity, and only isViewOnly tells the page it may not write.
|
||||
const VIEW_ONLY_ADMIN = { ...ADMIN, isViewOnly: true };
|
||||
|
||||
const renderPage = () => {
|
||||
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, gcTime: 0 } } });
|
||||
|
|
@ -99,6 +110,35 @@ describe("ModelsAndEndpointsPage", () => {
|
|||
expect(queryByRole("tab", { name: "Health Status" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("keeps the full admin tab order for a real admin", () => {
|
||||
const { getAllByRole } = renderPage();
|
||||
expect(getAllByRole("tab").map((tab) => tab.textContent)).toEqual([
|
||||
"All Models",
|
||||
"Add Model",
|
||||
"Auto-Routers Beta",
|
||||
"LLM Credentials",
|
||||
"Pass-Through Endpoints",
|
||||
"Health Status",
|
||||
"Model Retry Settings",
|
||||
"Model Group Alias",
|
||||
"Model Access Group Budgets Beta",
|
||||
"Price Data Reload",
|
||||
]);
|
||||
});
|
||||
|
||||
it("hides the admin write-form tabs from a view-only admin, keeping the read views", () => {
|
||||
mockUseAuthorized.mockReturnValue(VIEW_ONLY_ADMIN);
|
||||
const { getByRole, queryByRole } = renderPage();
|
||||
expect(getByRole("tab", { name: "All Models" })).toBeInTheDocument();
|
||||
expect(getByRole("tab", { name: "Health Status" })).toBeInTheDocument();
|
||||
expect(queryByRole("tab", { name: "LLM Credentials" })).not.toBeInTheDocument();
|
||||
expect(queryByRole("tab", { name: "Pass-Through Endpoints" })).not.toBeInTheDocument();
|
||||
expect(queryByRole("tab", { name: "Model Retry Settings" })).not.toBeInTheDocument();
|
||||
expect(queryByRole("tab", { name: "Model Group Alias" })).not.toBeInTheDocument();
|
||||
expect(queryByRole("tab", { name: /Model Access Group Budgets/ })).not.toBeInTheDocument();
|
||||
expect(queryByRole("tab", { name: "Price Data Reload" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Auto-routers are excluded from the All Models table, so this tab is their home: the only
|
||||
// place in the product to list, create, edit or delete one.
|
||||
describe("Auto-Routers tab", () => {
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ const renderPanel = (key: string) => {
|
|||
};
|
||||
|
||||
export default function ModelsAndEndpointsPage() {
|
||||
const { accessToken, userRole, userId: userID, premiumUser } = useAuthorized();
|
||||
const { accessToken, userRole, userId: userID, premiumUser, isViewOnly } = useAuthorized();
|
||||
const { data: teams } = useTeams();
|
||||
const { data: uiSettings } = useUISettings();
|
||||
const queryClient = useQueryClient();
|
||||
|
|
@ -106,19 +106,16 @@ export default function ModelsAndEndpointsPage() {
|
|||
"",
|
||||
...(canCreate ? (["add"] as const) : []),
|
||||
...(isAdmin || canCreate ? (["auto-routers"] as const) : []),
|
||||
...(isAdmin
|
||||
? ([
|
||||
"llm-credentials",
|
||||
"pass-through",
|
||||
"health",
|
||||
"retry-settings",
|
||||
"model-group-alias",
|
||||
"access-group-budgets",
|
||||
"price-data",
|
||||
] as const)
|
||||
// effectiveSessionRole reports proxy_admin_viewer as "Admin", so isAdmin alone would show a
|
||||
// viewer these write-only panels; only the raw-role isViewOnly separates them. Health Status
|
||||
// stays: it is the bucket's one read view, and viewers keep read parity with admins.
|
||||
...(isAdmin && !isViewOnly ? (["llm-credentials", "pass-through"] as const) : []),
|
||||
...(isAdmin ? (["health"] as const) : []),
|
||||
...(isAdmin && !isViewOnly
|
||||
? (["retry-settings", "model-group-alias", "access-group-budgets", "price-data"] as const)
|
||||
: []),
|
||||
],
|
||||
[canCreate, isAdmin],
|
||||
[canCreate, isAdmin, isViewOnly],
|
||||
);
|
||||
|
||||
const allModelsLabel = isAdmin ? "All Models" : "Your Models";
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue