mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-09-16 05:02:21 +02:00
fix(tasks): scope action_tidy_research broken-file sweep to admins (#6069)
action_tidy_research took an `owner` argument and never used it. Any user's scheduled tidy task swept data/deep_research globally, unlinking every empty or unparseable file regardless of who owned it. A broken file has no readable owner stamp, so it cannot be matched against `owner` the way _find_owned_research_path does, which is why the HTTP path and manage_research already treat parse failure as not-owned. Clearing one is a privileged act rather than an ownership one, so gate it on the canonical owner_is_admin_or_single_user helper: admins and the single-user operator keep the janitor, a regular user does not, and neither does the pre-setup window before an admin exists. Returns before the directory glob rather than filtering inside the loop, so a denied run reports why instead of reporting "none broken" over files it never inspected. That reason string surfaces in Activity as a skipped row.
This commit is contained in:
+15
-1
@@ -810,13 +810,27 @@ async def action_tidy_research(owner: str, **kwargs) -> Tuple[str, bool]:
|
||||
|
||||
Research history lives entirely in data/deep_research/<id>.json and is NOT
|
||||
backed by chat-session rows — so a file must never be deleted just because
|
||||
no chat session matches its id. Only prune files that fail to load."""
|
||||
no chat session matches its id. Only prune files that fail to load.
|
||||
|
||||
A broken file has no readable owner stamp, so it cannot be matched against
|
||||
`owner`. Clearing one is privileged: admins and the single-user operator
|
||||
(AUTH_ENABLED=false) may, a regular user may not, and neither may anyone
|
||||
during the pre-setup window before an admin exists.
|
||||
"""
|
||||
try:
|
||||
from pathlib import Path
|
||||
import json as _json
|
||||
from src.tool_security import owner_is_admin_or_single_user
|
||||
research_dir = Path(DEEP_RESEARCH_DIR)
|
||||
if not research_dir.exists():
|
||||
raise TaskNoop("no research directory")
|
||||
if not owner_is_admin_or_single_user(owner):
|
||||
# Return before the glob rather than filtering inside the loop: the
|
||||
# loop reports "none broken" off an empty `removed`, which reaches
|
||||
# Activity as a false report to a user whose files it skipped, and a
|
||||
# regular user need not read every owner's file to learn it may
|
||||
# delete none of them.
|
||||
raise TaskNoop("not permitted to remove unattributable research files")
|
||||
files = list(research_dir.glob("*.json"))
|
||||
removed = []
|
||||
for p in files:
|
||||
|
||||
Reference in New Issue
Block a user