Document team admins + Enforce assigning team admins as an enterprise feature (#7359)

* fix(team_endpoints.py): enforce assigning team admins as an enterprise feature

* fix(proxy/_types.py): fix common proxy error to link to trial key

* fix: fix linting errors
This commit is contained in:
Krish Dholakia 2024-12-21 20:28:31 -08:00 committed by GitHub
parent a8ae2f551a
commit 20feacc9d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 55 additions and 11 deletions

View file

@ -1892,7 +1892,7 @@ class CommonProxyErrors(str, enum.Enum):
db_not_connected_error = "DB not connected" db_not_connected_error = "DB not connected"
no_llm_router = "No models configured on proxy" no_llm_router = "No models configured on proxy"
not_allowed_access = "Admin-only endpoint. Not allowed to access this." not_allowed_access = "Admin-only endpoint. Not allowed to access this."
not_premium_user = "You must be a LiteLLM Enterprise user to use this feature. If you have a license please set `LITELLM_LICENSE` in your env. If you want to obtain a license meet with us here: https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat. \nPricing: https://www.litellm.ai/#pricing" not_premium_user = "You must be a LiteLLM Enterprise user to use this feature. If you have a license please set `LITELLM_LICENSE` in your env. Get a 7 day trial key here: https://www.litellm.ai/#trial. \nPricing: https://www.litellm.ai/#pricing"
class SpendCalculateRequest(LiteLLMPydanticObjectBase): class SpendCalculateRequest(LiteLLMPydanticObjectBase):

View file

@ -14,7 +14,7 @@ import json
import traceback import traceback
import uuid import uuid
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from typing import List, Optional, Union from typing import List, Optional, Union, cast
import fastapi import fastapi
from fastapi import APIRouter, Depends, Header, HTTPException, Request, status from fastapi import APIRouter, Depends, Header, HTTPException, Request, status
@ -547,6 +547,49 @@ async def update_team(
return {"team_id": team_row.team_id, "data": team_row} return {"team_id": team_row.team_id, "data": team_row}
def _check_team_member_admin_add(
member: Union[Member, List[Member]],
premium_user: bool,
):
if isinstance(member, Member) and member.role == "admin":
if premium_user is not True:
raise ValueError(
f"Assigning team admins is a premium feature. {CommonProxyErrors.not_premium_user.value}"
)
elif isinstance(member, List):
for m in member:
if m.role == "admin":
if premium_user is not True:
raise ValueError(
f"Assigning team admins is a premium feature. Got={m}. {CommonProxyErrors.not_premium_user.value}. "
)
def team_call_validation_checks(
prisma_client: Optional[PrismaClient],
data: TeamMemberAddRequest,
premium_user: bool,
):
if prisma_client is None:
raise HTTPException(status_code=500, detail={"error": "No db connected"})
if data.team_id is None:
raise HTTPException(status_code=400, detail={"error": "No team id passed in"})
if data.member is None:
raise HTTPException(
status_code=400, detail={"error": "No member/members passed in"}
)
try:
_check_team_member_admin_add(
member=data.member,
premium_user=premium_user,
)
except Exception as e:
raise HTTPException(status_code=400, detail={"error": str(e)})
@router.post( @router.post(
"/team/member_add", "/team/member_add",
tags=["team management"], tags=["team management"],
@ -578,21 +621,22 @@ async def team_member_add(
""" """
from litellm.proxy.proxy_server import ( from litellm.proxy.proxy_server import (
litellm_proxy_admin_name, litellm_proxy_admin_name,
premium_user,
prisma_client, prisma_client,
proxy_logging_obj, proxy_logging_obj,
user_api_key_cache, user_api_key_cache,
) )
if prisma_client is None: try:
raise HTTPException(status_code=500, detail={"error": "No db connected"}) team_call_validation_checks(
prisma_client=prisma_client,
if data.team_id is None: data=data,
raise HTTPException(status_code=400, detail={"error": "No team id passed in"}) premium_user=premium_user,
if data.member is None:
raise HTTPException(
status_code=400, detail={"error": "No member/members passed in"}
) )
except HTTPException as e:
raise e
prisma_client = cast(PrismaClient, prisma_client)
existing_team_row = await get_team_object( existing_team_row = await get_team_object(
team_id=data.team_id, team_id=data.team_id,