from __future__ import annotations from typing import Any from fastapi import APIRouter, Depends, HTTPException, Request, status from pydantic import BaseModel from open_webui.constants import ERROR_MESSAGES from open_webui.models.config import Config from open_webui.utils.access_control import has_permission from open_webui.utils.auth import get_verified_user from open_webui.utils.notifications import ( create_target, delete_target, get_notification_event_catalog, list_targets, set_default_target, test_target, update_target, ) router = APIRouter() class NotificationTargetForm(BaseModel): id: str | None = None type: str | None = None enabled: bool | None = None events: list[str] | None = None delivery: str | None = None config: dict[str, Any] | None = None async def _check_notifications_access(user) -> None: if not await Config.get('ui.enable_user_webhooks'): raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) if user.role != 'admin' and not await has_permission( user.id, 'features.webhooks', await Config.get('user.permissions') ): raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED) @router.get('/events') async def get_notification_events(user=Depends(get_verified_user)): await _check_notifications_access(user) return {'events': get_notification_event_catalog()} @router.get('/targets') async def get_notification_targets(user=Depends(get_verified_user)): await _check_notifications_access(user) return await list_targets(user.id) @router.post('/targets') async def create_notification_target(form_data: NotificationTargetForm, user=Depends(get_verified_user)): await _check_notifications_access(user) try: return await create_target(user.id, form_data.model_dump(exclude_unset=True)) except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) @router.put('/targets/{target_id}') async def update_notification_target( target_id: str, form_data: NotificationTargetForm, user=Depends(get_verified_user) ): await _check_notifications_access(user) try: return await update_target(user.id, target_id, form_data.model_dump(exclude_unset=True)) except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) @router.delete('/targets/{target_id}') async def delete_notification_target(target_id: str, user=Depends(get_verified_user)): await _check_notifications_access(user) if not await delete_target(user.id, target_id): raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) return {'ok': True} @router.put('/targets/{target_id}/default') async def set_default_notification_target(target_id: str, user=Depends(get_verified_user)): await _check_notifications_access(user) try: return await set_default_target(user.id, target_id) except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) @router.post('/targets/{target_id}/test') async def test_notification_target(request: Request, target_id: str, user=Depends(get_verified_user)): await _check_notifications_access(user) try: # LICENSE covers this Open WebUI notification identifier. # Do not alter, remove, obscure, or replace it except as LICENSE permits: # https://docs.openwebui.com/license. app_name = getattr(request.app.state, 'WEBUI_NAME', 'Open WebUI') return await test_target(user.id, target_id, app_name) except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))