fix disk monitor preferences profile ownership
This commit is contained in:
@@ -28,7 +28,7 @@ PROFILE_BACKUP_TABLES = [
|
||||
PROFILE_TABLE_SCOPES = {
|
||||
"rtorrent_profiles": "profile_id",
|
||||
"profile_preferences": "user_profile",
|
||||
"disk_monitor_preferences": "user_profile",
|
||||
"disk_monitor_preferences": "profile",
|
||||
"labels": "profile",
|
||||
"ratio_groups": "profile",
|
||||
"rss_feeds": "profile",
|
||||
@@ -44,7 +44,7 @@ PROFILE_TABLE_SCOPES = {
|
||||
PROFILE_TABLE_FILTERS = {
|
||||
"rtorrent_profiles": "id=?",
|
||||
"profile_preferences": "user_id=? AND profile_id=?",
|
||||
"disk_monitor_preferences": "user_id=? AND profile_id=?",
|
||||
"disk_monitor_preferences": "profile_id=?",
|
||||
"labels": "profile_id=?",
|
||||
"ratio_groups": "profile_id=?",
|
||||
"rss_feeds": "profile_id=?",
|
||||
@@ -273,6 +273,12 @@ def restore_app_backup(backup_id: int, user_id: int | None = None) -> dict:
|
||||
return {"restored": restored, "backup_type": "app"}
|
||||
|
||||
|
||||
def _single_profile_row(rows: list[dict]) -> list[dict]:
|
||||
if not rows:
|
||||
return []
|
||||
return [sorted(rows, key=lambda row: str(row.get("updated_at") or row.get("created_at") or ""), reverse=True)[0]]
|
||||
|
||||
|
||||
def _rewrite_profile_row(table: str, row: dict, user_id: int, target_profile_id: int) -> dict:
|
||||
clean = dict(row)
|
||||
if table == "rtorrent_profiles":
|
||||
@@ -305,6 +311,8 @@ def restore_profile_backup(backup_id: int, target_profile_id: int, user_id: int
|
||||
try:
|
||||
for table in PROFILE_BACKUP_TABLES:
|
||||
rows = tables.get(table) or []
|
||||
if table == "disk_monitor_preferences":
|
||||
rows = _single_profile_row([dict(row) for row in rows])
|
||||
where = PROFILE_TABLE_FILTERS.get(table)
|
||||
params = _profile_filter_params(table, user_id, int(target_profile_id))
|
||||
conn.execute(f"DELETE FROM {table} WHERE {where}", params)
|
||||
|
||||
@@ -296,17 +296,39 @@ def legacy_disk_monitor_preferences(user_id: int | None = None) -> dict:
|
||||
return _normalize_disk_monitor(row)
|
||||
|
||||
|
||||
def _disk_monitor_owner_label(row: dict | None) -> str:
|
||||
if not row:
|
||||
return ""
|
||||
return str(row.get("owner_display_name") or row.get("owner_username") or row.get("owner_email") or (f"user #{row.get('user_id')}" if row.get("user_id") else "")).strip()
|
||||
|
||||
|
||||
def get_disk_monitor_preferences(profile_id: int | None = None, user_id: int | None = None) -> dict:
|
||||
user_id = user_id or auth.current_user_id() or default_user_id()
|
||||
profile_id = int(profile_id or _active_profile_id_for_user(user_id) or 0)
|
||||
if not profile_id:
|
||||
return legacy_disk_monitor_preferences(user_id)
|
||||
if not auth.can_access_profile(profile_id, user_id):
|
||||
return legacy_disk_monitor_preferences(user_id)
|
||||
with connect() as conn:
|
||||
row = conn.execute("SELECT * FROM disk_monitor_preferences WHERE user_id=? AND profile_id=?", (user_id, profile_id)).fetchone()
|
||||
row = conn.execute(
|
||||
"""
|
||||
SELECT d.*, u.username AS owner_username, u.display_name AS owner_display_name, u.email AS owner_email
|
||||
FROM disk_monitor_preferences d
|
||||
LEFT JOIN users u ON u.id=d.user_id
|
||||
WHERE d.profile_id=?
|
||||
""",
|
||||
(profile_id,),
|
||||
).fetchone()
|
||||
if row:
|
||||
return _normalize_disk_monitor(row)
|
||||
clean = _normalize_disk_monitor(row)
|
||||
clean["disk_monitor_owner_user_id"] = int(row.get("user_id") or 0)
|
||||
clean["disk_monitor_owner_label"] = _disk_monitor_owner_label(row)
|
||||
return clean
|
||||
# Backward-compatible seed: existing global disk monitor values become defaults for first use of a profile.
|
||||
return legacy_disk_monitor_preferences(user_id)
|
||||
clean = legacy_disk_monitor_preferences(user_id)
|
||||
clean["disk_monitor_owner_user_id"] = 0
|
||||
clean["disk_monitor_owner_label"] = ""
|
||||
return clean
|
||||
|
||||
|
||||
def save_disk_monitor_preferences(profile_id: int | None, data: dict, user_id: int | None = None) -> dict:
|
||||
@@ -314,6 +336,8 @@ def save_disk_monitor_preferences(profile_id: int | None, data: dict, user_id: i
|
||||
profile_id = int(profile_id or _active_profile_id_for_user(user_id) or 0)
|
||||
if not profile_id:
|
||||
return legacy_disk_monitor_preferences(user_id)
|
||||
if not auth.can_write_profile(profile_id, user_id):
|
||||
raise PermissionError("No write access to profile")
|
||||
current = get_disk_monitor_preferences(profile_id, user_id)
|
||||
merged = dict(current)
|
||||
for key in ("disk_monitor_paths_json", "disk_monitor_mode", "disk_monitor_selected_path", "disk_monitor_stop_enabled", "disk_monitor_stop_threshold"):
|
||||
@@ -323,10 +347,14 @@ def save_disk_monitor_preferences(profile_id: int | None, data: dict, user_id: i
|
||||
now = utcnow()
|
||||
with connect() as conn:
|
||||
conn.execute(
|
||||
"INSERT INTO disk_monitor_preferences(user_id,profile_id,paths_json,mode,selected_path,stop_enabled,stop_threshold,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?) "
|
||||
"ON CONFLICT(user_id,profile_id) DO UPDATE SET paths_json=excluded.paths_json, mode=excluded.mode, selected_path=excluded.selected_path, stop_enabled=excluded.stop_enabled, stop_threshold=excluded.stop_threshold, updated_at=excluded.updated_at",
|
||||
(user_id, profile_id, clean["disk_monitor_paths_json"], clean["disk_monitor_mode"], clean["disk_monitor_selected_path"], clean["disk_monitor_stop_enabled"], clean["disk_monitor_stop_threshold"], now, now),
|
||||
"INSERT INTO disk_monitor_preferences(profile_id,user_id,paths_json,mode,selected_path,stop_enabled,stop_threshold,created_at,updated_at) VALUES(?,?,?,?,?,?,?,?,?) "
|
||||
"ON CONFLICT(profile_id) DO UPDATE SET user_id=excluded.user_id, paths_json=excluded.paths_json, mode=excluded.mode, selected_path=excluded.selected_path, stop_enabled=excluded.stop_enabled, stop_threshold=excluded.stop_threshold, updated_at=excluded.updated_at",
|
||||
(profile_id, user_id, clean["disk_monitor_paths_json"], clean["disk_monitor_mode"], clean["disk_monitor_selected_path"], clean["disk_monitor_stop_enabled"], clean["disk_monitor_stop_threshold"], now, now),
|
||||
)
|
||||
clean["disk_monitor_owner_user_id"] = int(user_id)
|
||||
with connect() as conn:
|
||||
row = conn.execute("SELECT display_name AS owner_display_name, username AS owner_username, email AS owner_email, id AS user_id FROM users WHERE id=?", (user_id,)).fetchone()
|
||||
clean["disk_monitor_owner_label"] = _disk_monitor_owner_label(row)
|
||||
return clean
|
||||
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ def _clear_disk_refresh_cache(profile_id: int) -> None:
|
||||
|
||||
def _emit_profile_disk_refresh(profile_id: int, reason: str, hash_count: int = 0, delay_seconds: int = 0) -> None:
|
||||
_clear_disk_refresh_cache(profile_id)
|
||||
# Note: The browser performs the fresh /api/system/disk read so user-specific disk monitor preferences stay respected.
|
||||
# Note: The browser performs the fresh /api/system/disk read so profile-scoped disk monitor preferences stay respected.
|
||||
_emit("disk_refresh_requested", {
|
||||
"profile_id": int(profile_id),
|
||||
"hash_count": int(hash_count or 0),
|
||||
|
||||
Reference in New Issue
Block a user