feat: add user-scope design rules for new functionality in documentation

This commit is contained in:
Nils-Johan Gynther
2026-05-01 02:33:48 +02:00
parent 9ee061d5f3
commit 8bc1bd3e21
2 changed files with 30 additions and 0 deletions
+13
View File
@@ -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.
+17
View File
@@ -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`.