Notiz-Medien & Sprachnachrichten: Fotos/Videos/Dateien + Audio an Notizen
Wiederverwendbarer UI.noteMediaAttacher für beide Notiz-Stellen (UI.noteModal
+ Notizblock-Seite). note_media-Tabelle + POST/DELETE /api/notes/{id}/media
(vor der gierigen /{parent_type}/{parent_id}-Route). Audio per MediaRecorder,
serverseitig nach m4a/AAC transkodiert (ffmpeg) — iOS spielt Chrome-Opus-webm
nicht ab. UI.lightbox global eingeführt. Mikrofon-Policy microphone=(self) +
CSP media-src 'self' blob:, Datenschutz v6. Disk-Cleanup für note_media bei
Notiz-, Account- und Admin-User-Delete. Reine Medien-Notiz ohne Text erlaubt.
noteModal-Bug gefixt: notes.get() liefert Array -> existing[0] statt
existing?.id (verhinderte Bearbeiten, erzeugte Duplikate). 12 neue Tests.
admin.py enthält außerdem KI-Vision-Statusfelder aus paralleler Arbeit
(nicht sauber trennbar ohne interaktives Staging).
This commit is contained in:
parent
203da50e1d
commit
e86d89f3d9
12 changed files with 947 additions and 59 deletions
|
|
@ -59,3 +59,30 @@ def test_delete_account_minimal_user(client):
|
|||
assert resp.status_code == 200, resp.text
|
||||
with db() as conn:
|
||||
assert conn.execute("SELECT 1 FROM users WHERE id=?", (uid,)).fetchone() is None
|
||||
|
||||
|
||||
def test_delete_account_purges_note_media(client):
|
||||
"""Account-Löschung entfernt Notiz-Medien — DB-Zeilen UND Dateien auf Disk."""
|
||||
import io, os
|
||||
from database import db
|
||||
from PIL import Image
|
||||
|
||||
uid, headers = _make_user(client)
|
||||
nid = client.post("/api/notes/diary/1", headers=headers,
|
||||
json={"text": "Mit Foto", "parent_label": "X"}).json()["id"]
|
||||
|
||||
buf = io.BytesIO(); Image.new("RGB", (10, 10), (1, 2, 3)).save(buf, format="JPEG")
|
||||
up = client.post(f"/api/notes/{nid}/media", headers=headers,
|
||||
files={"file": ("f.jpg", buf.getvalue(), "image/jpeg")})
|
||||
assert up.status_code == 200, up.text
|
||||
url = up.json()["url"]
|
||||
fpath = os.path.join(os.getenv("MEDIA_DIR", "/data/media"), url[len("/media/"):])
|
||||
assert os.path.exists(fpath)
|
||||
|
||||
resp = client.delete("/api/profile/account", headers=headers)
|
||||
assert resp.status_code == 200, resp.text
|
||||
|
||||
with db() as conn:
|
||||
assert conn.execute("SELECT COUNT(*) c FROM note_media WHERE note_id=?", (nid,)).fetchone()["c"] == 0
|
||||
assert conn.execute("SELECT COUNT(*) c FROM notes WHERE user_id=?", (uid,)).fetchone()["c"] == 0
|
||||
assert not os.path.exists(fpath), "note_media-Datei blieb als Leiche auf Disk"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue