From 93fe2219b92c611bf45fa44cd4ec588d5b4be877 Mon Sep 17 00:00:00 2001 From: team3 Date: Thu, 8 Oct 2026 16:03:27 +0200 Subject: [PATCH] update --- backend/app/clips.py | 15 +++---- backend/tests/test_clips.py | 7 ++-- frontend/src/App.vue | 2 +- frontend/src/components/ClipBild.vue | 58 ++++++++++++++++++++++++++ frontend/src/components/ClipEditor.vue | 18 ++++++-- frontend/src/components/ClipsTab.vue | 19 +++++---- 6 files changed, 94 insertions(+), 25 deletions(-) create mode 100644 frontend/src/components/ClipBild.vue diff --git a/backend/app/clips.py b/backend/app/clips.py index 35e7e86..36cf522 100644 --- a/backend/app/clips.py +++ b/backend/app/clips.py @@ -105,7 +105,8 @@ def holen(clip_id, session_id): def alle(session_id, host=False): - """Die eigenen Clips; der Host sieht alle — er räumt auf.""" + """Alle Clips, für jeden. Ändern darf nur der Besitzer — und der Host, + der aufräumt; dafür steht an jedem Clip, ob er einem gehört.""" ich = besitzer(session_id) with connect() as conn: rows = conn.execute( @@ -114,11 +115,7 @@ def alle(session_id, host=False): "LEFT JOIN movies m ON m.id = c.movie_id " "ORDER BY c.marke_at DESC" ).fetchall() - return [ - _oeffentlich(r, session_id, ich) - for r in rows - if host or gehoert_mir(r, session_id, ich) - ] + return [_oeffentlich(r, session_id, ich) for r in rows] def _zeile(conn, clip_id): @@ -189,10 +186,10 @@ def playback_url(row, vorher=None, dauer=None): def zeile(clip_id, session_id, host): - """Die rohe Zeile, wenn man sie sehen darf: Besitzer oder Host.""" + """Die rohe Zeile zum Ansehen — Clips sieht jeder. Ändern und + Löschen prüfen gesondert, ob es der Besitzer oder der Host ist.""" with connect() as conn: - row = _zeile(conn, clip_id) - return row if _darf(row, session_id, host) else None + return _zeile(conn, clip_id) async def schneiden(clip_id, session_id, host): diff --git a/backend/tests/test_clips.py b/backend/tests/test_clips.py index b580d44..02d1a6e 100644 --- a/backend/tests/test_clips.py +++ b/backend/tests/test_clips.py @@ -116,11 +116,12 @@ def test_taste_c_nimmt_den_film_der_laufenden_aufnahme(client, zuschauer, hostmo assert marke(client)["movie_id"] == film(3) -def test_fremde_sehen_nichts_der_host_alles(client, client2, zuschauer, hostmodus): +def test_alle_sehen_clips_aendern_nur_besitzer_und_host(client, client2, zuschauer, hostmodus): m = marke(client) - assert [c for c in client2.get("/api/clips").json() if c["id"] == m["id"]] == [] + fremd = [c for c in client2.get("/api/clips").json() if c["id"] == m["id"]] + assert len(fremd) == 1 and fremd[0]["mine"] is False assert client2.patch(f"/api/clips/{m['id']}", json={"titel": "x"}).status_code == 404 - assert client2.get(f"/api/clips/{m['id']}/video").status_code == 404 + assert client2.delete(f"/api/clips/{m['id']}").status_code == 404 hostmodus(zuschauer) assert zuschauer.patch(f"/api/clips/{m['id']}", json={"titel": "Vom Host"}).json()["titel"] == "Vom Host" assert zuschauer.get("/api/clips").json()[0]["id"] == m["id"] diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 4a26a39..3d88adf 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -144,7 +144,7 @@ const tabs = computed(() => [ { id: 'merkliste', label: 'Sammlungen', count: null }, { id: 'wheel', label: 'Rad', count: null }, { id: 'stream', label: 'Stream', count: null }, - ...(angemeldet.value || host.value ? [{ id: 'clips', label: 'Clips', count: null }] : []), + { id: 'clips', label: 'Clips', count: null }, { id: 'watched', label: 'Gesehen', count: gesehenZahl.value }, { id: 'wuensche', diff --git a/frontend/src/components/ClipBild.vue b/frontend/src/components/ClipBild.vue new file mode 100644 index 0000000..0c62394 --- /dev/null +++ b/frontend/src/components/ClipBild.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/frontend/src/components/ClipEditor.vue b/frontend/src/components/ClipEditor.vue index 1e1d834..1f0d2cd 100644 --- a/frontend/src/components/ClipEditor.vue +++ b/frontend/src/components/ClipEditor.vue @@ -6,6 +6,9 @@ import ClipTrimmer from './ClipTrimmer.vue' const props = defineProps({ clip: { type: Object, required: true }, + // Besitzer und Host dürfen schneiden, ändern und löschen — alle + // anderen schauen nur + darf: Boolean, }) const emit = defineEmits(['zu', 'geaendert']) @@ -72,6 +75,7 @@ onUnmounted(() => window.removeEventListener('keydown', escape))
window.removeEventListener('keydown', escape)) class="titel" @change="patch({ titel })" /> +

{{ clip.titel || 'Ohne Titel' }}

- + + window.removeEventListener('keydown', escape))

{{ fehler }}

- Herunterladen - +
diff --git a/frontend/src/components/ClipsTab.vue b/frontend/src/components/ClipsTab.vue index c270c32..294953d 100644 --- a/frontend/src/components/ClipsTab.vue +++ b/frontend/src/components/ClipsTab.vue @@ -5,6 +5,7 @@ import { computed, onMounted, onUnmounted, ref } from 'vue' import { abonnieren } from '../live' import { backdropUrl, posterUrl } from '../images' import ClipEditor from './ClipEditor.vue' +import ClipBild from './ClipBild.vue' import PersonName from './PersonName.vue' const props = defineProps({ @@ -149,7 +150,7 @@ onUnmounted(() => abbestellen?.())

Lade Clips…

{{ fehler }}

- Noch keine Marken. Im Stream-Reiter setzt die Taste C eine. + Noch keine Clips. Im Stream-Reiter setzt die Taste C eine Marke.

@@ -159,13 +160,7 @@ onUnmounted(() => abbestellen?.()) - + {{ Math.round(c.dauer) }} s @@ -183,7 +178,13 @@ onUnmounted(() => abbestellen?.())
- +