profles_and_ux #7
@@ -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()})
|
||||||
|
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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
2
pytorrent/static/js/bootstrap.js
vendored
2
pytorrent/static/js/bootstrap.js
vendored
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
Reference in New Issue
Block a user