feat: add user-scope design rules for new functionality in documentation
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
Reference in New Issue
Block a user