enh: automation

This commit is contained in:
Timothy Jaeryang Baek
2026-04-11 17:06:58 -06:00
parent ee9db91df0
commit 406251c2f3
6 changed files with 85 additions and 0 deletions
+12
View File
@@ -950,6 +950,8 @@ async def get_admin_config(request: Request, user=Depends(get_admin_user)):
'ENABLE_MESSAGE_RATING': request.app.state.config.ENABLE_MESSAGE_RATING,
'ENABLE_FOLDERS': request.app.state.config.ENABLE_FOLDERS,
'FOLDER_MAX_FILE_COUNT': request.app.state.config.FOLDER_MAX_FILE_COUNT,
'AUTOMATION_MAX_COUNT': request.app.state.config.AUTOMATION_MAX_COUNT,
'AUTOMATION_MIN_INTERVAL': request.app.state.config.AUTOMATION_MIN_INTERVAL,
'ENABLE_CHANNELS': request.app.state.config.ENABLE_CHANNELS,
'ENABLE_MEMORIES': request.app.state.config.ENABLE_MEMORIES,
'ENABLE_NOTES': request.app.state.config.ENABLE_NOTES,
@@ -976,6 +978,8 @@ class AdminConfig(BaseModel):
ENABLE_MESSAGE_RATING: bool
ENABLE_FOLDERS: bool
FOLDER_MAX_FILE_COUNT: Optional[int | str] = None
AUTOMATION_MAX_COUNT: Optional[int | str] = None
AUTOMATION_MIN_INTERVAL: Optional[int | str] = None
ENABLE_CHANNELS: bool
ENABLE_MEMORIES: bool
ENABLE_NOTES: bool
@@ -1001,6 +1005,12 @@ async def update_admin_config(request: Request, form_data: AdminConfig, user=Dep
request.app.state.config.FOLDER_MAX_FILE_COUNT = (
int(form_data.FOLDER_MAX_FILE_COUNT) if form_data.FOLDER_MAX_FILE_COUNT else ''
)
request.app.state.config.AUTOMATION_MAX_COUNT = (
int(form_data.AUTOMATION_MAX_COUNT) if form_data.AUTOMATION_MAX_COUNT else ''
)
request.app.state.config.AUTOMATION_MIN_INTERVAL = (
int(form_data.AUTOMATION_MIN_INTERVAL) if form_data.AUTOMATION_MIN_INTERVAL else ''
)
request.app.state.config.ENABLE_CHANNELS = form_data.ENABLE_CHANNELS
request.app.state.config.ENABLE_MEMORIES = form_data.ENABLE_MEMORIES
request.app.state.config.ENABLE_NOTES = form_data.ENABLE_NOTES
@@ -1042,6 +1052,8 @@ async def update_admin_config(request: Request, form_data: AdminConfig, user=Dep
'ENABLE_MESSAGE_RATING': request.app.state.config.ENABLE_MESSAGE_RATING,
'ENABLE_FOLDERS': request.app.state.config.ENABLE_FOLDERS,
'FOLDER_MAX_FILE_COUNT': request.app.state.config.FOLDER_MAX_FILE_COUNT,
'AUTOMATION_MAX_COUNT': request.app.state.config.AUTOMATION_MAX_COUNT,
'AUTOMATION_MIN_INTERVAL': request.app.state.config.AUTOMATION_MIN_INTERVAL,
'ENABLE_CHANNELS': request.app.state.config.ENABLE_CHANNELS,
'ENABLE_MEMORIES': request.app.state.config.ENABLE_MEMORIES,
'ENABLE_NOTES': request.app.state.config.ENABLE_NOTES,
+34
View File
@@ -19,6 +19,7 @@ from open_webui.utils.automations import (
next_run_ns,
next_n_runs_ns,
execute_automation,
rrule_interval_seconds,
)
from open_webui.utils.auth import get_verified_user, get_admin_user
from open_webui.utils.access_control import has_permission
@@ -60,6 +61,35 @@ def check_automation_access(automation, user):
)
def check_automation_limits(request, user, rrule_str: str, db, is_create: bool = False):
"""Enforce global automation limits. Admins bypass all checks."""
if user.role == 'admin':
return
# Max count (create only)
if is_create:
max_count = request.app.state.config.AUTOMATION_MAX_COUNT
if max_count:
max_count = int(max_count)
if max_count > 0 and Automations.count_by_user(user.id, db=db) >= max_count:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f'Automation limit reached ({max_count})',
)
# Min interval (create + update)
min_interval = request.app.state.config.AUTOMATION_MIN_INTERVAL
if min_interval:
min_interval = int(min_interval)
if min_interval > 0:
interval = rrule_interval_seconds(rrule_str)
if interval is not None and interval < min_interval:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f'Schedule too frequent. Minimum interval is {min_interval} seconds.',
)
def enrich_automation(automation: AutomationModel, db: Session, tz: str = None) -> AutomationResponse:
"""Full enrichment for single-item views (includes next_runs computation)."""
last_run = AutomationRuns.get_latest(automation.id, db=db)
@@ -135,6 +165,8 @@ async def create_new_automation(
detail=str(e),
)
check_automation_limits(request, user, form_data.data.rrule, db, is_create=True)
# Validate terminal server exists if linked
if form_data.data.terminal and form_data.data.terminal.server_id:
connections = request.app.state.config.TERMINAL_SERVER_CONNECTIONS or []
@@ -192,6 +224,8 @@ async def update_automation_by_id(
detail=str(e),
)
check_automation_limits(request, user, form_data.data.rrule, db, is_create=False)
# Validate terminal server exists if linked
if form_data.data.terminal and form_data.data.terminal.server_id:
connections = request.app.state.config.TERMINAL_SERVER_CONNECTIONS or []