fix(docs): update NEXT_STEPS, README, and TEKNISK_BESKRIVNING with user role management details and new category structure

This commit is contained in:
Nils-Johan Gynther
2026-04-18 14:41:04 +02:00
parent c8489ed613
commit 00dc0d6c69
4 changed files with 98 additions and 30 deletions
+39 -20
View File
@@ -89,6 +89,8 @@ docker exec recipe-db mariadb -uroot -p"LÖSENORD" recipe_app -e "SHOW TABLES;"
| | `app/matplan/MealPlanClient.tsx` | Veckovy, receptval per dag, portionsjustering, inköpslista, inventariejämförelse |
| **Kvittoimport** | `app/import/page.tsx` | Server component med Navigation + flikvy |
| | `app/import/ImportTabsClient.tsx` | Klientkomponent: kvitto/recept-flikar |
| **Admin: Användare** | `app/admin/users/page.tsx` | Server component: hämtar alla användare, kräver admin-roll |
| | `app/admin/users/UserAdminClient.tsx` | Klientkomponent: tabell med rollbyte-knappar, anropar `/api/admin-users/:id` |
| **Admin: Produkter** | `app/admin/products/page.tsx` | Produktadmin-panel |
| | `AdminProductList.tsx` | Lista produkter, sök, sortera, filter okategoriserade, bulk-select + bulk-kategorisering |
| | `EditProductForm.tsx` | Inline redigering: name, canonicalName, kategori (hierarkisk dropdown), brand, taggar |
@@ -106,6 +108,8 @@ Alla proxy-routes läser auth-token via `auth()` (Auth.js v5) och vidarebefordra
| Route | Metod | Syfte |
|-------|-------|-------|
| `/api/admin-users` | GET | Hämtar alla användare (kräver admin-roll i session) |
| `/api/admin-users/[id]` | PATCH | Ändrar roll för användare med givet id (kräver admin-roll i session) |
| `/api/auth/[...nextauth]` | GET, POST | Auth.js handlers (login, logout, session) |
| `/api/products` | GET | Produktlista (auth-wrappat med `auth(req)`) |
| `/api/categories` | GET | Kategorihierarki (publik, proxies `/api/categories/tree`) |
@@ -124,8 +128,8 @@ Alla proxy-routes läser auth-token via `auth()` (Auth.js v5) och vidarebefordra
### Autentisering (Auth.js v5)
- `auth.ts` — NextAuth-konfiguration med Credentials provider
- `middleware.ts` — Skyddar alla routes utom `/login`, `/register` och `/api/auth`
- `auth.ts` — NextAuth-konfiguration med Credentials provider; sparar `accessToken`, `userId`, `username` och `role` i JWT-token och session
- `proxy.ts` — Skyddar alla routes utom `/login`, `/register` och `/api/auth`; blockerar `/admin/*` om sessionens `role` inte är `admin`
- `lib/auth-headers.ts``getAuthHeaders()` hämtar Bearer-token från session (server-side)
- `lib/api.ts``fetchJson()` lägger automatiskt till auth-headers server-side, redirectar till `/login` vid 401
@@ -143,7 +147,8 @@ Alla proxy-routes läser auth-token via `auth()` (Auth.js v5) och vidarebefordra
- **Språk:** TypeScript 5.4.5
- **Databas:** MariaDB 11 (via Prisma 6.12.0 ORM)
- **API:** REST, validering med class-validator
- **Autentisering:** JWT (7 dagars token), JwtAuthGuard skyddar alla routes, `@Public()` dekorator för öppna endpoints
- **Autentisering:** JWT (7 dagars token), `JwtAuthGuard` skyddar alla routes globalt, `RolesGuard` kontrollerar rollkrav, `@Public()` dekorator för öppna endpoints
- **Rollbaserad behörighet:** `@Roles('admin')` dekoratorn via `SetMetadata`; `RolesGuard` kastar 403 om rätt roll saknas
- **Felhantering:** GlobalExceptionFilter (svenska felmeddelanden)
- **Hälsokontroll:** /health endpoints
- **Bygg:** `nest build`, körs i Docker-container
@@ -155,16 +160,22 @@ backend/src/
├── app.module.ts # Root module
├── main.ts # Startpunkt (port 8080, global prefix "api")
├── auth/
│ ├── auth.controller.ts # POST /api/auth/login
│ ├── auth.service.ts # validateUser, login (JWT-signering)
│ ├── auth.controller.ts # POST /api/auth/login, POST /api/auth/register
│ ├── auth.service.ts # validateUser, login (JWT-signering inkl. role)
│ ├── auth.module.ts
│ ├── jwt.strategy.ts # Passport JWT-strategi
│ ├── jwt.strategy.ts # Passport JWT-strategi (returnerar userId, username, role)
│ ├── jwt-auth.guard.ts # Global guard (skyddar allt utom @Public)
│ ├── roles.guard.ts # Guard som kontrollerar @Roles() metadata; kastar 403
│ └── decorators/
── public.decorator.ts # @Public() markerar öppen endpoint
── public.decorator.ts # @Public() markerar öppen endpoint
│ ├── current-user.decorator.ts # @CurrentUser() extraherar {userId, username, role}
│ └── roles.decorator.ts # @Roles('admin') sätter rollkrav via SetMetadata
├── users/
│ ├── users.controller.ts # GET/PATCH /api/users/me
├── users.service.ts # findByUsername, create, updateProfile
│ ├── users.controller.ts # GET /api/users/me, PATCH /api/users/me
│ # GET /api/users (admin), PATCH /api/users/:id/role (admin)
│ ├── users.service.ts # findByUsername, findById, create, updateProfile
│ │ # findAll, setRole
│ ├── admin-bootstrap.service.ts # OnApplicationBootstrap: skapar/uppdaterar 4 seed-användare
│ └── users.module.ts
├── categories/
│ ├── categories.controller.ts # GET /api/categories, GET /api/categories/tree (@Public)
@@ -379,9 +390,11 @@ GET /api/categories/tree Hierarkiskt träd (@Public)
### Användar-endpoints
```
POST /api/auth/login Logga in, returnerar JWT (@Public)
GET /api/users/me Hämta inloggad användares profil
POST /api/auth/login Logga in, returnerar JWT inkl. role (@Public)
GET /api/users/me Hämta inloggad användares profil (inkl. role)
PATCH /api/users/me Uppdatera firstName, lastName, email
GET /api/users Lista alla användare (kräver admin-roll)
PATCH /api/users/:id/role Ändra roll för användare (kräver admin-roll)
```
### Baslager-endpoints
@@ -422,17 +435,29 @@ DELETE /api/receipt-alias/:id Ta bort alias
### User
```prisma
model User {
id Int @id @default(autoincrement())
username String @unique
email String @unique
id Int @id @default(autoincrement())
username String @unique
email String @unique
firstName String?
lastName String?
passwordHash String
role String @default("user") # "user" eller "admin"
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
```
**Bootstrap-användare:** När backend startar kör `AdminBootstrapService.onApplicationBootstrap()` och skapar eller uppdaterar fyra användare baserade på miljövariabler:
| Användarnamn | Roll | E-post | Miljövariabel |
|---|---|---|---|
| Nadmin | admin | nadmin@localhost | `ADMIN_NADMIN_PASSWORD` |
| Padmin | admin | padmin@localhost | `ADMIN_PADMIN_PASSWORD` |
| user1 | user | user1@localhost | `SEED_USER1_PASSWORD` |
| user2 | user | user2@localhost | `SEED_USER2_PASSWORD` |
Om en användare redan finns men har fel roll rättas rollen automatiskt. Om miljövariabeln saknas hoppas den användaren över med en varning i loggen.
### Category
```prisma
model Category {
@@ -495,16 +520,10 @@ model InventoryItem {
unit String # Enhet (g, kg, ml, dl, st, tsk, msk, etc)
brand String? # Varumärke
location String? # Lagerplats (Kyl, Frys, Skafferi, etc)
priority Int? # Prioritetsordning
purchaseDate DateTime? # Köpdatum
opened Boolean? # Markering för öppnad produkt
shelfNote String? # Lagringsnot
suitableFor String? # Lämplighetsmärkning (t.ex. "vegetarian")
isOnSale Boolean? # Är på rea
priceLevel Int? # Priskategori (15)
bestBeforeDate DateTime? # Bäst före-datum
proteinType String? # Proteintyp (t.ex. "beef", "chicken")
isLeftover Boolean? # Är från tidigare lagnning
comment String? # Fri kommentar
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt