Hochgeladene Assets #344

Closed
opened 2026-10-06 21:47:23 +02:00 by admin · 3 comments

Grundsätzliche Frage: haben diese einen Besitzer? wenn nein, dann müsste dieser gespeichert werden. Dann: Admins und User mit Besitzrechten sollten diese hochgeladenen Dateien auch wieder löschen können. Außerdem sollen nur Admins und User mit Besitzrechten diese hochgeladenen Dateien sehen bei der Auswahl (Sounds, Texturen, Fonts, etc.) - Assets ohne Besitz sehen alle

Grundsätzliche Frage: haben diese einen Besitzer? wenn nein, dann müsste dieser gespeichert werden. Dann: Admins und User mit Besitzrechten sollten diese hochgeladenen Dateien auch wieder löschen können. Außerdem sollen nur Admins und User mit Besitzrechten diese hochgeladenen Dateien sehen bei der Auswahl (Sounds, Texturen, Fonts, etc.) - Assets ohne Besitz sehen alle
admin added the high-priority label 2026-10-06 21:47:23 +02:00
admin added this to the Development project 2026-10-06 21:47:23 +02:00
admin moved this to Next in Development on 2026-10-06 21:47:25 +02:00
Owner

Plan und Entscheidungen (2026-10-07)

Befund: Hochgeladene Dateien haben heute keinen Besitzer. Texturen, Fonts und Sounds liegen für alle Konten gemeinsam in data/<art>/<sha256>.<ext>, jeder angemeldete Nutzer sieht im Picker alle, löschen dürfen nur Admins über die API. Pixel-Cels und Plugins tauchen in keinem Picker auf und bleiben draußen.

Entscheidungen

  • Ein Unterordner pro Konto statt einer Besitzerliste: data/<art>/<ordner>/<sha256>.<ext>. Wem eine Datei gehört, steht im Pfad.
  • Ordnername = feste Kennung pro Konto (12 Hex-Zeichen, in users.json). Umbenennen ändert nichts an Dateien und Verweisen, in URLs veröffentlichter Spiele steht kein Kontoname.
  • Der Ordner ist Teil von asset.file (<ordner>/<hash>.<ext>), weil ein Projekt Dateien aus mehreren Ordnern enthalten kann. Namen ohne Ordner bleiben gültig und heißen „ohne Besitzer“.
  • Picker: Ein User sieht seine eigenen Dateien und die ohne Besitzer. Ein Admin sieht alle, mit Besitzer in der Infozeile.
  • Löschen (1a): Knopf Delete im Picker. Ein User löscht nur im eigenen Ordner, ein Admin überall. Abgelehnt, solange ein Projekt, Snapshot oder Release irgendeines Kontos die Datei verwendet. Die Meldung nennt eigene Projekte beim Namen, fremde nur als „Projekt eines anderen Kontos“.
  • Bestand (2a): Jede verwendete Datei wandert in den Ordner des Kontos, das sie verwendet (bei zwei Konten bekommt jedes eine Kopie). Verweise in Projekten, Snapshots und Releases werden auf den neuen Pfad umgeschrieben. Unbenutzte Dateien bleiben ohne Besitzer und für alle sichtbar. Vorher Backup von data/.
  • Gelöschtes Konto (3a): Der Ordner bleibt, nur Admins sehen ihn.
  • Die URL einer Datei bleibt ohne Login ladbar, weil veröffentlichte Spiele das brauchen. Der Besitz regelt, was der Picker zeigt und wer löscht.
  • Lädt ein zweites Konto dieselben Bytes hoch, liegt die Datei zweimal auf dem Server (je Konto einmal).
## Plan und Entscheidungen (2026-10-07) **Befund:** Hochgeladene Dateien haben heute keinen Besitzer. Texturen, Fonts und Sounds liegen für alle Konten gemeinsam in `data/<art>/<sha256>.<ext>`, jeder angemeldete Nutzer sieht im Picker alle, löschen dürfen nur Admins über die API. Pixel-Cels und Plugins tauchen in keinem Picker auf und bleiben draußen. ### Entscheidungen - **Ein Unterordner pro Konto** statt einer Besitzerliste: `data/<art>/<ordner>/<sha256>.<ext>`. Wem eine Datei gehört, steht im Pfad. - **Ordnername = feste Kennung pro Konto** (12 Hex-Zeichen, in `users.json`). Umbenennen ändert nichts an Dateien und Verweisen, in URLs veröffentlichter Spiele steht kein Kontoname. - **Der Ordner ist Teil von `asset.file`** (`<ordner>/<hash>.<ext>`), weil ein Projekt Dateien aus mehreren Ordnern enthalten kann. Namen ohne Ordner bleiben gültig und heißen „ohne Besitzer“. - **Picker:** Ein User sieht seine eigenen Dateien und die ohne Besitzer. Ein Admin sieht alle, mit Besitzer in der Infozeile. - **Löschen (1a):** Knopf *Delete* im Picker. Ein User löscht nur im eigenen Ordner, ein Admin überall. Abgelehnt, solange ein Projekt, Snapshot oder Release irgendeines Kontos die Datei verwendet. Die Meldung nennt eigene Projekte beim Namen, fremde nur als „Projekt eines anderen Kontos“. - **Bestand (2a):** Jede verwendete Datei wandert in den Ordner des Kontos, das sie verwendet (bei zwei Konten bekommt jedes eine Kopie). Verweise in Projekten, Snapshots und Releases werden auf den neuen Pfad umgeschrieben. Unbenutzte Dateien bleiben ohne Besitzer und für alle sichtbar. Vorher Backup von `data/`. - **Gelöschtes Konto (3a):** Der Ordner bleibt, nur Admins sehen ihn. - Die URL einer Datei bleibt ohne Login ladbar, weil veröffentlichte Spiele das brauchen. Der Besitz regelt, was der Picker zeigt und wer löscht. - Lädt ein zweites Konto dieselben Bytes hoch, liegt die Datei zweimal auf dem Server (je Konto einmal).
Owner

Erledigt mit 6b49a0b (Repo) und Wiki 1fa1da1.

Was jetzt gilt

  • Jedes Konto lädt in einen eigenen Ordner hoch: data/<art>/<ordner>/<sha256>.<ext>. Der Ordner steht mit in asset.file. Ein Name ohne Ordner gehört niemandem.
  • Der Ordner ist eine feste Kennung aus 12 Zeichen in users.json, vergeben beim ersten Upload. Umbenennen eines Kontos verschiebt nichts, und in den URLs veröffentlichter Spiele steht kein Kontoname.
  • Picker: Ein User sieht seine eigenen Dateien und die ohne Besitzer, ein Admin sieht alle. Unter der Liste steht der Besitzer („owner …“, „no owner“, „owner deleted“).
  • Delete im Picker: Der erste Druck fragt nach („Delete for good“), der zweite löscht. Ein User darf nur eigene Dateien löschen, ein Admin alle.
  • Solange ein Projekt, Snapshot oder Release irgendeines Kontos die Datei verwendet, antwortet der Server mit 409. Die Meldung nennt eigene Projekte beim Namen, fremde nur als „a project of another account“.
  • Der Ordner eines gelöschten Kontos bleibt, nur Admins sehen ihn.
  • Pixel-Cels und Plugins sind nicht betroffen.

Migration (2a)

  • Backup: /root/config-backup-20261007/data-before-344. Vorher lief ein Probelauf auf einer Kopie, ein zweiter Lauf hat dort nichts mehr geändert.
  • 25 verwendete Dateien sind in den Ordner ihres Kontos gewandert, als 27 Kopien (zwei nutzen e2e und user gemeinsam).
  • Umgeschrieben: 8 Projekte (Revision +1), 53 Snapshots, 1 Release. 30 unbenutzte Dateien bleiben ohne Besitzer.
  • Danach zeigen alle 600 Verweise auf eine vorhandene Datei im Ordner ihres Besitzers.
  • Das Skript liegt als tools/migrate-file-owners.php (mit --dry-run) im Repo.

Tests

PHP files.test.php (neu)   → 46 Checks, Gegenprobe 3 rot
Unit core + editor         → 220 Dateien, 3403 grün
e2e 34 (melektaus-atx)     → ALL PASSED – 67 Checks (2 neu)
Gate (melektaus-atx)       → CHECK EXIT 0, 256 Dateien, 3977 Tests
  • Per HTTP mit e2e und e2e-admin gemessen: eigene verwendete Datei 409, fremde oder besitzerlose 403, Pfadtricks 404.
  • Gefunden beim Bauen: Der Knopftext wurde nach dem ersten Druck zu „Del…“ abgeschnitten. Behoben, e2e prüft jetzt den angezeigten Text.

Nicht geprüft

  • Die 409-Meldung im Picker und die Ansicht als Admin im Browser. Beides ist nur per HTTP und im PHP-Test gemessen.
  • Den CI-Lauf zu 6b49a0b habe ich nicht abgewartet.
Erledigt mit `6b49a0b` (Repo) und Wiki `1fa1da1`. ## Was jetzt gilt - Jedes Konto lädt in einen eigenen Ordner hoch: `data/<art>/<ordner>/<sha256>.<ext>`. Der Ordner steht mit in `asset.file`. Ein Name ohne Ordner gehört niemandem. - Der Ordner ist eine feste Kennung aus 12 Zeichen in `users.json`, vergeben beim ersten Upload. Umbenennen eines Kontos verschiebt nichts, und in den URLs veröffentlichter Spiele steht kein Kontoname. - Picker: Ein User sieht seine eigenen Dateien und die ohne Besitzer, ein Admin sieht alle. Unter der Liste steht der Besitzer („owner …“, „no owner“, „owner deleted“). - *Delete* im Picker: Der erste Druck fragt nach („Delete for good“), der zweite löscht. Ein User darf nur eigene Dateien löschen, ein Admin alle. - Solange ein Projekt, Snapshot oder Release irgendeines Kontos die Datei verwendet, antwortet der Server mit 409. Die Meldung nennt eigene Projekte beim Namen, fremde nur als „a project of another account“. - Der Ordner eines gelöschten Kontos bleibt, nur Admins sehen ihn. - Pixel-Cels und Plugins sind nicht betroffen. ## Migration (2a) - Backup: `/root/config-backup-20261007/data-before-344`. Vorher lief ein Probelauf auf einer Kopie, ein zweiter Lauf hat dort nichts mehr geändert. - 25 verwendete Dateien sind in den Ordner ihres Kontos gewandert, als 27 Kopien (zwei nutzen `e2e` und `user` gemeinsam). - Umgeschrieben: 8 Projekte (Revision +1), 53 Snapshots, 1 Release. 30 unbenutzte Dateien bleiben ohne Besitzer. - Danach zeigen alle 600 Verweise auf eine vorhandene Datei im Ordner ihres Besitzers. - Das Skript liegt als `tools/migrate-file-owners.php` (mit `--dry-run`) im Repo. ## Tests ``` PHP files.test.php (neu) → 46 Checks, Gegenprobe 3 rot Unit core + editor → 220 Dateien, 3403 grün e2e 34 (melektaus-atx) → ALL PASSED – 67 Checks (2 neu) Gate (melektaus-atx) → CHECK EXIT 0, 256 Dateien, 3977 Tests ``` - Per HTTP mit `e2e` und `e2e-admin` gemessen: eigene verwendete Datei 409, fremde oder besitzerlose 403, Pfadtricks 404. - Gefunden beim Bauen: Der Knopftext wurde nach dem ersten Druck zu „Del…“ abgeschnitten. Behoben, e2e prüft jetzt den angezeigten Text. ## Nicht geprüft - Die 409-Meldung im Picker und die Ansicht als Admin im Browser. Beides ist nur per HTTP und im PHP-Test gemessen. - Den CI-Lauf zu `6b49a0b` habe ich nicht abgewartet.
admin moved this to Done in Development on 2026-10-07 11:05:12 +02:00
Owner

Nachtrag: Der volle CI-Lauf 304 hatte e2e 49a „only an administrator may delete a shared file“ rot. Ein normaler User bekam beim Löschen einer fremden Datei 404 statt 403.

  • Ursache: Seit 6b49a0b hat die DELETE-Route zuerst geprüft, ob die Datei existiert, und erst danach, wem sie gehört. Bei #344 lief nur e2e 34, nicht 49.
  • Fix in 8154569 (api/index.php): zuerst 403, dann 404. Wer keine Rechte hat, erfährt so nicht, welche Dateien es in anderen Ordnern gibt. Vor #344 war es auch so.
  • Tests: e2e 49 allein auf atx ALL PASSED – 22 checks, Gate grün (4040 Tests). Die PHP-Tests decken die Reihenfolge nicht ab.
  • Wiki API nennt die Reihenfolge (7545d2e).
Nachtrag: Der volle CI-Lauf 304 hatte **e2e 49a** „only an administrator may delete a shared file“ rot. Ein normaler User bekam beim Löschen einer fremden Datei 404 statt 403. - **Ursache:** Seit `6b49a0b` hat die DELETE-Route zuerst geprüft, ob die Datei existiert, und erst danach, wem sie gehört. Bei #344 lief nur e2e 34, nicht 49. - **Fix** in `8154569` (`api/index.php`): zuerst 403, dann 404. Wer keine Rechte hat, erfährt so nicht, welche Dateien es in anderen Ordnern gibt. Vor #344 war es auch so. - **Tests:** e2e 49 allein auf atx `ALL PASSED – 22 checks`, Gate grün (4040 Tests). Die PHP-Tests decken die Reihenfolge nicht ab. - Wiki *API* nennt die Reihenfolge (`7545d2e`).
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: meleki/feuerwerk#344