-- 260921-pi9 — Bilderrahmen-Widget: hochgeladene Bilder eines Benutzers. -- -- Zweck: die Tabelle "DashboardImage" traegt die Bilddaten (bytea) fuer das -- Dashboard-Widget „Bilderrahmen“. Bilder liegen in der Datenbank statt in -- einem Docker-Volume, damit die bestehende Sicherung sie mit abdeckt. -- -- Grenzen (durchgesetzt in der Anwendung, apps/api/src/dashboard/ -- dashboard-image-rules.ts + dashboard-images.service.ts): hoechstens 5 MiB -- je Datei (multer-Limit je Route), hoechstens 30 Bilder je Benutzer -- (Zaehler je Mandant+Benutzer vor dem Anlegen); erlaubt sind nur PNG, JPEG, -- GIF und WebP, erkannt an den Magic Bytes — "mimeType" ist der ERKANNTE Typ, -- nie der vom Browser behauptete. -- -- Besitz: ein Bild gehoert dem hochladenden Benutzer (gleicher Mandant UND -- gleicher Benutzer). Die Regel unten traegt deshalb von Anfang an die -- Benutzerdimension (Form aus 20260911120000_rls_user_dimension_personal_ -- tables); die Anwendung prueft den Besitz zusaetzlich in getBytes/remove und -- antwortet fuer fremde Kennungen mit 404 (nie 403). -- -- Rechte fuer die Anwendungsrolle tessera_app: kommen ueber ALTER DEFAULT -- PRIVILEGES aus 20260909130000_rls_app_role automatisch — hier nichts zu tun. -- -- WICHTIG: wie alle RLS-Regeln dieses Schemas wirkt die Regel erst, wenn die -- Anwendung als Rolle ohne Umgehungsrecht verbindet (Schalter heute AUS, siehe -- docs/mandantentrennung-datenbankrolle.md). -- CreateTable CREATE TABLE "DashboardImage" ( "id" TEXT NOT NULL, "userId" TEXT NOT NULL, "tenantId" TEXT NOT NULL, "originalName" TEXT NOT NULL, "mimeType" TEXT NOT NULL, "size" INTEGER NOT NULL, "data" BYTEA NOT NULL, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "DashboardImage_pkey" PRIMARY KEY ("id") ); -- CreateIndex CREATE INDEX "DashboardImage_userId_idx" ON "DashboardImage"("userId"); -- CreateIndex CREATE INDEX "DashboardImage_tenantId_idx" ON "DashboardImage"("tenantId"); -- Zeilenschutz: Mandant UND Benutzer (Muster 20260911120000) ALTER TABLE "DashboardImage" ENABLE ROW LEVEL SECURITY; ALTER TABLE "DashboardImage" FORCE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation_policy ON "DashboardImage" USING ( "tenantId" = current_tenant_id() AND (current_user_id() IS NULL OR "userId" = current_user_id()) );