Litellm dev 01 10 2025 p2 (#7679)

* test(test_basic_python_version.py): assert all optional dependencies are marked as extras on poetry

Fixes https://github.com/BerriAI/litellm/issues/7677

* docs(secret.md): clarify 'read_and_write' secret manager usage on aws

* docs(secret.md): fix doc

* build(ui/teams.tsx): add edit/delete button for updating user / team membership on ui

allows updating user role to admin on ui

* build(ui/teams.tsx): display edit member component on ui, when edit button on member clicked

* feat(team_endpoints.py): support updating team member role to admin via api endpoints

allows team member to become admin post-add

* build(ui/user_dashboard.tsx): if team admin - show all team keys

Fixes https://github.com/BerriAI/litellm/issues/7650

* test(config.yml): add tomli to ci/cd

* test: don't call python_basic_testing in local testing (covered by python 3.13 testing)
This commit is contained in:
Krish Dholakia 2025-01-10 21:50:53 -08:00 committed by GitHub
parent e0d5afbd3e
commit e54d23c919
15 changed files with 425 additions and 67 deletions

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
import Link from "next/link";
import { Typography } from "antd";
import { teamDeleteCall, teamUpdateCall, teamInfoCall } from "./networking";
import TeamMemberModal, { TeamMember } from "@/components/team/edit_membership";
import {
InformationCircleIcon,
PencilAltIcon,
@ -65,12 +66,12 @@ interface EditTeamModalProps {
import {
teamCreateCall,
teamMemberAddCall,
teamMemberUpdateCall,
Member,
modelAvailableCall,
teamListCall
} from "./networking";
const Team: React.FC<TeamProps> = ({
teams,
searchParams,
@ -112,11 +113,12 @@ const Team: React.FC<TeamProps> = ({
const [isTeamModalVisible, setIsTeamModalVisible] = useState(false);
const [isAddMemberModalVisible, setIsAddMemberModalVisible] = useState(false);
const [isEditMemberModalVisible, setIsEditMemberModalVisible] = useState(false);
const [userModels, setUserModels] = useState([]);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [teamToDelete, setTeamToDelete] = useState<string | null>(null);
const [selectedEditMember, setSelectedEditMember] = useState<null | TeamMember>(null);
// store team info as {"team_id": team_info_object}
const [perTeamInfo, setPerTeamInfo] = useState<Record<string, any>>({});
const EditTeamModal: React.FC<EditTeamModalProps> = ({
@ -257,16 +259,19 @@ const Team: React.FC<TeamProps> = ({
const handleMemberOk = () => {
setIsAddMemberModalVisible(false);
setIsEditMemberModalVisible(false);
memberForm.resetFields();
};
const handleCancel = () => {
setIsTeamModalVisible(false);
form.resetFields();
};
const handleMemberCancel = () => {
setIsAddMemberModalVisible(false);
setIsEditMemberModalVisible(false);
memberForm.resetFields();
};
@ -412,7 +417,7 @@ const Team: React.FC<TeamProps> = ({
return false;
}
const handleMemberCreate = async (formValues: Record<string, any>) => {
const _common_member_update_call = async (formValues: Record<string, any>, callType: "add" | "edit") => {
try {
if (accessToken != null && teams != null) {
message.info("Adding Member");
@ -421,13 +426,27 @@ const Team: React.FC<TeamProps> = ({
user_email: formValues.user_email,
user_id: formValues.user_id,
};
const response: any = await teamMemberAddCall(
accessToken,
selectedTeam["team_id"],
user_role
);
message.success("Member added");
console.log(`response for team create call: ${response["data"]}`);
let response: any;
if (callType == "add") {
response = await teamMemberAddCall(
accessToken,
selectedTeam["team_id"],
user_role
);
message.success("Member added");
} else {
response = await teamMemberUpdateCall(
accessToken,
selectedTeam["team_id"],
{
"role": formValues.role,
"user_id": formValues.id,
"user_email": formValues.email
}
);
message.success("Member updated");
}
// Checking if the team exists in the list and updating or adding accordingly
const foundIndex = teams.findIndex((team) => {
console.log(
@ -449,7 +468,15 @@ const Team: React.FC<TeamProps> = ({
} catch (error) {
console.error("Error creating the team:", error);
}
}
const handleMemberCreate = async (formValues: Record<string, any>) => {
_common_member_update_call(formValues, "add");
};
const handleMemberUpdate = async (formValues: Record<string, any>) => {
_common_member_update_call(formValues, "edit");
}
return (
<div className="w-full mx-4">
<Grid numItems={1} className="gap-2 p-8 h-[75vh] w-full mt-2">
@ -831,6 +858,30 @@ const Team: React.FC<TeamProps> = ({
: null}
</TableCell>
<TableCell>{member["role"]}</TableCell>
<TableCell>
{userRole == "Admin" ? (
<>
<Icon
icon={PencilAltIcon}
size="sm"
onClick={() => {
setIsEditMemberModalVisible(true);
setSelectedEditMember({
"id": member["user_id"],
"email": member["user_email"],
"team_id": selectedTeam["team_id"],
"role": member["role"]
})
}}
/>
<Icon
onClick={() => {}}
icon={TrashIcon}
size="sm"
/>
</>
) : null}
</TableCell>
</TableRow>
)
)
@ -838,6 +889,13 @@ const Team: React.FC<TeamProps> = ({
</TableBody>
</Table>
</Card>
<TeamMemberModal
visible={isEditMemberModalVisible}
onCancel={handleMemberCancel}
onSubmit={handleMemberUpdate}
initialData={selectedEditMember}
mode="edit"
/>
{selectedTeam && (
<EditTeamModal
visible={editModalVisible}