diff --git a/TEKNISK_BESKRIVNING.md b/TEKNISK_BESKRIVNING.md index 65e83af9..e59d10c0 100644 --- a/TEKNISK_BESKRIVNING.md +++ b/TEKNISK_BESKRIVNING.md @@ -1032,6 +1032,19 @@ Kvitto-alias lagrar mappningar frÃ¥n kvittots rÃ¥text till produkt-ID. Nä ## Arkitektur: User-scope för baslager och matplan (2026-04-22) +> **Designregel: User-scope vid ny funktionalitet** +> +> All data som tillhör en specifik användare **måste** ha ett `userId`-fält med FK till `User` och user-filtrering i service-lagret. Följ detta mönster vid all ny funktionsutveckling: +> +> 1. **Databasschema:** `userId Int` med `@relation` till `User`, icke-null. Sammansatt `@@unique([userId, ...])` om raden ska vara unik per användare. +> 2. **Migration:** Backfill till första användaren för befintliga rader innan kolumnen sätts NOT NULL. +> 3. **Backend service:** Alla `findAll`/`findOne`/`create`/`delete` filtrerar eller sätter `where: { userId }`. Returnera aldrig andra användares data. +> 4. **Controller:** Extrahera `userId` via `@CurrentUser()` eller `@Request() req` — aldrig från body (säkerhetsrisk). +> 5. **Globala vs. privata resurser:** Produkter och kategorier är globala. Inventarie, baslager, matplan och användarspecifika produkter (`isPrivate: true`) är user-scopade. +> 6. **Privata produkter** (`isPrivate: true`): skapas via `POST /products/private`, visas via `GET /products/mine`. Normaliserat namn prefixas med `private:{userId}:` för att undvika kollision med globala produkter. +> +> **Kontrollera alltid:** Kan två användare se varandras data? Om ja — lägg till `userId`-scope. + ### Bakgrund och beslut Baslager (`PantryItem`) och matplan (`MealPlanEntry`) var ursprungligen globala — delade av alla användare. Det skapade problem när flera användare loggade in eftersom de såg och påverkade varandras data. diff --git a/flutter/teknisk_beskrivning_flutter.md b/flutter/teknisk_beskrivning_flutter.md index 209ba6aa..29043d43 100644 --- a/flutter/teknisk_beskrivning_flutter.md +++ b/flutter/teknisk_beskrivning_flutter.md @@ -58,6 +58,23 @@ Viktigt att komma ihåg vid implementering av nya funktioner och kodning är att ## Kända fallgropar och API-gotchas +### Designregel: User-scope vid ny funktionalitet + +> **Regel:** Kontrollera alltid om ny data tillhör en specifik användare. Om ja — data **måste** ha user-scope i backend (`userId`-fält, filtrering i service) och Flutter-klienten får **inte** returnera/visa andra användares data. +> +> Resurser och deras scope: +> | Resurs | Scope | +> |---|---| +> | Produkter (globala) | Publik — `GET /products` | +> | Produkter (privata) | Per användare — `GET /products/mine`, `POST /products/private` | +> | Kategorier | Global (admin-only att skapa) | +> | Inventarie | Per användare — alltid filtrera på `userId` | +> | Baslager | Per användare — alltid filtrera på `userId` | +> | Matplan | Per användare — alltid filtrera på `userId` | +> | Recept | Per användare (ägare) eller delat | +> +> I Flutter: ladda user-scopad data med token, kombinera globala och egna produktlistor vid behov. + ### Flutter Web och PDF MIME-typ - Flutter Web skickar PDF-filer med MIME-typ `application/octet-stream` istället för `application/pdf`. - Backend (`receipt-import.controller.ts`) måste tillåta båda: `application/pdf` och `application/octet-stream` i `ALLOWED_MIMES`.