
    ht                     v   d Z ddlZddlmZmZmZ ddlmZmZm	Z	m
Z
mZ ddlmZ ddl ddlmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZmZ ddlmZ  e       Zej=                  ddg ee      ge       ee      fde de!fd       Z"de dee   dee#   fdZ$ejK                  ddg ee      ge&       ee      fde'de!fd       Z(de)de*de)fdZ+ejY                  ddg ee      gee&          ee      fde-de!fd       Z.ej_                  ddg ee      gee&          ee      fde!fd       Z0ej_                  ddg ee      ge&      d e#fd!       Z1ej=                  ddg ee      g"      de2fd#       Z3ej=                  d$dg ee      ge4      e ee      fde5d%e
de!de4fd&              Z6d'e#dede7fd(Z8ejK                  d)dg ee      ge9      e ee      fde:de!fd*              Z;ejY                  d+dg ee      g"       ee      fde<de!fd,       Z=d-e>d e#dedee7e9f   fd.Z?y)/z
Endpoints for /organization operations

/organization/new
/organization/update
/organization/delete
/organization/member_add
/organization/info
/organization/list
    N)ListOptionalTuple)	APIRouterDependsHTTPExceptionRequeststatus)verbose_proxy_logger)*)can_user_call_model)user_api_key_auth)
new_budgetupdate_budget)&handle_update_object_permission_common)get_new_internal_user_defaultsmanagement_endpoint_wrapper)PrismaClientz/organization/newzorganization management)tagsdependenciesresponse_modeldatauser_api_key_dictc                   K   ddl m}m}m} |'t	        ddt
        j                  j                  i      |j                  |j                  t        j                  k7  rt	        ddd|j                   i      |'t	        ddt
        j                  j                  i      d}|j                  T	 |j                  j                  j                  d	|j                  i
       d{   }t!        di |j#                         }| j&                  	 t(        j*                  j-                         }| j/                  d      }|j1                         D 	
ci c]  \  }	}
|	|v s|	|
 }}	}
t)        di |}|j3                  |j/                  d            }|j                  j4                  j7                  i ||j                  xs ||j                  xs |d       d{   }|j&                  | _        t9        | |       d{   }	 t;        |j<                        dk(  rnNt;        | j<                        dk(  rt	        dddi      | j<                  D ]  }t?        |||       d{     tA        di | j/                  d      ||j                  xs ||j                  xs |d}|j3                  |j/                  d            }tC        jD                  dt.        jG                  |d              |j                  jH                  j7                  i |       d{   }|S 7 K# t$        $ r Y <w xY wc c}
}	w 7 i7 F7 7 'w)a
  
    Allow orgs to own teams

    Set org level budgets + model access.

    Only admins can create orgs.

    # Parameters

    - organization_alias: *str* - The name of the organization.
    - models: *List* - The models the organization has access to.
    - budget_id: *Optional[str]* - The id for a budget (tpm/rpm/max budget) for the organization.
    ### IF NO BUDGET ID - CREATE ONE WITH THESE PARAMS ###
    - max_budget: *Optional[float]* - Max budget for org
    - tpm_limit: *Optional[int]* - Max tpm limit for org
    - rpm_limit: *Optional[int]* - Max rpm limit for org
    - max_parallel_requests: *Optional[int]* - [Not Implemented Yet] Max parallel requests for org
    - soft_budget: *Optional[float]* - [Not Implemented Yet] Get a slack alert when this soft budget is reached. Don't block requests.
    - model_max_budget: *Optional[dict]* - Max budget for a specific model
    - budget_duration: *Optional[str]* - Frequency of reseting org budget
    - metadata: *Optional[dict]* - Metadata for organization, store information for organization. Example metadata - {"extra_info": "some info"}
    - blocked: *bool* - Flag indicating if the org is blocked or not - will stop all calls from keys with this org_id.
    - tags: *Optional[List[str]]* - Tags for [tracking spend](https://litellm.vercel.app/docs/proxy/enterprise#tracking-spend-for-custom-tags) and/or doing [tag-based routing](https://litellm.vercel.app/docs/proxy/tag_routing).
    - organization_id: *Optional[str]* - The organization id of the team. Default is None. Create via `/organization/new`.
    - model_aliases: Optional[dict] - Model aliases for the team. [Docs](https://docs.litellm.ai/docs/proxy/team_based_routing#create-team-with-model-alias)
    - object_permission: Optional[LiteLLM_ObjectPermissionBase] - organization-specific object permission. Example - {"vector_stores": ["vector_store_1", "vector_store_2"]}. IF null or {} then no object permission.
    Case 1: Create new org **without** a budget_id

    ```bash
    curl --location 'http://0.0.0.0:4000/organization/new' 
    --header 'Authorization: Bearer sk-1234' 
    --header 'Content-Type: application/json' 
    --data '{
        "organization_alias": "my-secret-org",
        "models": ["model1", "model2"],
        "max_budget": 100
    }'


    ```

    Case 2: Create new org **with** a budget_id

    ```bash
    curl --location 'http://0.0.0.0:4000/organization/new' 
    --header 'Authorization: Bearer sk-1234' 
    --header 'Content-Type: application/json' 
    --data '{
        "organization_alias": "my-secret-org",
        "models": ["model1", "model2"],
        "budget_id": "428eeaa8-f3ac-4e85-a8fb-7dc8d7aa8689"
    }'
    ```
    r   )litellm_proxy_admin_name
llm_routerprisma_clientN  errorstatus_codedetail  z,Only admins can create orgs. Your role is = user_idwhereTexclude_none)
created_by
updated_byr   )r   r     z\User not allowed to give access to all models. Select models you want org to have access to.)r   user_object)object_permission_idr)   r*   znew_organization_row:    )indent )%litellm.proxy.proxy_serverr   r   r   r   CommonProxyErrorsdb_not_connected_errorvalue	user_roleLitellmUserRolesPROXY_ADMINno_llm_routerr$   dblitellm_usertablefind_uniqueLiteLLM_UserTable
model_dump	Exception	budget_idLiteLLM_BudgetTablemodel_fieldskeysjsonitemsjsonify_objectlitellm_budgettablecreate_set_object_permissionlenmodelsr   LiteLLM_OrganizationTabler   infodumpslitellm_organizationtable)r   r   r   r   r   user_object_correct_typer-   budget_params
_json_datakv_budget_data
budget_rowr   _budgetr.   morganization_rownew_organization_rowresponses                       u/var/www/Befach/backend/env/lib/python3.12/site-packages/litellm/proxy/management_endpoints/organization_endpoints.pynew_organizationr]   '   s    N  .EEKKL
 	
 	##+&&*:*F*FFGHYHcHcGde
 	
 W.?.M.M.S.S$T
 	
 =A  ,	 - 0 0 B B N N "3";";< !O ! K (9'T;;Q;Q;S'T$ ~~	
 ,88==? YYDY1
)3)9)9);RAqM?Q1RR(8<8
"11*//t/2TU
%((<<CC/77S;S/77S;S D 
 
 !** "8#" 
 ##$)t{{q {  A%j6N   
 1 
)))
&1$,,H0H$,,H0H	 )7740 
 ,@!K LM #%%??FF
"
 G  H OW  		 S

( s   B0M35L6 (L3)L6 AMM#M(A;M#M$%M	M
A%M/M0B<M,M-M3L6 6	M?MM
MMMMr   returnc                    K   |y| j                   V|j                  j                  j                  | j                   j	                  d             d{   }| ` |j
                  S y7 w)z
    Creates the LiteLLM_ObjectPermissionTable record for the organization.
    - Handles permissions for vector stores and mcp servers.

    Returns the object_permission_id if created, otherwise None.
    NTr'   r+   )object_permissionr:   litellm_objectpermissiontablerH   r>   r.   )r   r   created_object_permissions      r\   rI   rI      sz      )""@@GG++66D6I H   	"
 "(===s   AA+A)A+z/organization/updatec                   K   ddl m} |'t        ddt        j                  j
                  i      |j                  t        dddi      | j                  |j                  | _        |j                  | j                  d	
            }|j                  j                  j                  d| j                  i       d{   }|t        d| j                         | j                  t!        ||       d{   }|j                  j                  j#                  d| j                  i|d	d	d	d       d{   }|S 7 7 H7 
w)z 
    Update an organization
    r   r   Nr   r   r    r,   z]Cannot associate a user_id to this action. Check `/key/info` to validate if 'user_id' is set.Tr'   organization_idr%   +Organization not found for organization_id=)	data_jsonexisting_organization_rowmembersteamslitellm_budget_table)r&   r   include)r2   r   r   r3   r4   r5   r$   r*   rF   r>   r:   rO   r<   re   
ValueErrorr`   handle_update_object_permissionupdate)r   r   r   updated_organization_rowrh   r[   s         r\   update_organizationrr      sw     9.EEKKL
 	

   (x
 	
 +33,;;T*  88DD$d&:&:; E 
 	
  !(9$:N:N9OP
 	
 ))H.&?*
 $
 
 #%%??FF $"6"67% 4N G  H O-	
$

s6   B>E E:E;E<?E;E<EEErg   rh   c                 l   K   ddl m} t        | |j                  |       d{   }||| d<   | S 7 w)a  
    Handle the update of object permission for an organization.

    - Upserts the new object permission into the LiteLLM_ObjectPermissionTable
    - Adds object_permission_id to data_json (this gets added in the DB)
    - Pops the object_permission from data_json
    r   rd   )rg   existing_object_permission_idr   Nr.   )r2   r   r   r.   )rg   rh   r   r.   s       r\   ro   ro   1  sK      9 "H&?&T&T#"  ',@	()s   "424z/organization/deletec                   K   ddl m} |'t        ddt        j                  j
                  i      |j                  t        j                  k7  rt        dddi      g }| j                  D ]  }|j                  j                  j                  d	|i
       d{    |j                  j                  j                  d	|i
       d{    |j                  j                  j                  d	|i
       d{    |j                  j                  j!                  d	|idddd       d{   }|t        ddd| di      |j#                  |        |S 7 7 7 g7 4w)zx
    Delete an organization

    # Parameters:

    - organization_ids: List[str] - The organization ids to delete.
    r   rd   Nr   r   r    r#   z*Only proxy admins can delete organizationsre   r%   Tri   r&   rm     zOrganization=z
 not found)r2   r   r   r3   r4   r5   r6   r7   r8   organization_idsr:   litellm_teamtabledelete_manylitellm_organizationmembershiplitellm_verificationtokenrO   deleteappend)r   r   r   deleted_orgsre   deleted_orgs         r\   delete_organizationr   L  s    " 9.EEKKL
 	

 ""&6&B&BBIJ
 	

 L0000<<$o6 = 
 	
 	
 ==II$o6 J 
 	
 	
 88DD$o6 E 
 	
 	
 *,,FFMM$o6 $tTR N 
 
 =0A!LM  	K(/ 12 /	
	
	

sH   BE&E/E&
E /E&:E";4E&/E$0/E& E&"E&$E&z/organization/listc                 \  K   ddl m} |t        dddi      |'t        ddt        j                  j
                  i      | j                  t        j                  k(  r4|j                  j                  j                  d	d	d	d
       d{   }|S |j                  j                  j                  d| j                  i       d{   }|j                  j                  j                  dd|D cg c]  }|j                   c}iid	d	d	d
       d{   }|}|S 7 7 Yc c}w 7 w)z
    ```
    curl --location --request GET 'http://0.0.0.0:4000/organization/list'         --header 'Authorization: Bearer sk-1234'
    ```
    r   rd   Nr   r   No db connectedr    r,   T)rl   rj   rk   )rm   r$   r%   re   inrv   )r2   r   r   r3   r4   r5   r6   r7   r8   r:   rO   	find_manyr{   r$   re   )r   r   r[   org_memberships
membershiporg_objectss         r\   list_organizationr     sS     9W>O4PQQ.EEKKL
 	
 ""&6&B&BB&))CCMM-1dTR N 
 
* O  ""AAKK "3";";< L   	
 *,,FFPP!X*:55X$
 .2dTR Q 
 
 O+
 Y
sB   BD,D!;D,	D#
)D,3D%D,D*	D,#D,%D,z/organization/infore   c                    K   ddl m} |t        dddi      |j                  j                  j                  d| id	d	d	d	d
       d{   }|t        dddi      t        di |j                         }|S 7 0w)z*
    Get the org specific information
    r   rd   Nr   r   r   r    re   T)rl   rj   rk   r`   rv   rw   zOrganization not foundr1   )r2   r   r   r:   rO   r<   $LiteLLM_OrganizationTableWithMembersr>   )re   r   r[   response_pydantic_objs       r\   info_organizationr     s      9W>O4PQQ 88DD /2$(!%	
 E  	  W>V4WXX@ 



 ! #	s   A	A>A<1A>)r   r   c                 &  K   ddl m} |t        dddi      t        | j                        dk(  rt        ddd	| j                   i      |j
                  j                  j                  d
d| j                  iiddi       d{   }|S 7 w)z8
    DEPRECATED: Use GET /organization/info instead
    r   rd   Nr   r   r   r    r,   z6Specify list of organization id's to query. Passed in=re   r   rl   Trv   )r2   r   r   rJ   organizationsr:   rO   r   )r   r   r[   s      r\   deprecated_info_organizationr     s      9W>O4PQQ
4!#QRVRdRdQef
 	
 #%%??II 4););"<='. J  H
 Os   BBB	Bz/organization/member_addhttp_requestc                   K   	 ddl m} |t        dddi      |j                  j                  j                  d| j                  i	       d{   }|t        d
ddt        | dd       i      t        | j                  t              r| j                  }n| j                  g}g }g }|D ]G  }t        || j                  |       d{   \  }	}
|j                  |	       |j                  |
       I t        | j                  ||      S 7 7 E# t        $ r}t        j                   d|        t        |t              rYt#        t        |ddt%        |       d      t&        j(                  t        |dd      t        |dt*        j,                              t        |t"              r|t#        dt%        |      z   t&        j(                  t        |dd      t*        j,                        d}~ww xY ww)a  
    [BETA]

    Add new members (either via user_email or user_id) to an organization

    If user doesn't exist, new user row will also be added to User Table

    Only proxy_admin or org_admin of organization, allowed to access this endpoint.

    # Parameters:

    - organization_id: str (required)
    - member: Union[List[Member], Member] (required)
        - role: Literal[LitellmUserRoles] (required)
        - user_id: Optional[str]
        - user_email: Optional[str]

    Note: Either user_id or user_email must be provided for each member.

    Example:
    ```
    curl -X POST 'http://0.0.0.0:4000/organization/member_add'     -H 'Authorization: Bearer sk-1234'     -H 'Content-Type: application/json'     -d '{
        "organization_id": "45e3e396-ee08-4a61-a88e-16b3ce7e0849",
        "member": {
            "role": "internal_user",
            "user_id": "krrish247652@berri.ai"
        },
        "max_budget_in_organization": 100.0
    }'
    ```

    The following is executed in this function:

    1. Check if organization exists
    2. Creates a new Internal User if the user_id or user_email is not found in LiteLLM_UserTable
    3. Add Internal User to the `LiteLLM_OrganizationMembership` table
    r   rd   Nr   r   r   r    re   r%   rw   rf   )memberre   r   )re   updated_users updated_organization_membershipsz%Error adding member to organization: r"   zAuthentication Error()paramNoner!   )messagetyper   codezAuthentication Error, )r2   r   r   r:   rO   r<   re   getattr
isinstancer   r   add_member_to_organizationr~   OrganizationAddMemberResponser?   r   	exceptionProxyExceptionstrProxyErrorTypes
auth_errorr
   HTTP_500_INTERNAL_SERVER_ERROR)r   r   r   r   rh   rj   r   r   r   updated_userupdated_organization_membershipes               r\   organization_member_addr     s    h?
< CBS8TUU  ""<<HH($*>*>? I   	"
 %,J7SWYjlpKqJrs  dkk4(kkG{{mG13VX(F 1 $ 4 4+ /   .,334ST  - 00'-M
 	
E2  
&&)Nqc'RSa' 8/DSVHA-NO$//a&1Qv/T/TU	  >*G,s1v5 ++!Wf-66	
 	

sP   G:AD DA;D DAD G:D D 	G7CG22G77G:
user_emailc                    K   	 |j                   j                  j                  d| i       d{   }t        d	i |j                         }|S 7 # t        $ r t	        ddd|  di      w xY ww)
zA
    Find a member if the user_email is in LiteLLM_UserTable
    r   r%   Nr,   r   z%Unique user not found for user_email=z]. Potential duplicate OR non-existent user_email in LiteLLM_UserTable. Use 'user_id' instead.r    r1   )r:   r;   r<   r?   r   r=   r>   )r   r   existing_user_email_row existing_user_email_row_pydantics       r\   find_member_if_emailr   t  s     
""44@@#Z0 A   	  (9 (
!
,
,
.($ ,+  
@  Mj  k
 	

s+   A1+A AA A1A A..A1z/organization/member_updatec                   K   	 ddl m} |'t        ddt        j                  j
                  i      |j                  j                  j                  d| j                  i       d{   }|t        d	dd
t        | dd       i      | j                  ;| j                  /t        | j                  |       d{   }|j                  | _        	 |j                  j                  j                  d| j                  | j                  di       d{   }|t        ddd| j                   i      | j                   T|j                  j                  j#                  d| j                  | j                  did| j                   i       d{    | j$                  |j&                  xs t)        t+        j,                               }|j&                  -t/        || j$                        }t1        ||       d{    n*t3        t/        || j$                        |       d{    |j                  j                  j#                  d| j                  | j                  did|i       d{    |j                  j                  j                  d| j                  | j                  diddi       d{   }	|	)t        d	dd| j                   d| j                   i      t5        di |	j7                  d      }
|
S 7 7 U7 # t        $ r1}t        d	dd| j                   d| j                   d| i      d}~ww xY w7 7 U7 -7 7 # t        $ r}t9        j:                  d|        |d}~ww xY ww)z3
    Update a member's role in an organization
    r   rd   Nr   r   r    re   r%   r,   rf   user_id_organization_idr$   re   z2Error finding organization membership for user_id=z in organization=: rw   z-Member not found in organization for user_id=r6   )r&   r   )r@   
max_budget)
budget_objr   r@   rl   Trv   z!Member not found in organization=z for user_id=r'   z'Error updating member in organization: r1   )r2   r   r   r3   r4   r5   r:   rO   r<   re   r   r   r$   r   r{   r?   rolerp   max_budget_in_organizationr@   r   uuiduuid4BudgetNewRequestr   r   #LiteLLM_OrganizationMembershipTabler>   r   r   )r   r   r   rh   r    existing_organization_membershipr   r@   new_budget_objfinal_organization_membership&final_organization_membership_pydantics              r\   organization_member_updater     s1    z< !2!I!I!O!OP   ""<<HH($*>*>? I   	"
 %,J7SWYjlpKqJrs  ??&4<<+?,@- '# 3::DL	#&&EEQQ1'+||/3/C/C4 R   -" ,3LT\\N[  99 ""AAHH-#'<<+/+?+?0 "499- I    **68BBWc$**,FWI/99A!1'D4S4S" !-AR  
 $/"+8W8W  '8	    ""AAHH-#'<<+/+?+?0 "9- I     ""AAMM)#||'+';';, ,T2 N 
 
 	& )0@AUAU@VVcdhdpdpcqr  2U 2
+66D6I2
. 65Y'  	QRVR^R^Q__pqu  rF  rF  qG  GI  JK  IL  M 	" 

,  &&)PQRPS'TUs   NA$M" (L)AM" =L>M" AL LL A9M" MA.M" M*M" .M/A	M" 8M9A	M" M AM" NM" M" L 	M!,MMM" M" M" M"  M" "	N
+NN

Nz/organization/member_deletec                   K   	 ddl m} |'t        ddt        j                  j
                  i      | j                  ;| j                  /t        | j                  |       d{   }|j                  | _        |j                  j                  j                  d| j                  | j                  di	       d{   }|S 7 ^7 # t        $ r}t        j                  d
|        |d}~ww xY ww)z.
    Delete a member from an organization
    r   rd   Nr   r   r    r   r   r%   z)Error deleting member from organization: )r2   r   r   r3   r4   r5   r   r$   r   r:   r{   r}   re   r?   r   r   )r   r   r   r   member_to_deleter   s         r\   organization_member_deleter     s     < !2!I!I!O!OP 
 ??&4<<+?,@- '# 3::DL!.!1!1!P!P!W!W)#||'+';';, "X "
 
  '

  &&)RSTRU'VWsN   C2A C $C%AC <C=C C2C C 	C/C**C//C2r   c           	        K   	 d}d}d}| j                   :|j                  j                  j                  d| j                   i       d{   }|G| j                  ;	 |j                  j                  j                  d| j                  i       d{   }|{|y| j                   xs t        t        j                               }t        || j                        }|j                  |d	       d{   }	|	t        di |	j                         }n|t        |      d
kD  rt        dddi      |t        di |j                         }nE|t        di |j                         }n)t        ddd| j                    d| j                   i      |%t        d| j                    d| j                         |j                  j                   j#                  ||j                   | j$                  d       d{   }
t'        di |
j                         }||fS 7 7 # t
        $ r }t        d| j                   d|       d}~ww xY w7 ]7 V# t
        $ r}t        d|  d| d|       d}~ww xY ww)z
    Add a member to an organization

    - Checks if member.user_id or member.user_email is in LiteLLM_UserTable
    - If not found, create a new user in LiteLLM_UserTable
    - Add user to organization in LiteLLM_OrganizationMembership
    Nr$   r%   r   zdPotential NON-Existent or Duplicate user email in DB: Error finding a unique instance of user_email=z in LiteLLM_UserTable.: )r$   r   user)r   
table_name   r,   r   zIMultiple users with this email found in db. Please use 'user_id' instead.r    rw   zUser not found for user_id=z and user_email=z2User does not exist in LiteLLM_UserTable. user_id=)re   r$   r6   r+   zError adding member=z to organization=r   r1   )r$   r:   r;   r<   r   r?   rn   r   r   r   r   insert_datar=   r>   rJ   r   r{   rH   r   r   )r   re   r   r-   existing_user_id_rowr   r   r$   new_user_defaults_returned_user_organization_membershiporganization_memberships               r\   r   r   C  s    L
37#"&>>%)6)9)9)K)K)W)W &..1 *X * $   'F,=,=,I	'**<<HH+V->->? I   (  ',C,K!>>>S->G >!,,!
 $1#<#<BS`f#<#ggN)/N.2K2K2MN$0S9P5QTU5Uh  %0+S.E.P.P.RSK!-+P.B.M.M.OPK:6>>:JJZ[a[l[lZmn  DV^^DTTdekevevdwx   ""AAHH'6*22!' I   	! #F #
&113#
 333C$   z  |B  |M  |M  {N  Nf  gh  fi  j  h:  
"6(*;O;LBqcR
 	

s   I<AI H I 5H& H#H& AI 5I6DI >I? I I< I #H& &	I/I

II I 	I9 I44I99I<)@__doc__r   typingr   r   r   fastapir   r   r   r	   r
   litellm._loggingr   litellm.proxy._typeslitellm.proxy.auth.auth_checksr   $litellm.proxy.auth.user_api_key_authr   >litellm.proxy.management_endpoints.budget_management_endpointsr   r   8litellm.proxy.management_helpers.object_permission_utilsr   &litellm.proxy.management_helpers.utilsr   r   litellm.proxy.utilsr   routerpostNewOrganizationResponseNewOrganizationRequestUserAPIKeyAuthr]   r   rI   patchr   LiteLLM_OrganizationTableUpdaterr   dictrL   ro   r}   DeleteOrganizationRequestr   getr   r   OrganizationRequestr   r   OrganizationMemberAddRequestr   r=   r   r   OrganizationMemberUpdateRequestr   OrganizationMemberDeleteRequestr   	OrgMemberr   r1       r\   <module>r      s  	  ( ( F F 1 " > B -	 
#	$+,-*	   )00A(Bl
 l%ll^
 L) c]0 
#	$+,-7	   )00A(B4
)4%44n8 
6 
#	$+,-<=	   )00A(B3
#3%33l 
#	$+,-<=	   )00A(B+%++\ 
#	$+,-7	  !S !!> 
#	$+,-  
-@ 
0 
#	$+,-0	    )00A(Bl

&l
l
 &l
 #	l
 l
^,,$0,,4 !
#	$+,-6	    )00A(BA
)A%A AH !
#	$+,-   )00A(B"
)"%"
"JY
Y
Y
  Y
 AAB	Y
r   