Ë
    tPêjé�  ã                   ób  — U d dl Z d dlmZ d dlmZ d dlmZmZmZ d dl	m
Z
 d dlmZmZmZmZmZmZ ddlmZ  ed	d
ddddddddddddddej*                  j,                  ej.                  j,                  ej0                  j,                  ej2                  j,                  ej4                  j,                  ej6                  j,                  ej8                  j,                  ej:                  j,                  ej<                  j,                  g«      Zee d<   dZ!ee d<    ed«      Z"ee d<    G d„ d«      Z#y) é    N)ÚSequence)ÚFinal)ÚHTTPExceptionÚRequestÚstatus)Úverbose_proxy_logger)ÚCommonProxyErrorsÚKeyManagementRoutesÚLiteLLM_UserTableÚLiteLLMRoutesÚLitellmUserRolesÚUserAPIKeyAuthé   )Ú_user_is_org_adminú	/user/newú/user/deleteú/user/bulk_updateú	/team/newú/team/updateú/team/deletez/team/blockz/team/unblockz/team/permissions_updatez/team/permissions_bulk_updateú
/model/newú/model/updateú/model/deletez/jwt/key/mapping/newz/jwt/key/mapping/updatez/jwt/key/mapping/deleteÚ%_PROXY_ADMIN_VIEW_ONLY_BLOCKED_ROUTES)ú/regeneratez/reset_spendÚ+_PROXY_ADMIN_VIEW_ONLY_BLOCKED_KEY_SUFFIXES)Úopenai_routesÚllm_api_routesÚ(_AUTH_ENFORCED_PASS_THROUGH_ROUTE_GROUPSc                   ó<  — e Zd Ze	 d)dedededz  fd„«       Ze	 d)dedededz  defd„«       Z	ededefd	„«       Z
ed
edz  deddfd„«       Zed
edz  dedz  dedededefd„«       Zedefd„«       Zededefd„«       Zedededz  defd„«       Zededefd„«       Zededefd„«       Zededefd„«       Zedededefd„«       Zededefd„«       Zedededefd„«       Zedededefd„«       Zededee   defd„«       Zededz  dedz  fd„«       Zed)dededz  defd„«       Zededefd „«       Zedededdfd!„«       Z eded"edefd#„«       Z!ededefd$„«       Z"ededefd%„«       Z# e$h d&£«      Z% e$g d'¢«      Z&e	 d)dededededz  ddf
d(„«       Z'y)*ÚRouteChecksNÚrouteÚvalid_tokenÚrequestc                 ó    — 	 ddl m} |j                  | ¬«       t
        j                  | ||¬«       y# t        $ r}|‚d}~wt        $ r Y Œ2w xY w)zK
        Check if management route is disabled and raise exception
        r   )ÚEnterpriseRouteChecks©r"   N)r"   r#   r$   T)Ú*litellm_enterprise.proxy.auth.route_checksr&   Úshould_call_router   Ú	Exceptionr!   Ú$is_virtual_key_allowed_to_call_route)r"   r#   r$   r&   Úes        úd/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/auth/route_checks.pyr)   zRouteChecks.should_call_routeC   sY   € ð	ÝXà!×3Ñ3¸%Ð3Ô@ô 	×8Ñ8¸uÐR]ÐgnÐ8ÔoØøô ò 	ØˆGûÜò 	Ùð	ús   ‚3 ³	A¼>¾AÁAÚreturnc                 ó¤  — |j                   €yt        |j                   t        «      syt        |j                   «      dk(  ryd}|j                   D ]  }t        j                  | |¬«      sŒ y t        d„ |j                   D «       «      �rZ|j                   D �]J  }|t        j                  v sŒt        j                  | t        j                  |   j                  ¬«      rQ|t        v rGt        j                  | t        j                  |¬«      ¬«      rt        j                  | |¬	«      r yd}n y|d
k(  sŒ ddlm} |j%                  | ¬«      rIt        j                  | t        j                  |¬«      ¬«      rt        j                  | |¬	«      r yd}n yt        j'                  | |¬«      r yt        j                  | t        j(                  j                  ¬«      s�ŒK y |j                   D ]  }t        j+                  | |¬«      sŒ y |rt        j-                  | ¬«      ‚t/        t0        j2                  d|j                   › d| › �¬«      ‚)zR
        Raises Exception if Virtual Key is not allowed to call the route
        Tr   F©r"   Úallowed_routec              3   ó@   K  — | ]  }|t         j                  v –— Œ y ­w©N)r   Ú_member_names_)Ú.0r1   s     r-   ú	<genexpr>zCRouteChecks.is_virtual_key_allowed_to_call_route.<locals>.<genexpr>s   s   è ø€ ÒmÀˆ}¤× <Ñ <Ô<Ñmùs   ‚©r"   Úallowed_routes©r$   ©r"   Úmethod©r"   Úuser_api_key_dictr   ©ÚInitPassThroughEndpointHelpersr'   )r"   r$   ©r"   ÚpatternzLVirtual key is not allowed to call this route. Only allowed to call routes: z. Tried to call route: ©Ústatus_codeÚdetail)r8   Ú
isinstanceÚlistÚlenr!   Ú_route_matches_allowed_routeÚanyr   r4   Úcheck_route_accessÚ_member_map_Úvaluer   Ú#is_auth_enforced_pass_through_routeÚ_get_request_methodÚcheck_passthrough_route_accessÚ;litellm.proxy.pass_through_endpoints.pass_through_endpointsr?   Ú is_registered_pass_through_routeÚ"_is_get_mcp_server_discovery_routeÚagent_management_routesÚroute_matches_wildcard_patternÚ#_auth_pass_through_denied_exceptionr   r   ÚHTTP_403_FORBIDDEN)r"   r#   r$   Ú'denied_auth_enforced_pass_through_router1   r?   s         r-   r+   z0RouteChecks.is_virtual_key_allowed_to_call_routeY   so  € ð ×%Ñ%Ð-ØÜ˜+×4Ñ4´dÔ;ØÜˆ{×)Ñ)Ó*¨aÒ/Øà27Ð/ð )×7Ñ7ò 	ˆMÜ×7Ñ7¸eÐS`Ð7ÕaÙð	ô
 ÑmÐR]×RlÑRlÔmÕmØ!,×!;Ñ!;ó @(�Ø ¤M×$@Ñ$@Ò@Ü"×5Ñ5Ø#Ü'4×'AÑ'AÀ-Ñ'P×'VÑ'Vð 6ô ð
 *Ô-UÑUÜ +× OÑ OØ&+Ü'2×'FÑ'FÈwÐ'FÓ'Wð !Pô !ô
  +×IÑIÐPUÐitÐIÔuÙ'+ØFJÑCá#'ð
 %Ð(8Ó8õð :×ZÑZÐafÐZÔgÜ*×NÑNØ&+Ü'2×'FÑ'FÈwÐ'FÓ'Wð  Oô  ô $/×#MÑ#MØ*/À;ð $Nô $"ñ ,0ØJNÑ Gá'+ô '×IÑIÐPUÐ_fÐIÔgÙ#'ô '×9Ñ9Ø"'Ü+8×+PÑ+P×+VÑ+Vð :ö ñ $(ðA@(ðF )×7Ñ7ò 	ˆMÜ×9Ñ9ÀÈ}Ð9Õ]Ùð	ñ 3Ü×AÑAÈÐAÓNÐNäÜ×1Ñ1ØaÐbm×b|Ñb|Ða}ð  ~Uð  V[ð  U\ð  ]ô
ð 	
ó    Úuser_idc                 óh   — ddl m} | rt        | «      dk  ry |ddd¬«      }|j                  | «      S )	zô
        Mask user_id to prevent leaking sensitive information in error messages

        Args:
            user_id (str): The user_id to mask

        Returns:
            str: Masked user_id showing only first 2 and last 2 characters
        r   )ÚSensitiveDataMaskeré   z***é   é   Ú*)Úvisible_prefixÚvisible_suffixÚ	mask_char)Ú0litellm.litellm_core_utils.sensitive_data_maskerr[   rG   Ú_mask_value)rY   r[   Úmaskers      r-   Ú_mask_user_idzRouteChecks._mask_user_idÃ   s;   € õ 	Yáœ#˜g›,¨!Ò+Øñ ,¸1ÈQÐZ]Ô^ˆà×!Ñ! 'Ó*Ð*rX   Úuser_objc                 ó    — d}d}| � | j                   xs d}| j                  xs d}t        j                  |«      }t	        d|› d|› d|› �«      ‚)a'  
        Raise exception for routes that require proxy admin access

        Args:
            user_obj (Optional[LiteLLM_UserTable]): The user object
            route (str): The route being accessed

        Raises:
            Exception: With user role and masked user_id information
        Úunknownz^Only proxy admin can be used to generate, delete, update info for new keys/users/teams. Route=z. Your role=z. Your user_id=)Ú	user_rolerY   r!   rf   r*   )rg   r"   rj   rY   Úmasked_user_ids        r-   Ú!_raise_admin_only_route_exceptionz-RouteChecks._raise_admin_only_route_exceptionØ   s†   € ð ˆ	ØˆØÐØ ×*Ñ*Ò7¨iˆIØ×&Ñ&Ò3¨)ˆGä +× 9Ñ 9¸'Ó BˆÜØlÐmrÐlsÐsð  AJð  @Kð  KZð  [ið  Zjð  kó
ð 	
rX   Ú
_user_roleÚrequest_datac                 óì  — t         j                  |¬«       t         j                  |t         j                  |¬«      ¬«      rt         j	                  ||¬«       yt         j                  |¬«      ryt         j                  |¬«      r¸|dk(  ry|dk(  r—|j                  }|j                  d«      }t        j                  d||j                  «       |rl||j                  k7  r\|t        j                  j                  k7  r>t        t         j"                  d	|› d
|j                  › �¬«      ‚|dk(  ry|dk(  ry|dk(  ryyyyy|t$        j&                  j                  v rt)        |dd«      �dt)        |dg «      v ry|t        j                  j                  k(  rt         j+                  ||||¬«       y|t        j,                  j                  k(  r/t         j/                  |t$        j0                  j                  ¬«      s·t3        || ¬«      r/t         j/                  |t$        j4                  j                  ¬«      s{|t        j6                  j                  k(  r/t         j/                  |t$        j8                  j                  ¬«      s/t         j/                  |t$        j:                  j                  ¬«      ry|j=                  d«      s|j=                  d«      ryt         j?                  ||¬«      ry|j@                  �dd}|j@                  D ]8  }	t         jC                  ||	¬«      rd} nt         jE                  ||	¬«      sŒ6d} n |st         jG                  | |¬«       yyt         jG                  | |¬«       y)zO
        Checks if Non Proxy Admin User is allowed to access the route
        r'   r9   r:   ©r"   r#   z	/key/infoz
/user/inforY   z%user_id: %s & valid_token.user_id: %sz4key not allowed to access this user's info. user_id=z, key's user_id=rB   z/v2/user/infoz/model/infoz
/team/infoÚpermissionsNÚget_spend_routes)r"   rm   rn   r$   r7   )rn   Úuser_objectz/v1/mcp/z
/mcp-rest/r<   Fr0   Tr@   )rg   r"   )$r!   Úcustom_admin_only_route_checkrM   rN   Ú!_require_auth_pass_through_accessÚis_llm_api_routeÚis_info_routeÚquery_paramsÚgetr   ÚdebugrY   r   ÚPROXY_ADMIN_VIEW_ONLYrL   r   r   rV   r   Úglobal_spend_tracking_routesÚgetattrÚ _check_proxy_admin_viewer_accessÚINTERNAL_USERrJ   Úinternal_user_routesr   Úorg_admin_allowed_routesÚINTERNAL_USER_VIEW_ONLYÚinternal_user_view_only_routesÚself_managed_routesÚ
startswithrO   r8   rH   rT   rl   )
rg   rm   r"   r$   r#   rn   rx   rY   Úroute_allowedr1   s
             r-   Ú$non_proxy_admin_allowed_routes_checkz0RouteChecks.non_proxy_admin_allowed_routes_checkò   sV  € ô 	×1Ñ1Øð 	2ô 	
ô ×:Ñ:ØÜ×2Ñ2¸7Ð2ÓCð ;ô 
ô ×9Ñ9ÀÐS^Ð9Õ_Ü×)Ñ)°Ð)Ô6ØÜ×&Ñ&¨UÐ&Ô3à˜Ò#àØ˜,Ò&à&-×&:Ñ&:�Ø!-×!1Ñ!1°)Ó!<�Ü$×*Ñ*Ð+RÐT[Ð]h×]pÑ]pÔqáØ ;×#6Ñ#6Ò6Ø"Ô&6×&LÑ&L×&RÑ&RÒRä'Ü$*×$=Ñ$=Ø!UÐV]ÐU^Ð^nÐoz÷  pCñ  pCð  oDð   Eôð ð ˜/Ò)àØ˜-Ò'àØ˜,Ò&Øð 'ð Sð 7ð ð" ”]×?Ñ?×EÑEÑEÜ˜ ]°DÓ9ÐEØ"¤g¨k¸=È"Ó&MÑMàØÔ+×AÑA×GÑGÒGÜ×8Ñ8ØØ%Ø)Øð	 9õ ð Ô*×8Ñ8×>Ñ>Ò>Ü×.Ñ.°UÌ=×KmÑKm×KsÑKsÐ.ÔtÜ!¨|ÈÕRÜ×.Ñ.°UÌ=×KqÑKq×KwÑKwÐ.ÔxØÔ-×EÑE×KÑKÒKÜ×.Ñ.ØÜ,×KÑK×QÑQð /ô ô ×-Ñ-°EÌ-×JkÑJk×JqÑJqÐ-ÔràØ×Ñ˜jÔ)¨U×-=Ñ-=¸lÔ-KØÜ×7Ñ7¸eÐWbÐ7ÔcØØ×'Ñ'Ð3à!ˆMØ!,×!;Ñ!;ò �Ü×;Ñ;À%ÐWdÐ;ÔeØ$(�MÙä×=Ñ=ÀEÐS`Ð=ÕaØ$(�MÙðñ !Ü×=Ñ=ÀxÐW\Ð=Õ]ð !ô ×9Ñ9À8ÐSXÐ9ÕYrX   c                 óÐ   — ddl m}m} d|v rZ|dur/t        j                  dt
        j                  j                  «       y | |d   v rt        t        j                  d| › d�¬«      ‚y y )	Nr   )Úgeneral_settingsÚpremium_userÚadmin_only_routesTzHTrying to use 'admin_only_routes' this is an Enterprise only feature. %sz-user not allowed to access this route. Route=z is an admin only routerB   )Úlitellm.proxy.proxy_serverr‰   rŠ   r   Úerrorr	   Únot_premium_userrL   r   r   rV   )r"   r‰   rŠ   s      r-   rt   z)RouteChecks.custom_admin_only_route_checkU  sw   € çMàÐ"2Ñ2Ø 4Ñ'Ü$×*Ñ*Ø^Ü%×6Ñ6×<Ñ<ôð ØÐ(Ð)<Ñ=Ñ=Ü#Ü &× 9Ñ 9ØJÈ5È'ÐQhÐiôð ð >ð 3rX   c                 ó<  — t        | t        «      sy| t        j                  j                  v ry| t        j
                  j                  v ry| t        j                  j                  v ryt        j                  | t        j                  j                  ¬«      ryt        j                  | t        j                  j                  ¬«      ry| t        j                  j                  v ryt        j                  j                  D ]O  }d|v rt        j                  | |¬«      r yt        j                  |¬«      sŒ7t        j                  | |¬«      sŒO y t        j                  j                  D ]   }d|v sŒt        j                  | |¬«      sŒ  y t        j
                  j                  D ]   }d|v sŒt        j                  | |¬«      sŒ  y t        j                  | ¬«      ryt        j                   j                  D ]  }| |k(  s| j#                  |dz   «      sŒ y y)	z¿
        Helper to checks if provided route is an OpenAI route


        Returns:
            - True: if route is an OpenAI route
            - False: if route is not an OpenAI route
        FTr7   ú{r@   ©rA   r'   ú/)rE   Ústrr   r   rL   Úanthropic_routesÚgoogle_routesr!   rJ   Úmcp_inference_routesÚagent_inference_routesÚlitellm_native_routesÚ_route_matches_patternÚ_is_wildcard_patternrT   Ú_is_azure_openai_routeÚmapped_pass_through_routesr…   )r"   Úopenai_routeÚgoogle_routeÚanthropic_routeÚ_llm_passthrough_routes        r-   rv   zRouteChecks.is_llm_api_routef  sã  € ô ˜%¤Ô%Øà”M×/Ñ/×5Ñ5Ñ5Øà”M×2Ñ2×8Ñ8Ñ8Øà”M×/Ñ/×5Ñ5Ñ5Øä×)Ñ)°Äm×FhÑFh×FnÑFnÐ)ÔoØä×)Ñ)°Äm×FjÑFj×FpÑFpÐ)ÔqØà”M×7Ñ7×=Ñ=Ñ=Øô *×7Ñ7×=Ñ=ò 		 ˆLð �lÑ"Ü×5Ñ5¸EÈ<Ð5ÔXÙä×/Ñ/¸Ð/ÕEÜ×=Ñ=ÀEÐS_Ð=Õ`Ùð		 ô *×7Ñ7×=Ñ=ò 	 ˆLØ�lÒ"Ü×5Ñ5¸EÈ<Ð5ÕXÙð	 ô  -×=Ñ=×CÑCò 	 ˆOØ�oÒ%Ü×5Ñ5¸EÈ?Ð5Õ[Ùð	 ô
 ×-Ñ-°EÐ-Ô:Øä&3×&NÑ&N×&TÑ&Tò 	Ð"ØÐ.Ò.°%×2BÑ2BÐCYÐ\_ÑC_Õ2`Ùð	ð rX   c                 ó´   — |�|j                   j                  «       dk7  ry| dk(  ryd}| j                  |«      sy| t        |«      d }t	        |«      xr d|vS )aÕ  
        Returns True if `request` is a GET against one of the two read-only
        MCP-server discovery paths:

        - GET `/v1/mcp/server`               (list)
        - GET `/v1/mcp/server/{server_id}`   (single server, single segment)

        Multi-segment paths (`/v1/mcp/server/{id}/approve`, etc.) and any
        non-GET method return False, so admin-only management writes on the
        same path prefix are not reachable through this carve-out.
        NÚGETFz/v1/mcp/serverTz/v1/mcp/server/r’   )r;   Úupperr…   rG   Úbool)r"   r$   ÚprefixÚ	remainders       r-   rR   z.RouteChecks._is_get_mcp_server_discovery_route§  sf   € ð ˆ?˜gŸn™n×2Ñ2Ó4¸Ò=ØØÐ$Ò$ØØ)ˆØ×Ñ Ô'ØØ ¤ V£ Ð/ˆ	Ü�I‹Ò7 3¨iÐ#7Ð7rX   c                 ó`   — t         j                  | t        j                  j                  ¬«      S )z6
        Check if route is a management route
        r7   )r!   rJ   r   Úmanagement_routesrL   r'   s    r-   Úis_management_routezRouteChecks.is_management_route¾  s&   € ô
 ×-Ñ-°EÌ-×JiÑJi×JoÑJoÐ-ÓpÐprX   c                 ó:   — | t         j                  j                  v S )z1
        Check if route is an info route
        )r   Úinfo_routesrL   r'   s    r-   rw   zRouteChecks.is_info_routeÅ  s   € ð
 œ×1Ñ1×7Ñ7Ð7Ð7rX   c                 óˆ   — t        | t        «      syd}d}t        j                  || «      st        j                  || «      ryy)z¤
        Check if route is a route from AzureOpenAI SDK client

        eg.
        route='/openai/deployments/vertex_ai/gemini-1.5-flash/chat/completions'
        Fz2^/openai/deployments/[^/]+/[^/]+/chat/completions$z!^/engines/[^/]+/chat/completions$T)rE   r“   ÚreÚmatch)r"   Údeployment_patternÚengine_patterns      r-   r›   z"RouteChecks._is_azure_openai_routeÌ  s>   € ô ˜%¤Ô%Øà$YÐØ Dˆä�8‰8Ð&¨Ô.´"·(±(¸>È5Ô2QØØrX   rA   c                 óÂ   — t        | t        «      sydt        j                  dt        fd„}t        j                  d||«      }d|› d�}t        j
                  || «      ryy)	aˆ  
        Check if route matches the pattern placed in proxy/_types.py

        Example:
        - pattern: "/threads/{thread_id}"
        - route: "/threads/thread_49EIN5QF32s4mH20M7GFKdlZ"
        - returns: True


        - pattern: "/key/{token_id}/regenerate"
        - route: "/key/regenerate/82akk800000000jjsk"
        - returns: False, pattern is "/key/{token_id}/regenerate"
        Fr®   r.   c                 óh   — | j                  d«      j                  d«      }|j                  d«      ryy)Nr   z{}z:pathz[^:]+z[^/]+)ÚgroupÚstripÚendswith)r®   Úplaceholders     r-   Ú_placeholder_to_regexzARouteChecks._route_matches_pattern.<locals>._placeholder_to_regexò  s.   € Ø!&§¡¨Q£×!5Ñ!5°dÓ!;ˆKØ×#Ñ# GÔ,àØrX   z	\{[^}]+\}ú^ú$T)rE   r“   r­   ÚMatchÚsubr®   )r"   rA   r·   s      r-   r™   z"RouteChecks._route_matches_patternß  s^   € ô  ˜%¤Ô%Øð	¬¯©ð 	´có 	ô —&‘&˜Ð'<¸gÓFˆà�g�Y˜a�.ˆÜ�8‰8�G˜UÔ#ØØrX   c                 ó$   — | j                  d«      S )z8
        Check if pattern is a wildcard pattern
        r_   )rµ   r‘   s    r-   rš   z RouteChecks._is_wildcard_pattern   s   € ð
 ×Ñ Ó$Ð$rX   c                 óZ   — |j                  d«      r|dd }| j                  |«      S | |k(  S )aY  
        Check if route matches the wildcard pattern

        eg.

        pattern: "/scim/v2/*"
        route: "/scim/v2/Users"
        - returns: True

        pattern: "/scim/v2/*"
        route: "/chat/completions"
        - returns: False


        pattern: "/scim/v2/*"
        route: "/scim/v2/Users/123"
        - returns: True

        r_   Néÿÿÿÿ)rµ   r…   )r"   rA   r¥   s      r-   rT   z*RouteChecks.route_matches_wildcard_pattern  s;   € ð* ×Ñ˜CÔ à# C R˜LˆFØ×#Ñ# FÓ+Ð+ð ˜GÑ#Ð#rX   r1   c                 ó:   — | |k(  ry| j                  |dz   «      ryy)a¦  
        Check if route matches the allowed_route pattern.
        Supports both exact match and prefix match.

        Examples:
        - allowed_route="/fake-openai-proxy-6", route="/fake-openai-proxy-6" -> True (exact match)
        - allowed_route="/fake-openai-proxy-6", route="/fake-openai-proxy-6/v1/chat/completions" -> True (prefix match)
        - allowed_route="/fake-openai-proxy-6", route="/fake-openai-proxy-600" -> False (not a valid prefix)

        Args:
            route: The actual route being accessed
            allowed_route: The allowed route pattern

        Returns:
            bool: True if route matches (exact or prefix), False otherwise
        Tr’   F)r…   r0   s     r-   rH   z(RouteChecks._route_matches_allowed_route$  s(   € ð& �MÒ!Øà×Ñ˜M¨CÑ/Ô0ØØrX   r8   c                 ód   ‡ — ‰ |v ryt        ˆ fd„|D «       «      ryt        ˆ fd„|D «       «      ryy)a!  
        Check if a route has access by checking both exact matches and patterns

        Args:
            route (str): The route to check
            allowed_routes (Sequence): Allowed routes/patterns

        Returns:
            bool: True if route is allowed, False otherwise
        Tc              3   óx   •K  — | ]1  }t         j                  |¬ «      rt         j                  ‰|¬«      –— Œ3 y­w)r‘   r@   N)r!   rš   rT   ©r5   r1   r"   s     €r-   r6   z1RouteChecks.check_route_access.<locals>.<genexpr>T  s:   øè ø€ ò 
àÜ×/Ñ/¸Ð/ÔFô ×6Ñ6¸UÈMÐ6×Zñ
ùs   ƒ7:c              3   óL   •K  — | ]  }t         j                  ‰|¬ «      –— Œ y­w)r@   N)r!   r™   rÂ   s     €r-   r6   z1RouteChecks.check_route_access.<locals>.<genexpr>a  s&   øè ø€ ò 
ØWdŒK×.Ñ.°UÀMÐ.×Rñ
ùs   ƒ!$F)rI   r7   s   ` r-   rJ   zRouteChecks.check_route_access>  sK   ø€ ð �NÑ"Øô ó 
à!/ô
ô 
ð
 ô ó 
Øhvô
ô 
ð àrX   c                 óŽ   — | €y 	 | j                   }t        |t        «      sy |j                  «       S # t        t        f$ r Y y w xY wr3   )r;   ÚAttributeErrorÚKeyErrorrE   r“   r£   )r$   r;   s     r-   rN   zRouteChecks._get_request_methodh  sL   € àˆ?Øð	Ø#ŸN™NˆFô ˜&¤#Ô&Øà�|‰|‹~Ðøô ¤Ð)ò 	Ùð	ús   …2 ²AÁAr;   c                 ó`   — ddl m} |j                  | |¬«      }|€y|j                  d«      du S )a2  
        True for config/DB pass-through endpoints registered with auth=true.

        These routes are injected into ``openai_routes`` for spend/budget hooks but
        must not inherit blanket ``openai_routes`` RBAC; access is gated by
        ``allowed_passthrough_routes`` on the key or team.
        r   r>   r:   FÚauthT)rP   r?   Ú!get_registered_pass_through_routery   )r"   r;   r?   Ú
route_infos       r-   rM   z/RouteChecks.is_auth_enforced_pass_through_routev  s=   € õ	
ð ;×\Ñ\ÐchÐqwÐ\Óxˆ
ØÐØØ�~‰~˜fÓ%¨Ð-Ð-rX   c                 ó@   — t        t        j                  d| › d�¬«      S )Nz1Key/team not allowed to access passthrough route z<. Configure `allowed_passthrough_routes` on the team or key.rB   )r   r   rV   r'   s    r-   rU   z/RouteChecks._auth_pass_through_denied_exceptionˆ  s,   € äÜ×1Ñ1àCÀEÀ7ð KMð Mô
ð 	
rX   c                 ó^   — t         j                  | |¬«      ryt         j                  | ¬«      ‚)zf
        Require an explicit ``allowed_passthrough_routes`` match for auth=true pass-through.
        r<   Nr'   )r!   rO   rU   rp   s     r-   ru   z-RouteChecks._require_auth_pass_through_access’  s/   € ô ×5Ñ5¸EÐU`Ð5ÔaØÜ×=Ñ=ÀEÐ=ÓJÐJrX   r=   c                 ó.  — |j                   }|j                  xs i }|€|€yd|vrd|vry|j                  d«      €|j                  d«      €y|j                  d«      xs |j                  d«      xs g }|D ]  }t        j	                  | |¬«      sŒ y y)zl
        Check if route is a passthrough route.
        Supports both exact match and prefix match.
        FÚallowed_passthrough_routesr0   T)ÚmetadataÚteam_metadatary   r!   rH   )r"   r=   rÏ   rÐ   rÎ   r1   s         r-   rO   z*RouteChecks.check_passthrough_route_accessž  s¾   € ð ,×4Ñ4ˆØ0×>Ñ>ÒDÀ"ˆØÐ Ð 5ØØ'¨xÑ7Ð<XÐ`mÑ<mØà�L‰LÐ5Ó6Ð>Ø×!Ñ!Ð">Ó?ÐGàð �L‰LÐ5Ó6Òo¸-×:KÑ:KÐLhÓ:iÒoÐmoð 	#ð
 8ò 	ˆMÜ×7Ñ7¸eÐS`Ð7ÕaÙð	ð rX   c                 ó2   — ddl m}  || «      }d|v sd|v ryy)zý
        Returns True if `thread` or `assistant` is in the request path

        Args:
            request (Request): The request object

        Returns:
            bool: True if `thread` or `assistant` is in the request path, False otherwise
        r   )Úget_request_routeÚthreadÚ	assistantTF)Ú
auth_utilsrÒ   )r$   rÒ   r"   s      r-   Ú_is_assistants_api_requestz&RouteChecks._is_assistants_api_request»  s&   € õ 	2á(¨Ó1ˆØ�uÑ ¨uÑ 4ØØrX   c                 ó   — d| v ryd| v ryy)z±
        Returns True if this is a google generateContent or streamGenerateContent route

        These routes from google allow passing key=api_key in the query params
        ÚgenerateContentTÚstreamGenerateContentF© r'   s    r-   Úis_generate_content_routez%RouteChecks.is_generate_content_routeÎ  s   € ð  Ñ%ØØ" eÑ+ØØrX   >   r¢   ÚHEADÚOPTIONS)r   r   r   r   r   r   r   r   r   z/key/generatez/key/deletez/key/updatez/key/regeneratez/key/service-account/generatez
/key/blockz/key/unblockz/team/key/bulk_updatec                 ó¸  — t         j                  | ¬«      rt        t        j                  d|› �¬«      ‚t         j                  | t        j                  j                  ¬«      r§| dk(  rS|� t        |t        «      r�|j                  «       }|D ]+  }|dvsŒt        t        j                  d|› d	| › d
|› d�¬«      ‚ nO| t        v s&| j                  d«      r6| j                  t        «      r!t        t        j                  d|› d	| › �¬«      ‚|�|j                   j#                  «       nd}|t         j$                  v }|ry| dk(  rC|�@t        |t        «      r0|D ]+  }|dvsŒt        t        j                  d|› d	| › d
|› d�¬«      ‚ y| t         j&                  v s"| j                  d«      r2| j                  d«      r!t        t        j                  d|› d	| › �¬«      ‚t         j                  | t        j(                  j                  ¬«      ryt         j                  | t        j*                  j                  ¬«      ryt        t        j                  d|› d	| › �¬«      ‚)uk  
        Check access for PROXY_ADMIN_VIEW_ONLY role.

        Admin Viewer follows a read-parity-with-Proxy-Admin rule: anything Proxy
        Admin can read/list/get, Admin Viewer can read/list/get. The only
        exclusions are cost-incurring inference routes (Playground, /chat/
        completions, etc.) and any state-mutating request.

        Implementation:
          1. LLM/inference routes â†’ 403 (cost-incurring).
          2. Safe HTTP method (GET/HEAD/OPTIONS) â†’ allow by default. This is
             the read-parity guarantee â€” every new GET endpoint added anywhere
             in the codebase is automatically readable by Admin Viewer
             without needing to remember to add it to an allowlist.
          3. Unsafe HTTP method (POST/PUT/PATCH/DELETE):
             - Allow `/user/update` only when restricted to user_email/password.
             - Block all explicit writes in `_ADMIN_VIEWER_BLOCKED_WRITE_ROUTES`.
             - Otherwise allow only if the route is in admin_viewer_routes /
               global_spend_tracking_routes (legacy explicit-allow set).
             - Else 403.
        r'   z5user not allowed to access this OpenAI routes, role= rB   r7   z/user/updateN)Ú
user_emailÚpasswordz-user not allowed to access this route, role= z. Trying to access: z and updating invalid param: z-. only user_email and password can be updatedz/key/r¢   r   )r!   rv   r   r   rV   rJ   r   r¨   rL   rE   ÚdictÚkeysr   r…   rµ   r   r;   r£   Ú_SAFE_HTTP_METHODSÚ"_ADMIN_VIEWER_BLOCKED_WRITE_ROUTESÚadmin_viewer_routesr|   )r"   rm   rn   r$   Ú_params_updatedÚparamr;   Úis_safe_methods           r-   r~   z,RouteChecks._check_proxy_admin_viewer_accessý  s˜  € ô8 ×'Ñ'¨eÐ'Ô4ÜÜ"×5Ñ5ØNÈzÈlÐ[ôð ô ×)Ñ)°Äm×FeÑFe×FkÑFkÐ)Ôlà˜Ò&àÐ+´
¸<ÌÔ0NØ-9×->Ñ->Ó-@�OØ!0ò ˜Ø Ð(BÒBÜ"/Ü,2×,EÑ,EØ)VÐWaÐVbÐbvÐw|Ðv}ð  ~[ð  \að  [bð  bOð  (Pô#ð ñð Ô?Ñ?Ø× Ñ  Ô)¨e¯n©nÔ=hÔ.iô $Ü &× 9Ñ 9ØJÈ:È,ÐVjÐkpÐjqÐrôð ð
 3:Ð2E˜Ÿ™×,Ñ,Ô.È5ˆØ &¬+×*HÑ*HÐ Hˆñ Øð �NÒ"ØÐ'¬J°|ÄTÔ,JØ)ò 	�EØÐ$>Ò>Ü+Ü(.×(AÑ(Aà"OÐPZÈ|ð \5Ø5:°GÐ;XÐY^ÐX_ð `Nð!Nôð ð	ð ð
 ”K×BÑBÑBØ×Ñ˜WÔ%¨%¯.©.¸Ô*GäÜ"×5Ñ5ØFÀzÀlÐRfÐglÐfmÐnôð ô ×)Ñ)°Äm×FgÑFg×FmÑFmÐ)ÔnØÜ×)Ñ)°Äm×FpÑFp×FvÑFvÐ)ÔwØô Ü×1Ñ1ØBÀ:À,ÐNbÐchÐbiÐjô
ð 	
rX   r3   )(Ú__name__Ú
__module__Ú__qualname__Ústaticmethodr“   r   r   r)   r¤   r+   rf   r   rl   r   rá   r‡   rt   rv   rR   r©   rw   r›   r™   rš   rT   rH   r   rJ   rN   rM   r   rU   ru   rO   rÖ   rÛ   Ú	frozensetrã   rä   r~   rÚ   rX   r-   r!   r!   B   sj  „ Øð #'ñØðà#ðð ˜4‘òó ðð* ð #'ñg
Øðg
à#ðg
ð ˜4‘ðg
ð 
ò	g
ó ðg
ðR ð+˜sð + sò +ó ð+ð( ð
Ø# dÑ*ð
àð
ð 
ò
ó ð
ð2 ð`ZØ# dÑ*ð`Zà$ tÑ+ð`Zð ð`Zð ð	`Zð
 $ð`Zð ò`Zó ð`ZðD ð¨Sò ó ðð  ð> ð >¨ò >ó ð>ð@ ð8°#ð 8ÀÈ$Áð 8ÐSWò 8ó ð8ð, ðq 3ð q¨4ò qó ðqð ð8˜Sð 8 Tò 8ó ð8ð ð cð ¨dò ó ðð$ ð cð °Cð ¸Dò ó ðð@ ð% cð %¨dò %ó ð%ð ð$¨cð $¸Cð $ÀDò $ó ð$ð8 ð¨Cð Àð Èò ó ðð2 ð' #ð '°xÀ±}ð 'Èò 'ó ð'ðR ð W¨t¡^ð ¸¸d¹
ò ó ðð ñ.°3ð .ÀÀdÁ
ð .ÐVZò .ó ð.ð" ð
°3ð 
¸=ò 
ó ð
ð ð	KØð	Kà#ð	Kð 
ò	Kó ð	Kð ð¨cð Ànð ÐY]ò ó ðð8 ð¨Gð ¸ò ó ðð$ ð
¨ð 
°ò 
ó ð
ñ  #Ò#=Ó>Ðñ *3ò	
ó*Ð&ð, ð
 #'ñ	k
Øðk
àðk
ð ðk
ð ˜4‘ð	k
ð
 
òk
ó ñk
rX   r!   )$r­   Úcollections.abcr   Útypingr   Úfastapir   r   r   Úlitellm._loggingr   Úlitellm.proxy._typesr	   r
   r   r   r   r   Úauth_checks_organizationr   rí   ÚKEY_GENERATErL   Ú
KEY_UPDATEÚ
KEY_DELETEÚKEY_REGENERATEÚKEY_GENERATE_SERVICE_ACCOUNTÚ	KEY_BLOCKÚKEY_UNBLOCKÚKEY_BULK_UPDATEÚTEAM_KEY_BULK_UPDATEr   Ú__annotations__r   r   r!   rÚ   rX   r-   ú<module>rþ      s$  ðÜ 	Ý $Ý ç 2Ñ 2å 1÷÷ õ 9ñ 09ð 	ØØàØØØØØ"Ø'àØØàØ!Ø!à×(Ñ(×.Ñ.Ø×&Ñ&×,Ñ,Ø×&Ñ&×,Ñ,Ø×*Ñ*×0Ñ0Ø×8Ñ8×>Ñ>Ø×%Ñ%×+Ñ+Ø×'Ñ'×-Ñ-Ø×+Ñ+×1Ñ1Ø×0Ñ0×6Ñ6ð=ó!0Ð % uó !ðL 6UÐ +¨UÓ Tá2;Ð<_Ó2`Ð (¨%Ó `÷g
ò g
rX   