mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-13 01:02:25 -06:00
fix: enforce automation limits in the builtin automation tools (#27523)
The `create_automation` and `update_automation` builtin tools wrote straight to `Automations.insert` / `Automations.update_by_id`, skipping the limit checks that `/api/v1/automations/create` and `/api/v1/automations/{id}/update` run through `check_automation_limits`. A non-admin user could therefore ask the model to create automations indefinitely, ignoring `AUTOMATION_MAX_COUNT`, and could schedule them below `AUTOMATION_MIN_INTERVAL`, on both create and update.
Both tools now call the same `check_automation_limits` helper the routers use, so the limits and the admin bypass cannot drift between the chat path and the HTTP path. A rejection is returned to the model as a plain error message instead of raising. `update_automation` also gained the missing user lookup guard, since the helper needs the user's role.
The `automations.enable` toggle and the `features.automations` user permission were already enforced when the tool set is assembled, so they are unaffected.
Fixes #27121
This commit is contained in:
@@ -14,7 +14,7 @@ import logging
|
||||
import time
|
||||
from typing import Literal, Optional
|
||||
|
||||
from fastapi import Request
|
||||
from fastapi import HTTPException, Request
|
||||
|
||||
from open_webui.models.channels import Channel, ChannelMember, Channels
|
||||
from open_webui.models.chats import Chats
|
||||
@@ -3292,6 +3292,7 @@ async def create_automation(
|
||||
try:
|
||||
from open_webui.models.automations import AutomationData, AutomationForm, Automations
|
||||
from open_webui.models.users import Users
|
||||
from open_webui.routers.automations import check_automation_limits
|
||||
from open_webui.utils.automations import next_n_runs_ns, next_run_ns, validate_rrule
|
||||
|
||||
user_id = __user__.get('id')
|
||||
@@ -3313,6 +3314,11 @@ async def create_automation(
|
||||
except ValueError as e:
|
||||
return json.dumps({'error': f'Invalid schedule: {e}'})
|
||||
|
||||
try:
|
||||
await check_automation_limits(__request__, user, rrule, None, is_create=True)
|
||||
except HTTPException as e:
|
||||
return json.dumps({'error': e.detail})
|
||||
|
||||
tz = user.timezone
|
||||
form = AutomationForm(
|
||||
name=name,
|
||||
@@ -3370,10 +3376,13 @@ async def update_automation(
|
||||
try:
|
||||
from open_webui.models.automations import AutomationData, AutomationForm, Automations
|
||||
from open_webui.models.users import Users
|
||||
from open_webui.routers.automations import check_automation_limits
|
||||
from open_webui.utils.automations import next_n_runs_ns, next_run_ns, validate_rrule
|
||||
|
||||
user_id = __user__.get('id')
|
||||
user = await Users.get_user_by_id(user_id)
|
||||
if not user:
|
||||
return json.dumps({'error': 'User not found'})
|
||||
|
||||
automation = await Automations.get_by_id(automation_id)
|
||||
if not automation:
|
||||
@@ -3390,11 +3399,16 @@ async def update_automation(
|
||||
# Validate RRULE if changed
|
||||
if rrule is not None:
|
||||
try:
|
||||
validate_rrule(new_rrule, tz=user.timezone if user else None)
|
||||
validate_rrule(new_rrule, tz=user.timezone)
|
||||
except ValueError as e:
|
||||
return json.dumps({'error': f'Invalid schedule: {e}'})
|
||||
|
||||
tz = user.timezone if user else None
|
||||
try:
|
||||
await check_automation_limits(__request__, user, new_rrule, None)
|
||||
except HTTPException as e:
|
||||
return json.dumps({'error': e.detail})
|
||||
|
||||
tz = user.timezone
|
||||
form = AutomationForm(
|
||||
name=new_name,
|
||||
data=AutomationData(
|
||||
|
||||
Reference in New Issue
Block a user