
    ^hUu                        S r SSKrSSKrSSKJrJrJrJrJrJ	r	  SSK
Jr  SSKrSSKJr  SSKJr  SSKJr  SSKJrJrJrJrJrJrJrJrJrJr  SS	KJr  SS
K J!r!J"r"J#r#  SSK$J%r%  SSK&J'r'  SSK(J)r)  \(       a	  SSK*J+r,  \,r+O\r+\" SS9r-Sr.\R^                  R`                  \Rb                  R`                  -   r2S\3S\	\   S\	\   S\	\   S\	\4   S\3S\5S\	\%   S\64S jr7S\5S\8S\64S jr9S \\Rt                  \Rv                  \Rx                  4   S\5S!\S\64S" jr=S#\S$\	\5   S\64S% jr>S\8S\84S& jr?\#  SQS'\	\5   S(\	\!   S)\S*\	\+   S+\	\"   S\	\   4S, jj5       r@S-\5S.\	\\5      S\	\%   S\64S/ jrAS0\5S1\S2\BS\64S3 jrCS0\5S4\	\   S1\4S5 jrD\#  SQS6\5S(\	\!   S)\S7\6S*\	\+   S+\	\"   S\	\   4S8 jj5       rES0\5S4\S)\S+\	\"   4S9 jrFS:\5S;\S)\S+\	\"   4S< jrGS=\5S>\S)\S+\	\"   4S? jrHS=\5S)\S+\	\"   4S@ jrI\#S:\5S(\!4SA j5       rJS:\5S(\!4SB jrKS:\5S(\!S)\S1\S2\BS+\	\"   S0\5S\4SC jrLS0\5S+\	\"   S)\S*\	\+   S\	\   4
SD jrM    SRS:\5S(\	\!   S)\S*\	\+   S+\	\"   SE\	\6   SF\	\6   S\4SG jjrN\#   SSS=\5S(\	\!   S)\S*\	\+   S+\	\"   SE\	\6   S\4SH jj5       rOSI\PS\4SJ jrQ\#  SQSK\5S(\	\!   S)\S*\	\+   S+\	\"   4
SL jj5       rRS-\5SM\	\8   SN\S\	\RJ                     S\SO   4
SP jrSg)Tz
Got Valid Token from Cache, DB
Run checks for: 

1. If user can call model
2. If user is in budget 
3. If end_user ('user' passed to /chat/completions, /embeddings endpoint) is in budget 
    N)TYPE_CHECKINGAnyDictListLiteralOptional)	BaseModel)verbose_proxy_logger)	DualCache)LimitedSizeOrderedDict)
DB_CONNECTION_ERROR_TYPESLiteLLM_EndUserTableLiteLLM_JWTAuthLiteLLM_OrganizationTableLiteLLM_TeamTableLiteLLM_TeamTableCachedObjLiteLLM_UserTableLiteLLMRoutesLitellmUserRolesUserAPIKeyAuth)RouteChecks)PrismaClientProxyLogginglog_db_metrics)Router)ServiceTypes   )$organization_role_based_access_check)Spand   )max_size   request_bodyteam_objectuser_objectend_user_objectglobal_proxy_spendgeneral_settingsroute
llm_routerreturnc           
         U R                  SS5      nUb(  UR                  SL a  [        SUR                   S35      eUb  Ub  UR                  b  [        UR                  5      S:  a  XR                  ;  a  SUR                  ;   d   SUR                  ;   d  S	UR                  ;   a  ON[        XR                  US
9SL a  O6U(       a  SU;   a  O([        SUR                   SU SUR                   35      eUb  UR                  bx  UR                  bk  UR                  UR                  :  aQ  [        R                  " UR                  UR                  SUR                   SUR                   SUR                   3S9eUb  UR                  ch  Ube  UR                  bX  UR                  n	XR                  :  a=  [        R                  " UR                  U	SUR                   SUR                   SU	 3S9eUbs  UR                  bf  UR                  R                  n
U
bM  UR                  U
:  a=  [        R                  " UR                  U
SUR                   SUR                   SU
 3S9eUR                  SS5      b8  US   SL a0  [        R                  " US9(       a  SU ;  a  [        SUS    35      e[        R                  S:  a_  Ub\  [        R                  " US9(       aC  US:w  a=  US:w  a7  U[        R                  :  a#  [        R                  " U[        R                  S9eU R                  S0 5      =(       d    0 nUR                  S5      (       a"  SSKJn  U" U5      nUSL a  SSKJn  U" SSS 0S!9e['        X&U S"9  g)#a  
Common checks across jwt + key-based auth.

1. If team is blocked
2. If team can call model
3. If team is in budget
4. If user passed in (JWT or key.user_id) - is in budget
5. If end_user (either via JWT or 'user' passed to /chat/completions, /embeddings endpoint) is in budget
6. [OPTIONAL] If 'enforce_end_user' enabled - did developer pass in 'user' param for openai endpoints
7. [OPTIONAL] If 'litellm.max_budget' is set (>0), is proxy under budget
8. [OPTIONAL] If guardrails modified - is request allowed to change this
9. Check if request body is safe
10. [OPTIONAL] Organization checks - is user_object.organization_id is set, run these checks
modelNTzTeam=z6 is blocked. Update via `/team/unblock` if your admin.r   zall-proxy-models*zopenai/*)r-   team_modelsr*   z not allowed to call model=z. Allowed team models = z over budget. Spend=z	, Budget=)current_cost
max_budgetmessagezExceededBudget: User=zExceededBudget: End User=enforce_user_param)r)   userz1'user' param not passed in. 'enforce_user_param'=z
/v1/modelsz/modelsr0   r1   metadata
guardrails)can_modify_guardrailsF)HTTPExceptioni  errorz8Your team does not have permission to modify guardrails.)status_codedetail)r%   r)   r#   )getblocked	Exceptionteam_idmodelslenmodel_in_access_groupr1   spendlitellmBudgetExceededErroruser_idlitellm_budget_tabler   is_llm_api_route*litellm.proxy.guardrails.guardrail_helpersr8   fastapir9   r   )r#   r$   r%   r&   r'   r(   r)   r*   _modeluser_budgetend_user_budget_request_metadatar8   
can_modifyr9   s                  X/home/james-whalen/.local/lib/python3.13/site-packages/litellm/proxy/auth/auth_checks.pycommon_checksrR   7   s   0 gt,F;#6#6$#>K''((^_
 	

 	#*""#a',,, +"4"44k((([///  "*<*< 
 v++,,GxOghshzhzg{| 
 	"".) 6 66))$**"--K//00D[EVEVDWW`alawaw`xy
 	
 
	 3 3 ;#"".!,,***--(..&/0C0C/DDXYdYjYjXkkt  vA  uB  C  "'K'K'W)>>II&?+@+@?+R--,22*3O4K4K3LL`apavav`w  xA  BQ  AR  S  	148D12d:''e4|9SCDTUiDjCkl 
 	Q* ((u5\!Y 2 22--/G<N<N  +..z2>D"\**T0=
-W  )<     
user_routeallowed_routesc                 ~    U H7  nU[         R                  ;   a  U [         U   R                  ;   a    gX :X  d  M7    g   g)z
Return if a user is allowed to access route. Helper function for `allowed_routes_check`.

Parameters:
- user_route: str - the route the user is trying to call
- allowed_routes: List[str|LiteLLMRoutes] - the list of allowed routes for the user.
TF)r   __members__value)rT   rU   allowed_routes      rQ   _allowed_routes_checkrZ      s@     (]666mM:@@@( ( rS   	user_rolelitellm_proxy_rolesc                     U [         R                  :X  a  [        UUR                  S9nU$ U [         R                  :X  a?  UR
                  c   [        USS/S9nU$ UR
                  b  [        UUR
                  S9nU$ g)z=
Check if user -> not admin - allowed to access these routes
)rT   rU   openai_routesinfo_routesF)r   PROXY_ADMINrZ   admin_allowed_routesTEAMteam_allowed_routes)r[   rT   r\   
is_alloweds       rQ   allowed_routes_checkre      s     $000*!.CC

 	&++	+22: /%6VJ  44@.%2FFJ rS   user_api_key_dictrequested_user_idc                     SnU R                   [        R                  :w  a   U R                   [        R                  :w  a  SnUb  U R                  b  U R                  U:X  a  SnU$ )NTF)r[   r   r`   PROXY_ADMIN_VIEW_ONLYrG   )rf   rg   ret_vals      rQ    allowed_route_check_inside_routerk      sc     G##'7'C'CC''+;+Q+QQ$):)B)B)N$$(99GNrS   c                     / nU  H  n [         U   R                  nX-   nM     U$ ! [         a    UR                  U5         M?  f = fN)r   rX   KeyErrorappend)rU   actual_routes
route_nameroute_values       rQ   get_actual_routesrs     sU    M$
	-'
399K)7M %   	-  ,	-s   &AAend_user_idprisma_clientuser_api_key_cacheparent_otel_spanproxy_logging_objc                   #    Uc  [        S5      eU c  gSR                  U 5      nS[        4S jnUR                  US9I Sh  vN nUbG  [	        U[
        5      (       a  [        S0 UD6nU" US9  U$ [	        U[        5      (       a
  UnU" US9  U$  UR                  R                  R                  SU 0S	S
0S9I Sh  vN n	U	c  [         eUR                  SR                  U 5      U	S9I Sh  vN   [        S0 U	R                  5       D6n
U" U
S9  U
$  N NW N)! [          a+  n[	        U[        R                  5      (       a  Ue SnAgSnAff = f7f)aZ  
Returns end user object, if in db.

Do a isolated check for end user in table vs. doing a combined key + team + user + end-user check, as key might come in frequently for different end-users. Larger call will slowdown query time. This way we get to cache the constant (key/team/user info) and only update based on the changing value (end-user).
NNo db connectedzend_user_id:{}end_user_objc                     U R                   c  g U R                   R                  nUb0  U R                  U:  a  [        R                  " U R                  US9eg g )Nr5   )rH   r1   rD   rE   rF   )r{   rN   s     rQ   check_in_budget,get_end_user_object.<locals>.check_in_budget.  s\    ,,4&;;FF&<+=+=+O--)//O  ,P&rS   key)r{   rG   rH   Twhereincluder   rX    )r?   formatr   async_get_cache
isinstancedictdblitellm_endusertablefind_uniqueasync_set_cacherE   rF   )rt   ru   rv   rw   rx   _keyr}   cached_user_obj
return_objresponse	_responsees               rQ   get_end_user_objectr     s}     )**"";/D&:  />>4>HHO"ot,,-@@J4)=>>(J4&))>>JJk*+T2 K 
 

 O !00 ''4H 1 
 	
 	
 );8==?;	Y/; I
	
  a4455Gsa   AEDAE+D >D?/D .D/$D ED D 
E$!E
E
EEr-   r/   c                    SSK Jn  Uc  gX;   a  gU" [        5      nU(       a  UR                  U S9n[	        U5      S:  a  [        U5       H  u  pVXd;   d  M    g   U Vs/ s H  ofU;  d  M
  UPM     nnX;   a  ggs  snf )Nr   defaultdictT
model_nameF)collectionsr   listget_model_access_groupsrB   	enumerate)r-   r/   r*   r   access_groupsidxmfiltered_modelss           rQ   rC   rC   \  s     (*5d*;M"::e:L
=A
FC !	
 #.H+Q-1Gq+OH Is   !	A=.A=r   last_db_access_timedb_cache_expiryc                 t    [         R                   " 5       nX;  a  gX   S   b  gX   S   c  X1U    -
  U:  a  gg)zE
Prevent calling db repeatedly for items that don't exist in the db.
Tr   Ftime)r   r   r   current_times       rQ   _should_check_dbr   z  sM     99;L
% #/		!!	$	,c22oErS   rX   c                 6    U[         R                   " 5       4X '   g rm   r   r   rX   r   s      rQ   _update_last_db_access_timer     s     !&tyy{3rS   rG   user_id_upsertc                   #    U c  gUR                  U S9I Sh  vN nUb7  [        U[        5      (       a  [        S0 UD6$ [        U[        5      (       a  U$ Uc  [	        S5      e SR                  U 5      n[        U[        [        S9nU(       a1  UR                  R                  R                  SU 0SS0S	9I Sh  vN n	OSn	U	c>  U(       a1  UR                  R                  R                  SU 0SS0S
9I Sh  vN n	O[        eU	R                  bN  [        U	R                  5      S:  a5  U	R                   V
s/ s H  n
U
c  M  U
R                  5       PM     nn
Xl        [        S0 [        U	5      D6nUR                  5       nUR!                  XS9I Sh  vN   [#        UU[        S9  U$  GN N Ns  sn
f  N!! [         a  n[%        SU  SU 35      eSnAff = f7f)z
- Check if user id in proxy User Table
- if valid, return LiteLLM_UserTable object with defined limits
- if not, then raise an error
Nr   rz   z
user_id:{}r   r   r   rG   organization_membershipsTr   )datar   r   r   r   z$User doesn't exist in db. 'user_id'=z0. Create user via `/user/new` call. Got error - r   )r   r   r   r   r?   r   r   r   r   r   litellm_usertabler   creater   rB   
model_dumpr   r   
ValueError)rG   ru   rv   r   rw   rx   r   db_access_time_keyshould_check_dbr   
membership_dumped_membershipsr   response_dictr   s                  rQ   get_user_objectr     s"      />>7>KKO"ot,,$777):;;"")**5
)009*" 3+
 *--??KK '*5OQU4V L  H H!.!1!1!C!C!J!J#W-7> "K " 
   --9H556:
 #+"C"C#"CJ (
%%'"C   #
 1D-%7X7	!,,. !00W0RRR 	$" 3	
 u L$# 	S  
27);klmkno
 	

s}   GF-AG'AF; =F0><F; :F2;?F; :F4F4>F; F9F; ,G0F; 2F; 4F; ;
GGGGc                 >   #    UR                  XS9I S h  vN   g  N7f)Nr   )r   r   rX   rv   rx   s       rQ   _cache_management_objectr     s      
,
,
,
BBBs   r@   
team_tablec                    #    SR                  U 5      n[        R                  " 5       Ul        [        UUUUS9I S h  vN   g  N7f)N
team_id:{}r   )r   r   last_refreshed_atr   )r@   r   rv   rx   r   s        rQ   _cache_team_objectr     sE      

g
&C $(99;J 
"-+	  s   ;AAAhashed_tokenuser_api_key_objc                 p   #    U n[         R                   " 5       Ul        [        UUUUS9I S h  vN   g  N7f)Nr   )r   r   r   )r   r   rv   rx   r   s        rQ   _cache_key_objectr     s;      C *.&
"-+	  s   ,646c                    #    U nUR                  US9  Ub,  UR                  R                  R                  US9I S h  vN   g g  N7f)Nr   )delete_cacheinternal_usage_cache
dual_cacheasync_delete_cache)r   rv   rx   r   s       rQ   _delete_cache_key_objectr     s\     
 C###, $44??RR S 
 	
 	
 %	
s   ;AAAc                 h   #    UR                   R                  R                  SU 0S9I S h  vN $  N7fNr@   r   r   litellm_teamtabler   r@   ru   s     rQ   _get_team_db_checkr   '  s<     !!33??'" @       )202c                 h   #    UR                   R                  R                  SU 0S9I S h  vN $  N7fr   r   r   s     rQ   _get_team_object_from_dbr   .  s<     !!33??'" @    r   c                    #    Un[        UUUS9nU(       a  [        XS9I S h  vN n	OS n	U	c  [        e[        S0 U	R	                  5       D6n
[        U U
UUS9I S h  vN   [        UU
US9  U
$  NJ N7f)Nr   r   )r@   r   rv   rx   r   r   )r   r   r?   r   r   r   r   )r@   ru   rv   r   r   rx   r   r   r   r   r   s              rQ   (_get_team_object_from_user_api_key_cacher   4  s      &/'O
 +
 
 *=X]]_=I
-+	    / 5
s!   !A2A.8A2A0A20A2c                 R  #    S nUbF  UR                   R                  (       a+  UR                   R                  R                  XS9I S h  vN nUc  UR                  U S9I S h  vN nUb7  [        U[        5      (       a  [        S0 UD6$ [        U[
        5      (       a  U$ g  NY NA7f)N)r   rw   r   r   )r   r   r   r   r   r   )r   rx   rv   rw   cached_team_objs        rQ   _get_team_object_from_cacher   a  s      =AO 	%22== $88CCSS T   	  2 B Bs B KK"ot,,-@@@)CDD"" Ls%   AB'	B#
B'#B%$A B'%B'check_cache_onlycheck_db_onlyc           
      6  #    Uc  [        S5      eSR                  U 5      nU(       d/  [        UUUUS9I Sh  vN nUb  U$ U(       a  [        SU  S35      e [        U UUU[        [
        US9I Sh  vN $  N? N! [          a    [        SU  S	35      ef = f7f)

- Check if team id in proxy Team Table
- if valid, return LiteLLM_TeamTable object with defined limits
- if not, then raise an error
NFNo DB Connected. See - https://docs.litellm.ai/docs/proxy/virtual_keysr   )r   rx   rv   rw   z:Team doesn't exist in cache + check_cache_only=True. Team=.)r@   ru   rv   rx   r   r   r   zTeam doesn't exist in db. Team=z#. Create team via `/team/new` call.)r?   r   r   r   r   r   )	r@   ru   rv   rw   rx   r   r   r   r   s	            rQ   get_team_objectr     s      T
 	

 

g
&C ;/1-	!
 
 &""LWIUVW 

='1/ 3+
 
 	
#
"
  
-gY6YZ
 	

s9   6BA8BA< 3A:4A< 7B:A< <BBc                 T  #    Uc  [        S5      eU nUR                  US9I Sh  vN nUb7  [        U[        5      (       a  [	        S0 UD6$ [        U[        5      (       a  U$ U(       a  [        SU S35      e UR                  U SUUS9I Sh  vN nUc  [         e[	        S0 UR                  SS	9D6n	[        U U	UUS
9I Sh  vN   U	$  N N= N
! [         a  n
[        U
S9I Sh  vN  s Sn
A
$ Sn
A
f[          a%    [        R                  " 5         [        SU  S35      ef = f7f)r   Nr   r   z8Key doesn't exist in cache + check_cache_only=True. key=r   combined_view)token
table_namerw   rx   T)exclude_none)r   r   rv   rx   )r   zKey doesn't exist in db. key=z&. Create key via `/key/generate` call.r   )r?   r   r   r   r   get_datar   r   r   /_handle_failed_db_connection_for_get_key_object	traceback	print_exc)r   ru   rv   rw   rx   r   r   cached_key_obj_valid_tokenr   r   s              rQ   get_key_objectr     sq     T
 	

 C5G5W5W 6X 6 0N !nd++!3N3377!!Fse1M
 	


2?2H2H&-/	 3I 3
 -
 O"P\%<%<$%<%OP	  %&1/	
 	
 	
 K0"-
	
 % JDqIIII 
+L>9_`
 	

sp   #D(CAD(;C C4C CC D(C C 
D%C3(C+)C3-D%.D(32D%%D(r   c                    #    SSK JnJnJn  UR	                  SS5      SL a5  UR
                  R                  [        R                  SU SS9  [        S	S	US
9$ U e7f)a   
Handles httpx.ConnectError when reading a Virtual Key from LiteLLM DB

Use this if you don't want failed DB queries to block LLM API reqiests

Returns:
    - UserAPIKeyAuth: If general_settings.allow_requests_on_db_unavailable is True

Raises:
    - Orignal Exception in all other cases
r   )r(   litellm_proxy_admin_namerx    allow_requests_on_db_unavailableFTr   g        )service	call_typer:   durationzfailed-to-connect-to-db)key_namer   rG   )
litellm.proxy.proxy_serverr(   r   rx   r=   service_logging_objservice_failure_hookr   DBr   )r   r(   r   rx   s       rQ   r   r     sp       >F$N--BB OO&	 	C 	
 .+,
 	
 s   AAorg_idc                 t  #    Uc  [        S5      eUR                  SR                  U 5      S9nUb.  [        U[        5      (       a  U$ [        U[
        5      (       a  U$  UR                  R                  R                  SU 0S9I Sh  vN nUc  [         eU$  N! [          a    [        SU  S35      ef = f7f)	zx
- Check if org id in proxy Org Table
- if valid, return LiteLLM_OrganizationTable object
- if not, then raise an error
Nr   z	org_id:{}r   organization_idr   z/Organization doesn't exist in db. Organization=z3. Create organization via `/organization/new` call.)	r?   r   r   r   r   r   r   litellm_organizationtabler   )r   ru   rv   rw   rx   cached_org_objr   s          rQ   get_org_objectr   %  s      T
 	

 (77K<N<Nv<V7WN!nd++!!(ABB!!
&))CCOO$f- P 
 
 O
  
=fXExy
 	

s0   AB8!(B 	B
B B8B B55B8llm_model_listvalid_tokenTc                   #    U [         R                  ;   a  [         R                  U    n [        R                  " SU 35        SSKJn  U" [        5      nU(       a  UR                  U S9n[        U5      S:  a(  Ub%  [        UR                  5       H  u  pgXu;   d  M    g   UR                   Vs/ s H  owU;  d  M
  UPM     nn[        R                  " SU  SU 35        Sn	[        U5      S:X  a  [        UR                  5      S:X  d  S	U;   a  Sn	U b%  X;  a   U	SL a  [        S
UR                   SU  35      eXl
        [        R                  " SU SUR                   35        gs  snf 7f)z
Checks if token can call a given model

Returns:
    - True: if token allowed to call model

Raises:
    - Exception: If token not allowed to call model
z'LLM Model List pre access group check: r   r   r   Tzmodel: z; allowed_models: Fr.   zGAPI Key not allowed to access model. This token can only access models=z. Tried to access zfiltered allowed_models: z; valid_token.models: )rE   model_alias_mapr
   debugr   r   r   r   rB   r   rA   r   )
r-   r   r  r*   r   r   r   r   r   all_model_accesss
             rQ   can_key_call_modelr  N  s     '''''. 
1.1AB (*5d*;M"::e:LMQ:#9
FC !	
 #."4"4O"4Q8Nq"4OO/A/ARST" 	O!c+*<*<&=&B		U9>NRW>WUVaVhVhUii{  }B  |C  D
 	
 )
#O#44J;K]K]J^_ ' Ps   BE-E-0	E(=E(B*E-)NN)NNNN)NNN)T__doc__r   r   typingr   r   r   r   r   r   pydanticr	   rE   litellm._loggingr
   litellm.caching.cachingr   litellm.caching.dual_cacher   litellm.proxy._typesr   r   r   r   r   r   r   r   r   r   litellm.proxy.auth.route_checksr   litellm.proxy.utilsr   r   r   litellm.routerr   litellm.types.servicesr   auth_checks_organizationr   opentelemetry.tracer   _Spanr   r   r^   rX   management_routes
all_routesr   floatstrboolrR   r   rZ   r`   rb   INTERNAL_USERre   rk   rs   r   rC   intr   r   r   r   r   r   r   r   r   r   r   r   r   r?   r   r   r  r   rS   rQ   <module>r     s:     D D   1 - =   8 J J ! / J1DD -c: ((..1P1P1V1VV
LL+,L +,L 23	L
 !L L L  L 
L^c 4 D &#$$&&	(# # )# 
#L%} 
 d t  
 (,04>#>L)> "> tn	>
  -> "#> >B%d3i0>Fv>N	<	#9LO	(4	4c]49O4  (,04P
P
L)P
 "P
 	P

 tnP
  -P
  P
 P
fC	CC "C  -	C* "  -	&$ "  -	&

!
  -
  c ,  C  *** "* 0	*
 *  -* 
*  *Z	- " tn	
 ()H (,04'+$(4
4
L)4
 "4
 tn	4

  -4
 tn4
 D>4
  4
n 
 (,04'+A
A
L)A
 "A
 tn	A

  -A
 tnA
 A
 A
H%%%P 
 (,04%
%
L)%
 "%
 tn	%

  -%
 %
P88TN8  8 (	8
 T]8rS   