
    gR              	          d Z ddlZddlmZmZ ddlZddlmZmZmZm	Z	m
Z
 ddlZddlmZ ddl ddlmZ  e       Zej%                  dd	g ee      gd
      ej%                  dd	g ee      g      defd              Zej%                  dd	g ee      gd
      ej%                  dd	g ee      g      defd              Zdedee   fdZej%                  dd	gd
 ee      g      ej%                  dd	g ee      g       ee      fdedefd              Zej7                  dd	g ee      ge      ej7                  dd	gd
 ee      g       ej:                  d      fdefd               Zej%                  d!d	g ee      g      ej%                  d"d	gd
 ee      g       ee      fde defd#              Z!ej%                  d$d	g ee      g      ej%                  d%d	gd
 ee      g       ee      fde"defd&              Z#ej7                  d'd	g ee      gee         ej7                  d(d	gd
 ee      g       ee      fd)e	defd*              Z$y)+z}
CUSTOMER MANAGEMENT

All /customer management endpoints 

/customer/new   
/customer/info
/customer/update
/customer/delete
    N)ListOptional)	APIRouterDependsHTTPExceptionRequeststatus)verbose_proxy_logger)*)user_api_key_authz/end_user/blockzCustomer ManagementF)tagsdependenciesinclude_in_schemaz/customer/block)r   r   datac                   K   ddl m} 	 g }|\| j                  D ]L  }|j                  j                  j                  d|i|ddddid	       d{   }|j                  |       N nt        d
ddi      d|iS 7 +# t        $ r>}t        j                  dt        |              t        d
dt        |      i      d}~ww xY ww)a  
    [BETA] Reject calls with this end-user id

    Parameters:
    - user_ids (List[str], required): The unique `user_id`s for the users to block

        (any /chat/completion call with this user={end-user-id} param, will be rejected.)

        ```
        curl -X POST "http://0.0.0.0:8000/user/block"
        -H "Authorization: Bearer sk-1234"
        -d '{
        "user_ids": [<user_id>, ...]
        }'
        ```
    r   prisma_clientNuser_idT)r   blockedr   )createupdatewherer     errorzPostgres DB Not connectedstatus_codedetailblocked_userszAn error occurred - )litellm.proxy.proxy_serverr   user_idsdblitellm_endusertableupsertappendr   	Exceptionr
   r   str)r   r   recordsidrecordes         j/var/www/openai/venv/lib/python3.12/site-packages/litellm/proxy/management_endpoints/customer_endpoints.py
block_userr-      s     8 9G$mm,//DDKK$b/.0T"B#,d"3  L    v& $  !<= 
  ))  G""%9#a&#BCWc!f4EFFGs;   C	AA? A=*A? <C	=A? ?	C9CCC	z/end_user/unblockz/customer/unblockc                 z  K   ddl m t        fdt        j                  D              rt        j
                  t        dddi      t        t        j
                  t              r1| j                  D ]!  }t        j
                  j                  |       # nt        ddd	i      d
t        j
                  iS w)z
    [BETA] Unblock calls with this user id

    Example
    ```
    curl -X POST "http://0.0.0.0:8000/user/unblock"
    -H "Authorization: Bearer sk-1234"
    -d '{
    "user_ids": [<user_id>, ...]
    }'
    ```
    r   )_ENTERPRISE_BlockedUserListc              3   6   K   | ]  }t        |        y w)N)
isinstance).0xr/   s     r,   	<genexpr>zunblock_user.<locals>.<genexpr>n   s     VDUq
19:DUs     r   z:Blocked user check was never set. This call has no effect.r   r   zF`blocked_user_list` must be set as a list. Filepaths can't be updated.r   )-enterprise.enterprise_hooks.blocked_user_listr/   anylitellm	callbacksblocked_user_listr   r1   listr!   remove)r   r)   r/   s     @r,   unblock_userr=   Q   s     0
 VGDUDUVV$$,U
 	
 '++T2--B%%,,R0   a
 	
 W6677s   B8B;returnc                     t         j                  j                         }i }|D ]  }|dk(  r	t        | |d      }||||<    |rt        di |S y)zE
    Return a new budget object if new budget params are passed.
    	budget_idN )BudgetNewRequestmodel_fieldskeysgetattr)r   budget_paramsbudget_kv_pairs
field_namevalues        r,   new_budget_requestrJ      sh     %11668MO $
$j$/*/OJ' $ 2/22    z/end_user/new)r   r   r   z/customer/newuser_api_key_dictc                 @  K   	 ddl m}m}m} |'t	        ddt
        j                  j                  i      	 | j                  |'t	        ddt
        j                  j                  i      | j                  |j                         vr@t	        dddj                  | j                  t        |j                                     i      i }t        |       }|r	 |j                  j                  j!                  i |j#                  d	
      |j$                  xs ||j$                  xs |d       d{   }|j*                  |d<   n| j*                  | j*                  |d<   | j-                  d	      }	|	j/                         D ]+  \  }
}|
t0        j2                  j5                         vs'|||
<   - |j                  j6                  j!                  |dd	i       d{   }|S 7 # t&        $ r}t	        ddt)        |      i      d}~ww xY w7 1# t&        $ r}t9        j:                  dj                  t)        |                   dt)        |      v rt=        d| j$                   dddd      t?        |t              rKt=        tA        |ddt)        |       d      dtA        |dd      tA        |dtB        jD                               t?        |t<              r|t=        d!t)        |      z   dtA        |dd      tB        jD                         d}~ww xY ww)"a	  
    Allow creating a new Customer 


    Parameters:
    - user_id: str - The unique identifier for the user.
    - alias: Optional[str] - A human-friendly alias for the user.
    - blocked: bool - Flag to allow or disallow requests for this end-user. Default is False.
    - max_budget: Optional[float] - The maximum budget allocated to the user. Either 'max_budget' or 'budget_id' should be provided, not both.
    - budget_id: Optional[str] - The identifier for an existing budget allocated to the user. Either 'max_budget' or 'budget_id' should be provided, not both.
    - allowed_model_region: Optional[Union[Literal["eu"], Literal["us"]]] - Require all user requests to use models in this specific region.
    - default_model: Optional[str] - If no equivalent model in the allowed region, default all requests to this model.
    - metadata: Optional[dict] = Metadata for customer, store information for customer. Example metadata = {"data_training_opt_out": True}
    - budget_duration: Optional[str] - Budget is reset at the end of specified duration. If not set, budget is never reset. You can set duration as seconds ("30s"), minutes ("30m"), hours ("30h"), days ("30d").
    - tpm_limit: Optional[int] - [Not Implemented Yet] Specify tpm limit for a given customer (Tokens per minute)
    - rpm_limit: Optional[int] - [Not Implemented Yet] Specify rpm limit for a given customer (Requests per minute)
    - model_max_budget: Optional[dict] - [Not Implemented Yet] Specify max budget for a given model. Example: {"openai/gpt-4o-mini": {"max_budget": 100.0, "budget_duration": "1d"}}
    - max_parallel_requests: Optional[int] - [Not Implemented Yet] Specify max parallel requests for a given customer.
    - soft_budget: Optional[float] - [Not Implemented Yet] Get alerts when customer crosses given budget, doesn't block requests.
    
    
    - Allow specifying allowed regions 
    - Allow specifying default model

    Example curl:
    ```
    curl --location 'http://0.0.0.0:4000/customer/new'         --header 'Authorization: Bearer sk-1234'         --header 'Content-Type: application/json'         --data '{
            "user_id" : "ishaan-jaff-3",
            "allowed_region": "eu",
            "budget_id": "free_tier",
            "default_model": "azure/gpt-3.5-turbo-eu" <- all calls from this user, use this model? 
        }'

        # return end-user object
    ```

    NOTE: This used to be called `/end_user/new`, we will still be maintaining compatibility for /end_user/XXX for these endpoints
    r   )litellm_proxy_admin_name
llm_routerr   Nr   r   r   i  zmDefault Model not on proxy. Configure via `/model/new` or config.yaml. Default_model={}, proxy_model_names={}T)exclude_unset)
created_by
updated_by)r   r@   exclude_nonelitellm_budget_table)r   includez\litellm.proxy.management_endpoints.customer_endpoints.new_end_user(): Exception occured - {}z3Unique constraint failed on the fields: (`user_id`)z(Customer already exists, passed user_id=z. Please pass a new user_id.bad_requestr5   r   )messagetypecodeparamr   Internal Server Error()internal_errorr[   Noner   rX   rY   r[   rZ   Internal Server Error, )#r    rN   rO   r   r   CommonProxyErrorsdb_not_connected_errorrI   default_modelno_llm_routerget_model_namesformatsetrJ   r"   litellm_budgettabler   
model_dumpr   r&   r'   r@   dictitemsrB   rC   rD   r#   r
   	exceptionProxyExceptionr1   rE   r	   HTTP_500_INTERNAL_SERVER_ERROR)r   rL   rN   rO   r   new_end_user_obj_new_budgetbudget_recordr+   
_user_datakvend_user_records                r,   new_end_userrw      sP    p
  .EEKKL
 	
Q
 )!# ##%6%D%D%J%JK  ##:+E+E+GG# #  "Q  "X  "X ..J4N4N4P0Q"  "$ )."
O&3&6&6&J&J&Q&Q%00t0D&7&?&?&[C[&7&?&? '43	 'R ' ! -:,C,C[)^^',0NN[)YYDY1
$$&DAq(55::<<&' # '
 !. 0 0 E E L L!+T2 !M !
 

 7!  O#Wc!f<MNNO
  
&&jqqA	

 ACFJ B4<<.Plm"	  a' 8/Ec!fXQ-OP%a&1Qv/T/TU	  >*G-A6!!Wf-66	
 	
/
st   5LB H AG* 5G(6G* :A3H .3H !H"H 'L(G* *	H3HHH 	LC8LLLz/customer/info)r   r   response_modelz/end_user/infoz%End User ID in the request parameters)descriptionend_user_idc                 6  K   ddl m} |'t        ddt        j                  j
                  i      |j                  j                  j                  d| idd	i
       d{   }|t        dddj                  |       i      |j                  d	      S 7 6w)ae  
    Get information about an end-user. An `end_user` is a customer (external user) of the proxy.

    Parameters:
    - end_user_id (str, required): The unique identifier for the end-user

    Example curl:
    ```
    curl -X GET 'http://localhost:4000/customer/info?end_user_id=test-litellm-user-4'         -H 'Authorization: Bearer sk-1234'
    ```
    r   r   Nr   r   r   r   rU   T)r   rV   r5   z#End User Id={} does not exist in dbrS   )r    r   r   rb   rc   rI   r"   r#   
find_firstrg   rj   )rz   r   	user_infos      r,   end_user_infor~   <  s     : 9.EEKKL
 	

 $&&;;FF+&1G0N G  I BII+VW
 	
 T22s   AB B!7Bz/customer/updatez/end_user/updatec                   K   ddl m} 	 | j                         }|t        d      i }|j	                         D ]  \  }}|	|g i dfvs|||<    t        j                  d|        | j                  t        | j                        dkD  r| j                  |d<   t        j                  d       |j                  j                  j                  d| j                  i|       d{   }|t        d	| j                         t        j                  d
|        |S t        d| j                         7 P# t        $ r}t        j                  dj                  t        |                   t        j                  t!        j"                                t%        |t&              rKt)        t+        |ddt        |       d      dt+        |dd      t+        |dt,        j.                              t%        |t(              r|t)        dt        |      z   dt+        |dd      t,        j.                        d}~ww xY ww)a  
    Example curl 

    Parameters:
    - user_id: str
    - alias: Optional[str] = None  # human-friendly alias
    - blocked: bool = False  # allow/disallow requests for this end-user
    - max_budget: Optional[float] = None
    - budget_id: Optional[str] = None  # give either a budget_id or max_budget
    - allowed_model_region: Optional[AllowedModelRegion] = (
        None  # require all user requests to use models in this specific region
    )
    - default_model: Optional[str] = (
        None  # if no equivalent model in allowed region - default all requests to this model
    )

    Example curl:
    ```
    curl --location 'http://0.0.0.0:4000/customer/update'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
        "user_id": "test-litellm-user-4",
        "budget_id": "paid_tier"
    }'

    See below for all params 
    ```
    r   r   NNot connected to DB!z$/customer/update: Received data = %sr   z,In update customer, user_id condition block.r   zEFailed updating customer data. User ID does not exist passed user_id=8received response from updating prisma client. response=&user_id is required, passed user_id = zDlitellm.proxy.proxy_server.update_end_user(): Exception occured - {}r   r\   r]   r^   r[   r_   r   r`   ra   )r    r   jsonr&   rl   r
   debugr   lenr"   r#   r   
ValueErrorr   rg   r'   	traceback
format_excr1   r   rn   rE   r	   ro   )	r   rL   r   	data_jsonnon_default_valuesrt   ru   responser+   s	            r,   update_end_userr   m  s8    Z 99
))+	 233  OO%DAq}+ "
 )*"1% & 	""#I4P<<#DLL(9A(=,0LLy) &&'UV*--BBII $,,/6H J  H  [\`\h\h[ij  !&&J8*U OEdll^TUU  
""RYYA	

 	""9#7#7#9:a' 8/Ec!fXQ-OP%a&1Qv/T/TU	  >*G-A6!!Wf-66	
 	
!
sH   H>7D8 D8 
BD8 %D6&7D8 H>D8 8	H;C5H66H;;H>z/customer/deletez/end_user/deletec                   K   ddl m} 	 |t        d      t        j                  d|        | j
                  t        | j
                  t              rt        | j
                        dkD  r|j                  j                  j                  dd| j
                  ii       d{   }|t        d	| j
                         |t        | j
                        k7  r2t        d
| j
                   d| dt        | j
                         d      t        j                  d|        |dt        | j
                        z   dS t        d| j
                         7 # t        $ r}t        j                  dj                  t        |                   t        j                  t!        j"                                t        |t$              rKt'        t)        |ddt        |       d      dt)        |dd      t)        |dt*        j,                              t        |t&              r|t'        dt        |      z   dt)        |dd      t*        j,                        d}~ww xY ww)a  
    Delete multiple end-users.

    Parameters:
    - user_ids (List[str], required): The unique `user_id`s for the users to delete

    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 
    ```
    r   r   Nr   z$/customer/delete: Received data = %sr   in)r   zEFailed deleting customer data. User ID does not exist passed user_id=zIFailed deleting all customer data. User ID does not exist passed user_id=z
. Deleted z customers, passed z
 customersr   z)Successfully deleted customers with ids: )deleted_customersrX   r   zDlitellm.proxy.proxy_server.delete_end_user(): Exception occured - {}r   r\   r]   r^   r[   r_   r   r`   ra   )r    r   r&   r
   r   r!   r1   r;   r   r"   r#   delete_manyr   r'   r   rg   r   r   r   rn   rE   r	   ro   )r   rL   r   r   r+   s        r,   delete_end_userr     sv    B 96
 233""#I4PMM%4==$/DMM"Q&*--BBNN 4"78 O  H  [\`\i\i[jk  3t}}-- _`d`m`m_nnx  zB  yC  CV  WZ  [_  [h  [h  Wi  Vj  jt  u  !&&J8*U &.Fdmm$%  Edmm_UVV).  
""RYYA	

 	""9#7#7#9:a' 8/Ec!fXQ-OP%a&1Qv/T/TU	  >*G-A6!!Wf-66	
 	
!
s=   IBE #E$BE >I?E 	I"C5IIIz/customer/listz/end_user/listhttp_requestc           	        K   ddl m} |j                  t        j                  k7  rE|j                  t        j
                  k7  r(t        dddj                  |j                        i      |'t        ddt        j                  j                  i      |j                  j                  j                  d	d
i       d{   }g }|D ]*  }|j                  t        di |j!                                , |S 7 7w)z
    [Admin-only] List all available customers

    Example curl:
    ```
    curl --location --request GET 'http://0.0.0.0:4000/customer/list'         --header 'Authorization: Bearer sk-1234'
    ```

    r   r   i  r   z&Admin-only endpoint. Your user role={}r   Nr5   rU   T)rV   rA   )r    r   	user_roleLitellmUserRolesPROXY_ADMINPROXY_ADMIN_VIEW_ONLYr   rg   rb   rc   rI   r"   r#   	find_manyr%   LiteLLM_EndUserTablerj   )r   rL   r   r   returned_responseitems         r,   list_end_userr   6  s     4 9 	##'7'C'CC''+;+Q+QQAHH%//
 	
 .EEKKL
 	

 #%%::DD'. E  H 57  !5!J8I!JK s   B=C9?C7 8C9)%__doc__r   typingr   r   fastapir   r   r   r   r	   r8   litellm._loggingr
   litellm.proxy._types$litellm.proxy.auth.user_api_key_authr   routerpost
BlockUsersr-   r=   NewCustomerRequestrB   rJ   UserAPIKeyAuthrw   getr   Queryr'   r~   UpdateCustomerRequestr   DeleteCustomerRequestr   r   rA   rK   r,   <module>r      s  	  !  F F  1 " B	 
	 +,-	   
	 +,-  
(G: (G(GV 
	 +,-	   
	 +,-  
'8Z '8'8T/ H=M4N ( 
	 +,-	   
	 +,-   )00A(BT

T
%T
T
n 
	 +,-'	   
	 +,-	   %w}};"3"3"3J 
	 +,-  
 
	 +,-	   )00A(B^	
^	%^	^	B 
	 +,-  
 
	 +,-	   )00A(BO	
O	%O	O	d 
	 +,-,-	   
	 +,-	   )00A(B**%**rK   