o
    ưi/                     @   s   d Z ddlmZmZmZmZmZmZmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZ ddlmZmZ ddlmZmZ dd	lmZmZmZ erTdd
lmZ ddlmZ G dd deZdS )z
Security hook to prevent user B from seeing response from user A.

This hook uses the DBSpendUpdateWriter to batch-write response IDs to the database
instead of writing immediately on each request.
    )TYPE_CHECKINGAnyAsyncGeneratorOptionalTupleUnioncast)HTTPException)verbose_proxy_logger)CustomLogger)LitellmUserRoles)decrypt_value_helperencrypt_value_helper)BaseLiteLLMOpenAIResponseObjectResponsesAPIResponse)CallTypesLiteralLLMResponseTypesSpecialEnums)	DualCache)UserAPIKeyAuthc                   @   s  e Zd Zdd Zdddddeded	eeee	ef  f
d
dZ
dee	 dee	 ddd	efddZde	d	efddZde	d	ee	ee	 ee	 f fddZd	ee	 fddZ	d!dedddeee	e	f  d	efddZdeddded	efddZdddeded	eedf fdd ZdS )"ResponsesIDSecurityc                 C   s   d S N )selfr   r   `/home/app/Keep/.python/lib/python3.10/site-packages/litellm/proxy/hooks/responses_id_security.py__init__   s   zResponsesIDSecurity.__init__user_api_key_dictr   cacher   data	call_typereturnc                    s   h d}||vrd S |dkr0| d}|r.| |r.| |\}}}	| ||	| ||d< |S |dv rS| d}
|
rS| |
rS| |
\}}}	| ||	| ||d< |S )N>   
aresponsesadelete_responsesacancel_responsesaget_responsesr!   previous_response_id>   r"   r#   r$   response_id)get_is_encrypted_response_id_decrypt_response_id check_user_access_to_response_id)r   r   r   r   r   Zresponses_api_call_typesr%   original_response_iduser_idteam_idr&   r   r   r   async_pre_call_hook"   s8   



z'ResponsesIDSecurity.async_pre_call_hookresponse_id_user_idresponse_id_team_idc              	   C   s   ddl m} |jtjjks|jtjkrdS |r7||jkr7|ddr1t	d|j d| d dS t
d	d
d|r]||jkr]|ddrWt	d| d|j d|j d dS t
d	dddS )Nr   general_settingsTdisable_responses_id_securityFz(Responses ID Security is disabled. User z is accessing response id z# which is not associated with them.i  zForbidden. The response id is not associated with the user, who this key belongs to. To disable this security feature, set general_settings::disable_responses_id_security to True in the config.yaml file.)status_codedetailz<Responses ID Security is disabled. Response belongs to team z
 but user z is accessing it with team id .zForbidden. The response id is not associated with the team, who this key belongs to. To disable this security feature, set general_settings::disable_responses_id_security to True in the config.yaml file.)litellm.proxy.proxy_serverr2   Z	user_roler   ZPROXY_ADMINvaluer,   r'   r
   debugr	   r-   )r   r/   r0   r   r2   r   r   r   r*   M   s2   z4ResponsesIDSecurity.check_user_access_to_response_idr&   c                 C   sR   | d}t|dk rdS |d }t|ddd}|d u rdS |tjjr'dS dS )Nresp_   F   r&   Tr8   keyZreturn_original_valuesplitlenr   
startswithr   ZLITELM_MANAGED_FILE_ID_PREFIXr8   )r   r&   split_resultremaining_stringdecrypted_valuer   r   r   r(   s   s   
z-ResponsesIDSecurity._is_encrypted_response_idc                 C   s   | d}t|dk r|ddfS |d }t|ddd}|du r$|ddfS |tjjra| d}t|dkr\|d	 }| d
d }|d }| dd }	|d }
|
 dd }||	|fS |ddfS |ddfS )z
        Returns:
         - original_response_id: the original response id
         - user_id: the user id
         - team_id: the team id
        r:   r;   Nr<   r&   Tr=   ;r   zresponse_id:zuser_id:zteam_id:r?   )r   r&   rC   rD   rE   partsZresponse_id_partr+   Zuser_id_partr,   Zteam_id_partr-   r   r   r   r)      s*   
	





z(ResponsesIDSecurity._decrypt_response_idc                 C   s0   ddl }ddlm} |dd}|du r|}|S )z.Get the signing key for encryption/decryption.r   N)
master_keyZLITELLM_SALT_KEY)osr7   rI   getenv)r   rJ   rI   Zsalt_keyr   r   r   _get_signing_key   s   z$ResponsesIDSecurity._get_signing_keyNresponserequest_cachec           
      C   sZ  |   }|d u rtd |S t|dd }t|dd }|rbt|trb|drb|d ur9||v r9t|d||  |S tj	j
||jpBd|jpFd}t|d}d| }	|d urZ|	||< t|d|	 |S |rt|tr|d ur||j|v r|t|d||j  n)tj	j
|j|jpd|jpd}t|d}d| }	|d ur|	||j< t|d|	 t|d| |S )NzResponse ID encryption is enabled but no signing key is configured. Please set LITELLM_SALT_KEY environment variable or configure a master_key. Skipping response ID encryption. See: https://docs.litellm.ai/docs/proxy/prod#5-set-litellm-salt-keyidrM   r:    )r8   )rL   r
   r9   getattr
isinstancestrrB   setattrr   Z5LITELLM_MANAGED_RESPONSE_API_RESPONSE_ID_COMPLETE_STRr8   formatr,   r-   r   r   rO   )
r   rM   r   rN   Zsigning_keyr&   Zresponse_objZencrypted_response_idZencoded_user_id_and_response_idZencrypted_idr   r   r   _encrypt_response_id   s^   
"


z(ResponsesIDSecurity._encrypt_response_idc                    sB   ddl m} |ddr|S t|trtt| j||dd}|S )a  
        Queue response IDs for batch processing instead of writing directly to DB.

        This method adds response IDs to an in-memory queue, which are then
        batch-processed by the DBSpendUpdateWriter during regular database update cycles.
        r   r1   r3   FN)rN   )r7   r2   r'   rR   r   r   rV   )r   r   r   rM   r2   r   r   r   async_post_call_success_hook   s   
z0ResponsesIDSecurity.async_post_call_success_hookrequest_datac                 C  s^   ddl m} i }|2 z 3 d H W }t|tr(|jdkr(|dds(| |||}|V  q6 d S )Nr   r1   z/v1/responsesr3   F)r7   r2   rR   r   Zrequest_router'   rV   )r   r   rM   rX   r2   Zrequest_encryption_cachechunkr   r   r   'async_post_call_streaming_iterator_hook  s   
z;ResponsesIDSecurity.async_post_call_streaming_iterator_hookr   )__name__
__module____qualname__r   dictr   r   r   	ExceptionrS   r.   boolr*   r(   r   r)   rL   r   rV   r   r   rW   r   rZ   r   r   r   r   r      sr    
+
&
,
B

r   N)__doc__typingr   r   r   r   r   r   r   Zfastapir	   Zlitellm._loggingr
   Z"litellm.integrations.custom_loggerr   Zlitellm.proxy._typesr   Z0litellm.proxy.common_utils.encrypt_decrypt_utilsr   r   Zlitellm.types.llms.openair   r   Zlitellm.types.utilsr   r   r   Zlitellm.caching.cachingr   r   r   r   r   r   r   <module>   s    $