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:
2026-08-10 18:46:54 +07:00
parent 67ad2b8e4b
commit 61cb4b846f
33 changed files with 1097 additions and 103 deletions
+36 -5
View File
@@ -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),
}