
    g8             L       
   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 dd	l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)m*Z*m+Z+m,Z,m-Z- ddl.m/Z/ ddl0m1Z1 ddl2m3Z3m4Z4m5Z5 de6fdZ7de8dee9   dee:   fdZ;de<dee9   dee9   de=fdZ>dee9   de8de<de5fdZ?de6deee9      fdZ@de8de<de6fdZAde<d ee4   fd!ZBde<de6fd"ZCdee8   de<de6de=fd#ZD e       ZEeEj                  d$d%g ee$      geG&      e( ee$       edd'(      fde6de<d)ee9   fd*              ZHdeId+eJd,eJdeJfd-ZKdeLeMeNf   fd.ZOeEj                  d/d%g ee$      g0      e( ee$       edd'(      fd1edeMde<d)ee9   fd2              ZPeEj                  d3d%g ee$      g0      e( ee$       edd'(      fdeQde<d)ee9   fd4              ZReEj                  d5d%g ee$      gd67      d ee$      fdeeQ   de<fd8       ZSeEj                  d9d%g ee$      g0       ej*                  dd:;       ee$      fd<ee9   de<fd=       ZUd>eee9      d?ee/   d@e=dedA   fdBZVdg i i dCdddddddddddddddi dddDddg i i dddddddf$dEedF   dGee9   d>eWdHeJdIeJdJeXdKeeX   dLee9   dMeeX   dNeeX   dOeeX   dPee=   dQee9   dRee9   d<ee9   dee9   dSee9   dee9   dTee9   dUee9   dVeeY   dWeeJ   dXeeY   dYeeY   dZed[   d\eeJ   d]ee9   d^eeW   d_eeJ   d`eeJ   daeeJ   dbeeJ   dceeW   ddeeW   deee9   dfeedg      dhee=   fJdiZZ	 ddjedkedee9   deee[   ee\   f   fdlZ]	 ddmee9   dkedne*dee9   deee[   ee\   f   f
doZ^eEj                  dpd%g ee$      g0      e(d ee$       edd'(      fd<e9deeN   de<d)ee9   deeG   f
dq              Z_eEj                  drd%g ee$      g0      e( ee$       edsdtdsu       edvdwdsdxy       eddz(       edd{(       edd|(      fd1ede<d}eYd~eYdee9   dee9   d]ee9   fd              Z`eEj                  dd%g ee$      g0      e( ee$       edd'(      fdeadede<d)ee9   dee\   f
d              ZbeEj                  dd%g ee$      g0      e( ee$       edd'(      fdeadede<d)ee9   fd              ZceEj                  dd%g ee$      ged&      e( ee$      fd1ede<fd              Zede<d<ee9   de\de=fdZfde<d1edee[e9egf      dehfdZi	 dd]ee9   dnegdee9   ddfdZjd`ee[   ddfdZky)za
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)*)_cache_key_object_delete_cache_key_objectget_key_objectget_team_object)user_api_key_auth)KeyManagementEventHooks)management_endpoint_wrapper)PrismaClient_hash_token_if_neededduration_in_secondshandle_exception_on_proxy)Router)
get_secret)BudgetConfigPersonalUIKeyGenerationConfigTeamUIKeyGenerationConfigdatac                     | j                   d uS N)team_idr%   s    p/var/www/openai/venv/lib/python3.12/site-packages/litellm/proxy/management_endpoints/key_management_endpoints.py_is_team_keyr+   4   s    <<t##    
team_tableuser_idreturnc                 l    |y | j                   D ]"  }|j                  |j                  |k(  s |c S  y r'   )members_with_rolesr.   )r-   r.   members      r*   _get_user_in_teamr3   8   s;     //>>%&..G*CM 0 r,   user_api_key_dictr(   c                 t   | j                   (| j                   t        j                  j                  k(  ry|0|| j                  k(  s!J dj                  || j                               |P| j                  | j                  t        k(  ry| j                  |k(  s!J dj                  || j                               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={}zEUser can only create keys for their own team. Got={}, Your Team ID={})	user_roleLitellmUserRolesPROXY_ADMINvaluer.   formatr(   
UI_TEAM_IDr4   r.   r(   s      r*   _is_allowed_to_create_keyr=   C   s     	##/''+;+G+G+M+MM(000	
QXX&..
	
0
 %%1!))Z7%%0	
RYY&..
	
0
 r,   assigned_user_idteam_key_generationc                    | ,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          y)
N)r-   r.     zUser=z not assigned to team=status_codedetailTallowed_team_member_roleszTeam member role z" not in allowed_team_member_roles=)	r3   r   r(   r.   r6   r7   r8   r9   role)r>   r-   r4   r?   key_assigned_user_in_teamkey_creating_user_in_teamis_admins          r*   &_team_key_generation_team_member_checkrJ   h   sD    #$5!+;%
! %,/00FzGYGYFZ[ 
 !2'8'@'@!
 	##4/ 	N''+;+G+G+M+MM 
 	"	*,4455KJL^L^K_`
 	

 	$'::%**"#>?@ &'@'E'E&FFhi|  ~Y  jZ  i[  \
 	
 r,   required_paramsc                 f    |y| j                  d      }|D ]  }||vst        dd| d       y)NTexclude_unsetrA   zRequired param z not in datarB   )
model_dumpr   )r%   rK   	data_dictparams       r*   $_key_generation_required_param_checkrR      sP     d3I 	!(|<  ! r,   c                     t         j                  &dt         j                  v rt         j                  d   }nt        ddg      }t        |j                  | ||       t        ||j                  d             y)Nr?   adminr2   )rE   )r>   r-   r4   r?   rK   T)litellmkey_generation_settingsr$   rJ   r.   rR   get)r-   r4   r%   _team_key_generations       r*   _team_key_generation_checkrY      s~     	''3!W%D%DD&>>?TU8'.&9 
 ++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_rolesTrA   zBPersonal key creation has been restricted by admin. Allowed roles=rZ   z. Your role=rB   )r6   r   rU   rV   )r4   rZ   s     r*   _personal_key_membership_checkr]      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)NrZ   T)rZ   rK   )rU   rV   rW   r]   rR   )r4   r%   _personal_key_generations      r*   _personal_key_generation_checkr`      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)   rA   z1Unable to find team object in database. Team ID: rB   Tr-   r4   r%   )r4   r%   )r+   rU   rV   r   r(   rY   r`   )r-   r4   r%   is_team_keys       r*   key_generation_checkrd      su     D)K'"A"A"MJ4<<.Y  )!/
 	
 ./d
 	
r,   z/key/generatezkey management)tags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)descriptionlitellm_changed_byc           
      
  K   	 ddl m}m}m}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{   }t)        |||        	 t+        || j,                  | j                          t3        | j4                  ||       t6        j8                  | D ]  }|\  }}|0|dv r,t;        | |t6        j8                  j                  |d             :|dk(  r1|g k(  r,t;        | |t6        j8                  j                  |g              p|dk(  sv|i k(  s|t;        | |t6        j8                  j                  |i               t6        j<                  | D ]  }|\  }}t?        t6        j<                  |d      }|&|t;        | ||       6|dv r||kD  s@t        dd| d| d| i
      |dv s\tA        |      }tA        |      }||kD  szt        dd| d| d| i
       | jB                  }|| jD                  tG        | jD                  | jH                  xs i       }|jK                  |jM                  d            }|jN                  jP                  jS                  i ||j,                  xs ||j,                  xs |d       d{   }t?        |d d      }| jU                  dd!      }d"|v r|jW                  d"d      |d#<   |||d <   d$|v r|jW                  d$d      |d%<   d&|v radd'l m} |dur+|d&   &t        d(tX        jZ                  j\                         |d   d&|d&   i|d<   n|d&   |d   d&<   |jW                  d&       t_        |j                  d)d      |*       d{    ta        d1d+d,i|d-d,i d{   }| jD                  |d.<   t        jb                  te        jf                  | |||/             ti        d1i |S 7 '7 # t&        $ r%}t        j                  d|        d}Y d}~d}~ww xY w# t.        $ r}t        dt1        |      
      d}~wt&        $ r}t        dt1        |      
      d}~ww xY w7 7 7 # t&        $ r=}t        jj                  d0jm                  t1        |                   to        |      d}~ww xY ww)2a  
    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)

    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   )litellm_proxy_admin_name
llm_routerpremium_userprisma_clientuser_api_key_cacheuser_custom_key_generatezentered /key/generateNz,user_custom_key_generate must be a coroutinedecisionTmessagez(Authentication Failed - Custom Auth RulerB   )r(   rn   ro   parent_otel_spanz.Error getting team object in `/key/generate`: rb   r<   i  i  )modelsrl   rm   )
max_budgetr.   r(   max_parallel_requests	tpm_limit	rpm_limitbudget_durationrt   metadata)ru   rv   rw   rx   rA   errorz. is over max limit set in config - user_value=z; max_value=)ry   durationr|   )soft_budgetmodel_max_budget)exclude_none)
created_by
updated_byr)   	budget_idrN   r   ru   key_max_budgetry   key_budget_durationre   )rm   z)Only premium users can add tags to keys. 	key_alias)r   rn   request_typekey
table_namer~   )r%   responser4   ri   zDlitellm.proxy.proxy_server.generate_key_fn(): Exception occured - {} )8litellm.proxy.proxy_serverrk   rl   rm   rn   ro   rp   r   debugasyncioiscoroutinefunction
ValueErrorrW   r   r   HTTP_403_FORBIDDENr(   r   rs   	Exceptionrd   r=   r.   AssertionErrorstr_check_model_access_grouprt   rU   default_key_generate_paramssetattrupperbound_key_generate_paramsgetattrr   r   r~   LiteLLM_BudgetTabler   jsonify_objectjsondblitellm_budgettablecreaterO   popCommonProxyErrorsnot_premium_userr9   _enforce_unique_key_aliasgenerate_key_helper_fncreate_taskr   async_key_generated_hookGenerateKeyResponse	exceptionr:   r   )r%   r4   ri   rk   rl   rm   rn   ro   rp   resultrq   rr   r-   eelemr   r9   upperbound_valueupperbound_durationuser_duration
_budget_id
budget_row
new_budget_budget	data_jsonr   s                             r*   generate_key_fnr     s    FL+	
 	
 	""#:;#/**+CD7== !OPPzz*d3Hjj,VWG# & 9 9'  <@
<<#"#2 LL"/'9%6%G%G	$ 
 	!/	
	%"3  	";;!%	
 ..:!
U=S - & c7#F#F#J#J3PT#U H_"D#w'J'J'N'NsTV'WXJ&5B;D#w'J'J'N'NsTV'WX# ( 11=!
U#*::C$  $/}c+;<  #   %'77&303(/C58fglfmmy  {K  zL  2M,&'" !" !$CC2E)93/ -@,OM,/BB&303(/C58fglfmmy  {K  zL  2M,&'" !"? N ^^
$)9)9)E, ,,!%!6!6!<"J '55T2J *,,@@GG "3";";"W?W"3";";"W?W H  G !+t<JOO$TOJ	 9$*3--d*KI&'!%/Ik"	)/8}}=NPT/UI+, Y?4'If,=,I ?@Q@b@b@h@h?ij  $,)/61B(C	*%09&0A	*%f-MM&!'mmK6'
 	
 	

 0 

"+
8=
 

  	 	#<<!"3#5		
 #.X..o >  "$**DQCH "
	"$  	1v   	1v 	jF	


$  +&&RYYA	

 (**+s  UAS9 Q2AS9 ,&Q8 Q5Q8 S9 &"R) BS9 (S9 .A$S9 S9 -S9 	S9 'CS9 +S2,C"S9 S5S9 'S7(A	S9 1U2S9 5Q8 8	R&R!S9 !R&&S9 )	S/2SS/S**S//S9 5S9 7S9 9	T?8T::T??Unon_default_valuesexisting_metadatac                 `   d|vr|j                         |d<   t        t        |d         }| j                  dd      }	 |j	                         D ]  \  }}|t
        v s|||<    	 ||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
    rz   Tr   zLlitellm.proxy.proxy_server.prepare_metadata_fields(): Exception occured - {}N)copyr
   dictrO   items)LiteLLM_ManagementEndpoint_MetadataFieldsr   r   r   r:   r   )r%   r   r   casted_metadatar   kvr   s           r*   prepare_metadata_fieldsr   !  s     ++):)?)?)A:&4!3J!?@OdFI

OO%DAq==%&" & &5z"  
&&ZaaA	
 	

s   A- A- -	B-6-B((B-c                    | j                  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 rw|j                  d	      }	|	rdt	        |	t
              rTt        |	      dkD  rFt        |	      }t        j                  t        j                        t        |      z   }
|
|d
<   |	|d	<   |j                  xs i }d|v rt        |d          t        | ||      }|S )NTrM   r   r|   r   r}   secondsexpiresry   budget_reset_atr   )r%   r   r   )rO   r   r   r   
isinstancer   lenr   r   nowr   utcr   rz   validate_model_max_budgetr   )r%   existing_key_rowr   r   r   r   r|   
duration_sr   ry   key_reset_at	_metadatas               r*   prepare_key_update_datar   >  sn    ooDo9IMM%!199 !1 "
 ''%))*5Hc2H8I,h?Jll8<<09Z3PPG,3y)..,001BCOS1O$q(,oFJ#<<5	*8UUL4@014C01 ))/RI //!"45G"HI0&8I r,   z/key/update)re   rf   requestc                   K   ddl m}m}m} 	 |j	                  dd      }|j                  d      }|t        d      |j                  |j                  dd	       d{   }	|	t        d
dd|j                   i      t        ||	      }
t        |
j                  dd      ||	j                         d{    |j                  |i |
d|i       d{   }t!        t#        |      ||       d{    t%        j&                  t)        j*                  ||	|||             |t-        d      d|i|d   S 7 7 7 j7 M# t        $ r}t/        j0                  dj3                  t5        |                   t7        |t              rYt9        t;        |ddt5        |       d      t<        j>                  t;        |dd      t;        |dt@        jB                              t7        |t8              r|t9        dt5        |      z   t<        j>                  t;        |dd      t@        jB                        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.

    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   )rn   proxy_logging_objro   Tr   r   NNot connected to DB!find_uniquetokenr   
query_typei  r{   zTeam not found, passed team_id=rB   r%   r   r   )r   rn   existing_key_tokenr   )r   r%   hashed_tokenro   r   )r%   r   r   r4   ri   z(Failed to update key got response = Noner%   zBlitellm.proxy.proxy_server.update_key_fn(): Exception occured - {}rD   zAuthentication Error()rQ   NonerC   rr   typerQ   codeAuthentication Error, )"r   rn   r   ro   rO   r   r   get_datar   r   r(   r   r   rW   r   update_datar   
hash_tokenr   r   r   async_key_updated_hookr   r   r   r:   r   r   ProxyExceptionr   ProxyErrorTypes
auth_errorr   HTTP_400_BAD_REQUEST)r   r%   r4   ri   rn   r   ro   r   r   r   r   r   r   s                r*   update_key_fnr   i  sr    x J
//4/P	mmE" 233!.!7!7((u "8 "
 
 ##B4<<.!QR 
 5(8
 ((,,[$?'/55
 	
 	
 '22@1@7C@ 3 
 
 '#C1/
 	
 	
 	#::!1!"3#5	
 GHHs/hv.//[
	

	
*  
&&PWWA	

 a' 8/DSVHA-NO$//a&1Qv/J/JK	  >*G,s1v5 ++!Wf-,,	
 	

st   IAE  E!AE ;E< E EE ;E	<AE IE E E 	E 	IC*H>>IIz/key/deletec           
        K   	 ddl m}m} |t        d      |j                  }t        j                  d|j                          |j                  |j                  t        j                  k(  rd}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|d           	 ||d   k(  sJ 	 t        j                  d|j,                  j.                          t1        j2                  t5        j6                  | |	|||             d|iS 7 87 # t        $ r t+        ddd| d|d    i      w xY w# t        $ r=}
t        j8                  dj;                  t=        |
                   t?        |
      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   )rn   ro   Nr   zuser_api_key_dict.user_role: tokensro   r.   )key_aliasesrn   ro   r.   zInvalid request typezFFailed to delete keys got None response from delete_verification_tokenkeysr   z/key/delete - deleted_keys=deleted_keysrA   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 =rB   z#/keys/delete - cache after delete: )r%   keys_being_deletedr4   ri   r   zBlitellm.proxy.proxy_server.delete_key_fn(): Exception occured - {}) r   rn   ro   r   r.   r   r   r6   r7   r8   r   delete_verification_tokenr   r   delete_key_aliasesr   r   r   internal_server_errorr   HTTP_500_INTERNAL_SERVER_ERRORr   in_memory_cache
cache_dictr   r   r   async_key_deleted_hookr   r:   r   r   )r%   r4   ri   rn   ro   r.   num_keys_to_be_deletedr   number_deleted_keys_keys_being_deletedr   s              r*   delete_key_fnr     s    FQ+P 233 $++""+,=,G,G+HI	
 ''3!++/?/K/KKG!"99=Vyy#5> 84!4
 &)^"99L=O ,,+#5	> 84!4 &))9)9%:"++L344& `$::::	  	"")*=n*M)NO	
	)-@-PPPP 	""12D2T2T2_2_1`a	
 	#::#6"3#5,	
 --m880  	   `  aw  `x  xH  I\  ]k  Il  Hm  n 	.  +&&PWWA	

 (**+sh   IBG? GAG? /G0A<G? -
G 7AG? IG? G? "G<<G? ?	I8I  IIz/v2/key/infoF)re   rf   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   rn   NDatabase not connected. Connect a database to your proxy - https://docs.litellm.ai/docs/simple_proxy#managing-auth---virtual-keysrr   z%Malformed request. No keys passed in.rB   r   find_allr   zNo keys foundr   info)r   rn   r   r   r   HTTP_422_UNPROCESSABLE_ENTITYr   r   HTTP_404_NOT_FOUNDrO   r   appendr   )r%   r4   rn   key_infofiltered_key_infor   r   s          r*   info_key_fn_v2r	  o  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)defaultrh   r   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ur4t        t        j                  dj!                  |j"                              	 |j%                         }|j)                  d       | |dS 7 # t        $ r |j'                         }Y 3w 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   r   r4   r   r  z;You are not allowed to access this key's info. Your role={}rB   r  )r   rn   r   api_keyr   r   litellm_verificationtokenr   r   r   not_found_errorr   r  _can_user_query_key_infor   r   r:   r6   rO   r   r   r   )r   r4   rn   
hashed_keyr  r   s         r*   info_key_fnr    si    : 9.+  T 
 .&..$'
?.S9J&))CCOOJ'+T2 P 
 
  3$44..	  %"3!
   "55T[[%// 	'**,H 	WH--C
:  	'}}H	'
  +'**+s`   D?AD# %D&A5D# D ,D# D?D# D D# D  D# #	D<,D77D<<D?rt   rl   rm   Tc                     | |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.{}rB   ))_is_model_access_group_for_wildcard_router   r   r   r:   r   r   r9   )rt   rl   rm   models       r*   r   r     s     ~+??$ @ 
  # & 9 9  "F  "M  "M->>DD"   r,   g        insert_datar   )userr   r|   aliasesconfigspendr   r   r   r~   ru   blockedry   r   
user_alias
user_emailr6   rv   rz   rw   rx   r   )r  r   update_key_valuesr   allowed_cache_controlspermissionsr   model_rpm_limitmodel_tpm_limit
guardrailsteamsorganization_idr   )r   r  send_invite_emailc%                 F
  K   ddl m}%m}&m}' |'t	        d      |||}ndt        j                  d       }|d }(n<t        |      })t        j                  t        j                        t        |)      z   }(|d }*n<t        |      })t        j                  t        j                        t        |)      z   }*|d }+n<t        |      })t        j                  t        j                        t        |)      z   }+t        j                  |      },t        j                  |      }-t        j                  |      }.||xs i }||d<   ||xs i }||d	<   | |xs i }| |d
<   t        j                  |      }/t        |       t        j                  |      }0|}|}|}|}	 i d|
d|d|d|d|d|"d|d|d|d|/d|d|d|d|d|+d|}1|!|!|1d<   i d|d|d|(d|d|,d |-d|d|d|d|d|d|/d|d|d|d|*d||.|0||d!}2t!        d"d#      d$u rnd%|d&d   |2d'<   t#        j$                  |2      }3t'        |3d   t(              rt        j*                  |3d         |3d<   t'        |3d    t(              rt        j*                  |3d          |3d <   t'        |3d   t(              rt        j*                  |3d         |3d<   t'        |3d(   t(              r1d)|3d(   v r|&d$urt-        d*      t        j*                  |3d(         |3d(<   t'        |3d+   t(              rt        j*                  |3d+         |3d+<   |3j/                  dd       )t'        |3d   t              r|3d   j1                         |3d<   |'|#|#d,k(  r|d-k(  ra|'j3                  |1d,.       d {   }4|4t	        d/      t5        |4j6                        dkD  rBt5        |2d         dk(  r1|4j6                  |2d<   n!|d0k(  r|'j9                  |1d,|1       d {   }4||%k(  s|#|#d,k(  r|1S t;        j<                  d2|2       |'j3                  |2d3.       d {   }5t?        |5dd       |2d4<   t?        |5d5d       |2d5<   ||2d:<   | d,k(  r|2jO                  |1       |2S 7 7 7 E# t        $ r}6t;        j@                  d6jC                  t)        |6                   t;        j<                  tE        jF                                t'        |6tH              r|6tI        tJ        jL                  d7d8i9      d }6~6ww xY ww);Nr   )litellm_proxy_budget_namerm   rn   z]Connect Proxy to database to generate keys - https://docs.litellm.ai/docs/proxy/virtual_keys sk-   r}   r   r&  r'  r(  ru   r"  r.   r!  r(   r*  r6   r  rt   rz   rv   rw   rx   ry   r   r$  r)  r   r   r   r  r  )r%  r   r   r   DISABLE_KEY_NAMEFTsk-...key_namer%  get_spend_routeszJget_spend_routes permission is only available for LiteLLM Enterprise usersr   r  r  )r%   r   zFailed to create userr   )r%   r   r#  zprisma_client: Creating Key= %sr   token_idr  zKlitellm.proxy.proxy_server.generate_key_helper_fn(): Exception occured - {}r{   zInternal Server Error.rB   r   )(r   r-  rm   rn   r   secretstoken_urlsafer   r   r   r   r   r   r   dumpsr   r!   r   deepcopyr   r   loadsr   rW   	isoformatr  r   rt   r   r   r   r   r{   r:   	traceback
format_excr   r   r   update)7r   r|   rt   r  r  r  r   r   r   r~   ru   r   ry   r   r   r.   r!  r(   r"  r6   rv   rz   rw   rx   r   r#  r   r$  r%  r   r&  r'  r(  r)  r*  r   r+  r-  rm   rn   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   s7                                                          r*   r   r     s    Z  k
 	
 }?E'//345E((;
,,x||,y/LL"(2EF
||HLL1Ij4QQ(/B
<<-	*0MM::g&L**V$Kzz+. ">r&5"#">r&5"#>r!+JJx(M./ JJ'78III3@

*
*
 w
 *	

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

 |
 k
 U
 .
 w
 w
 $%:
 
 
 
 2
  |!
" %&<#
$ , 5"+
2 )51T9%+E"#J<#8HZ 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
 33&:+?
 !  !&&'H(S(5(A(A% )B ) # $++>#NHZ /6#%;T0H+,$ &H[v	"Oi  #  
""Y``A	

 	""9#7#7#9:a'G==56
 	

so   FT! G?R R A&R R	R T!,R R$R *T!R 	R R 	TBTTT!r   ro   c                   K   ddl m}m} 	 |r| D cg c]  }t        |       } }|j                  j
                  j                  dd| ii       d{   }||k(  r|j                  |        d{   }nj|j                  | |	       d{   }|t        d
      |j                  dd      }|t        |       k7  r"t        dt        |      z         t        d      | D ]/  }|j%                  |       t'        |      }
|j%                  |
       1 ||fS c c}w 7 7 7 # t        $ r[}	t        j                  dj                  t        |	                   t        j                  t!        j"                                |	d}	~	ww xY ww)aj  
    Helper that deletes the list of tokens from the database

    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   )rk   rn   r  r   inr  N)r   )r   r.   z>Failed to delete tokens got response None when deleting tokensr   zOFailed to delete all tokens. Tried to delete tokens that don't belong to user: 'DB not connected. prisma_client is NonezNlitellm.proxy.proxy_server.delete_verification_token(): Exception occured - {})r   rk   rn   r   r   r  	find_manydelete_datar   rW   r   r   r   r   r:   r   r<  r=  delete_cacher   )r   ro   r.   rk   rn   r   r   deleted_tokens_num_deleted_tokensr   r   s              r*   r   r     s    ( S%BHI&3+#6&FI#&&@@JJ"T6N3 K     22'4'@'@'@'O!O (5'@'@!7 (A ( " ")#X  '5&8&8&K#&#f+5#ig,' 
 EFF '',!#''5	  ...W J "P"  &&\ccA	

 	""9#7#7#9:sj   	FD& D/D& D D& 3D"4D& D$AD& #8FD& "D& $D& &	F
/AFF

Fr   rn   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   rK  rL  r   )r   r  rN  r   r   )r   ro   rn   r.   r   r   r   s          r*   r   r   Q  s      !. 0 0 J J T TT;/0 !U !  $77#6Ccii#6F7**<g   8s,   .A-A$A-A&A-A+ A-&A-z/key/{key:path}/regeneratec                   K   	 ddl m}m}m}m}m} |dur&t        dt        j                  j                         |t        t        j                  ddi      d	| vr| }	n ||       }	|j                  j                  j                  d
|	i       d{   }
|
!t        t        j                   dd|  di      t#        j$                  d|
       dt'        j(                  d       } ||      }d|dd  }||d}i }|#t+        ||
      }t#        j$                  d|       |j-                  |       |j/                  |      }|j                  j                  j-                  d
|	i|       d{   }i }|t1        |      }||d<   |j3                  d
       | rt5         ||       ||       d{    |	rt5         ||       ||       d{    t7        di |S 7 R7 s7 27 # t8        $ r}t;        |      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_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   )r   rm   rn   r   ro   Tz4Regenerating Virtual Keys is an Enterprise feature, Nr{   rM  rB   skr   rL  Key z not found.zkey_in_db: %sr.  r/  r1  r2  )r   r3  r   znon_default_values: %sr)   r  r%   r   r   r   )r   r   rm   rn   r   ro   r   r   r   r9   r   r   r   r   r  r   r  r   r   r6  r7  r   r>  r   r   r   r   r   r   r   )r   r%   r4   ri   r   rm   rn   r   ro   hashed_api_key
_key_in_db	new_tokennew_token_hashnew_token_key_namer   r   updated_tokenupdated_token_dictr   s                      r*   regenerate_key_fnr_  a  s    zd+	
 	
 t#FGXGiGiGoGoFpq   "AA!JK 
 s? N'_N(++EEQQN+ R 
 

 "554uK!89 
 	""?J?'//345	#I.%in%56 $*

  !8J" !&&'?AST-.#222D+..HHOON+ P 
 

  $!%m!4$-5!w' *'_#5"3   *'_#5"3   # 
 
 	
y
@
  +'**+ss   HBG0 G'C G0 6G*7AG0 9G,:G0 G.G0 &H'G0 *G0 ,G0 .G0 0	H	9HH		Hz	/key/list   zPage number)rh   ge
   z	Page sized   )rh   ra  lezFilter keys by user IDzFilter keys by team IDzFilter keys by key aliaspagesizec                   K   	 dd l }ddlm} |j                  d       ||j	                  d       t        d      h d}	t        | j                  j                               |	z
  }
|
r^t        ddj                  |
       ddj                  |	       t        j                  dj                  |
      t        j                  	      i }|rt        |t               r||d
<   |rt        |t               r||d<   |rt        |t               r||d<   |j                  d|        |dz
  |z  }|j                  d| d|        |j"                  j$                  j'                  |||       d {   }|j                  dt)        |       d       |j"                  j$                  j+                  |       d {   }|j                  d|        | |z   }g }|D ]4  }|j-                         }|j/                  d      }|j1                  |       6 ||||d}|j                  d       |S 7 7 v# t
        $ r}t        |t2              rYt        t5        |ddt!        |       d      t        j6                  t5        |dd      t5        |dt        j8                        	      t        |t              r|t        dt!        |      z   t        j6                  t5        |dd      t        j8                  	      d }~ww xY ww) Nr   r   zEntering list_keys functionzDatabase not connected>   re  rf  r(   r.   r   zUnsupported parameter(s): z, z. Supported parameters: r   r.   r(   r   zFilter conditions: r`  zPagination: skip=z, take=)r  skiptakezFetched z keysrL  zTotal count of keys: r   )r   total_countcurrent_pagetotal_pageszSuccessfully prepared responserD   zerror(r   rQ   r   rC   r   )loggingr   rn   r   r{   r   setquery_paramsr   r   joinr   bad_request_errorr   r   r   r   r   r  rN  r   countr   rW   r  r   r   r   r   )r   r4   re  rf  r.   r(   r   rm  rn   supported_paramsunsupported_paramsr  rh  r   rj  rl  key_listr   key_dict_tokenr   r   s                         r*   	list_keysrx    s    Z
<34 MM23455 O !5!5!:!:!<=@PP 4TYY?Q5R4SSklplulu  wG  mH  lI  J$66ii 2300	  z'3/&E)z'3/&E)Is3!*E++E734 qD )$wtf=> #%%??II J 
 
 	T512 *,,FFLL M 
 
 	-k];< %,- CxxzH\\'*FOOF#  & &	
 	67E

6  
a' 8vc!fXQ-?@$::a&1Qv/T/TU	  >*G,s1v5 66!Wf-66	
 	

sP   K?E(H1 ,H--AH1 8H/9A3H1 ,K?-H1 /H1 1	K<:B=K77K<<K?z
/key/blockhttp_requestc                 0  K   ddl m}m}m}m}m}m}	 |2t        dj                  t        j                  j                              | j                  j                  d      r || j                        }
n| j                  }
t        j                  du r|j                   j"                  j%                  d|
i	       d{   }|9t'        d
| j                   dt(        j*                  dt,        j.                        t1        j2                   |t5        t7        t9        j:                               t=        j>                  t@        jB                        |xs |jD                  xs ||jF                  tH        jJ                  |
dd|jM                         	                   |j                   j"                  jO                  d|
iddi       d{   }tQ        |
||	d|       d{   }d|_)        tU        |
||	|       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_updater   rk   rn   r   ro   N{}r.  r  Tr   rL  rV  
 not foundr   r   r   	id
updated_at
changed_bychanged_by_api_keyr   	object_idactionupdated_valuesbefore_valuerequest_datarW  r   rn   ro   rs   r   r   user_api_key_objro   r   +r   r|  r   rk   rn   r   ro   r   r:   r   db_not_connected_errorr9   r   
startswithrU   store_audit_logsr   r  r   r   r   rq  r   r  r   r   LiteLLM_AuditLogsr   uuiduuid4r   r   r   r   r.   r  LitellmTableNamesKEY_TABLE_NAMEmodel_dump_jsonr>  r   r   r   r%   ry  r4   ri   r|  r   rk   rn   r   ro   r   record
key_objects                r*   	block_keyr  q  s    >  $5$L$L$R$RSTTxx5!!1xx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   B>H HDHHH(H)HHHHHHz/key/unblockc                 0  K   ddl m}m}m}m}m}m}	 |2t        dj                  t        j                  j                              | j                  j                  d      r || j                        }
n| j                  }
t        j                  du r|j                   j"                  j%                  d|
i	       d{   }|9t'        d
| j                   dt(        j*                  dt,        j.                        t1        j2                   |t5        t7        t9        j:                               t=        j>                  t@        jB                        |xs |jD                  xs ||jF                  tH        jJ                  |
dd|jM                         	                   |j                   j"                  jO                  d|
iddi       d{   }tQ        |
||	d|       d{   }d|_)        tU        |
||	|       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  Tr   rL  rV  r~  r   r   r   r  r  FrW  r  r  r  r  s                r*   unblock_keyr    s    >  $5$L$L$R$RSTTxx5!!1xx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r  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_callbacksrm  )r4   r   key_loggingr  r   	unhealthyr   zKey health check failed: rQ   r   r   r   )rz   KeyHealthResponsetest_key_loggingrW   r   r   r   r   r   r   r   r   )r   r4   key_metadatahealth_statuslogging_statusesr   s         r*   
key_healthr  G  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:r  c                     | j                   t        j                  j                  k(  s'| j                   t        j                  j                  k(  ry| j
                  |k(  ry|j                  | j                  k(  ryy)zB
    Helper to check if the user has access to the key's info
    TF)r6   r7   r8   r9   PROXY_ADMIN_VIEW_ONLYr  r.   r  s      r*   r  r    si     	##'7'C'C'I'II&&*:*P*P*V*VV		"	"c	)			.66	6r,   r  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_settingsproxy_configcallback_namez(callback_name is required in key_loggingzopenai/litellm-key-health-testr  zQHello, this is a test from litellm /key/health. No LLM API call was made for this)rF   contentztest response)r  messagesmock_response)r%   r4   r  r  r   r  zLogging test failed: )	callbacksr   details   z2Logger exceptions triggered, system is unhealthy: r  zWNo logger exceptions triggered, system is healthy. Manually check if logs were sent to  r   )rm  ior  $litellm.proxy.litellm_pre_call_utilsr  r   r  r  rW   r  r   StreamHandlersetLevelERROR	getLogger
addHandlerrU   acompletionr   LoggingCallbackStatusr   r   sleepgetvalueremoveHandler)r4   r   r  rm  r  r  r  r  r  callbacklog_capture_stringchloggerr%   r   log_contentss                   r*   r  r    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   NOTrL  zKey with alias 'zB' already exists. Unique key aliases across all keys are required.r   )r   r  
find_firstr   r   rq  r   r   )r   rn   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   rm   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   rm   r   r   r9   r   r   r   floatr"   r   )r   r   rm   _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r'   )l__doc__r   r   r   r6  r<  r  r   r   r   typingr   r   r   r	   r
   fastapir   r   r   r   r   r   r   rU   litellm._loggingr   litellm.cachingr   litellm.proxy._typeslitellm.proxy.auth.auth_checksr   r   r   r   $litellm.proxy.auth.user_api_key_authr   .litellm.proxy.hooks.key_management_event_hooksr   &litellm.proxy.management_helpers.utilsr   litellm.proxy.utilsr   r   r   r   litellm.routerr    litellm.secret_managers.mainr!   litellm.types.utilsr"   r#   r$   GenerateKeyRequestr+   LiteLLM_TeamTableCachedObjr   Memberr3   UserAPIKeyAuthboolr=   rJ   rR   rY   r]   r`   rd   routerpostr   r   	BaseModelr   r   UnionUpdateKeyRequestRegenerateKeyRequestr   r   
KeyRequestr   r	  rW   r  r   listr  intr   DictLiteLLM_VerificationTokenr   r   r_  rx  BlockKeyRequestr  r  r  r  r  Anyr  r  r   r   r   r,   r*   <module>r     s  	       2 2 7 7  U U U  1 % "  C R N  " 3 $) $*5=c]f"%"08"HPQT"	"J*sm*** &* 3	*Z
/7S	/B *% :%%&CD&%-?2
34
%
 
 
	
< 
 
	+,-&	    )00A(B(. t)H+
H+%H+ !H+ H+V
)-BF	:(
 "66
7(V )*'BS:T9U    )00A(B(. t)	H
H

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

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