This commit is contained in:
Timothy Jaeryang Baek
2026-06-25 03:31:45 +01:00
parent 35f8bf97e3
commit b5c43968db
32 changed files with 2251 additions and 120 deletions
+40 -3
View File
@@ -26,6 +26,7 @@ from zoneinfo import ZoneInfo
from dateutil.rrule import rrulestr
from fastapi import Request
from open_webui.constants import ERROR_MESSAGES
from open_webui.events import EVENTS, publish_event
from open_webui.internal.db import get_async_db
from open_webui.models.automations import AutomationModel, AutomationRuns, Automations
from open_webui.models.chats import ChatForm, Chats
@@ -357,6 +358,12 @@ async def execute_automation(app, automation: AutomationModel) -> None:
user = await Users.get_user_by_id(automation.user_id)
if not user:
await _record_run(automation.id, 'error', error='User not found')
await publish_event(
app,
EVENTS.AUTOMATION_RUN_FAILED,
subject_id=automation.id,
data={'name': automation.name, 'error': 'User not found'},
)
return
# Re-gate the rehydrated owner: a demoted/deactivated or de-permissioned owner must not run.
@@ -366,7 +373,15 @@ async def execute_automation(app, automation: AutomationModel) -> None:
user.role != 'admin'
and not await has_permission(user.id, 'features.automations', await Config.get('user.permissions'))
):
await _record_run(automation.id, 'error', error='Owner no longer permitted to run automations')
error = 'Owner no longer permitted to run automations'
await _record_run(automation.id, 'error', error=error)
await publish_event(
app,
EVENTS.AUTOMATION_RUN_FAILED,
actor=user,
subject_id=automation.id,
data={'name': automation.name, 'error': error},
)
return
prompt = await prompt_template(automation.data['prompt'], user)
@@ -418,7 +433,15 @@ async def execute_automation(app, automation: AutomationModel) -> None:
)
if not chat:
await _record_run(automation.id, 'error', error='Failed to create chat')
error = 'Failed to create chat'
await _record_run(automation.id, 'error', error=error)
await publish_event(
app,
EVENTS.AUTOMATION_RUN_FAILED,
actor=user,
subject_id=automation.id,
data={'name': automation.name, 'error': error},
)
return
# Notify frontend to refresh chat list
@@ -488,10 +511,24 @@ async def execute_automation(app, automation: AutomationModel) -> None:
)
await _record_run(automation.id, 'success', chat_id=chat.id)
await publish_event(
app,
EVENTS.AUTOMATION_RUN_COMPLETED,
actor=user,
subject_id=automation.id,
data={'name': automation.name, 'chat_id': chat.id},
)
except Exception as e:
log.exception(f'Automation {automation.id} failed')
await _record_run(automation.id, 'error', error=str(e)[:4000])
error = str(e)[:4000]
await _record_run(automation.id, 'error', error=error)
await publish_event(
app,
EVENTS.AUTOMATION_RUN_FAILED,
subject_id=automation.id,
data={'name': automation.name, 'error': error},
)
####################
+11 -15
View File
@@ -62,7 +62,8 @@ from open_webui.config import (
OAUTH_USERNAME_CLAIM,
WEBHOOK_URL,
)
from open_webui.constants import ERROR_MESSAGES, WEBHOOK_MESSAGES
from open_webui.constants import ERROR_MESSAGES
from open_webui.events import EVENTS, publish_event
from open_webui.env import (
AIOHTTP_CLIENT_ALLOW_REDIRECTS,
AIOHTTP_CLIENT_SESSION_SSL,
@@ -73,7 +74,6 @@ from open_webui.env import (
REDIS_KEY_PREFIX,
WEBUI_AUTH_COOKIE_SAME_SITE,
WEBUI_AUTH_COOKIE_SECURE,
WEBUI_NAME,
)
from open_webui.models.auths import Auths
from open_webui.models.config import Config
@@ -84,7 +84,6 @@ from open_webui.retrieval.web.utils import validate_url
from open_webui.utils.auth import create_token, get_password_hash
from open_webui.utils.groups import apply_default_group_assignment
from open_webui.utils.misc import parse_duration
from open_webui.utils.webhook import post_webhook
from starlette.responses import RedirectResponse
@@ -1248,6 +1247,7 @@ class OAuthManager:
"""
provider = session.provider
token_data = session.token
auth_config = await get_oauth_runtime_config()
if not token_data.get('refresh_token'):
log.warning(f'No refresh token available for session {session.id}')
@@ -1837,20 +1837,16 @@ class OAuthManager:
await Users.update_user_role_by_id(user.id, 'admin', db=db)
user = await Users.get_user_by_id(user.id, db=db)
if auth_config.WEBHOOK_URL:
await post_webhook(
WEBUI_NAME,
auth_config.WEBHOOK_URL,
WEBHOOK_MESSAGES.USER_SIGNUP(user.name),
{
'action': 'signup',
'message': WEBHOOK_MESSAGES.USER_SIGNUP(user.name),
'user': user.model_dump_json(exclude_none=True),
},
)
default_group_id = await Config.get('ui.default_group_id')
await apply_default_group_assignment(default_group_id, user.id, db=db)
await publish_event(
request,
EVENTS.USER_CREATED,
actor=user,
subject_id=user.id,
source='oauth',
data={'role': user.role, 'provider': provider},
)
else:
raise HTTPException(
+5 -3
View File
@@ -34,12 +34,14 @@ async def post_webhook(name: str, url: str, message: str, event_data: dict) -> b
# Microsoft Teams Webhooks
elif 'webhook.office.com' in url:
action = event_data.get('action', 'undefined')
user_data = event_data.get('user', '{}')
user_data = event_data.get('user') or event_data.get('actor') or {}
if isinstance(user_data, dict):
user_dict = user_data
else:
user_dict = json.loads(user_data)
facts = [{'name': name, 'value': value} for name, value in user_dict.items()]
facts = [{'name': key, 'value': value} for key, value in user_dict.items()]
if event_data.get('event'):
facts.insert(0, {'name': 'event', 'value': event_data.get('event')})
payload = {
'@type': 'MessageCard',
'@context': 'http://schema.org/extensions',
@@ -57,7 +59,7 @@ async def post_webhook(name: str, url: str, message: str, event_data: dict) -> b
}
# Default Payload
else:
payload = {**event_data}
payload = event_data
log.debug(f'payload: {payload}')
async with aiohttp.ClientSession(