fix automation visibility and execution by profile ownership
This commit is contained in:
@@ -2,6 +2,11 @@ from __future__ import annotations
|
||||
|
||||
from ._shared import *
|
||||
|
||||
|
||||
def _automation_user_id() -> int:
|
||||
return int(default_user_id() or 0)
|
||||
|
||||
|
||||
@bp.get('/automations')
|
||||
def automations_get():
|
||||
from ..services import automation_rules
|
||||
@@ -9,13 +14,15 @@ def automations_get():
|
||||
if not profile:
|
||||
return ok({'rules': [], 'history': [], 'error': 'No profile'})
|
||||
try:
|
||||
user_id = default_user_id()
|
||||
return ok({'rules': automation_rules.list_rules(profile['id'], user_id=user_id), 'history': automation_rules.list_history(profile['id'], user_id=user_id)})
|
||||
user_id = _automation_user_id()
|
||||
return ok({
|
||||
'rules': automation_rules.list_rules(profile['id'], user_id=user_id),
|
||||
'history': automation_rules.list_history(profile['id'], user_id=user_id),
|
||||
})
|
||||
except Exception as exc:
|
||||
return jsonify({'ok': False, 'error': str(exc), 'rules': [], 'history': []}), 500
|
||||
|
||||
|
||||
|
||||
@bp.get('/automations/export')
|
||||
def automations_export():
|
||||
from ..services import automation_rules
|
||||
@@ -23,14 +30,12 @@ def automations_export():
|
||||
if not profile:
|
||||
return jsonify({'ok': False, 'error': 'No profile'}), 400
|
||||
try:
|
||||
# Note: JSON export is profile-scoped and excludes execution history/cooldown state.
|
||||
data = automation_rules.export_rules(profile['id'], user_id=default_user_id())
|
||||
data = automation_rules.export_rules(profile['id'], user_id=_automation_user_id())
|
||||
return ok({'export': data, 'count': len(data.get('rules') or [])})
|
||||
except Exception as exc:
|
||||
return jsonify({'ok': False, 'error': str(exc)}), 400
|
||||
|
||||
|
||||
|
||||
@bp.post('/automations/import')
|
||||
def automations_import():
|
||||
from ..services import automation_rules
|
||||
@@ -40,15 +45,13 @@ def automations_import():
|
||||
try:
|
||||
payload = request.get_json(silent=True) or {}
|
||||
replace = str(request.args.get('replace') or '').lower() in {'1', 'true', 'yes'} or bool(payload.get('replace')) if isinstance(payload, dict) else False
|
||||
# Note: Import appends rules by default, so existing automations remain untouched.
|
||||
user_id = default_user_id()
|
||||
user_id = _automation_user_id()
|
||||
imported = automation_rules.import_rules(profile['id'], payload, user_id=user_id, replace=replace)
|
||||
return ok({'imported': len(imported), 'rules': automation_rules.list_rules(profile['id'], user_id=user_id)})
|
||||
except Exception as exc:
|
||||
return jsonify({'ok': False, 'error': str(exc)}), 400
|
||||
|
||||
|
||||
|
||||
@bp.post('/automations')
|
||||
def automations_save():
|
||||
from ..services import automation_rules
|
||||
@@ -56,14 +59,13 @@ def automations_save():
|
||||
if not profile:
|
||||
return jsonify({'ok': False, 'error': 'No profile'}), 400
|
||||
try:
|
||||
user_id = default_user_id()
|
||||
user_id = _automation_user_id()
|
||||
rule = automation_rules.save_rule(profile['id'], request.get_json(silent=True) or {}, user_id=user_id)
|
||||
return ok({'rule': rule, 'rules': automation_rules.list_rules(profile['id'], user_id=user_id)})
|
||||
except Exception as exc:
|
||||
return jsonify({'ok': False, 'error': str(exc)}), 400
|
||||
|
||||
|
||||
|
||||
@bp.delete('/automations/<int:rule_id>')
|
||||
def automations_delete(rule_id: int):
|
||||
from ..services import automation_rules
|
||||
@@ -71,14 +73,13 @@ def automations_delete(rule_id: int):
|
||||
if not profile:
|
||||
return jsonify({'ok': False, 'error': 'No profile'}), 400
|
||||
try:
|
||||
user_id = default_user_id()
|
||||
user_id = _automation_user_id()
|
||||
automation_rules.delete_rule(rule_id, profile['id'], user_id=user_id)
|
||||
return ok({'rules': automation_rules.list_rules(profile['id'], user_id=user_id)})
|
||||
except Exception as exc:
|
||||
return jsonify({'ok': False, 'error': str(exc)}), 400
|
||||
|
||||
|
||||
|
||||
@bp.post('/automations/<int:rule_id>/run')
|
||||
def automations_run_rule(rule_id: int):
|
||||
from ..services import automation_rules
|
||||
@@ -86,9 +87,12 @@ def automations_run_rule(rule_id: int):
|
||||
if not profile:
|
||||
return jsonify({'ok': False, 'error': 'No profile'}), 400
|
||||
try:
|
||||
# Note: Single-rule run ignores disabled state and cooldown for manual troubleshooting.
|
||||
user_id = default_user_id()
|
||||
return ok({'result': automation_rules.check(profile, user_id=user_id, force=True, rule_id=rule_id), 'rules': automation_rules.list_rules(profile['id'], user_id=user_id), 'history': automation_rules.list_history(profile['id'], user_id=user_id)})
|
||||
user_id = _automation_user_id()
|
||||
return ok({
|
||||
'result': automation_rules.check(profile, user_id=user_id, force=True, rule_id=rule_id),
|
||||
'rules': automation_rules.list_rules(profile['id'], user_id=user_id),
|
||||
'history': automation_rules.list_history(profile['id'], user_id=user_id),
|
||||
})
|
||||
except Exception as exc:
|
||||
return jsonify({'ok': False, 'error': str(exc)}), 500
|
||||
|
||||
@@ -100,14 +104,16 @@ def automations_check():
|
||||
if not profile:
|
||||
return jsonify({'ok': False, 'error': 'No profile'}), 400
|
||||
try:
|
||||
# Note: Force check ignores disabled state and cooldown, allowing a one-off manual automation pass.
|
||||
user_id = default_user_id()
|
||||
return ok({'result': automation_rules.check(profile, user_id=user_id, force=True), 'rules': automation_rules.list_rules(profile['id'], user_id=user_id), 'history': automation_rules.list_history(profile['id'], user_id=user_id)})
|
||||
user_id = _automation_user_id()
|
||||
return ok({
|
||||
'result': automation_rules.check(profile, user_id=user_id, force=True),
|
||||
'rules': automation_rules.list_rules(profile['id'], user_id=user_id),
|
||||
'history': automation_rules.list_history(profile['id'], user_id=user_id),
|
||||
})
|
||||
except Exception as exc:
|
||||
return jsonify({'ok': False, 'error': str(exc)}), 500
|
||||
|
||||
|
||||
|
||||
@bp.delete('/automations/history')
|
||||
def automations_history_clear():
|
||||
from ..services import automation_rules
|
||||
@@ -115,8 +121,7 @@ def automations_history_clear():
|
||||
if not profile:
|
||||
return jsonify({'ok': False, 'error': 'No profile'}), 400
|
||||
try:
|
||||
# Note: Clear only automation execution logs; rules and cooldown state stay unchanged.
|
||||
user_id = default_user_id()
|
||||
user_id = _automation_user_id()
|
||||
deleted = automation_rules.clear_history(profile['id'], user_id=user_id)
|
||||
return ok({'deleted': deleted, 'history': automation_rules.list_history(profile['id'], user_id=user_id), 'cleanup': cleanup_summary()})
|
||||
except Exception as exc:
|
||||
|
||||
@@ -260,14 +260,13 @@ def cleanup_automations():
|
||||
if not profile:
|
||||
return jsonify({"ok": False, "error": "No profile"}), 400
|
||||
profile_id = int(profile["id"])
|
||||
user_id = default_user_id()
|
||||
with connect() as conn:
|
||||
exists = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='automation_history'").fetchone()
|
||||
if not exists:
|
||||
deleted = 0
|
||||
else:
|
||||
# Note: Cleanup panel removes only current-user automation logs for the active profile; saved rules stay intact.
|
||||
cur = conn.execute("DELETE FROM automation_history WHERE user_id=? AND profile_id=?", (user_id, profile_id))
|
||||
# Note: Automation history is profile-scoped and can include rules owned by multiple users.
|
||||
cur = conn.execute("DELETE FROM automation_history WHERE profile_id=?", (profile_id,))
|
||||
deleted = int(cur.rowcount or 0)
|
||||
return ok({"deleted": deleted, "cleanup": cleanup_summary()})
|
||||
|
||||
@@ -303,8 +302,8 @@ def cleanup_all():
|
||||
if not exists_auto:
|
||||
deleted_auto = 0
|
||||
else:
|
||||
# Note: Full cleanup clears only the current user's automation history for the active profile.
|
||||
cur = conn.execute("DELETE FROM automation_history WHERE user_id=? AND profile_id=?", (default_user_id(), active_profile_id))
|
||||
# Note: Full cleanup clears automation history for the active profile, regardless of rule owner.
|
||||
cur = conn.execute("DELETE FROM automation_history WHERE profile_id=?", (active_profile_id,))
|
||||
deleted_auto = int(cur.rowcount or 0)
|
||||
return ok({"deleted": {"jobs": deleted_jobs, "smart_queue_history": deleted_smart, "operation_logs": deleted_logs, "planner_history": deleted_planner, "automation_history": deleted_auto}, "cleanup": cleanup_summary()})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user