feat(260923-lrr): API — Favoriten-Symbol hochladen, Vorrang, Versionszaehler, Abrufprobe

- FavoriteLink: neue Spalten uploadedIconMime/iconVersion (Migration 20260923160000)
- favorite-icon-files.ts: Erkennung PNG/JPEG/GIF/WebP/ICO/SVG, Pfadbildung ohne
  Byte aus der Anfrage im Pfad (T-LRR-01), best-effort Dateientfernung
- FavoritesService: uploadIcon/removeUploadedIcon, Vorrang der hochgeladenen
  Datei in getIconBytes, Abrufprobe fuer eine neue iconUrl (422 statt stiller
  Speicherung), iconVersion-Erhoehung bei jeder Aenderung der Symbolquelle
- FavoritesController: POST/DELETE /favorites/:id/icon, Cache-Control private
- T-LRR-07 (Restrisiko aus dem Plan-Threat-Model geschlossen, ueber den Plan
  hinaus): DashboardService.removeWidget/deleteDashboard raeumen jetzt die
  Symboldateien der per Datenbank-Kaskade mitgeloeschten Favoriten auf
  (best effort, nie blockierend)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-23 16:04:29 +02:00
parent bf4384ad73
commit 7704372c3c
11 changed files with 1454 additions and 21 deletions
+10
View File
@@ -419,6 +419,16 @@ model FavoriteLink {
title String
url String
iconUrl String?
// quick-260923-lrr: Typ eines hochgeladenen eigenen Symbols (erkannt an
// den Bytes, NIE aus der Anfrage uebernommen); null = kein hochgeladenes
// Symbol. Kein Pfad gespeichert — die Datei liegt ableitbar unter
// user-files/favorite-icons/<userId>/<id>.<ext>.
uploadedIconMime String?
// quick-260923-lrr: Zaehler fuer die ausgelieferte Symbol-Adresse
// (?v=<iconVersion>), steigt bei jeder Aenderung der Symbolquelle
// (neue iconUrl, Upload, Entfernen) — macht den 24-h-Browser-Zwischenspeicher
// nach einer Aenderung sofort ungueltig.
iconVersion Int @default(0)
position Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt