mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-11 22:51:28 +00:00
Fix single-org team modal locking for admins
Co-authored-by: Shivam Rawat <shivamrawat1@users.noreply.github.com>
This commit is contained in:
parent
121c633d6e
commit
ff9329a0ce
2 changed files with 88 additions and 4 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { act, fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
import { act, fireEvent, render, screen, waitFor, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import React from "react";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { fetchAvailableModelsForTeamOrKey } from "./key_team_helpers/fetch_available_models_team_key";
|
||||
|
|
@ -1004,3 +1005,84 @@ describe("OldTeams - organization alias display", () => {
|
|||
expect(screen.getByText("N/A")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("OldTeams - single organization create team behavior", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockTeamInfoView.mockClear();
|
||||
vi.mocked(fetchAvailableModelsForTeamOrKey).mockResolvedValue(["gpt-4", "gpt-3.5-turbo"]);
|
||||
vi.mocked(fetchMCPAccessGroups).mockResolvedValue([]);
|
||||
vi.mocked(getGuardrailsList).mockResolvedValue({ guardrails: [] });
|
||||
mockUseOrganizations.mockReturnValue({
|
||||
data: [{ organization_id: "org-1", organization_alias: "Org 1", models: [], members: [] }],
|
||||
});
|
||||
});
|
||||
|
||||
it("should allow Admin users to change a preselected single organization", async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
renderWithQueryClient(
|
||||
<OldTeams
|
||||
teams={[]}
|
||||
searchParams={{}}
|
||||
accessToken="test-token"
|
||||
setTeams={vi.fn()}
|
||||
userID="user-123"
|
||||
userRole="Admin"
|
||||
organizations={[{ organization_id: "org-1", organization_alias: "Org 1", models: [], members: [] }]}
|
||||
/>,
|
||||
);
|
||||
|
||||
await user.click(screen.getByRole("button", { name: /create new team/i }));
|
||||
|
||||
const modal = await screen.findByRole("dialog", { name: /create team/i });
|
||||
expect(within(modal).queryByText("You can only create teams within this organization")).not.toBeInTheDocument();
|
||||
|
||||
const organizationFormItem = within(modal).getByText("Organization").closest(".ant-form-item");
|
||||
expect(organizationFormItem).not.toBeNull();
|
||||
|
||||
const organizationSelect = within(organizationFormItem as HTMLElement).getByRole("combobox");
|
||||
const organizationSelectContainer = organizationSelect.closest(".ant-select");
|
||||
expect(organizationSelectContainer).not.toBeNull();
|
||||
expect(organizationSelectContainer).not.toHaveClass("ant-select-disabled");
|
||||
});
|
||||
|
||||
it("should lock the organization selection for Org Admin users with one organization", async () => {
|
||||
const user = userEvent.setup();
|
||||
const orgAdminOrganizations = [
|
||||
{
|
||||
organization_id: "org-1",
|
||||
organization_alias: "Org 1",
|
||||
models: [],
|
||||
members: [{ user_id: "user-123", user_role: "org_admin" }],
|
||||
},
|
||||
];
|
||||
|
||||
mockUseOrganizations.mockReturnValue({ data: orgAdminOrganizations });
|
||||
|
||||
renderWithQueryClient(
|
||||
<OldTeams
|
||||
teams={[]}
|
||||
searchParams={{}}
|
||||
accessToken="test-token"
|
||||
setTeams={vi.fn()}
|
||||
userID="user-123"
|
||||
userRole="Org Admin"
|
||||
organizations={orgAdminOrganizations as any}
|
||||
/>,
|
||||
);
|
||||
|
||||
await user.click(screen.getByRole("button", { name: /create new team/i }));
|
||||
|
||||
const modal = await screen.findByRole("dialog", { name: /create team/i });
|
||||
expect(within(modal).getByText("You can only create teams within this organization")).toBeInTheDocument();
|
||||
|
||||
const organizationFormItem = within(modal).getByText("Organization").closest(".ant-form-item");
|
||||
expect(organizationFormItem).not.toBeNull();
|
||||
|
||||
const organizationSelect = within(organizationFormItem as HTMLElement).getByRole("combobox");
|
||||
const organizationSelectContainer = organizationSelect.closest(".ant-select");
|
||||
expect(organizationSelectContainer).not.toBeNull();
|
||||
expect(organizationSelectContainer).toHaveClass("ant-select-disabled");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1063,9 +1063,11 @@ const Teams: React.FC<TeamProps> = ({
|
|||
</Form.Item>
|
||||
{(() => {
|
||||
const adminOrgs = getAdminOrganizations(userRole, userID, organizations);
|
||||
const isOrgAdmin = userRole !== "Admin";
|
||||
const isGlobalAdmin = userRole === "Admin";
|
||||
const isOrgAdmin = !isGlobalAdmin;
|
||||
const isSingleOrg = adminOrgs.length === 1;
|
||||
const hasNoOrgs = adminOrgs.length === 0;
|
||||
const shouldLockSingleOrgSelection = isOrgAdmin && isSingleOrg;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -1110,7 +1112,7 @@ const Teams: React.FC<TeamProps> = ({
|
|||
: []
|
||||
}
|
||||
help={
|
||||
isSingleOrg
|
||||
shouldLockSingleOrgSelection
|
||||
? "You can only create teams within this organization"
|
||||
: isOrgAdmin
|
||||
? "required"
|
||||
|
|
@ -1120,7 +1122,7 @@ const Teams: React.FC<TeamProps> = ({
|
|||
<Select2
|
||||
showSearch
|
||||
allowClear={!isOrgAdmin}
|
||||
disabled={isSingleOrg}
|
||||
disabled={shouldLockSingleOrgSelection}
|
||||
placeholder={hasNoOrgs ? "No organizations available" : "Search or select an Organization"}
|
||||
onChange={(value) => {
|
||||
form.setFieldValue("organization_id", value);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue