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:
@@ -11,8 +11,11 @@ client = TestClient(app)
|
||||
|
||||
|
||||
def get_admin_token():
|
||||
resp = client.post("/api/v1/auth/login", json={"username": "admin", "password": "admin123"})
|
||||
if resp.status_code == 200:
|
||||
# test_auth_and_quota.py có thể đã rotate password; thử cả 2.
|
||||
for pwd in ("admin123", "admin_new_password_2026"):
|
||||
resp = client.post("/api/v1/auth/login", json={"username": "admin", "password": pwd})
|
||||
if resp.status_code != 200:
|
||||
continue
|
||||
token = resp.json()["access_token"]
|
||||
# Admin is seeded with must_change_password=1; the app blocks music
|
||||
# processing until the first password change. Complete that flow here
|
||||
@@ -20,7 +23,7 @@ def get_admin_token():
|
||||
user = resp.json()["user"]
|
||||
if user.get("must_change_password"):
|
||||
r = client.post("/api/v1/auth/change-password", headers={"Authorization": f"Bearer {token}"},
|
||||
json={"old_password": "admin123", "new_password": "admin123"})
|
||||
json={"old_password": pwd, "new_password": pwd})
|
||||
if r.status_code == 200:
|
||||
token = r.json()["access_token"]
|
||||
return token
|
||||
@@ -145,3 +148,67 @@ class TestPluginAPI:
|
||||
client.post("/api/v1/plugins/dirs", headers=h, json={"plugin_dirs": [d1]})
|
||||
g = client.get("/api/v1/plugins/dirs", headers=h)
|
||||
assert g.json()["plugin_dirs"] == [d1]
|
||||
|
||||
class TestMidiRenderVSTi:
|
||||
"""Preview/export MIDI notes với âm VSTi — feature Carla bridge → pedalboard."""
|
||||
|
||||
def test_midi_render_requires_auth(self):
|
||||
client.cookies.clear() # TestClient giữ cookie login từ test trước
|
||||
resp = client.post("/api/v1/plugins/midi-render",
|
||||
json={"instrument_id": "x", "notes": [{"pitch": 60}]})
|
||||
assert resp.status_code == 401
|
||||
|
||||
def test_midi_render_no_notes(self):
|
||||
token = get_admin_token()
|
||||
if not token:
|
||||
pytest.skip("Cannot get admin token")
|
||||
resp = client.post("/api/v1/plugins/midi-render", headers={"Authorization": f"Bearer {token}"},
|
||||
json={"instrument_id": "x", "notes": []})
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_midi_render_unknown_instrument(self):
|
||||
token = get_admin_token()
|
||||
if not token:
|
||||
pytest.skip("Cannot get admin token")
|
||||
resp = client.post("/api/v1/plugins/midi-render", headers={"Authorization": f"Bearer {token}"},
|
||||
json={"instrument_id": "NoSuchPluginXYZ",
|
||||
"notes": [{"pitch": 60, "start_beat": 0, "duration_beats": 1, "velocity": 0.8}]})
|
||||
assert resp.status_code == 404
|
||||
assert "VSTi" in resp.json()["detail"]
|
||||
|
||||
def test_midi_render_requires_pedalboard(self):
|
||||
# Nếu pedalboard thiếu → 501 (không crash)
|
||||
import app.api.v1.plugins as plugins_mod
|
||||
token = get_admin_token()
|
||||
if not token:
|
||||
pytest.skip("Cannot get admin token")
|
||||
if not plugins_mod.HAS_PEDALBOARD:
|
||||
resp = client.post("/api/v1/plugins/midi-render", headers={"Authorization": f"Bearer {token}"},
|
||||
json={"instrument_id": "x",
|
||||
"notes": [{"pitch": 60, "start_beat": 0, "duration_beats": 1}]})
|
||||
assert resp.status_code == 501
|
||||
else:
|
||||
pytest.skip("pedalboard present — render path covered by unknown-instrument test")
|
||||
|
||||
def test_carla_play_notes_requires_auth(self):
|
||||
client.cookies.clear() # TestClient giữ cookie login từ test trước
|
||||
resp = client.post("/api/v1/plugins/carla-play-notes",
|
||||
json={"notes": [{"pitch": 60}], "bpm": 120})
|
||||
assert resp.status_code == 401
|
||||
|
||||
def test_carla_play_notes_no_notes(self):
|
||||
token = get_admin_token()
|
||||
if not token:
|
||||
pytest.skip("Cannot get admin token")
|
||||
resp = client.post("/api/v1/plugins/carla-play-notes", headers={"Authorization": f"Bearer {token}"},
|
||||
json={"notes": [], "bpm": 120})
|
||||
assert resp.status_code == 400
|
||||
|
||||
def test_carla_play_notes_no_carla(self):
|
||||
# Máy test không có Carla local → 409 hướng dẫn định vị/mở Carla.
|
||||
token = get_admin_token()
|
||||
if not token:
|
||||
pytest.skip("Cannot get admin token")
|
||||
resp = client.post("/api/v1/plugins/carla-play-notes", headers={"Authorization": f"Bearer {token}"},
|
||||
json={"notes": [{"pitch": 60, "start_beat": 0, "duration_beats": 1}], "bpm": 120})
|
||||
assert resp.status_code == 409
|
||||
|
||||
Reference in New Issue
Block a user