Spaces:
Configuration error
Configuration error
""" | |
Hooks that are triggered when a litellm user event occurs | |
""" | |
import asyncio | |
import uuid | |
from datetime import datetime, timezone | |
from typing import Optional | |
from pydantic import BaseModel | |
import litellm | |
from litellm._logging import verbose_proxy_logger | |
from litellm.proxy._types import ( | |
AUDIT_ACTIONS, | |
CommonProxyErrors, | |
LiteLLM_AuditLogs, | |
Litellm_EntityType, | |
LiteLLM_UserTable, | |
LitellmTableNames, | |
NewUserRequest, | |
NewUserResponse, | |
UserAPIKeyAuth, | |
WebhookEvent, | |
) | |
from litellm.proxy.management_helpers.audit_logs import create_audit_log_for_update | |
class UserManagementEventHooks: | |
async def async_user_created_hook( | |
data: NewUserRequest, | |
response: NewUserResponse, | |
user_api_key_dict: UserAPIKeyAuth, | |
): | |
""" | |
This hook is called when a new user is created on litellm | |
Handles: | |
- Creating an audit log for the user creation | |
- Sending a user invitation email to the user | |
""" | |
from litellm.proxy.proxy_server import litellm_proxy_admin_name, prisma_client | |
######################################################### | |
########## Send User Invitation Email ################ | |
######################################################### | |
await UserManagementEventHooks.async_send_user_invitation_email( | |
data=data, | |
response=response, | |
user_api_key_dict=user_api_key_dict, | |
) | |
######################################################### | |
########## CREATE AUDIT LOG ################ | |
######################################################### | |
try: | |
if prisma_client is None: | |
raise Exception(CommonProxyErrors.db_not_connected_error.value) | |
user_row: BaseModel = await prisma_client.db.litellm_usertable.find_first( | |
where={"user_id": response.user_id} | |
) | |
user_row_litellm_typed = LiteLLM_UserTable( | |
**user_row.model_dump(exclude_none=True) | |
) | |
asyncio.create_task( | |
UserManagementEventHooks.create_internal_user_audit_log( | |
user_id=user_row_litellm_typed.user_id, | |
action="created", | |
litellm_changed_by=user_api_key_dict.user_id, | |
user_api_key_dict=user_api_key_dict, | |
litellm_proxy_admin_name=litellm_proxy_admin_name, | |
before_value=None, | |
after_value=user_row_litellm_typed.model_dump_json( | |
exclude_none=True | |
), | |
) | |
) | |
except Exception as e: | |
verbose_proxy_logger.warning( | |
"Unable to create audit log for user on `/user/new` - {}".format(str(e)) | |
) | |
pass | |
async def async_send_user_invitation_email( | |
data: NewUserRequest, | |
response: NewUserResponse, | |
user_api_key_dict: UserAPIKeyAuth, | |
): | |
""" | |
Send a user invitation email to the user | |
""" | |
event = WebhookEvent( | |
event="internal_user_created", | |
event_group=Litellm_EntityType.USER, | |
event_message="Welcome to LiteLLM Proxy", | |
token=response.token, | |
spend=response.spend or 0.0, | |
max_budget=response.max_budget, | |
user_id=response.user_id, | |
user_email=response.user_email, | |
team_id=response.team_id, | |
key_alias=response.key_alias, | |
) | |
######################################################### | |
########## V2 USER INVITATION EMAIL ################ | |
######################################################### | |
try: | |
from litellm_enterprise.enterprise_callbacks.send_emails.base_email import ( | |
BaseEmailLogger, | |
) | |
use_enterprise_email_hooks = True | |
except ImportError: | |
verbose_proxy_logger.warning( | |
"Defaulting to using Legacy Email Hooks." | |
+ CommonProxyErrors.missing_enterprise_package.value | |
) | |
use_enterprise_email_hooks = False | |
if use_enterprise_email_hooks: | |
initialized_email_loggers = litellm.logging_callback_manager.get_custom_loggers_for_type( | |
callback_type=BaseEmailLogger # type: ignore | |
) | |
if len(initialized_email_loggers) > 0: | |
for email_logger in initialized_email_loggers: | |
if isinstance(email_logger, BaseEmailLogger): # type: ignore | |
await email_logger.send_user_invitation_email( # type: ignore | |
event=event, | |
) | |
######################################################### | |
########## LEGACY V1 USER INVITATION EMAIL ################ | |
######################################################### | |
if data.send_invite_email is True: | |
await UserManagementEventHooks.send_legacy_v1_user_invitation_email( | |
data=data, | |
response=response, | |
user_api_key_dict=user_api_key_dict, | |
event=event, | |
) | |
async def send_legacy_v1_user_invitation_email( | |
data: NewUserRequest, | |
response: NewUserResponse, | |
user_api_key_dict: UserAPIKeyAuth, | |
event: WebhookEvent, | |
): | |
""" | |
Send a user invitation email to the user | |
""" | |
from litellm.proxy.proxy_server import general_settings, proxy_logging_obj | |
# check if user has setup email alerting | |
if "email" not in general_settings.get("alerting", []): | |
raise ValueError( | |
"Email alerting not setup on config.yaml. Please set `alerting=['email']. \nDocs: https://docs.litellm.ai/docs/proxy/email`" | |
) | |
# If user configured email alerting - send an Email letting their end-user know the key was created | |
asyncio.create_task( | |
proxy_logging_obj.slack_alerting_instance.send_key_created_or_user_invited_email( | |
webhook_event=event, | |
) | |
) | |
async def create_internal_user_audit_log( | |
user_id: str, | |
action: AUDIT_ACTIONS, | |
litellm_changed_by: Optional[str], | |
user_api_key_dict: UserAPIKeyAuth, | |
litellm_proxy_admin_name: Optional[str], | |
before_value: Optional[str] = None, | |
after_value: Optional[str] = None, | |
): | |
""" | |
Create an audit log for an internal user. | |
Parameters: | |
- user_id: str - The id of the user to create the audit log for. | |
- action: AUDIT_ACTIONS - The action to create the audit log for. | |
- user_row: LiteLLM_UserTable - The user row to create the audit log for. | |
- litellm_changed_by: Optional[str] - The user id of the user who is changing the user. | |
- user_api_key_dict: UserAPIKeyAuth - The user api key dictionary. | |
- litellm_proxy_admin_name: Optional[str] - The name of the proxy admin. | |
""" | |
if not litellm.store_audit_logs: | |
return | |
await create_audit_log_for_update( | |
request_data=LiteLLM_AuditLogs( | |
id=str(uuid.uuid4()), | |
updated_at=datetime.now(timezone.utc), | |
changed_by=litellm_changed_by | |
or user_api_key_dict.user_id | |
or litellm_proxy_admin_name, | |
changed_by_api_key=user_api_key_dict.api_key, | |
table_name=LitellmTableNames.USER_TABLE_NAME, | |
object_id=user_id, | |
action=action, | |
updated_values=after_value, | |
before_value=before_value, | |
) | |
) | |