
    h             X       f   d Z ddlZddlZddlZddlZddlZddlZddlmZmZm	Z	 ddl
mZmZmZmZmZ ddlZddlmZmZmZmZmZmZmZ ddlZddlmZ ddlmZ ddlmZmZ dd	l m!Z! dd
l" ddl#m$Z$m%Z%m&Z&m'Z'm(Z( ddl)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0 ddl1m2Z2m3Z3 ddl4m5Z5 ddl6m7Z7m8Z8 ddl9m:Z: ddl;m<Z< ddl=m>Z> ddl?m@Z@mAZAmBZBmCZCmDZD ddlEmFZF ddlGmHZH ddlImJZJ ddlKmLZLmMZMmNZN deOePeQf   fdZRdeSdeeT   deeU   fd ZVd!eWdeeT   d"eeT   deXfd#ZYd$eeT   deSd!eWd%eNd&eZf
d'Z[dePd(eeeT      fd)Z\deSd!eWdePd&eZfd*Z]d!eWd+eeM   fd,Z^d!eWdePfd-Z_deeS   d!eWdePd&eZdeXf
d.Z`d!eWdeOePeaf   d/eeF   d0eXded1   f
d2Zb e       ZcdePd3eddedfd4ZedePd!eWd5eeT   deeS   deff
d6Zgecj                  d7d8g ee,      gef9      e< ee,       edd:;      fdePd!eWd5eeT   fd<              Ziecj                  d=d8g ee,      g>      e< ee,       edd:;      fdePd!eWd5eeT   fd?              Zjdekd@eddAeddedfdBZld3eddCee@   fdDZmdeOeaenf   dEeQfdFZod3eddEeQdedfdGZpdeadEeQdeXfdHZqecj                  dId8g ee,      g>      e< ee,       edd:;      fdJedead!eWd5eeT   fdK              ZrdLeQdMesdNeWd/eFfdOZtecj                  dPd8g ee,      g>      e< ee,       edd:;      fdeud!eWd5eeT   fdQ              Zvecj                  dRd8g ee,      gdST      d ee,      fdeeu   d!eWfdU       Zwecj                  dVd8g ee,      g>       ej*                  ddWX       ee,      fdLeeT   d!eWfdY       ZydZeeeT      d/eeF   d0eXded1   fd[Zzdg i i d\dddddddddddddddi ddd]ddg i i dddddddddddddf*d^ed_   d`eeT   dZe{daeddbeddce|ddee|   deeeT   dfee|   dgee|   dhee|   dieeX   djeeT   dkeeT   dLeeT   deeT   dleeT   d"eeT   dmeeT   dneeT   doee}   dpeed   dqee}   dree}   dsedt   dueed   dveeT   dwee{   dxeed   dyeed   dzeed   d{eed   d|ee{   d}ee{   d~eeT   deed      deeX   deeT   deeT   dee{   deeT   deeT   dee~   fVdZd!eWdeQdCe@defdZdeQded!eWdCe@deXf
dZdeded!eWdeee   eeQ   f   fdZdeeT   dedCe@d!eWdeee   eeQ   f   f
dZdCe@d!eWdeTdeTddf
dZdeen   deTfdZecj                  dd8g ee,      g>      ecj                  dd8g ee,      g>      e<dd ee,       edd:;      fdLeeT   deen   d!eWd5eeT   deef   f
d                     Zd!eWdeeT   d"eeT   d~eeT   dveeT   deeT   dCe@dee   fdZdee   d!eWdCe@deeT   fdZecj                  dd8g ee,      g>      e< ee,       eddd       edddd       edd;       edd;       edd;       edd;       edd;       edSd;       edSd;       eddX       eddX      fdJed!eWde}de}deeT   d"eeT   d~eeT   deeT   dveeT   deXdeXdeeT   deTdefd              ZdeeT   deTdeeeTeTf      fdZ	 	 	 	 	 ddCe@de}de}deeT   d"eeT   d~eeT   dveeT   deeT   deeT   deXdeeeT      deeT   deTdefdZdeeTef   fdZecj                  dd8g ee,      g>      e< ee,       edd:;      fdeded!eWd5eeT   deeQ   f
d              Zecj                  dd8g ee,      g>      e< ee,       edd:;      fdeded!eWd5eeT   fd              Zecj                  dd8g ee,      ge9      e< ee,      fdJed!eWfd              Zd!eWdLeeT   deQdeXfdZd!eWdJedeeeTef      defdÄZ	 ddveeT   dCedeeT   ddfdńZdyee   ddfdƄZy)z`
KEY MANAGEMENT

All /key management endpoints

/key/generate
/key/info
/key/update
/key/delete
    N)datetime	timedeltatimezone)ListLiteralOptionalTuplecast)	APIRouterDependsHeaderHTTPExceptionQueryRequeststatus)verbose_proxy_logger)	DualCache)LENGTH_OF_LITELLM_GENERATED_KEYUI_SESSION_TOKEN_TEAM_ID)duration_in_seconds)*)_cache_key_object_delete_cache_key_objectcan_team_access_modelget_key_objectget_team_object)abbreviate_api_key)user_api_key_authget_budget_reset_time)KeyManagementEventHooks)_is_user_team_admin_set_object_metadata_field)_add_model_to_db) attach_object_permission_to_dict&handle_update_object_permission_common)TeamMemberPermissionChecks)management_endpoint_wrapper)_is_master_key)PrismaClient_hash_token_if_neededhandle_exception_on_proxyjsonify_objectis_valid_api_key)Router)
get_secret)
Deployment)BudgetConfigPersonalUIKeyGenerationConfigTeamUIKeyGenerationConfigdatac                     | j                   d uS Nteam_idr5   s    w/var/www/Befach/backend/env/lib/python3.12/site-packages/litellm/proxy/management_endpoints/key_management_endpoints.py_is_team_keyr<   J   s    <<t##    
team_tableuser_idreturnc                 l    |y | j                   D ]"  }|j                  |j                  |k(  s |c S  y r7   )members_with_rolesr?   )r>   r?   members      r;   _get_user_in_teamrD   N   s;     //>>%&..G*CM 0 r=   user_api_key_dictr9   c                    | j                   (| j                   t        j                  j                  k(  ry|0|| j                  k(  s!J dj                  || j                               | | j                  | j                  t        k(  ryy)zz
    Assert user only creates keys for themselves

    Relevant issue: https://github.com/BerriAI/litellm/issues/7336
    TzDUser can only create keys for themselves. Got user_id={}, Your ID={})	user_roleLitellmUserRolesPROXY_ADMINvaluer?   formatr9   
UI_TEAM_IDrE   r?   r9   s      r;   _is_allowed_to_make_key_requestrN   Z   s     	##/''+;+G+G+M+MM(000	
QXX&..
	
0
 %%1!))Z7r=   assigned_user_idteam_key_generationroutec                    | ,t        ||       }|t        dd|  d|j                         t        ||j                        }|j                  d uxr' |j                  t
        j                  j                  k(  }|ry|'t        dd|j                   d|j                         d|v r1|j                  |d   vr t        dd|j                   d	|d          t        j                  |||
       y)N)r>   r?     User=z not assigned to team=status_codedetailTallowed_team_member_roleszTeam member role z" not in allowed_team_member_roles=)team_member_objectr>   rQ   )rD   r   r9   r?   rG   rH   rI   rJ   roler'   .does_team_member_have_permissions_for_endpoint)rO   r>   rE   rP   rQ   key_assigned_user_in_teamrY   is_admins           r;   %_team_key_operation_team_member_checkr^   z   s]    #$5!+;%
! %,/00FzGYGYFZ[ 
 +'8'@'@
 	##4/ 	N''+;+G+G+M+MM 
 		#,4455KJL^L^K_`
 	

 	$'::##"#>?@ &'9'>'>&??abu  wR  cS  bT  U
 	

 MM-
 r=   required_paramsc                 f    |y| j                  d      }|D ]  }||vst        dd| d       y)NTexclude_unsetrS   zRequired param z not in datarU   )
model_dumpr   )r5   r_   	data_dictparams       r;   $_key_generation_required_param_checkrf      sP     d3I 	!(|<  ! r=   c                 F   |j                   t        j                  j                  k(  ryt        j
                  &dt        j
                  v rt        j
                  d   }nt        ddg      }t        |j                  | |||       t        ||j                  d             y)NTrP   adminuserrX   rO   r>   rE   rP   rQ   r_   )rG   rH   rI   rJ   litellmkey_generation_settingsr4   r^   r?   rf   get)r>   rE   r5   rQ   _team_key_generations        r;   _team_key_generation_checkrp      s     ""&6&B&B&H&HH''3!W%D%DD&>>?TU8'.&7 
 *+0 )  !23
 r=   personal_key_generationc                     |d|vry| j                   |d   vr1t        ddt        j                  d   d    d| j                          y)Nallowed_user_rolesTrS   zBPersonal key creation has been restricted by admin. Allowed roles=rq   z. Your role=rU   )rG   r   rl   rm   )rE   rq   s     r;   _personal_key_membership_checkrt      s    
 	 ''>>""*ABV*WWWX_XwXw  yR  YS  Th  Yi  Xj  jv  wH  wR  wR  vS  T
 	

 r=   c                     t         j                  t         j                  j                  d      yt         j                  d   }t        | |       t	        ||j                  d             y)Nrq   T)rq   r_   )rl   rm   rn   rt   rf   )rE   r5   _personal_key_generations      r;   _personal_key_generation_checkrw      sl     	''/**../HIQ&>>?XY" 8
 ) $$%67
 r=   c                     t        |      }|r>| *t        j                  t        dd|j                         | yt        | |||      S t        ||      S )z^
    Check if admin has restricted key creation to certain roles for teams or individuals
    r:   rS   z1Unable to find team object in database. Team ID: rU   Tr>   rE   r5   rQ   )rE   r5   )r<   rl   rm   r   r9   rp   rw   )r>   rE   r5   rQ   is_team_keys        r;   key_generation_checkr{   
  sx     D)K'"A"A"MJ4<<.Y  )!/	
 	
 ./d
 	
r=   
llm_routerpremium_userTc                    	 t        | |j                  |j                         t        |j                  ||       y# t        $ r}t	        dt        |            d}~wt        $ r}t	        dt        |            d}~ww xY w)zF
    Check if user is allowed to make a key request, for this key
    rM     rU   Ni  )modelsr|   r}   T)	rN   r?   r9   AssertionErrorr   str	Exception_check_model_access_groupr   )rE   r5   r|   r}   es        r;   common_key_access_checksr   *  s    
'/LLLL	
  {{!
 !  
q6
 	
  
q6
 	

s!   "= 	BAB(A>>B	data_jsonc                     | j                   }|j                  dd       |t        j                  k(  rdg|d<   |S |t        j                  k(  rdg|d<   |S |t        j
                  k(  rdg|d<   |S )z
    Handle the key type.
    key_typeNllm_api_routesallowed_routesmanagement_routesinfo_routes)r   popLiteLLMKeyTypeLLM_API
MANAGEMENT	READ_ONLY)r5   r   r   s      r;   handle_key_typer   O  s     }}HMM*d#>)))'7&8	"#
 	 
^..	.':&;	"#  
^--	-'4o	"#r=   litellm_changed_byc           
        K   ddl m}m}m}m} t        || ||       t        j                  | D ]  }|\  }	}
|
0|	dv r,t        | |	t        j                  j                  |	d              :|	dk(  r1|
g k(  r,t        | |	t        j                  j                  |	g              p|	dk(  sv|
i k(  s|t        | |	t        j                  j                  |	i               t        j                  | D ]  }|\  }	}
t        t        j                  |	d       }|&|
t        | |	|       6|	dv r|
|kD  s@t        dd	|	 d
|
 d| i      |	dv s\t        |      }t        |
      }||kD  szt        dd	|	 d
|
 d| i       	 ddlm}  || |      } | j*                  }|| j,                  t/        | j,                  | j0                  xs i       }|j3                  |j5                  d            }|j6                  j8                  j;                  i ||j<                  xs ||j<                  xs |d       d {   }t        |dd       }t>        D ](  }t        | |d       tA        | |t        | |             * | jC                  dd      }tE        | |      }d|v r|jG                  dd       |d<   |||d<   d|v r|jG                  dd       |d<   |j<                  |j<                  |d<   |j<                  |d<   d|v rodd l m} |dur+|d   &tI        d!tJ        jL                  jN                         |j                  d      }|sd|d   i|d<   n|d   |d   d<   |jG                  d       tQ        ||"       d {   }tS        |j                  d#d       |$       d {    tU        d*d%d&i|d'd&i d {   }| j,                  |d(<   tW        d*i |}|jX                  |_-        t]        j^                  ta        jb                  | |||)             |S # t         $ r8}t#        j$                  dj'                  t)        |                   Y d }~d }~ww xY w7 (7 7 7 w)+Nr   )litellm_proxy_admin_namer|   r}   prisma_clientrE   r5   r|   r}   )
max_budgetr?   r9   max_parallel_requests	tpm_limit	rpm_limitbudget_durationr   metadata)r   r   r   r   rS   errorz. is over max limit set in config - user_value=z; max_value=rU   )r   durationr   )&apply_enterprise_key_management_paramsz_litellm.proxy.proxy_server.generate_key_fn(): Enterprise key management params not applied - {})soft_budgetmodel_max_budgetT)exclude_none)
created_by
updated_byr:   	budget_id)object_data
field_namerJ   rb   r   r   key_max_budgetr   key_budget_durationr   r   tags)r}   z)Only premium users can add tags to keys. )r   r   	key_alias)r   r   request_typekey
table_namer   )r5   responserE   r    )2litellm.proxy.proxy_serverr   r|   r}   r   r   rl   default_key_generate_paramssetattrrn   upperbound_key_generate_paramsgetattrr   r   Flitellm_enterprise.proxy.management_endpoints.key_management_endpointsr   r   r   inforK   r   r   r   LiteLLM_BudgetTabler   r-   jsondblitellm_budgettablecreater?   1LiteLLM_ManagementEndpoint_MetadataFields_Premiumr#   rc   r   r   
ValueErrorCommonProxyErrorsnot_premium_userrJ   _set_object_permission_enforce_unique_key_aliasgenerate_key_helper_fnGenerateKeyResponsetoken_idtokenasynciocreate_taskr!   async_key_generated_hook)r5   rE   r   r>   r   r|   r}   r   elemr   rJ   upperbound_valueupperbound_durationuser_durationr   r   
_budget_id
budget_row
new_budget_budgetfieldr   	_metadatar   s                           r;   _common_key_generation_helperr   ^  s8      +!	 **6DJC} ) " c7#F#F#J#J3PT#UVUb[c7#F#F#J#J3PR#ST
"u{c7#F#F#J#J3PR#ST $ --9DJC&66T   +=D#'78    !#33"/,/$+u4bchbiiu  wG  vH  .I("#   ??.A%5/+ )<U(K(+>>"/,/$+u4bchbiiu  wG  vH  .I("# ? N
	
 6dJG J T%5%5%A(((!228b

 #11*//t/2TU
%((<<CC/77S;S/77S;S D 
 
 Wk48
 C4%1&  dE* C dFIi0Iy &/mmL$&G	"#!+	+I%+4==9JD+Q	'(  ,"3";";	,"3";";	, ;t#	&(9(E;<M<^<^<d<d;ef  MM*-	%+Yv->$?Ij!,5f,=Ij!&)f,# I
 $--T2#  
 , '49 H
 	 ] #.X.H 	 N 88/1		
 OM  
!!mttA	
 	

"
h

s   B#Q*&Q*,A$Q*Q*+Q*Q*%Q*>P B,Q*9Q!:'Q*"DQ*Q$$Q*&Q&'Q*?Q( AQ*	Q&-QQ*QQ*$Q*&Q*(Q*z/key/generatezkey management)r   dependenciesresponse_modelzThe litellm-changed-by header enables tracking of actions performed by authorized users on behalf of other users, providing an audit trail for accountability)descriptionc                   K   	 ddl m}m}m} t	        j
                  d       |rt        j                  |      r ||        d{   }nt        d      |j                  dd      }|j                  dd	      }|st        t        j                  |
      d}	| j                  -	 t        | j                  |||j                  d       d{   }	t#        |	|| t$        j&                         t)        | |||	       d{   S 7 7 :# t         $ r$}
t	        j
                  d|
        d}	Y d}
~
`d}
~
ww xY w7 8# t         $ r=}
t	        j*                  dj-                  t/        |
                   t1        |
      d}
~
ww xY ww)a  
    Generate an API key based on the provided data.

    Docs: https://docs.litellm.ai/docs/proxy/virtual_keys

    Parameters:
    - duration: Optional[str] - Specify the length of time the token is valid for. You can set duration as seconds ("30s"), minutes ("30m"), hours ("30h"), days ("30d").
    - key_alias: Optional[str] - User defined key alias
    - key: Optional[str] - User defined key value. If not set, a 16-digit unique sk-key is created for you.
    - team_id: Optional[str] - The team id of the key
    - user_id: Optional[str] - The user id of the key
    - budget_id: Optional[str] - The budget id associated with the key. Created by calling `/budget/new`.
    - models: Optional[list] - Model_name's a user is allowed to call. (if empty, key is allowed to call all models)
    - aliases: Optional[dict] - Any alias mappings, on top of anything in the config.yaml model list. - https://docs.litellm.ai/docs/proxy/virtual_keys#managing-auth---upgradedowngrade-models
    - config: Optional[dict] - any key-specific configs, overrides config in config.yaml
    - spend: Optional[int] - Amount spent by key. Default is 0. Will be updated by proxy whenever key is used. https://docs.litellm.ai/docs/proxy/virtual_keys#managing-auth---tracking-spend
    - send_invite_email: Optional[bool] - Whether to send an invite email to the user_id, with the generate key
    - max_budget: Optional[float] - Specify max budget for a given key.
    - 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").
    - max_parallel_requests: Optional[int] - Rate limit a user based on the number of parallel requests. Raises 429 error, if user's parallel requests > x.
    - metadata: Optional[dict] - Metadata for key, store information for key. Example metadata = {"team": "core-infra", "app": "app2", "email": "ishaan@berri.ai" }
    - guardrails: Optional[List[str]] - List of active guardrails for the key
    - permissions: Optional[dict] - key-specific permissions. Currently just used for turning off pii masking (if connected). Example - {"pii": false}
    - model_max_budget: Optional[Dict[str, BudgetConfig]] - Model-specific budgets {"gpt-4": {"budget_limit": 0.0005, "time_period": "30d"}}}. IF null or {} then no model specific budget.
    - model_rpm_limit: Optional[dict] - key-specific model rpm limit. Example - {"text-davinci-002": 1000, "gpt-3.5-turbo": 1000}. IF null or {} then no model specific rpm limit.
    - model_tpm_limit: Optional[dict] - key-specific model tpm limit. Example - {"text-davinci-002": 1000, "gpt-3.5-turbo": 1000}. IF null or {} then no model specific tpm limit.
    - allowed_cache_controls: Optional[list] - List of allowed cache control values. Example - ["no-cache", "no-store"]. See all values - https://docs.litellm.ai/docs/proxy/caching#turn-on--off-caching-per-request
    - blocked: Optional[bool] - Whether the key is blocked.
    - rpm_limit: Optional[int] - Specify rpm limit for a given key (Requests per minute)
    - tpm_limit: Optional[int] - Specify tpm limit for a given key (Tokens per minute)
    - soft_budget: Optional[float] - Specify soft budget for a given key. Will trigger a slack alert when this soft budget is reached.
    - tags: Optional[List[str]] - Tags for [tracking spend](https://litellm.vercel.app/docs/proxy/enterprise#tracking-spend-for-custom-tags) and/or doing [tag-based routing](https://litellm.vercel.app/docs/proxy/tag_routing).
    - enforced_params: Optional[List[str]] - List of enforced params for the key (Enterprise only). [Docs](https://docs.litellm.ai/docs/proxy/enterprise#enforce-required-params-for-llm-requests)
    - allowed_routes: Optional[list] - List of allowed routes for the key. Store the actual route or store a wildcard pattern for a set of routes. Example - ["/chat/completions", "/embeddings", "/keys/*"]
    - object_permission: Optional[LiteLLM_ObjectPermissionBase] - key-specific object permission. Example - {"vector_stores": ["vector_store_1", "vector_store_2"]}. IF null or {} then no object permission.
    - key_type: Optional[str] - Type of key that determines default allowed routes. Options: "llm_api" (can call LLM API routes), "management" (can call management routes), "read_only" (can only call info/read routes), "default" (uses default allowed routes). Defaults to "default".
    Examples:

    1. Allow users to turn on/off pii masking

    ```bash
    curl --location 'http://0.0.0.0:4000/key/generate'         --header 'Authorization: Bearer sk-1234'         --header 'Content-Type: application/json'         --data '{
            "permissions": {"allow_pii_controls": true}
    }'
    ```

    Returns:
    - key: (str) The generated api key
    - expires: (datetime) Datetime object for when key expires.
    - user_id: (str) Unique user id - used for tracking spend across multiple keys for same user id.
    r   r   user_api_key_cacheuser_custom_key_generateentered /key/generateN,user_custom_key_generate must be a coroutinedecisionTmessage(Authentication Failed - Custom Auth RulerU   r9   r   r   parent_otel_spancheck_db_only.Error getting team object in `/key/generate`: ry   r5   rE   r   r>   zDlitellm.proxy.proxy_server.generate_key_fn(): Exception occured - {})r   r   r   r   r   debugr   iscoroutinefunctionr   rn   r   r   HTTP_403_FORBIDDENr9   r   r   r   r{   KeyManagementRoutesKEY_GENERATEr   	exceptionrK   r   r,   r5   rE   r   r   r   r   resultr   r   r>   r   s              r;   generate_key_fnr     s    J7+	
 	
 	""#:;#/**+CD7== !OPPzz*d3Hjj,VWG# & 9 9'  <@
<<#"#2 LL"/'9%6%G%G"&$ 
 	!/%22		
 3/1!	
 
 	
A >  "$**DQCH "
	"
  +&&RYYA	

 (**+s   FAD< DAD< &'D
 DD
 /D< D:D< FD< D
 
	D7D2-D< 2D77D< <	F8E==FFz/key/service-account/generate)r   r   c                   K   ddl m}m}m} t	        j
                  d       |rt        j                  |      r ||        d{   }nt        d      |j                  dd      }|j                  dd	      }|st        t        j                  |
      d}	| j                  -	 t        | j                  |||j                  d       d{   }	t#        |	|| t$        j&                         d| _        t+        | |||	       d{   S 7 7 A# t         $ r$}
t	        j
                  d|
        d}	Y d}
~
gd}
~
ww xY w7 8w)as  
    Generate a Service Account API key based on the provided data. This key does not belong to any user. It belongs to the team.

    Why use a service account key?
    - Prevent key from being deleted when user is deleted.
    - Apply team limits, not team member limits to key.

    Docs: https://docs.litellm.ai/docs/proxy/virtual_keys

    Parameters:
    - duration: Optional[str] - Specify the length of time the token is valid for. You can set duration as seconds ("30s"), minutes ("30m"), hours ("30h"), days ("30d").
    - key_alias: Optional[str] - User defined key alias
    - key: Optional[str] - User defined key value. If not set, a 16-digit unique sk-key is created for you.
    - team_id: Optional[str] - The team id of the key
    - user_id: Optional[str] - [NON-FUNCTIONAL] THIS WILL BE IGNORED. The user id of the key
    - budget_id: Optional[str] - The budget id associated with the key. Created by calling `/budget/new`.
    - models: Optional[list] - Model_name's a user is allowed to call. (if empty, key is allowed to call all models)
    - aliases: Optional[dict] - Any alias mappings, on top of anything in the config.yaml model list. - https://docs.litellm.ai/docs/proxy/virtual_keys#managing-auth---upgradedowngrade-models
    - config: Optional[dict] - any key-specific configs, overrides config in config.yaml
    - spend: Optional[int] - Amount spent by key. Default is 0. Will be updated by proxy whenever key is used. https://docs.litellm.ai/docs/proxy/virtual_keys#managing-auth---tracking-spend
    - send_invite_email: Optional[bool] - Whether to send an invite email to the user_id, with the generate key
    - max_budget: Optional[float] - Specify max budget for a given key.
    - 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").
    - max_parallel_requests: Optional[int] - Rate limit a user based on the number of parallel requests. Raises 429 error, if user's parallel requests > x.
    - metadata: Optional[dict] - Metadata for key, store information for key. Example metadata = {"team": "core-infra", "app": "app2", "email": "ishaan@berri.ai" }
    - guardrails: Optional[List[str]] - List of active guardrails for the key
    - permissions: Optional[dict] - key-specific permissions. Currently just used for turning off pii masking (if connected). Example - {"pii": false}
    - model_max_budget: Optional[Dict[str, BudgetConfig]] - Model-specific budgets {"gpt-4": {"budget_limit": 0.0005, "time_period": "30d"}}}. IF null or {} then no model specific budget.
    - model_rpm_limit: Optional[dict] - key-specific model rpm limit. Example - {"text-davinci-002": 1000, "gpt-3.5-turbo": 1000}. IF null or {} then no model specific rpm limit.
    - model_tpm_limit: Optional[dict] - key-specific model tpm limit. Example - {"text-davinci-002": 1000, "gpt-3.5-turbo": 1000}. IF null or {} then no model specific tpm limit.
    - allowed_cache_controls: Optional[list] - List of allowed cache control values. Example - ["no-cache", "no-store"]. See all values - https://docs.litellm.ai/docs/proxy/caching#turn-on--off-caching-per-request
    - blocked: Optional[bool] - Whether the key is blocked.
    - rpm_limit: Optional[int] - Specify rpm limit for a given key (Requests per minute)
    - tpm_limit: Optional[int] - Specify tpm limit for a given key (Tokens per minute)
    - soft_budget: Optional[float] - Specify soft budget for a given key. Will trigger a slack alert when this soft budget is reached.
    - tags: Optional[List[str]] - Tags for [tracking spend](https://litellm.vercel.app/docs/proxy/enterprise#tracking-spend-for-custom-tags) and/or doing [tag-based routing](https://litellm.vercel.app/docs/proxy/tag_routing).
    - enforced_params: Optional[List[str]] - List of enforced params for the key (Enterprise only). [Docs](https://docs.litellm.ai/docs/proxy/enterprise#enforce-required-params-for-llm-requests)
    - allowed_routes: Optional[list] - List of allowed routes for the key. Store the actual route or store a wildcard pattern for a set of routes. Example - ["/chat/completions", "/embeddings", "/keys/*"]
    - object_permission: Optional[LiteLLM_ObjectPermissionBase] - key-specific object permission. Example - {"vector_stores": ["vector_store_1", "vector_store_2"]}. IF null or {} then no object permission.
    Examples:

    1. Allow users to turn on/off pii masking

    ```bash
    curl --location 'http://0.0.0.0:4000/key/generate'         --header 'Authorization: Bearer sk-1234'         --header 'Content-Type: application/json'         --data '{
            "permissions": {"allow_pii_controls": true}
    }'
    ```

    Returns:
    - key: (str) The generated api key
    - expires: (datetime) Datetime object for when key expires.
    - user_id: (str) Unique user id - used for tracking spend across multiple keys for same user id.

    r   r   r   Nr   r   Tr   r   rU   r   r   ry   r   )r   r   r   r   r   r   r   r   r   rn   r   r   r   r9   r   r   r   r{   r   KEY_GENERATE_SERVICE_ACCOUNTr?   r   r   s              r;   generate_service_account_key_fnr     sH    P  67+&&'?@3D99FKLL::j$/**Y(RSF,E,EgVV7;J||	.+#5!2!C!C"  J +!>>	 DL.+-	  A :  	 &&@D J		s[   AEDAE%'D DD 6EE ED 	D=D83E8D==Enon_default_valuesexisting_metadatac                    d|vr|j                         |d<   t        t        |d         }| j                  dd      }	 |j	                         D ]7  \  }}|t
        v st        |t              r|j                         ||<   3|||<   9 	 ||d<   |S # t        $ r7}t        j                  dj                  t        |                   Y d}~Bd}~ww xY w)zu
    Check LiteLLM_ManagementEndpoint_MetadataFields (proxy/_types.py) for fields that are allowed to be updated
    r   Tr   zLlitellm.proxy.proxy_server.prepare_metadata_fields(): Exception occured - {}N)copyr
   dictrc   items)LiteLLM_ManagementEndpoint_MetadataFields
isinstancer   	isoformatr   r   r   rK   r   )r5   r   r   casted_metadatar   kvr   s           r;   prepare_metadata_fieldsr    s     ++):)?)?)A:&4!3J!?@OdFI
OO%DAq==a*)*OA&)*OA& & &5z"  
&&ZaaA	
 	

s   B +B 	C-CCr   c                    K   || S d| v rQ|j                   j                  j                  | d          d{   }|j                  | d<   | j	                  d       | S 7 &w)z
    Creates the LiteLLM_ObjectPermissionTable record for the key.
    - Handles permissions for vector stores and mcp servers.
    Nobject_permissionr:   object_permission_id)r   litellm_objectpermissiontabler   r  r   )r   r   created_object_permissions      r;   r   r   6  s      i'""@@GG23 H   	" &:: 	() 	)*s   5A A'A existing_key_rowc                   K   | j                  d      }|j                  dd        |j                  dd        i }|j                         D ]  \  }}|t        v r|||<    d|v rr|j                  d      }|r_t	        |t
              rOt        |      dkD  rAt        |      }t        j                  t        j                        t        |      z   }||d	<   d
|v rJ|j                  d
      }	|	r7t	        |	t
              r't        |	      dkD  rddlm}
  |
|	      }||d<   |	|d
<   d|v rt        ||       d {   }|j                   xs i }d|v rt#        |d          t%        | ||      }|S 7 6w)NTra   r   new_keyr   r   r   secondsexpiresr   r   r   budget_reset_atr  )r   r  r   )r5   r   r   )rc   r   r   r   r   r   lenr   r   nowr   utcr   )litellm.proxy.common_utils.timezone_utilsr     _handle_update_object_permissionr   validate_model_max_budgetr  )r5   r  r   r   r   r  r   
duration_sr  r   r    key_reset_atr   s                r;   prepare_key_update_datar  O  s     ooDo9IMM%MM)T"!199 !1 "
 ''%))*5Hc2H8I,h?Jll8<<09Z3PPG,3y)..,001BCOS1O$q(W0QL4@014C0100#C(-$
 

 !))/RI //!"45G"HI0&8I 
s   D7E29E0:7E2c                    K   ddl m} t        | |j                  |       d{   }||| d<   t	        j
                  d|        | S 7 %w)z1
    Handle the update of object permission.
    r   r   )r   existing_object_permission_idr   Nr  zupdated object_permission_id: )r   r   r&   r  r   r   )r   r  r   r  s       r;   r  r    sg      9 "H&6&K&K#"  ',@	()"",-A,BC	
 s   "AA
&Ac                 h    | j                   y|j                   y| j                   |j                   k7  S )NFTr8   r5   r  s     r;   is_different_teamr    s6     ||'<<+3333r=   z/key/updaterequestc                   K   ddl m}m}m}m}m} 	 |j                  dd      }	|	j                  d      }
|t        d      t        ||||       |j                  |j                  dd	
       d{   }|t        ddd|j                   i      t        j                  |t         j"                  |||       d{    t%        ||      rOt'        t)        t*        |j                        ||d       d{   }|t        dddi      t-        ||||       t/        ||       d{   }t1        |j3                  dd      ||j4                         d{    i |d|
i}|j7                  |
|       d{   }t9        t;        |
      ||       d{    t=        j>                  tA        jB                  |||||             |tE        d      d|
i|d   S 7 y7 .7 7 7 7 r7 U# t        $ r}tG        jH                  djK                  t+        |                   tM        |t              rYtO        tQ        |ddt+        |       d       tR        jT                  tQ        |d!d"      tQ        |d#tV        jX                        $      tM        |tN              r|tO        d%t+        |      z   tR        jT                  tQ        |d!d"      tV        jX                  $      d}~ww xY ww)&a  
    Update an existing API key's parameters.

    Parameters:
    - key: str - The key to update
    - key_alias: Optional[str] - User-friendly key alias
    - user_id: Optional[str] - User ID associated with key
    - team_id: Optional[str] - Team ID associated with key
    - budget_id: Optional[str] - The budget id associated with the key. Created by calling `/budget/new`.
    - models: Optional[list] - Model_name's a user is allowed to call
    - tags: Optional[List[str]] - Tags for organizing keys (Enterprise only)
    - enforced_params: Optional[List[str]] - List of enforced params for the key (Enterprise only). [Docs](https://docs.litellm.ai/docs/proxy/enterprise#enforce-required-params-for-llm-requests)
    - spend: Optional[float] - Amount spent by key
    - max_budget: Optional[float] - Max budget for key
    - model_max_budget: Optional[Dict[str, BudgetConfig]] - Model-specific budgets {"gpt-4": {"budget_limit": 0.0005, "time_period": "30d"}}
    - budget_duration: Optional[str] - Budget reset period ("30d", "1h", etc.)
    - soft_budget: Optional[float] - [TODO] Soft budget limit (warning vs. hard stop). Will trigger a slack alert when this soft budget is reached.
    - max_parallel_requests: Optional[int] - Rate limit for parallel requests
    - metadata: Optional[dict] - Metadata for key. Example {"team": "core-infra", "app": "app2"}
    - tpm_limit: Optional[int] - Tokens per minute limit
    - rpm_limit: Optional[int] - Requests per minute limit
    - model_rpm_limit: Optional[dict] - Model-specific RPM limits {"gpt-4": 100, "claude-v1": 200}
    - model_tpm_limit: Optional[dict] - Model-specific TPM limits {"gpt-4": 100000, "claude-v1": 200000}
    - allowed_cache_controls: Optional[list] - List of allowed cache control values
    - duration: Optional[str] - Key validity duration ("30d", "1h", etc.)
    - permissions: Optional[dict] - Key-specific permissions
    - send_invite_email: Optional[bool] - Send invite email to user_id
    - guardrails: Optional[List[str]] - List of active guardrails for the key
    - blocked: Optional[bool] - Whether the key is blocked
    - aliases: Optional[dict] - Model aliases for the key - [Docs](https://litellm.vercel.app/docs/proxy/virtual_keys#model-aliases)
    - config: Optional[dict] - [DEPRECATED PARAM] Key-specific config.
    - temp_budget_increase: Optional[float] - Temporary budget increase for the key (Enterprise only).
    - temp_budget_expiry: Optional[str] - Expiry time for the temporary budget increase (Enterprise only).
    - allowed_routes: Optional[list] - List of allowed routes for the key. Store the actual route or store a wildcard pattern for a set of routes. Example - ["/chat/completions", "/embeddings", "/keys/*"]
    - object_permission: Optional[LiteLLM_ObjectPermissionBase] - key-specific object permission. Example - {"vector_stores": ["vector_store_1", "vector_store_2"]}. IF null or {} then no object permission.
    Example:
    ```bash
    curl --location 'http://0.0.0.0:4000/key/update'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
        "key": "sk-1234",
        "key_alias": "my-key",
        "user_id": "user-1234",
        "team_id": "team-1234",
        "max_budget": 100,
        "metadata": {"any_key": "any-val"},
    }'
    ```
    r   )r|   r}   r   proxy_logging_objr   Tr   r   NNot connected to DB!r   find_uniquer   r   
query_typei  r   zTeam not found, passed team_id=rU   rE   rQ   r   r  r   r  r9   r   r   r   rS   zeLLM router not found. Please set it up by passing in a valid config.yaml or adding models via the UI.)r   teamchange_initiated_byr|   r   )r   r   existing_key_tokenr   )r   r5   hashed_tokenr   r!  r5   r  r   rE   r   z(Failed to update key got response = Noner5   zBlitellm.proxy.proxy_server.update_key_fn(): Exception occured - {}rW   zAuthentication Error()re   NonerV   r   typere   codeAuthentication Error, )-r   r|   r}   r   r!  r   rc   r   r   r   get_datar   r   r9   r'   /can_team_member_execute_key_management_endpointr   
KEY_UPDATEr  r   r
   r   validate_key_team_changer  r   rn   r   update_datar   
hash_tokenr   r   r!   async_key_updated_hookr   r   r   rK   r   ProxyExceptionr   ProxyErrorTypes
auth_errorr   HTTP_400_BAD_REQUEST)r  r5   rE   r   r|   r}   r   r!  r   r   r   r  team_objr   _datar   r   s                    r;   update_key_fnrA    s=    ~ o
//4/P	mmE"  233 /!%		
 "/!7!7((u "8 "
 
 ##B4<<.!QR  )XX/%00'-1
 	
 	
 $9IJ,S$,,/+#5"	 H !# #  "I  %$$5%	 $;(8$
 
 ((,,[$?'/55
 	
 	
 5%4w4&2252II '#C1/
 	
 	
 	#::!1!"3#5	
 GHHs/hv.//U
	
&
	
 J	
*  
&&PWWA	

 a' 8/DSVHA-NO$//a&1Qv/J/JK	  >*G,s1v5 ++!Wf-,,	
 	

s   K7A!G< 3G,4AG< G/;G< =G2>4G< 2G43/G< "G6#"G< G8G< $G:%AG< +K7,G< /G< 2G< 4G< 6G< 8G< :G< <	K4C*K//K44K7r   r(  r)  c           
         t        | j                        dkD  r| j                  D ]  }t        |||        | j                  Zd}|j                  D ]  }|j                  | j                  k(  sd} n |s(t        dd| j                   d|j                   d	
      | j                  |j                  rN| j                  |j                  kD  r5t        dd| j                   d| j                   d|j                   d
      |j                  rZ| j                  rN| j                  |j                  kD  r5t        dd| j                   d| j                   d|j                   d
      |j                  t        j                  j                  k(  ryt        ||      ryt        dd|j                   d|j                   d
      )a<  
    Validate that a key can be moved to a new team.

    - The team must have access to the key's models
    - The key's user_id must be a member of the team
    - The key's tpm/rpm limit must be less than the team's tpm/rpm limit
    - The person initiating the change must be either Proxy Admin or Team Admin
    r   )modelteam_objectr|   NFTr   rT   z is not a member of the team=z&. Check team members via `/team/info`.rU   zKey=z has a tpm_limit=z, which is greater than the team's tpm_limit=.z has a rpm_limit=z, which is greater than the team's rpm_limit=rE   r?  z- is not a Proxy Admin or Team Admin for team=)r  r   r   r?   rB   r   r9   r   r   r   rG   rH   rI   rJ   r"   )r   r(  r)  r|   rC  	is_memberrC   s          r;   r7  r7  `  s    3::ZZE! %   {{	--F~~, 	 . s{{m+HV|}  }} >>cmmdnn<cii[(9#--Htuy  vD  vD  uE  EF  G  >>cmm0Ncii[(9#--Htuy  vD  vD  uE  EF  G  $$(8(D(D(J(JJ	-
 	.6677deieqeqdrrst
 	
r=   z/key/deletec           	      &  K   	 ddl m}m} |t        d      t	        j
                  d|j                          d}g }| j                  rEt        | j                  ||       d{   \  }}t        | j                        }| j                  }n]| j                  rFt        | j                  |||       d{   \  }}t        | j                        }| j                  }nt        d      |+t        d	t        j                  d
t         j"                        t	        j
                  d|        	 |t        |      k(  sJ 	 t	        j
                  d|j&                  j(                          t+        j,                  t/        j0                  | ||||             d|iS 7 ;7 # t        $ r t%        ddd| d| i      w xY w# t        $ r=}	t	        j2                  dj5                  t7        |	                   t9        |	      d}	~	ww xY ww)a  
    Delete a key from the key management system.

    Parameters::
    - keys (List[str]): A list of keys or hashed keys to delete. Example {"keys": ["sk-QWrxEynunsNpV1zT48HIrw", "837e17519f44683334df5291321d97b8bf1098cd490e49e215f6fea935aa28be"]}
    - key_aliases (List[str]): A list of key aliases to delete. Can be passed instead of `keys`.Example {"key_aliases": ["alias1", "alias2"]}

    Returns:
    - deleted_keys (List[str]): A list of deleted keys. Example {"deleted_keys": ["sk-QWrxEynunsNpV1zT48HIrw", "837e17519f44683334df5291321d97b8bf1098cd490e49e215f6fea935aa28be"]}

    Example:
    ```bash
    curl --location 'http://0.0.0.0:4000/key/delete'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
        "keys": ["sk-QWrxEynunsNpV1zT48HIrw"]
    }'
    ```

    Raises:
        HTTPException: If an error occurs during key deletion.
    r   )r   r   Nr"  zuser_api_key_dict.user_role: tokensr   rE   )key_aliasesr   r   rE   zInvalid request typezFFailed to delete keys got None response from delete_verification_tokenkeysr0  z/key/delete - deleted_keys=rS   r   zNot all keys passed in were deleted. This probably means you don't have access to delete all the keys passed in. Keys passed in=z, Deleted keys =rU   z#/keys/delete - cache after delete: )r5   keys_being_deletedrE   r   r   deleted_keyszBlitellm.proxy.proxy_server.delete_key_fn(): Exception occured - {})r   r   r   r   r   r   rG   rL  delete_verification_tokensr  rK  delete_key_aliasesr   r;  r<  internal_server_errorr   HTTP_500_INTERNAL_SERVER_ERRORr   in_memory_cache
cache_dictr   r   r!   async_key_deleted_hookr   rK   r   r,   )
r5   rE   r   r   r   num_keys_to_be_deletedrN  number_deleted_keys_keys_being_deletedr   s
             r;   delete_key_fnrY    sR    FI+P 233 	""+,=,G,G+HI	
 "#99=Wyy#5"3> 84!4
 &)^"99L=O ,,+#5"3	> 84!4 &))9)9%:"++L344& `$::::	  	""%@AT@U#VW	)S->>>> 	""12D2T2T2_2_1`a	
 	#::#6"3#5,	
 --i88,  	   `  aw  `x  xH  I\  H]  ^ 	.  +&&PWWA	

 (**+sh   HA"G &F!'AG 8F$9A9G 3F& AG  H!G $G &GG 	H8H		HHz/v2/key/infoF)r   r   include_in_schemac                   K   ddl m} 	 |t        d      | t        t        j
                  ddi      |j                  | j                  dd	
       d{   }|t        t        j                  ddi      g }|D ]$  }	 |j                         }|j                  |       & | j                  |dS 7 ]# t        $ r |j                         }Y ?w xY w# t        $ r}t        |      d}~ww xY ww)a  
    Retrieve information about a list of keys.

    **New endpoint**. Currently admin only.
    Parameters:
        keys: Optional[list] = body parameter representing the key(s) in the request
        user_api_key_dict: UserAPIKeyAuth = Dependency representing the user's API key
    Returns:
        Dict containing the key and its associated information

    Example Curl:
    ```
    curl -X GET "http://0.0.0.0:4000/key/info"     -H "Authorization: Bearer sk-1234"     -d {"keys": ["sk-1", "sk-2", "sk-3"]}
    ```
    r   r  NDatabase not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keysr   z%Malformed request. No keys passed in.rU   r   find_allr$  No keys foundr   r   )r   r   r   r   r   HTTP_422_UNPROCESSABLE_ENTITYr4  rL  HTTP_404_NOT_FOUNDrc   r   appendr,   )r5   rE   r   key_infofiltered_key_infor   r   s          r;   info_key_fn_v2re    s    6 9+  T  <"@@!#JK 
 '//))* 0 
 
 "55!?3  ALLN $$Q'  yy*;<<!
  FFH  +'**+s_   C2AC B5*C B7!C 4C25C 7CC CC 	C/C**C//C2z	/key/infozKey in the request parameters)defaultr   c                   K   ddl m} 	 |t        d      | xs |j                  } | }| t	        |       }|j
                  j                  j                  d|iddi	       d{   }|+t        d
t        j                  dt        j                        t        || |       d{   dur4t        t        j                  dj!                  |j"                              	 |j%                         }|j)                  d       | |dS 7 7 c# t        $ r |j'                         }Y 5w xY w# t        $ r}t+        |      d}~ww xY ww)a  
    Retrieve information about a key.
    Parameters:
        key: Optional[str] = Query parameter representing the key in the request
        user_api_key_dict: UserAPIKeyAuth = Dependency representing the user's API key
    Returns:
        Dict containing the key and its associated information

    Example Curl:
    ```
    curl -X GET "http://0.0.0.0:4000/key/info?key=sk-02Wr4IAlN3NvPXvL5JVvDA" -H "Authorization: Bearer sk-1234"
    ```

    Example Curl - if no key is passed, it will use the Key Passed in Authorization Header
    ```
    curl -X GET "http://0.0.0.0:4000/key/info" -H "Authorization: Bearer sk-02Wr4IAlN3NvPXvL5JVvDA"
    ```
    r   r  Nr\  r   r   litellm_budget_tableTwhereincludezKey not found in databaser   r0  rE   r   rc  ;You are not allowed to access this key's info. Your role={}rU   r_  )r   r   r   api_keyr+   r   litellm_verificationtokenr#  r;  r<  not_found_errorr   ra  _can_user_query_key_infor   r   rK   rG   rc   r   r   r,   )r   rE   r   
hashed_keyrc  r   s         r;   info_key_fnrt  M  st    : 9.+  T 
 .&..$'
?.S9J&))CCOOJ'+T2 P 
 
  3$44..	  +"3! 
   "55T[[%// 	'**,H 	WH--C
   	'}}H	'
  +'**+sr   E	AD- %D
&AD- (D):D- $D 4D- 	E	
D- D- D*'D- )D**D- -	E6EEE	r   c                     | |y| D ][  }|j                  |      s|rt        t        j                  ddj	                  t
        j                  j                        i       y)z
    if is_model_access_group is True + is_wildcard_route is True, check if user is a premium user

    Return True if user is a premium user, False otherwise
    T)model_access_groupr   zbSetting a model access group on a wildcard model is only available for LiteLLM Enterprise users.{}rU   ))_is_model_access_group_for_wildcard_router   r   r   rK   r   r   rJ   )r   r|   r}   rC  s       r;   r   r     s     ~+??$ @ 
  # & 9 9  "F  "M  "M->>DD"   r=   g        insert_datar   )ri   r   r   aliasesconfigspendr   r   r   r   r   blockedr   r   
user_alias
user_emailrG   r   r   r   r   r%  )rx  r8  update_key_valuesr   allowed_cache_controlspermissionsr   model_rpm_limitmodel_tpm_limit
guardrailsteamsorganization_idr   )r   ri   send_invite_emailr   r   r   sso_user_idr  r  c+           
      J
  K   ddl m}+m}, |,t        d      |!||}ndt	        j
                  t               }|d }-n<t        |      }.t        j                  t        j                        t        |.      z   }-|d }/n<t        |      }.t        j                  t        j                        t        |.      z   }/|d }0nt        |      }0t        j                  |      }1t        j                  |      }2t        j                  |      }3||xs i }||d<   ||xs i }||d	<   | |xs i }| |d
<   t        j                  |      }4t!        |       t        j                  |      }5|}|}|}|}	 i d|
d|d|d|d|d|"d|d|d|d|4d|d|d|d|d|0d|d|(d|)i}6|!|!|6d<   i d|d|d |-d|d!|1d"|2d|d|d|d|d|d|4d|d|d|d|/d||3|5|||%|&|'xs g |)d#}7t#        d$d%      d&u rnt%        |'      |7d(<   t'        j(                  |7      }8t+        |8d!   t,              rt        j.                  |8d!         |8d!<   t+        |8d"   t,              rt        j.                  |8d"         |8d"<   t+        |8d   t,              rt        j.                  |8d         |8d<   t+        |8d)   t,              r1d*|8d)   v r|+d&urt1        d+      t        j.                  |8d)         |8d)<   t+        |8d,   t,              rt        j.                  |8d,         |8d,<   |8j3                  d d       )t+        |8d    t              r|8d    j5                         |8d <   |,|#|#d-k(  r|d.k(  ra|,j7                  |6d-/       d {   }9|9t        d0      t9        |9j:                        dkD  rBt9        |7d         dk(  r1|9j:                  |7d<   n!|d1k(  r|,j=                  |6d-|2       d {   }9|#|#d-k(  r|6S t?        j@                  d3|7       |,j7                  |7d4/       d {   }:tC        |:dd       |7d5<   tC        |:d6d       |7d6<   tC        |:d7d       |7d7<   tC        |:d8d       |7d8<   ||7d=<   | d-k(  r|7jS                  |6       |7S 7 7 7 f# t        $ r};t?        jD                  d9jG                  t-        |;                   t?        j@                  tI        jJ                                t+        |;tL              r|;tM        tN        jP                  d:d;i<      d };~;ww xY ww)>Nr   )r}   r   z]Connect Proxy to database to generate keys - https://docs.litellm.ai/docs/proxy/virtual_keys sk-r   r  r  r  r  r  r   r~  r?   r}  r9   r  rG   r{  r   r   r   r   r   r   r  r  r  r  r  r   r   r  ry  rz  )r  r   r   r|  r   r   r   r  DISABLE_KEY_NAMEFT)ro  key_namer  get_spend_routeszJget_spend_routes permission is only available for LiteLLM Enterprise usersr   ri   rx  )r5   r   zFailed to create userr8  )r5   r   r  zprisma_client: Creating Key= %sr   r   ri  
created_at
updated_atzKlitellm.proxy.proxy_server.generate_key_helper_fn(): Exception occured - {}r   zInternal Server Error.rU   r   )*r   r}   r   r   secretstoken_urlsafer   r   r   r  r   r  r   r    r   dumpsr  r0   r   r   deepcopyr   r   loadsr   rn   r   rx  r  r   r8  r   r   r   r   rK   	traceback
format_excr   r   rR  update)<r   r   r   ry  rz  r{  r   r   r   r   r   r|  r   r   r   r?   r}  r9   r~  rG   r   r   r   r   r%  r  r   r  r  r   r  r  r  r  r  r   r  r   r   r   r  r  r  r}   r   r  r  r  reset_ataliases_jsonconfig_jsonpermissions_jsonmetadata_jsonmodel_max_budget_json	user_datakey_datasaved_tokenuser_rowcreate_key_responser   s<                                                               r;   r   r     s    j Gk
 	
 }?E'//0OPQRE((;
,,x||,y/LL"(2EF
||HLL1Ij4QQ(I::g&L**V$Kzz+. ">r&5"#">r&5"#>r!+JJx(M./ JJ'78III3H

*
*
 w
 *	

 w
 
 
 U
 f
 
 $%:
 
 
 
 x
  %&<!
" ;#
$ #$8%
	( !&Ig
U

 w
 f	

 |
 k
 U
 .
 w
 w
 $%:
 
 
 
 2
  |!
" %&<#
$ , 5"$$,2$83
: )51T9#5e#DHZ mmH-k),c2%)ZZI0F%GK	"k(+S1$(JJ{8/D$EK!k*-s3&*jjZ1H&IK
#k-0#6"k-&@@ , `  *.K4N)OK&k"45s;.2jj.//K*+ ??9d+7J	"H=
 &1%;%E%E%GK	"$"jF&: .%2%>%>&6 &? &  H  ''(?@@8??+a/C8J4Kq4P-5__*=0%2%>%>&#)*; &? &  H
 %**> !  !&&'H(S(5(A(A% )B ) # $++>#NHZ /6#%;T0H+, &--@,PT%UH\"%,-@,PT%UH\"  &H[v	"Ok  #  
""Y``A	

 	""9#7#7#9:a'G==56
 	

sp   E/T#2HR RA&R ,R-R 9T#:,R &R'AR +T#R R R 	T BTT  T#rc  r   c                   K   t        |      }|r|j                  t        |j                  ||d       d {   }t        j                  &dt        j                  v rt        j                  d   }nt        ddg      }|(t        | j                  || |t        j                        S t        t        j                  d	d
|j                   i      y7 w)Nr:   Tr'  rP   rh   ri   rj   rk   r   z:Team not found in db, and user not proxy admin. Team id = rU   F)r<   r9   r   rl   rm   r4   r^   r?   r   
KEY_DELETEr   r   ra  )rE   rc  r   r   rz   r>   ro   s          r;   _team_key_deletion_checkr    s      H-Kx''3*$$'1	
 

 ++7%)H)HH#*#B#B%$  $=+2F*;$  !8!2!:!:%"3$8)44   "55YZbZjZjYkl  C
s   7CCBCc                   K   t        |       }|j                  t        j                  j                  k(  ry|r#| j
                  t        || ||       d{   S | j                  | j                  |j                  k(  ryy7 +w)z
    - check if user is proxy admin
    - check if user is team admin and key is a team key
    - check if key is personal key
    r:   TN)rE   rc  r   r   F)r<   rG   rH   rI   rJ   r9   r  r?   )rc  r   rE   r   rz   s        r;   can_delete_verification_tokenr    s      H-K""&6&B&B&H&HH	))5-/'1	
 
 	
 
			%(*:*:>O>W>W*W
s   ABB,BrJ  c                 J  K   ddl m 	 rG| D cg c]  }t        |       } }j                  j                  j                  dd| ii       d{   }t        |      dk(  rt        t        j                  dd	i
      j                  t        j                  j                  k(  rj                  |        d{   ng }g |D ](  }dt        ffd}|j!                   ||             * t#        j$                  |  d{    t              }|t        |       k7  r6| D cg c]	  }|vs| }	}t'        dt)        |	      z         t'        d      | D ]=  }j7                  |       t9        t;        t(        |            }j7                  |       ? di|fS c c}w 7 Y7 7 c c}w # t&        $ r[}
t+        j,                  dj/                  t)        |
                   t+        j0                  t3        j4                                |
d}
~
ww xY ww)a  
    Helper that deletes the list of tokens from the database

    - check if user is proxy admin
    - check if user is team admin and key is a team key

    Args:
        tokens: List of tokens to delete
        user_id: Optional user_id to filter by

    Returns:
        Tuple[Optional[Dict], List[LiteLLM_VerificationToken]]:
            Optional[Dict]:
                - Number of deleted tokens
            List[LiteLLM_VerificationToken]:
                - List of keys being deleted, this contains information about the key_alias, token, and user_id being deleted,
                this is passed down to the KeyManagementEventHooks to delete the keys from the secret manager and handle audit logs
    r   r  rh  r   inrk  Nr   r^  rU   rJ  r   c                    K   t        |        d {   rAj                  | j                  g       d {    j                  | j                         y t	        t
        j                  ddi      7 b7 ?w)N)rc  r   rE   r   r  r   z)You are not authorized to delete this keyrU   )r  delete_datar   rb  r   r   r   )r   deleted_tokensr   r   rE   s    r;   _delete_keyz/delete_verification_tokens.<locals>._delete_key0  s     !>%(/A.?*7	"   #0";";CII;";"OOO*11#))<"/,2,E,E$+-X("#  Ps   A=A9$A=A;>A=;A=z6Failed to delete all tokens. Failed to delete tokens: 'DB not connected. prisma_client is NonezOlitellm.proxy.proxy_server.delete_verification_tokens(): Exception occured - {}rN  )r   r   r+   r   rp  	find_manyr  r   r   ra  rG   rH   rI   rJ   r  LiteLLM_VerificationTokenrb  r   gatherr   r   r   r   rK   r   r  r  delete_cacher9  r
   )rJ  r   rE   r   rX  tasksr  _num_deleted_tokensr   failed_tokensr   r,  r  r   s    ``         @@r;   rO  rO    s3    . 9?BHI3+#6IFI#&&@@JJ"T6N3 K     &'1,# & 9 9#_5  !**.>.J.J.P.PP'4'@'@'@'O!O !#.C/H  " LLS!12' /( nne,,,&).&9#&#f+5+1%"'U.5P%M % $Pm,- 
 EFF '',!$sC.1''5	  N+-@@@K J "P2 -%  &&]ddA	

 	""9#7#7#9:s   H#F< F+/F< F0A+F< F3AF< F5!F< 1	F7;F7?$F< #AH#+F< 3F< 5F< 7F< <	H AHH  H#rK  c                    K   |j                   j                  j                  dd| ii       d {   }|D cg c]  }|j                   }}t	        |||       d {   S 7 3c c}w 7 w)Nr   r  r  rI  )r   rp  r  r   rO  )rK  r   r   rE   rX  r   rJ  s          r;   rP  rP  a  s      !. 0 0 J J T TT;/0 !U !  $77Ccii7F7+-+   8s,   .A-A$A-A&A-A+ A-&A-current_master_keynew_master_keyc                 ~  K   ddl m} 	 | j                  j                  j	                          d{   }|r|j                  |      }t        j                  dt        |             g }|D ]N  }t        t        di ||| |d       d{   }	|	s'|j                  t        |	j                                      P t        j                  d       | j                  j                  j                          d{    t        j                  d	t        |             | j                  j                  j!                  |
       d{    	 | j                  j"                  j	                          d{   }
|
r	 i }|
D ]  }|j$                  dk(  s|j&                  }  |re|j)                  |      }|j+                  ||      }|r=| j                  j"                  j-                  ddidt        |      i       d{    yyyy7 # t
        $ r d}Y w xY w7 7 (7 7 # t
        $ r d}
Y w xY w7 8w)aR  
    Rotate the master key

    1. Get the values from the DB
        - Get models from DB
        - Get config from DB
    2. Decrypt the values
        - ModelTable
            - [{"model_name": "str", "litellm_params": {}}]
        - ConfigTable
    3. Encrypt the values with the new master key
    4. Update the values in the DB
    r   )proxy_configN)
new_modelsz2ABLE TO DECRYPT MODELS - len(decrypted_models): %sF)model_paramsrE   r   new_encryption_keyshould_create_model_in_dbzResetting proxy model tablezCreating %s modelsr:   environment_variables)r  )r  r  
param_nameparam_valuerk  r5   r   )r   r  r   litellm_proxymodeltabler  r   decrypt_model_list_from_dbr   r   r  r$   r1   rb  r-   rc   delete_manycreate_manylitellm_configr  r  !_decrypt_and_set_db_env_variables_encrypt_env_variablesr  )r   rE   r  r  r  r   decrypted_modelsr  rC  	new_modelrz  environment_variables_dictcdecrypted_env_varsencrypted_env_varss                  r;   _rotate_master_keyr  s  s[    & 8""::DDFF 	 'BBfBU!!@#FVBW	
 
%E.'0%0"3+#1*/ I !!.1E1E1G"HI & 	!!"?@66BBDDD!!"6JH66BB C 
 	
 	
$''66@@BB b%'"A||66-.]]*  &!-!O!O&@ "P " ".!D!D&8#1 "E "
 "#&&55<<')@A'8J)KL =    " & C G  	E	

 C (s   H='H HH AH=H H=A&H=;H#<AH=H&	H='H* 5H(6H* :H=A.H=H;H=H HH=HH=#H=&H=(H* *H85H=7H88H=c                     | rR| j                   F| j                   }| j                   j                  d      st        t        j                  ddi      |S dt        j                  t               }|S )Nr  r   zNew key must start with 'sk-'. This is to distinguish a key hash (used by litellm for logging / internal logic) from the actual key.rU   )r
  
startswithr   r   r>  r  r  r   )r5   	new_tokens     r;   get_new_tokenr    sv    (LL	||&&u-"77  d   '//0OPQR	r=   z/key/{key:path}/regeneratez/key/regeneratec           	        K   	 ddl m}m}m}m}m}m}	 |xr |j                  du}
|dur(|
s&t        dt        j                  j                         |r|j                  r|j                  n| } | st        dddi	      |t        t        j                  dd
i	      t!        | |      }|{|ry|rw|j                  t        t        j"                  ddi	      t%        ||||j                         d{    t'        |j                  |j                  |j                  d      S d| vr| }n ||       }|j(                  j*                  j-                  d|i       d{   }|!t        t        j.                  dd|  di	      t1        j2                  |t4        j6                  |||	       d{    t9        j:                  d|       t=        |      } ||      }d|dd  }||d}i }|+t?        ||       d{   }t9        j:                  d|       |jA                  |       |jC                  |      }|j(                  j*                  jA                  d|i|       d{   }i }|tE        |      }||d<   |jG                  d      |d<   | rtI         ||       |	|       d{    |rtI         ||       |	|       d{    t'        d"i |}tK        jL                  tO        jP                  |||||              |S 7 7 7 c7 7 7 j7 N# tR        $ r&}t9        jT                  d!|       tW        |      d}~ww xY ww)#a
  
    Regenerate an existing API key while optionally updating its parameters.

    Parameters:
    - key: str (path parameter) - The key to regenerate
    - data: Optional[RegenerateKeyRequest] - Request body containing optional parameters to update
        - key: Optional[str] - The key to regenerate.
        - new_master_key: Optional[str] - The new master key to use, if key is the master key.
        - new_key: Optional[str] - The new key to use, if key is not the master key. If both set, new_master_key will be used.
        - key_alias: Optional[str] - User-friendly key alias
        - user_id: Optional[str] - User ID associated with key
        - team_id: Optional[str] - Team ID associated with key
        - models: Optional[list] - Model_name's a user is allowed to call
        - tags: Optional[List[str]] - Tags for organizing keys (Enterprise only)
        - spend: Optional[float] - Amount spent by key
        - max_budget: Optional[float] - Max budget for key
        - model_max_budget: Optional[Dict[str, BudgetConfig]] - Model-specific budgets {"gpt-4": {"budget_limit": 0.0005, "time_period": "30d"}}
        - budget_duration: Optional[str] - Budget reset period ("30d", "1h", etc.)
        - soft_budget: Optional[float] - Soft budget limit (warning vs. hard stop). Will trigger a slack alert when this soft budget is reached.
        - max_parallel_requests: Optional[int] - Rate limit for parallel requests
        - metadata: Optional[dict] - Metadata for key. Example {"team": "core-infra", "app": "app2"}
        - tpm_limit: Optional[int] - Tokens per minute limit
        - rpm_limit: Optional[int] - Requests per minute limit
        - model_rpm_limit: Optional[dict] - Model-specific RPM limits {"gpt-4": 100, "claude-v1": 200}
        - model_tpm_limit: Optional[dict] - Model-specific TPM limits {"gpt-4": 100000, "claude-v1": 200000}
        - allowed_cache_controls: Optional[list] - List of allowed cache control values
        - duration: Optional[str] - Key validity duration ("30d", "1h", etc.)
        - permissions: Optional[dict] - Key-specific permissions
        - guardrails: Optional[List[str]] - List of active guardrails for the key
        - blocked: Optional[bool] - Whether the key is blocked


    Returns:
    - GenerateKeyResponse containing the new key and its updated parameters

    Example:
    ```bash
    curl --location --request POST 'http://localhost:4000/key/sk-1234/regenerate'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data-raw '{
        "max_budget": 100,
        "metadata": {"team": "core-infra"},
        "models": ["gpt-4", "gpt-3.5-turbo"]
    }'
    ```

    Note: This is an Enterprise feature. It requires a premium license to use.
    r   )r9  
master_keyr}   r   r!  r   NTz4Regenerating Virtual Keys is an Enterprise feature, rS   r   zNo key passed in.rU   r  )ro  _master_keyzNew master key is required.)r   rE   r  r  )r   r   r  r  skr   r  Key z not found.r&  zkey_in_db: %sr:   zsk-...)r   r  r  znon_default_values: %sr  r   r   r+  r-  zError regenerating key: %sr   ),r   r9  r  r}   r   r!  r   r  r   r   r   rJ   r   r   r   rR  r)   r>  r  r   r   rp  r#  ra  r'   r5  r   KEY_REGENERATEr   r   r  r  r  r-   r   r   r   r   r   r!   async_key_rotated_hookr   r   r,   )r   r5   rE   r   r9  r  r}   r   r!  r   is_master_key_regeneration_is_master_key_validhashed_api_key
_key_in_dbr  new_token_hashnew_token_key_namer8  r   updated_tokenupdated_token_dictr   r   s                          r;   regenerate_key_fnr    s    JV+	
 	
 &*%Md.A.A.M" $-GFGXGiGiGoGoFpq 
 488dhhCBU8VWW  "AA!JK 
  .czR!d/C""*# & ; ;#%BC  %+"3#-#22	   ''')),,	  s? N'_N(++EEQQN+ R 
 

 "554uK!89  )XX/%44''1
 	
 	
 	""?J?!t,	#I.%in%56 $*

  '>J( " !&&'?AST-.#222D+..HHOON+ P 
 

  $!%m!4$-5!);)?)?)H:& *'_#5"3   *'_#5"3   ' 
 
 	#::!+!"3#5	
 M$
	
0"
*  +&&'CQG'**+s   MC2L$ 6L70L$ 'M(:L$ "L#AL$ 5L6AL$ LA)L$ /L0AL$ 5L 6L$ L"=L$ ML$ L$ L$ L$ L$  L$ "L$ $	M-!MMMkey_hashc                   K   | j                   t        j                  j                  k(  ry | j                  +t        dt        j                  dt        j                        |j                  j                  j                  d| j                  iddi       d {   }|+t        dt        j                  dt        j                        t        di |j                         }|r:|j                  |k7  r+t        dt        j                  dt        j                        |r9||j                  vr+t        dt        j                  d	t        j                        |r]|j                   &||j                   D 	cg c]  }	|	j"                   c}	vr+t        d
t        j                  dt        j                        |r}	 |j                  j$                  j                  d|i       d {   }
t)        | ||
       d {   }|s4t+        t        j                  dj-                  | j                               |S 7 c c}	w 7 Z# t&        $ r, t        dt        j                  dt        j                        w xY w7 ~w)Nz]You are not authorized to access this endpoint. No 'user_id' is associated with your API key.r?   r0  organization_membershipsTrj  z3You are not authorized to check another user's keysz0You are not authorized to check this team's keysr9   z8You are not authorized to check this organization's keysr  r   r  zKey Hash not found.r  rm  rn  rU   r   )rG   rH   rI   rJ   r?   r;  r<  bad_request_errorr   r   r   litellm_usertabler#  LiteLLM_UserTablerc   r  r  r  rp  r   rr  r   rK   )rE   r?   r9   r  r   r  r   complete_user_info_db_objcomplete_user_info
membershiprc  can_user_query_key_infos               r;   validate_key_list_checkr    s     ""&6&B&B&H&HH  (s 22**	
 	
 00<</778/6 = 
 	
  !(s 22**	
 	
 +T-F-Q-Q-ST %%0 M$66..	  ,222 J$66..	  77? #5"M"M ** !R$66'..	  
	*--GGSS) T  H )A/)
 #

 '"55T[[%//  W	
N  	 -$66 ..	 	#
s[   BJ H<CJ 9H?1J >+I )I*I .J ?I> =J ?J I 5I;;J r  c           	      F  K   | g S |j                   j                  j                  dd| j                  ii       d{   }|g S |D cg c]  }t	        di |j                          }}|D cg c]  }t        ||      r|j                   }}|S 7 Vc c}w c c}w w)z6
    Get all team IDs where the user is an admin.
    Nr9   r  r  rF  r   )r   litellm_teamtabler  r  LiteLLM_TeamTablerc   r"   r9   )r  rE   r   r  r(  teams_pydantic_objadmin_team_idss          r;   get_admin_team_idsr  	  s      !	 00::t%7%=%=>? ; 
 	
 

 }	MRST+@doo.?@SS '1BTR 	N 
 	
 Ts-   <B!BB! B+B!1 BB!
B!z	/key/list   zPage number)r   ge
   z	Page sized   )r   r  lezFilter keys by user IDzFilter keys by team IDzFilter keys by organization IDzFilter keys by key hashzFilter keys by key aliaszReturn full key objectz4Include all keys for teams that user is an admin of.z9Column to sort by (e.g. 'user_id', 'created_at', 'spend')desczSort order ('asc' or 'desc')pagesizereturn_full_objectinclude_team_keyssort_by
sort_orderc                   K   	 ddl m} t        j                  d       | t        j                  d       t        d      t        |||||||       d{   }|
rt        |||       d{   }nd}|L|j                  t        j                  j                  t        j                  j                  fvr|j                  }t        ||||||||	||||       d{   }t        j                  d	       |S 7 7 7 # t
        $ r}t        j                  d
|        t!        |t"              rYt%        t'        |ddt)        |       d      t*        j,                  t'        |dd      t'        |dt.        j0                              t!        |t$              r|t%        dt)        |      z   t*        j,                  t'        |dd      t.        j0                        d}~ww xY ww)z
    List all keys for a given user / team / organization.

    Returns:
        {
            "keys": List[str] or List[UserAPIKeyAuth],
            "total_count": int,
            "current_page": int,
            "total_pages": int,
        }
    r   r  zEntering list_keys functionNzDatabase not connected)rE   r?   r9   r  r   r  r   )r  rE   r   )r   r  r   r?   r9   r   r  r  r  r  r  r  zSuccessfully prepared responsezError in list_keys: rW   zerror(r.  re   r/  rV   r0  r3  )r   r   r   r   r   r   r  r  rG   rH   rI   rJ   PROXY_ADMIN_VIEW_ONLYr?   _list_key_helperr   r   r   r;  r   r   r<  rQ  r   rR  )r  rE   r  r   r?   r9   r  r  r   r  r  r  r  r   r  r  r   r   s                     r;   	list_keysr  .	  s    NE
<""#@A  &&'?@455#:/+'$
 
 #5#5"3+$ N "N?0::((..2288C
  
 (//G)'1+)!
 
 	""#CDU

&  
&&)=aS'ABa' 8vc!fXQ-?@$::a&1Qv/T/TU	  >*G,s1v5 66!Wf-66	
 	

sa   G&AD  C:D  .C</A/D  C>D  9G&:D  <D  >D   	G#	CGG##G&c                     i }| y g d}| |vr!t        ddddj                  |       i      |j                         dvrt        dddi      |j                         || <   |S )	N)r{  r   r  r  r   r   rS   r   z%Invalid sort column. Must be one of: z, rU   )ascr  z+Invalid sort order. Must be 'asc' or 'desc')r   joinlower)r  r  order_byvalid_columnss       r;   _validate_sort_paramsr  	  s      "HM m#@=AY@Z[
 	
 0JK
 	

 #((*HWOr=   exclude_team_idr  c                 X  K   i }|j                  t                      g }i }|rt        |t              r||d<   |rt        |t              r||d<   |rt        |t              r||d<   |rt        |t              rd|i|d<   |rt        |t              r||d<   |rt        |t              r||d<   |r|j	                  |       |
r|j	                  dd|
ii       t        |      dkD  r	d	|d
|igi}n"t        |      dk(  r|j                  |d          t        j                  d|        |dz
  |z  }t        j                  d| d|        |t        |t              rt        ||      nd}| j                  j                  j                  ||||r|nddiddigddi       d{   }t        j                  dt        |       d       | j                  j                  j                  |       d{   }t        j                  d|        | |z   }g }|D ]u  }|j                         }t        ||        d{   }|	du r|j	                  t        di |       F|j!                  d      }|j	                  t#        t        |             w t%        ||||      S 7 7 7 hw)a  
    Helper function to list keys
    Args:
        page: int
        size: int
        user_id: Optional[str]
        team_id: Optional[str]
        key_alias: Optional[str]
        exclude_team_id: Optional[str] # exclude a specific team_id
        return_full_object: bool # when true, will return UserAPIKeyAuth objects instead of just the token
        admin_team_ids: Optional[List[str]] # list of team IDs where the user is an admin

    Returns:
        KeyListResponseObject
        {
            "keys": List[str] or List[UserAPIKeyAuth],  # Updated to reflect possible return types
            "total_count": int,
            "current_page": int,
            "total_pages": int,
        }
    r?   r9   r   notr  r   r  r  ANDORr   zFilter conditions: zPagination: skip=z, take=Nr  r  r  T)rk  skiptakeorderrl  zFetched z keysr  zTotal count of keys: )rL  total_countcurrent_pagetotal_pagesr   )r  ._get_condition_to_filter_out_ui_session_tokensr   r   rb  r  r   r   r  r   rp  r  countr   r%   UserAPIKeyAuthrn   r
   KeyListResponseObject)r   r  r   r?   r9   r  r   r  r  r  r  r  r  rk  or_conditionsuser_conditionr  r  rL  r  r  key_listr   key_dict_tokens                            r;   r  r  	  s    N JLE	LL?AB +-M &(N:gs+$+y!:gs+$+y!Z	3/&/{#:os;%*O$<y!:os;,;()Jx-"*w^, i$)?@A =A} 567	]	q	 ]1%&!4UG<= 1HD!24&vFG :gs#; 	gz2  !!;;EE   v&&!
 %d+ F  D #d)E:; &((BBHH I  K !6{mDE !LD()K 24H88:9(MRR%OON6X67\\'*FOODf-.  !	 O$ Ss9   F#J*%J$&AJ*5J&6A	J*?J( A%J*&J*(J*c                  "    dddiddt         iigiS )z3
    Condition to filter out UI session tokens
    r  r9   Nr  )r   r   r=   r;   r  r  G
  s.    
 	E#;<
 r=   z
/key/blockhttp_requestc                 `  K   ddl m}m}m}m}m}m}	 |2t        dj                  t        j                  j                              t        | j                        s+t        dt        j                   dt"        j$                         || j                        }
t&        j(                  d	u r|j*                  j,                  j/                  d
|
i       d{   }|9t        d| j                   dt        j                   dt"        j0                        t3        j4                   |t7        t9        t;        j<                               t?        j@                  tB        jD                        |xs |jF                  xs ||jH                  tJ        jL                  |
dd|jO                         	                   |j*                  j,                  jQ                  d
|
idd	i       d{   }tS        |
||	d|       d{   }d	|_*        tW        |
||	|       d{    |S 7 M7 ?7 )7 w)a  
    Block an Virtual key from making any requests.

    Parameters:
    - key: str - The key to block. Can be either the unhashed key (sk-...) or the hashed key value

     Example:
    ```bash
    curl --location 'http://0.0.0.0:4000/key/block'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
        "key": "sk-Fn8Ej39NxjAXrvpUGKghGw"
    }'
    ```

    Note: This is an admin-only endpoint. Only proxy admins can block keys.
    r   create_audit_log_for_updater9  r   r   r!  r   N{}Invalid key format.r   r0  rh  Tr   r  r  
 not foundr|  	idr  
changed_bychanged_by_api_keyr   	object_idactionupdated_valuesbefore_valuerequest_datar  r,  r   r   r   r!  r,  user_api_key_objr   r!  ,r   r(  r9  r   r   r!  r   r   rK   r   db_not_connected_errorrJ   r.   r   r;  r<  r  r   r>  rl   store_audit_logsr   rp  r#  ra  r   r   LiteLLM_AuditLogsr   uuiduuid4r   r  r   r  r?   ro  LitellmTableNamesKEY_TABLE_NAMEmodel_dump_jsonr  r   r|  r   r5   r%  rE   r   r(  r9  r   r   r!  r   r,  record
key_objects                r;   	block_keyrE  U
  s    >  $5$L$L$R$RSTTDHH%) 22,,	
 	
 DHH-L4'$''AAMML) N 
 
 > txxj
3$66..	  	'.4::<('||HLL91  0(00 0/'8'@'@0??*$#'!'!7!7!9	
$ !##==DD%Y,= E  F &!#-+ J J !#-+	   Mm
8I   CH.H%DH.(H()H. H*H.H,H.(H.*H.,H.z/key/unblockc                 `  K   ddl m}m}m}m}m}m}	 |2t        dj                  t        j                  j                              t        | j                        s+t        dt        j                   dt"        j$                         || j                        }
t&        j(                  d	u r|j*                  j,                  j/                  d
|
i       d{   }|9t        d| j                   dt        j                   dt"        j0                        t3        j4                   |t7        t9        t;        j<                               t?        j@                  tB        jD                        |xs |jF                  xs ||jH                  tJ        jL                  |
dd|jO                         	                   |j*                  j,                  jQ                  d
|
iddi       d{   }tS        |
||	d|       d{   }d|_*        tW        |
||	|       d{    |S 7 M7 ?7 )7 w)a  
    Unblock a Virtual key to allow it to make requests again.

    Parameters:
    - key: str - The key to unblock. Can be either the unhashed key (sk-...) or the hashed key value

    Example:
    ```bash
    curl --location 'http://0.0.0.0:4000/key/unblock'     --header 'Authorization: Bearer sk-1234'     --header 'Content-Type: application/json'     --data '{
        "key": "sk-Fn8Ej39NxjAXrvpUGKghGw"
    }'
    ```

    Note: This is an admin-only endpoint. Only proxy admins can unblock keys.
    r   r'  Nr)  r*  r   r0  rh  Tr   r  r  r+  r|  r,  r4  Fr  r6  r7  r9  rB  s                r;   unblock_keyrH  
  s    >  $5$L$L$R$RSTTDHH%) 22,,	
 	
 DHH-L4'$''AAMML) N 
 
 > txxj
3$66..	  	'.4::<('||HLL91  0(00 0/'8'@'@0??*$#'!'!7!7!9	
$ !##==DD%Y,> E  F &!#-+ J J !#-+	   Mm
8rF  z/key/healthc           
      x  K   	 |j                   }t        dd      }|r;d|v r7t        || |d          d{   }||d<   |j                  d      dk(  rd|d	<   t        di |S 7 -# t        $ rG}t        d
t        |       t        j                  t        |dd      t        j                        d}~ww xY ww)aS  
    Check the health of the key

    Checks:
    - If key based logging is configured correctly - sends a test log

    Usage 

    Pass the key in the request header

    ```bash
    curl -X POST "http://localhost:4000/key/health"      -H "Authorization: Bearer sk-1234"      -H "Content-Type: application/json"
    ```

    Response when logging callbacks are setup correctly:

    ```json
    {
      "key": "healthy",
      "logging_callbacks": {
        "callbacks": [
          "gcs_bucket"
        ],
        "status": "healthy",
        "details": "No logger exceptions triggered, system is healthy. Manually check if logs were sent to ['gcs_bucket']"
      }
    }
    ```


    Response when logging callbacks are not setup correctly:
    ```json
    {
      "key": "unhealthy",
      "logging_callbacks": {
        "callbacks": [
          "gcs_bucket"
        ],
        "status": "unhealthy",
        "details": "Logger exceptions triggered, system is unhealthy: Failed to load vertex credentials. Check to see if credentials containing partial/invalid information."
      }
    }
    ```
    healthyN)r   logging_callbackslogging)rE   r  key_loggingrK  r   	unhealthyr   zKey health check failed: re   r/  r0  r   )r   KeyHealthResponsetest_key_loggingrn   r   r;  r   r<  rQ  r   r   rR  )r  rE   key_metadatahealth_statuslogging_statusesr   s         r;   
key_healthrT  3  s     r
(11+<",
 I5%5"3(3&  
 2BM-.  ##H-<'2e$ 1=11   
/Ax8 66!Wf-66	
 	

s9   B:3A' A%,A' $B:%A' '	B70AB22B77B:c                 B  K   | j                   t        j                  j                  k(  s'| j                   t        j                  j                  k(  ry| j
                  |k(  ry|j                  | j                  k(  ryt        j                  | |       d{   ryy7 w)zB
    Helper to check if the user has access to the key's info
    T)rE   r  NF)	rG   rH   rI   rJ   r  ro  r?   r'   user_belongs_to_keys_teamrm  s      r;   rr  rr    s      	##'7'C'C'I'II&&*:*P*P*V*VV		"	"c	)			.66	6)CC+! 
 
 
s   BBBBrM  c           	         K   ddl }ddlm} ddlm} ddlm}m} g }|D ]2  }	|	j                  d      |j                  |	d          )t        d        |       }
|j                  |
      }|j                  |j                         |j                         }|j                  |       	 dd	d
dgdd} ||| |||       d{   }t!        j"                  di | d{    t+        j,                  d       d{    |
j/                         }|j1                  |       |rt'        |dd|       S t'        |dd| d      S 7 7 i# t$        $ r$}t'        |ddt)        |             cY d}~S d}~ww xY w7 ~w)a3  
    Test the key-based logging

    - Test that key logging is correctly formatted and all args are passed correctly
    - Make a mock completion call -> user can check if it's correctly logged
    - Check if any logger.exceptions were triggered -> if they were then returns it to the user client side
    r   N)StringIO)add_litellm_data_to_request)general_settingsr  callback_namez(callback_name is required in key_loggingzopenai/litellm-key-health-testri   zQHello, this is a test from litellm /key/health. No LLM API call was made for this)rZ   contentztest response)rC  messagesmock_response)r5   rE   r  rZ  r  rN  zLogging test failed: )	callbacksr   details   z2Logger exceptions triggered, system is unhealthy: rJ  zWNo logger exceptions triggered, system is healthy. Manually check if logs were sent to  r   )rL  iorX  $litellm.proxy.litellm_pre_call_utilsrY  r   rZ  r  rn   rb  r   StreamHandlersetLevelERROR	getLogger
addHandlerrl   acompletionr   LoggingCallbackStatusr   r   sleepgetvalueremoveHandler)rE   r  rM  rL  rX  rY  rZ  r  rK  callbacklog_capture_stringchloggerr5   r   log_contentss                   r;   rP  rP    s     PI#%<<(4$$Xo%>?GHH	   "			1	2BKK F
b
5 #r -	
 1/%-
 
 !! 

 	
 	
 --	  
 &..0L
$'HW
 	
 %'mn  nA  AB  C
 	
?
	
  
$'+CF84
 	

sg   B&E>)E EE  E
!E %E>=E<>A
E>E 
E 	E9E4.E9/E>4E99E>r*  c                    K   | p|md| i}|rd|i|d<   |j                   j                  j                  |       d{   }|/t        d|  dt        j
                  dt        j                        yyy7 8w)	a(  
    Helper to enforce unique key aliases across all keys.

    Args:
        key_alias (Optional[str]): The key alias to check
        prisma_client (Any): Prisma client instance
        existing_key_token (Optional[str]): ID of existing key being updated, to exclude from uniqueness check
            (The Admin UI passes key_alias, in all Edit key requests. So we need to be sure that if we find a key with the same alias, it's not the same key we're updating)

    Raises:
        ProxyException: If key alias already exists on a different key
    Nr   r   NOTr  zKey with alias 'zB' already exists. Unique key aliases across all keys are required.r0  )r   rp  
find_firstr;  r<  r  r   r>  )r   r   r*  where_clauseexisting_keys        r;   r   r     s     " !:(3Y'?#*,>"?L*--GGRR S 
 
 # *9+5wx$66!00	  $ ";
s   ;A8A69A8c                 r   	 | yt        |       dk(  ry| yddlm}m} |dur"t	        d|j
                  j                         | j                         D ]7  \  }}t        |t              sJ d|v rt        |d         |d<   t        d	i | 9 yy# t        $ r}t	        dt        |       d      d}~ww xY w)
z
    Validate the model_max_budget is GenericBudgetConfigType + enforce user has an enterprise license

    Raises:
        Exception: If model_max_budget is not a valid GenericBudgetConfigType
    Nr   )r   r}   Tz=You must have an enterprise license to set model_max_budget. budget_limitzInvalid model_max_budget: zM. Example of valid model_max_budget: https://docs.litellm.ai/docs/proxy/usersr   )r  r   r   r}   r   r   rJ   r   r   r   floatr2   r   )r   r   r}   _model_budget_infor   s         r;   r  r    s    
# A%'R4' STeTvTvT|T|S}~  )9(>(>(@$!&#... "\138n9U3VL0,|, )A (  
(Q0}~
 	

s"   B B A:B 	B6B11B6)NFNNr  r7   )__doc__r   r   r   r  r  r=  r   r   r   typingr   r   r   r	   r
   fastapir   r   r   r   r   r   r   rl   litellm._loggingr   litellm.cachingr   litellm.constantsr   r   *litellm.litellm_core_utils.duration_parserr   litellm.proxy._typeslitellm.proxy.auth.auth_checksr   r   r   r   r   litellm.proxy.auth.auth_utilsr   $litellm.proxy.auth.user_api_key_authr   r  r    .litellm.proxy.hooks.key_management_event_hooksr!   /litellm.proxy.management_endpoints.common_utilsr"   r#   =litellm.proxy.management_endpoints.model_management_endpointsr$   8litellm.proxy.management_helpers.object_permission_utilsr%   r&   >litellm.proxy.management_helpers.team_member_permission_checksr'   &litellm.proxy.management_helpers.utilsr(   1litellm.proxy.spend_tracking.spend_tracking_utilsr)   litellm.proxy.utilsr*   r+   r,   r-   r.   litellm.routerr/   litellm.secret_managers.mainr0   litellm.types.routerr1   litellm.types.utilsr2   r3   r4   UnionGenerateKeyRequestr  r<   LiteLLM_TeamTableCachedObjr   MemberrD   r  boolrN   r   r^   rf   rp   rt   rw   r{   UpdateKeyRequestr   routerr   r   r   r   postr   r   	BaseModelr  r   RegenerateKeyRequestr  r  r  rA  r  r7  
KeyRequestrY  re  rn   rt  r   listr{  intLiteLLM_ObjectPermissionBaser   r  r  DictrO  rP  r  r  r  r  r  r  r  r  r  r  Anyr  BlockKeyRequestrE  rH  rO  rT  rr  rk  rP  r   r  r   r=   r;   <module>r     sl  	       2 2 7 7  U U U  1 % W J "  = B K R O L  " 3 + $u/1JJK $	*	5=c]	f	%08HPQT	@1sm1*1 &1 3	1
 1h
/7S	/B *%  	B%%&CD&%-?0
34
%
 
 	

 

@%
"$44
5   	
 T]D 
,  $ |
|%| !| 34	|
 |~ 
	+,-&	    )00A(B(. t)u+
u+%u+ !u+ u+p #
	+,-  
  )00A(B(. t)q
q%q !q qh
)-BF	@L)21
 "66
71/1h/ 
44
4.G4	4 )*'BS:T9U    )00A(B(. t)	r
r

r
 &r
 !	r
 r
j=
	"=

=
 (=
 	=
@ )*'BS:T9U    )00A(B(. t)h+
h+%h+ !h+ h+V 
	+,-	   "&(/0A(B5+
:
5+%5+5+p '(@Q8R7S   '"A )00A(B	J+	#J+ &	J+J+ZT#Y-5f-=MQT]@ #&*)-!% 	"&"%) 	! $! $#+/!##8E(,#-/"$')&*&*!% %)37(, $ $%)!% 	@Dgzz sm	z
 z z z z UOz "#z z z z  d^!z" c]#z$ C=%z& 

'z, c]-z. /z0 c]1z2 3z4 }5z6 $C=7z8 tn9z: };z< }=z> 45?z@  ~AzB }CzD %TNEzF $GzH tnIzJ d^KzL d^MzN OzP D>QzR c]SzT /0UzV  ~WzX YzZ [z\ TN]z^ #_z` #azf   <=gzz*%*'*  * "	*Z'! &  	
 
6`A`A!`A &`A 8D>4 9::;	`AFc!   &	
 8D>4 9::;$LL%L L 	L
 
L^!56 3   
	+,-  
 
	+,-  
 +/(/0A(B(. t)	P+	#P+
'
(P+ &P+ !	P+ !"P+ P+f_%_c]_ c]_ c]	_
 }_ sm_  _  _D !23%   
#Y	: 
	+,-  
  )00A(Ba]q9bkaC@"45MN"45MN%*:& $D6OP$T7QR$U8PQ#Q #O F8VW)f
f
%f
 f
 	f

 c]f
 c]f
 c]f
 smf
 }f
 f
 f
  c]!f
( )f
* +f
 f
R!c]!(+!d38n!Z &*$ 	!CC
C C c]	C
 c]C c]C }C smC c]C C S	C c]C C  !CLS#X  ()AR9S8T    )00A(B(. t)	h
hh &h !	h '(h hV *+7CT;U:V    )00A(B(. t)	h
hh &h !	h hV 
	+,-$	    )00A(BP
P
%P
 P
f%	# ( 
	4M
%M
M
 d38n%M
 	M
f )- }   !  
	 F
 
4 
r=   