o
    ưi?                     @   s2  d dl 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mZmZmZmZmZmZmZmZmZmZ d dlmZ erLd dl
mZmZ d dlmZmZ ded	efd
dZdeded	efddZdeded	efddZdededed	efddZ			d=deded ded ded d	ef
ddZ deded	efdd Z!dedededdd	ef
d!d"Z"			d=d#ededed ded ded d	efd$d%Z#d&eeeeed'd(f d)ed*ed	dfd+d,Z$ddd-d.ed/ed0ee% d1ee ded2ee& d3ee& fd4d5Z'd6e(d)ed	dfd7d8Z)d*ed	efd9d:Z*d6e(d	dfd;d<Z+dS )>    )TYPE_CHECKINGAnyDictOptionalUnion)verbose_proxy_logger	DualCache)KeyRequestBase)LiteLLM_ManagementEndpoint_MetadataFields1LiteLLM_ManagementEndpoint_MetadataFields_PremiumLiteLLM_OrganizationTableLiteLLM_ProjectTableLiteLLM_TeamTableLiteLLM_UserTableLitellmUserRolesNewProjectRequestUpdateProjectRequestUserAPIKeyAuth)_premium_user_check)r   r   )PrismaClientProxyLogginguser_api_key_dictreturnc                 C   s   | j tjkp| j tjkS )N)	user_roler   PROXY_ADMINZPROXY_ADMIN_VIEW_ONLYr    r   f/home/app/Keep/.python/lib/python3.10/site-packages/litellm/proxy/management_endpoints/common_utils.py_user_has_admin_view   s   
r   team_objc                 C   s6   |j D ]}|jd ur|j| jkr|jdkr dS qdS )NZadminTF)members_with_rolesuser_idZrole)r   r    memberr   r   r   _is_user_team_admin    s   

r$   c                    s   |j r| js	dS ddlm} ddlm}m}m} || j||d|dI dH }|du r,dS |jp0g D ]}|j |j krC|j	t
jjkrC dS q1dS )z
    Check if user is an org admin for the team's organization.

    Returns True if:
    - The team belongs to an organization, AND
    - The user has org_admin role in that organization
    Fr   get_user_object)prisma_clientproxy_logging_objuser_api_key_cacher"   r'   r)   Zuser_id_upsertr(   NT)organization_idr"   litellm.proxy.auth.auth_checksr&   Zlitellm.proxy.proxy_serverr'   r(   r)   organization_membershipsr   r   	ORG_ADMINvalue)r   r    r&   r'   r(   r)   Zcaller_usermr   r   r   _is_user_org_admin_for_team,   s(   
r1   
permissionc                 C   sD   |j sdS ||j vrdS |jD ]}|jdur|j| jkr dS qdS )zECheck if a non-admin team member has a specific permission on a team.FNT)Zteam_member_permissionsr!   r"   )r   r    r2   r#   r   r   r   _team_member_has_permissionT   s   


r3   Nr'   r   r)   r	   r(   r   c              
      sT  | j tjkr	dS |du s| jdu rdS ddlm} ddlm} zj|| j||p)| d|dI dH }|du r8W dS |jdurN|jD ]}|j tj	j
krM W dS q@|jdurt|jdkr|jjjdd	|jiid
I dH }|D ]}	tdi |	 }
t| |
dr W dS qlW dS W dS W dS  ty } ztd| j d|  W Y d}~dS d}~ww )a  
    Check if user has admin privileges (proxy admin, team admin, or org admin).

    Args:
        user_api_key_dict: User API key authentication object
        prisma_client: Prisma client for database operations
        user_api_key_cache: Cache for user API keys
        proxy_logging_obj: Proxy logging object

    Returns:
        True if user is proxy admin, team admin for any team, or org admin for any organization
    TNFr   r   r%   r*   team_idinwherer   r    z)Error checking admin privileges for user : r   )r   r   r   r"   litellm.cachingr	   r,   r&   r-   r.   r/   teamslendblitellm_teamtable	find_manyr   
model_dumpr$   	Exceptionr   debug)r   r'   r)   r(   DualCacheImportr&   Zuser_objZ
membershipr;   teamr    er   r   r   _user_has_admin_privilegesg   s\   

rF   admin_user_objtarget_user_objc                 C   sP   | j du rdS dd | j D }|sdS |j du rdS dd |j D }t||@ S )a  
    Check if an org admin can invite the target user.
    Target user must be in at least one org where the admin has org admin role.

    Args:
        admin_user_obj: The admin user's full object (from get_user_object)
        target_user_obj: The target user's full object (from get_user_object)

    Returns:
        True if target user is in an org where admin has org admin role
    NFc                 S   s    h | ]}|j tjjkr|jqS r   )r   r   r.   r/   r+   .0r0   r   r   r   	<setcomp>   s
    z-_org_admin_can_invite_user.<locals>.<setcomp>c                 S   s   h | ]}|j qS r   )r+   rI   r   r   r   rK      s    )r-   bool)rG   rH   Zadmin_org_idsZtarget_org_idsr   r   r   _org_admin_can_invite_user   s   

rM   c                    s   |j rt|j dkrdS |j rt|j dkrdS |jjjdd|j iidI dH } fdd|D }|s6dS t|j }tt||@ S )	a  
    Check if a team admin can invite the target user.
    Target user must be in at least one team where the admin has team admin role.

    Args:
        user_api_key_dict: The admin user's API key auth object
        admin_user_obj: The admin user's full object (from get_user_object)
        target_user_obj: The target user's full object (from get_user_object)
        prisma_client: Prisma client for database operations

    Returns:
        True if target user is in a team where admin has team admin role
    r   Fr4   r5   r6   Nc              	      s,   g | ]}t  tdi | d r|jqS )r8   r   )r$   r   r@   r4   )rJ   rD   r   r   r   
<listcomp>   s    z/_team_admin_can_invite_user.<locals>.<listcomp>)r;   r<   r=   r>   r?   setrL   )r   rG   rH   r'   r;   Zadmin_team_idsZtarget_team_idsr   r   r   _team_admin_can_invite_user   s   

rP   target_user_idc              
      s
  |j tjkr	dS |du s|jdu rdS ddlm} ddlm} zE|p%| }||j||d|dI dH }|du r:W dS || ||d|dI dH }	|	du rMW dS t||	rUW dS t	|||	|dI dH rcW dS W dS  t
y }
 ztd	|j d
|
  W Y d}
~
dS d}
~
ww )a  
    Check if the admin can create an invitation for the target user.
    - Proxy admins: can invite any user
    - Org admins: can only invite users in their org(s)
    - Team admins: can only invite users in their team(s)

    Uses get_user_object for caching of both admin and target user objects.

    Args:
        target_user_id: The user_id of the user to invite
        user_api_key_dict: The admin user's API key auth object
        prisma_client: Prisma client for database operations
        user_api_key_cache: Cache for user API keys
        proxy_logging_obj: Proxy logging object

    Returns:
        True if user can invite the target user
    TNFr   r   r%   r*   )r   rG   rH   r'   z*Error checking invite permission for user r9   )r   r   r   r"   r:   r	   r,   r&   rM   rP   rA   r   rB   )rQ   r   r'   r)   r(   rC   r&   cacherG   rH   rE   r   r   r   admin_can_invite_user   sX   

rS   object_datar   r   
field_namer/   c                 C   s*   |t v rt| | jpi | _|| j|< dS )a	  
    Helper function to set metadata fields that require premium user checks

    Args:
        object_data: The team/key/organization/project data object to modify
        field_name: Name of the metadata field to set
        value: Value to set for the field
    N)r   r   metadata)rT   rU   r/   r   r   r   _set_object_metadata_fieldC  s   rW   )	tpm_limit	rpm_limitr4   r"   
max_budgetexisting_budget_idrX   rY   c          
         s   |du r#|du r#|du r#| j jd||didddiidI dH  dS |jp'd|jp+dd	}|dur6||d
< |dur>||d< |durF||d< | jj|ddidI dH }	| j jd||di||dd|	jiidddd|	jiiiddI dH  dS )a  
    Helper function to Create/Update or Delete the budget within the team membership
    Args:
        tx: The transaction object
        team_id: The ID of the team
        user_id: The ID of the user
        max_budget: The maximum budget for the team
        existing_budget_id: The ID of the existing budget, if any
        user_api_key_dict: User API Key dictionary containing user information
        tpm_limit: Tokens per minute limit for the team member
        rpm_limit: Requests per minute limit for the team member

    If max_budget, tpm_limit, and rpm_limit are all None, the user's budget is removed from the team membership.
    If any of these values exist, a budget is updated or created and linked to the team membership.
    NZuser_id_team_id)r"   r4   litellm_budget_tableZ
disconnectT)r7   data )Z
created_byZ
updated_byrZ   rX   rY   Zteam_membership)r]   includeconnect	budget_id)r"   r4   r\   )createupdate)Zlitellm_teammembershiprc   r"   Zlitellm_budgettablerb   Zupsertra   )
Ztxr4   r"   rZ   r[   r   rX   rY   Zcreate_dataZ
new_budgetr   r   r   _upsert_budget_and_membership^  sJ   


rd   
updated_kvc                 C   s   |t v r| |}|dur|g kr|i krt  || v rA| | durC| |}d| v r9| d dur9|| d |< dS ||i| d< dS dS dS )z
    Helper function to update metadata fields that require premium user checks in the update endpoint

    Args:
        updated_kv: The key-value dict being used for the update
        field_name: Name of the metadata field being updated
    NrV   )r   getr   pop)re   rU   r/   _valuer   r   r   _update_metadata_field  s   

ri   c                 C   sD   | du rdS t | trt| dkrdS t | tr |  dkr dS dS )zOCheck if a value has real content (not None, not empty list, not blank string).NFr   r^   T)
isinstancelistr<   strstrip)r/   r   r   r   _has_non_empty_value  s   rn   c                 C   sX   t D ]}|| v r| | durt| |d qtD ]}|| v r)| | dur)t| |d qdS )z
    Helper function to update all metadata fields (both premium and standard).

    Args:
        updated_kv: The key-value dict being used for the update
    N)re   rU   )r   ri   r   )re   fieldr   r   r   _update_metadata_fields  s   rp   )NNN),typingr   r   r   r   r   Zlitellm._loggingr   r:   r	   Zlitellm.proxy._typesr
   r   r   r   r   r   r   r   r   r   r   Zlitellm.proxy.utilsr   r   r   rL   r   r$   r1   rl   r3   rF   rM   rP   rS   rW   floatintrd   dictri   rn   rp   r   r   r   r   <module>   s    4

(

H
 
,
K	

#	
K