profles_and_ux #7

Merged
gru merged 10 commits from profles_and_ux into master 2026-05-27 14:38:06 +02:00
15 changed files with 30 additions and 19 deletions
Showing only changes of commit 514482f0b5 - Show all commits

View File

@@ -198,12 +198,17 @@ def cleanup_jobs():
@bp.post("/cleanup/smart-queue") @bp.post("/cleanup/smart-queue")
def cleanup_smart_queue(): def cleanup_smart_queue():
profile = preferences.active_profile()
if not profile:
return jsonify({"ok": False, "error": "No profile"}), 400
profile_id = int(profile["id"])
with connect() as conn: with connect() as conn:
exists = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='smart_queue_history'").fetchone() exists = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='smart_queue_history'").fetchone()
if not exists: if not exists:
deleted = 0 deleted = 0
else: else:
cur = conn.execute("DELETE FROM smart_queue_history") # Note: Cleanup is limited to the active profile so read/write permissions never affect other profiles.
cur = conn.execute("DELETE FROM smart_queue_history WHERE profile_id=?", (profile_id,))
deleted = int(cur.rowcount or 0) deleted = int(cur.rowcount or 0)
return ok({"deleted": deleted, "cleanup": cleanup_summary()}) return ok({"deleted": deleted, "cleanup": cleanup_summary()})
@@ -232,13 +237,17 @@ def cleanup_planner():
@bp.post("/cleanup/automations") @bp.post("/cleanup/automations")
def cleanup_automations(): def cleanup_automations():
profile = preferences.active_profile()
if not profile:
return jsonify({"ok": False, "error": "No profile"}), 400
profile_id = int(profile["id"])
with connect() as conn: with connect() as conn:
exists = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='automation_history'").fetchone() exists = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='automation_history'").fetchone()
if not exists: if not exists:
deleted = 0 deleted = 0
else: else:
# Note: Cleanup panel removes only automation logs, not saved automation rules. # Note: Cleanup panel removes only active profile automation logs, not saved automation rules.
cur = conn.execute("DELETE FROM automation_history") cur = conn.execute("DELETE FROM automation_history WHERE profile_id=?", (profile_id,))
deleted = int(cur.rowcount or 0) deleted = int(cur.rowcount or 0)
return ok({"deleted": deleted, "cleanup": cleanup_summary()}) return ok({"deleted": deleted, "cleanup": cleanup_summary()})
@@ -256,13 +265,13 @@ def cleanup_all():
if not exists: if not exists:
deleted_smart = 0 deleted_smart = 0
else: else:
cur = conn.execute("DELETE FROM smart_queue_history") cur = conn.execute("DELETE FROM smart_queue_history WHERE profile_id=?", (active_profile_id,))
deleted_smart = int(cur.rowcount or 0) deleted_smart = int(cur.rowcount or 0)
exists_auto = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='automation_history'").fetchone() exists_auto = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='automation_history'").fetchone()
if not exists_auto: if not exists_auto:
deleted_auto = 0 deleted_auto = 0
else: else:
cur = conn.execute("DELETE FROM automation_history") cur = conn.execute("DELETE FROM automation_history WHERE profile_id=?", (active_profile_id,))
deleted_auto = int(cur.rowcount or 0) 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()}) 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()})

View File

@@ -35,6 +35,7 @@ RTORRENT_WRITE_PREFIXES = (
"/api/poller/settings", "/api/poller/settings",
"/api/operation-logs", "/api/operation-logs",
"/api/jobs", "/api/jobs",
"/api/cleanup",
) )
RTORRENT_CONFIG_PREFIXES = ("/api/rtorrent-config",) RTORRENT_CONFIG_PREFIXES = ("/api/rtorrent-config",)
ADMIN_PREFIXES = ("/api/auth/users", "/api/profiles") ADMIN_PREFIXES = ("/api/auth/users", "/api/profiles")

View File

@@ -344,8 +344,9 @@ def save_auto_backup_settings(data: dict, user_id: int | None = None, backup_typ
if backup_type == "app": if backup_type == "app":
_require_admin(user_id) _require_admin(user_id)
else: else:
if not profile_id or not auth.can_access_profile(int(profile_id), user_id): # Note: Profile backup schedules affect profile operations, so read-only users may view/export backups but cannot change automation.
raise PermissionError("No access to profile") if not profile_id or not auth.can_write_profile(int(profile_id), user_id):
raise PermissionError("No write access to profile")
current = get_auto_backup_settings(user_id, backup_type, profile_id) current = get_auto_backup_settings(user_id, backup_type, profile_id)
settings = { settings = {
**current, **current,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long