FIX: 11 bugs bảo mật/ổn định (static mount chặn dotfile, delete traversal, cleanup giữ clips serverFileId, upload whitelist, password strength, auth audio endpoints, pedalboard==0.9.19, vendor CDN local) + FEATURE: Carla bridge preview/export MIDI notes âm VSTi (POST /midi-render, /carla-play-notes, nút Preview VSTi/Export MIDI->Audio; pedalboard 0.9.19 raw MIDI bytes; SONICFORGE_STORAGE_DIR cô lập test storage)
This commit is contained in:
+36
-5
@@ -371,16 +371,46 @@ def cleanup_expired_files_task(max_age_hours: int = 24):
|
||||
"""
|
||||
now = time.time()
|
||||
max_age_seconds = max_age_hours * 3600
|
||||
|
||||
|
||||
# Bug #3: KHÔNG xóa file đang được project tham chiếu (tracks[].serverFileId)
|
||||
# — trước đây xóa mọi file > 24h → mất audio của project đã lưu (JSON còn,
|
||||
# file mất, track câm). Quét DB giống list_user_files.
|
||||
referenced = set()
|
||||
try:
|
||||
import json as _json
|
||||
from app.models.user import get_db_connection
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT data_json FROM projects")
|
||||
for row in cursor.fetchall():
|
||||
try:
|
||||
proj = _json.loads(row["data_json"])
|
||||
except Exception:
|
||||
continue
|
||||
for track in proj.get("tracks", []):
|
||||
fid = track.get("serverFileId")
|
||||
if fid:
|
||||
referenced.add(os.path.basename(fid.replace("\\", "/")))
|
||||
# Clip audio (kể cả clip sinh từ MIDI render) cũng giữ file
|
||||
for clip in track.get("clips", []):
|
||||
cfid = clip.get("serverFileId")
|
||||
if cfid:
|
||||
referenced.add(os.path.basename(cfid.replace("\\", "/")))
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
logger.warning("cleanup: không đọc được projects DB, bỏ qua tham chiếu: %s", e)
|
||||
|
||||
cleaned_count = 0
|
||||
cleaned_size = 0
|
||||
|
||||
|
||||
for directory in [settings.PROCESSED_DIR]:
|
||||
if not os.path.exists(directory):
|
||||
continue
|
||||
|
||||
|
||||
for filepath in glob.glob(os.path.join(directory, "*")):
|
||||
if os.path.isfile(filepath):
|
||||
if os.path.basename(filepath) in referenced:
|
||||
continue
|
||||
file_age = now - os.path.getmtime(filepath)
|
||||
if file_age > max_age_seconds:
|
||||
file_size = os.path.getsize(filepath)
|
||||
@@ -390,11 +420,12 @@ def cleanup_expired_files_task(max_age_hours: int = 24):
|
||||
cleaned_size += file_size
|
||||
except Exception as e:
|
||||
logger.warning("Failed to remove expired file %s: %s", filepath, e)
|
||||
|
||||
|
||||
return {
|
||||
"cleaned_files": cleaned_count,
|
||||
"cleaned_size_mb": round(cleaned_size / (1024 * 1024), 2),
|
||||
"max_age_hours": max_age_hours
|
||||
"max_age_hours": max_age_hours,
|
||||
"referenced_files_kept": len(referenced),
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user