Add remaining org CRUD endpoints + support deleting orgs on UI (#8561)

* feat(organization_endpoints.py): expose new `/organization/delete` endpoint. Cascade org deletion to member, teams and keys

Ensures any org deletion is handled correctly

* test(test_organizations.py): add simple test to ensure org deletion works

* feat(organization_endpoints.py): expose /organization/update endpoint, and define response models for org delete + update

* fix(organizations.tsx): support org delete on UI + move org/delete endpoint to use DELETE

* feat(organization_endpoints.py): support `/organization/member_update` endpoint

Allow admin to update member's role within org

* feat(organization_endpoints.py): support deleting member from org

* test(test_organizations.py): add e2e test to ensure org member flow works

* fix(organization_endpoints.py): fix code qa check

* fix(schema.prisma): don't introduce ondelete:cascade - breaking change

* docs(organization_endpoints.py): document missing params

* refactor(organization_view.tsx): initial commit creating a generic update member component shared between org and team member classes

* feat(organization_view.tsx): support updating org member role on UI

* feat(organization_view.tsx): allow proxy admin to delete members from org
This commit is contained in:
Krish Dholakia 2025-02-15 15:48:06 -08:00 committed by GitHub
parent 3a64d86e65
commit 0b85f05028
9 changed files with 932 additions and 94 deletions

View file

@ -905,6 +905,37 @@ export const organizationCreateCall = async (
}
};
export const organizationDeleteCall = async (
accessToken: string,
organizationID: string
) => {
try {
const url = proxyBaseUrl ? `${proxyBaseUrl}/organization/delete` : `/organization/delete`;
const response = await fetch(url, {
method: "DELETE",
headers: {
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
organization_ids: [organizationID]
}),
});
if (!response.ok) {
const errorData = await response.text();
handleError(errorData);
throw new Error(`Error deleting organization: ${errorData}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("Failed to delete organization:", error);
throw error;
}
};
export const getTotalSpendCall = async (accessToken: String) => {
/**
* Get all models on proxy
@ -2642,6 +2673,85 @@ export const organizationMemberAddCall = async (
}
};
export const organizationMemberDeleteCall = async (
accessToken: string,
organizationId: string,
userId: string
) => {
try {
console.log("Form Values in organizationMemberDeleteCall:", userId); // Log the form values before making the API call
const url = proxyBaseUrl
? `${proxyBaseUrl}/organization/member_delete`
: `/organization/member_delete`;
const response = await fetch(url, {
method: "DELETE",
headers: {
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
organization_id: organizationId,
user_id: userId
}),
});
if (!response.ok) {
const errorData = await response.text();
handleError(errorData);
console.error("Error response from the server:", errorData);
throw new Error("Network response was not ok");
}
const data = await response.json();
console.log("API Response:", data);
return data;
} catch (error) {
console.error("Failed to delete organization member:", error);
throw error;
}
};
export const organizationMemberUpdateCall = async (
accessToken: string,
organizationId: string,
formValues: Member // Assuming formValues is an object
) => {
try {
console.log("Form Values in organizationMemberUpdateCall:", formValues); // Log the form values before making the API call
const url = proxyBaseUrl
? `${proxyBaseUrl}/organization/member_update`
: `/organization/member_update`;
const response = await fetch(url, {
method: "PATCH",
headers: {
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
organization_id: organizationId,
...formValues, // Include formValues in the request body
}),
});
if (!response.ok) {
const errorData = await response.text();
handleError(errorData);
console.error("Error response from the server:", errorData);
throw new Error("Network response was not ok");
}
const data = await response.json();
console.log("API Response:", data);
return data;
} catch (error) {
console.error("Failed to update organization member:", error);
throw error;
}
};
export const userUpdateUserCall = async (
accessToken: string,
formValues: any, // Assuming formValues is an object