diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index d93c1e33b..13d83cbc2 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -519,7 +519,11 @@ class UpdateUserRequest(GenerateRequestBase): return values -class NewEndUserRequest(LiteLLMBase): +class NewCustomerRequest(LiteLLMBase): + """ + Create a new customer, allocate a budget to them + """ + user_id: str alias: Optional[str] = None # human-friendly alias blocked: bool = False # allow/disallow requests for this end-user @@ -540,7 +544,12 @@ class NewEndUserRequest(LiteLLMBase): return values -class UpdateEndUserRequest(LiteLLMBase): +class UpdateCustomerRequest(LiteLLMBase): + """ + Update a Customer, use this to update customer budgets etc + + """ + user_id: str alias: Optional[str] = None # human-friendly alias blocked: bool = False # allow/disallow requests for this end-user @@ -554,6 +563,14 @@ class UpdateEndUserRequest(LiteLLMBase): ) +class DeleteCustomerRequest(LiteLLMBase): + """ + Delete multiple Customers + """ + + user_ids: List[str] + + class Member(LiteLLMBase): role: Literal["admin", "user"] user_id: Optional[str] = None diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 66a1d5e16..0778e678a 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -7792,7 +7792,7 @@ async def unblock_user(data: BlockUsers): dependencies=[Depends(user_api_key_auth)], ) async def new_end_user( - data: NewEndUserRequest, + data: NewCustomerRequest, user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), ): """ @@ -7950,7 +7950,7 @@ async def end_user_info( dependencies=[Depends(user_api_key_auth)], ) async def update_end_user( - data: UpdateEndUserRequest, + data: UpdateCustomerRequest, user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), ): """ @@ -8037,10 +8037,76 @@ async def update_end_user( include_in_schema=False, dependencies=[Depends(user_api_key_auth)], ) -async def delete_end_user(): +async def delete_end_user( + data: DeleteCustomerRequest, + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), +): """ - [TODO] Needs to be implemented. + Example curl + + ``` + curl --location 'http://0.0.0.0:4000/customer/delete' \ + --header 'Authorization: Bearer sk-1234' \ + --header 'Content-Type: application/json' \ + --data '{ + "user_ids" :["ishaan-jaff-5"] + }' + + See below for all params + ``` """ + global prisma_client + + try: + if prisma_client is None: + raise Exception("Not connected to DB!") + + verbose_proxy_logger.debug("/customer/delete: Received data = %s", data) + if ( + data.user_ids is not None + and isinstance(data.user_ids, list) + and len(data.user_ids) > 0 + ): + response = await prisma_client.db.litellm_endusertable.delete_many( + where={"user_id": {"in": data.user_ids}} + ) + if response is None: + raise ValueError( + f"Failed deleting customer data. User ID does not exist passed user_id={data.user_ids}" + ) + if response != len(data.user_ids): + raise ValueError( + f"Failed deleting all customer data. User ID does not exist passed user_id={data.user_ids}. Deleted {response} customers, passed {len(data.user_ids)} customers" + ) + verbose_proxy_logger.debug( + f"received response from updating prisma client. response={response}" + ) + return { + "deleted_customers": response, + "message": "Successfully deleted customers with ids: " + + str(data.user_ids), + } + else: + raise ValueError(f"user_id is required, passed user_id = {data.user_ids}") + + # update based on remaining passed in values + except Exception as e: + traceback.print_exc() + if isinstance(e, HTTPException): + raise ProxyException( + message=getattr(e, "detail", f"Internal Server Error({str(e)})"), + type="internal_error", + param=getattr(e, "param", "None"), + code=getattr(e, "status_code", status.HTTP_500_INTERNAL_SERVER_ERROR), + ) + elif isinstance(e, ProxyException): + raise e + raise ProxyException( + message="Internal Server Error, " + str(e), + type="internal_error", + param=getattr(e, "param", "None"), + code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) pass