o
    ưib                     @   sr   d dl Z d dlmZ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 ddlmZ G dd	 d	ZdS )
    N)ListOptional)HTTPExceptionRequeststatus)verbose_proxy_logger)CommonProxyErrorsLiteLLM_UserTableLiteLLMRoutesLitellmUserRolesUserAPIKeyAuth   )_user_is_org_adminc                   @   s  e Zd ZededefddZedededefddZededefd	d
Z	ede
e deddfddZede
e de
e dedededefddZedefddZededefddZededefddZededefddZededefddZedededefdd Zededefd!d"Zedededefd#d$Zeded%edefd&d'Zeded(ee defd)d*Zeded+edefd,d-Zededefd.d/Zededefd0d1Zededededdfd2d3ZdS )4RouteChecksroutevalid_tokenc              
   C   s\   zddl m} |j| d W n ty } z|d}~w ty$   Y nw tj| |d dS )zK
        Check if management route is disabled and raise exception
        r   )EnterpriseRouteChecksr   N)r   r   T)Z*litellm_enterprise.proxy.auth.route_checksr   should_call_router   	Exceptionr   $is_virtual_key_allowed_to_call_route)r   r   r   e r   V/home/app/Keep/.python/lib/python3.10/site-packages/litellm/proxy/auth/route_checks.pyr      s   zRouteChecks.should_call_routereturnc                 C   s   |j du rdS t|j tsdS t|j dkrdS |j D ]}tj| |dr' dS qtdd |j D r^|j D ](}|tjv r]tj	| tj
| jdrJ dS |dkr]dd	lm} |j| d
r] dS q5|j D ]}tj| |drm dS qattjd|j  d|  d)zR
        Raises Exception if Virtual Key is not allowed to call the route
        NTr   r   allowed_routec                 s   s    | ]}|t jv V  qd S )N)r
   _member_names_.0r   r   r   r   	<genexpr>?   s
    
zCRouteChecks.is_virtual_key_allowed_to_call_route.<locals>.<genexpr>r   allowed_routesZllm_api_routes)InitPassThroughEndpointHelpersr   r   patternzLVirtual key is not allowed to call this route. Only allowed to call routes: z. Tried to call route: status_codedetail)r"   
isinstancelistlenr   _route_matches_allowed_routeanyr
   r   check_route_access_member_map_valueZ;litellm.proxy.pass_through_endpoints.pass_through_endpointsr#   Z is_registered_pass_through_route_route_matches_wildcard_patternr   r   HTTP_403_FORBIDDEN)r   r   r   r#   r   r   r   r   '   sN   
	




z0RouteChecks.is_virtual_key_allowed_to_call_routeuser_idc                 C   s8   ddl m} | rt| dkrdS |dddd}|| 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***      *)Zvisible_prefixZvisible_suffixZ	mask_char)Z0litellm.litellm_core_utils.sensitive_data_maskerr4   r+   Z_mask_value)r3   r4   Zmaskerr   r   r   _mask_user_idd   s
   
zRouteChecks._mask_user_iduser_objNc                 C   sH   d}d}| dur| j pd}| jpd}t|}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
        unknownNz^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_roler3   r   r9   r   )r:   r   r<   r3   Zmasked_user_idr   r   r   !_raise_admin_only_route_exceptiony   s   


z-RouteChecks._raise_admin_only_route_exception
_user_rolerequestrequest_datac           
      C   s  t j|d t j|drdS t j|drX|dkrdS |dkrI|j}|d}td| d|j  |rE||jkrGt	t
jd||jddS dS |d	krOdS |d
krV	 dS dS |tjjv rpt|dddurpdt|dg v rpdS |tjjkrt j|||d dS |tjjkrt j|tjjdrdS t|| drt j|tjjdrdS |tjjkrt j|tjjdrdS t j|tjjdrdS |ds|drdS t j||drdS |jdurd}|jD ]}	t j||	drd} nt j ||	drd} nq|st j!| |d dS dS t j!| |d dS )zO
        Checks if Non Proxy Admin User is allowed to access the route
        r   z	/key/infoz
/user/infor3   z	user_id: z & valid_token.user_id: zHkey not allowed to access this user's info. user_id={}, key's user_id={}r&   z/model/infoz
/team/infoZpermissionsNZget_spend_routes)r   r>   r@   r!   )r@   Zuser_objectz/v1/mcp/z
/mcp-rest/)r   user_api_key_dictFr   Tr$   )r:   r   )"r   custom_admin_only_route_checkis_llm_api_routeis_info_routequery_paramsgetr   debugr3   r   r   r2   formatr
   global_spend_tracking_routesr0   getattrr   ZPROXY_ADMIN_VIEW_ONLY _check_proxy_admin_viewer_accessZINTERNAL_USERr.   Zinternal_user_routesr   Zorg_admin_allowed_routesZINTERNAL_USER_VIEW_ONLYZinternal_user_view_only_routesZself_managed_routes
startswithcheck_passthrough_route_accessr"   r,   r1   r=   )
r:   r>   r   r?   r   r@   rE   r3   Zroute_allowedr   r   r   r   $non_proxy_admin_allowed_routes_check   s   




z0RouteChecks.non_proxy_admin_allowed_routes_checkc                 C   s^   ddl m}m} d|v r-|durtdtjj  d S | |d v r-tt	j
d|  ddd S )	Nr   )general_settingspremium_userZadmin_only_routesTzFTrying to use 'admin_only_routes' this is an Enterprise only feature. z-user not allowed to access this route. Route=z is an admin only router&   )Zlitellm.proxy.proxy_serverrO   rP   r   errorr   Znot_premium_userr0   r   r   r2   )r   rO   rP   r   r   r   rB     s   
z)RouteChecks.custom_admin_only_route_checkc                 C   sH  t | tsdS | tjjv rdS | tjjv rdS | tjjv rdS tj| tj	jdr*dS tj| tj
jdr5dS | tjjv r=dS tjjD ] }d|v rQtj| |drQ dS tj|dratj| |dra dS qAtjjD ]}d|v rvtj| |drv dS qftjjD ]}d|v rtj| |dr dS q{tj| drdS tjjD ]	}|| v r dS qdS )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
        FTr!   {r$   r%   r   )r)   strr
   Zopenai_routesr0   Zanthropic_routesZgoogle_routesr   r.   Z
mcp_routesZagent_routesZlitellm_native_routes_route_matches_pattern_is_wildcard_patternr1   _is_azure_openai_routeZmapped_pass_through_routes)r   Zopenai_routeZgoogle_routeZanthropic_routeZ_llm_passthrough_router   r   r   rC     sf   
zRouteChecks.is_llm_api_routec                 C      | t jjv S )z6
        Check if route is a management route
        )r
   management_routesr0   r   r   r   r   is_management_routea     zRouteChecks.is_management_routec                 C   rX   )z1
        Check if route is an info route
        )r
   Zinfo_routesr0   r   r   r   r   rD   h  r[   zRouteChecks.is_info_routec                 C   s6   t | tsdS d}d}t|| st|| rdS dS )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)r)   rT   rematch)r   Zdeployment_patternZengine_patternr   r   r   rW   o  s   
	z"RouteChecks._is_azure_openai_router%   c                 C   sP   t | tsdS dtjdtfdd}td||}d| d}t|| r&d	S dS )
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                 S   s"   |  dd}|drdS dS )Nr   z{}z:pathz[^:]+z[^/]+)groupstripendswith)r]   placeholderr   r   r   _placeholder_to_regex  s   
zARouteChecks._route_matches_pattern.<locals>._placeholder_to_regexz	\{[^}]+\}^$T)r)   rT   r\   Matchsubr]   )r   r%   rb   r   r   r   rU     s   
z"RouteChecks._route_matches_patternc                 C   s
   |  dS )z8
        Check if pattern is a wildcard pattern
        r8   )r`   rS   r   r   r   rV     s   
z RouteChecks._is_wildcard_patternc                 C   s(   | dr|dd }| |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

        r8   N)r`   rL   )r   r%   prefixr   r   r   r1     s   

z+RouteChecks._route_matches_wildcard_patternr   c                 C   s"   | |krdS |  |d rdS dS )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
        T/F)rL   r   r   r   r   r,     s
   z(RouteChecks._route_matches_allowed_router"   c                    sV    |v rdS dd |D }|D ]}t j |dr dS qt fdd|D r)dS dS )a%  
        Check if a route has access by checking both exact matches and patterns

        Args:
            route (str): The route to check
            allowed_routes (list): List of allowed routes/patterns

        Returns:
            bool: True if route is allowed, False otherwise
        Tc                 S   s   g | ]
}t j|d r|qS )rS   )r   rV   )r   r   r   r   r   
<listcomp>  s    
z2RouteChecks.check_route_access.<locals>.<listcomp>r$   c                 3   s    | ]
}t j |d V  qdS )r$   N)r   rU   r   r   r   r   r      s
    
z1RouteChecks.check_route_access.<locals>.<genexpr>F)r   r1   r-   )r   r"   Zwildcard_allowed_routesr   r   r   r   r.     s    zRouteChecks.check_route_accessrA   c                 C   s   |j }|jpi }|du r|du rdS d|vrd|vrdS |ddu r,|ddu r,dS |dp7|dp7g }|D ]}tj| |drF dS q:dS )zl
        Check if route is a passthrough route.
        Supports both exact match and prefix match.
        NFallowed_passthrough_routesr   T)metadatateam_metadatarF   r   r,   )r   rA   rl   rm   rk   r   r   r   r   rM     s,   

z*RouteChecks.check_passthrough_route_accessc                 C   s    d| j jv sd| j jv rdS dS )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
        threadZ	assistantTF)urlpath)r?   r   r   r   _is_assistants_api_request6  s   z&RouteChecks._is_assistants_api_requestc                 C   s   d| v rdS d| v rdS dS )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
        ZgenerateContentTZstreamGenerateContentFr   r   r   r   r   is_generate_content_routeE  s
   z%RouteChecks.is_generate_content_routec              
   C   s  t j| drttjd| dt j| tjjdrc| dkrF|durDt	|t
rD| }|D ]}|dvrCttjd| d	|  d
| ddq,dS | dv sT| dra| drattjd| d	|  ddS t j| tjjdrndS t j| tjjdrydS ttjd| d	|  d)z=
        Check access for PROXY_ADMIN_VIEW_ONLY role
        r   z5user not allowed to access this OpenAI routes, role= r&   r!   z/user/updateN)Z
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 updated)z	/user/newz/user/deletez	/team/newz/team/updatez/team/deletez
/model/newz/model/updatez/model/deletez/key/generatez/key/deletez/key/updatez/key/regeneratez/key/service-account/generatez
/key/blockz/key/unblockz/key/z/regenerate)r   rC   r   r   r2   r.   r
   rY   r0   r)   dictkeysrL   r`   Zadmin_viewer_routesrI   )r   r>   r@   Z_params_updatedparamr   r   r   rK   R  sV   	!z,RouteChecks._check_proxy_admin_viewer_access) __name__
__module____qualname__staticmethodrT   r   r   boolr   r9   r   r	   r=   r   r   rt   rN   rB   rC   rZ   rD   rW   rU   rV   r1   r,   r   r.   rM   rq   rr   rK   r   r   r   r   r      s    <oL .%r   )r\   typingr   r   Zfastapir   r   r   Zlitellm._loggingr   Zlitellm.proxy._typesr   r	   r
   r   r   Zauth_checks_organizationr   r   r   r   r   r   <module>   s    