diff --git a/backend/src/controllers/creditNote.controller.ts b/backend/src/controllers/creditNote.controller.ts index e60681e1..39b8ac8c 100644 --- a/backend/src/controllers/creditNote.controller.ts +++ b/backend/src/controllers/creditNote.controller.ts @@ -50,13 +50,18 @@ function handleError(res: Response, error: unknown, fallback: string) { export async function listAll(req: AuthRequest, res: Response): Promise { try { // Portal-User: nur eigene + vertretene Kunden MIT Vollmacht. + // Fail-closed (Pentest R144): Ein Portal-Token wird IMMER gescoped. Fehlt + // wider Erwarten die customerId (null/0), ergibt das eine LEERE Menge – + // nicht den Staff-Zweig (der alle Belege zeigen würde). let customerIds: number[] | undefined; - if (req.user?.isCustomerPortal && req.user.customerId) { - customerIds = [req.user.customerId]; - const representedIds: number[] = (req.user as any).representedCustomerIds || []; - for (const repCustId of representedIds) { - if (await authorizationService.hasAuthorization(repCustId, req.user.customerId)) { - customerIds.push(repCustId); + if (req.user?.isCustomerPortal) { + customerIds = req.user.customerId ? [req.user.customerId] : []; + if (req.user.customerId) { + const representedIds: number[] = (req.user as any).representedCustomerIds || []; + for (const repCustId of representedIds) { + if (await authorizationService.hasAuthorization(repCustId, req.user.customerId)) { + customerIds.push(repCustId); + } } } } diff --git a/docs/todo.md b/docs/todo.md index 11229897..8cde4d89 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -107,6 +107,9 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung `customerIds` kommt aus dem JWT (nicht aus Query/Body → nicht manipulierbar). Für Portal wird `receiptPath` aus der Response entfernt (Belege bleiben staff-only). Verifiziert (Staff alle, Portal nur eigene). + - **Fail-closed (Pentest R144):** Ein Portal-Token wird jetzt IMMER gescoped; + fehlt wider Erwarten die `customerId` (null/0), ergibt das eine **leere + Menge** statt des Staff-Zweigs. Verifiziert (`customerIds=[]` → 0 Belege). - [x] **🚫 Gutschrift nur mit Empfängeradresse (Rechnung > Liefer)** (2026-08-12) - Beim Klick auf „Gutschrift anlegen" wird geprüft, ob der Vertrag eine Empfängeradresse hat: **Rechnungsadresse hat Vorrang, sonst Lieferadresse**.