HTTP-Endpunkte und Anwendungsaufbau
Eingaben werden mit zod validiert, jede aendernde Aktion schreibt ins Audit-Log. Beim ersten Start entsteht ein Administrator samt Startwerten fuer die Produkterkennung; solange ein Erstpasswort gilt, bleiben schreibende Wege bis auf den Passwortwechsel gesperrt. Nicht-API-Pfade fallen auf die SPA zurueck, damit Deep-Links funktionieren.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import type { FastifyRequest } from 'fastify';
|
||||
import { z } from 'zod';
|
||||
import { badRequest, unauthorized } from '../errors.js';
|
||||
import type { ActionContext } from '../services/audit.js';
|
||||
|
||||
// z.output statt z.input: nur so zaehlen .default()-Werte als gesetzt.
|
||||
export function parseWith<S extends z.ZodTypeAny>(schema: S, input: unknown): z.output<S> {
|
||||
const result = schema.safeParse(input);
|
||||
if (!result.success) {
|
||||
const message = result.error.issues
|
||||
.map((issue) => {
|
||||
const path = issue.path.join('.');
|
||||
return path ? `${path}: ${issue.message}` : issue.message;
|
||||
})
|
||||
.join('; ');
|
||||
throw badRequest('VALIDATION_FAILED', message);
|
||||
}
|
||||
return result.data;
|
||||
}
|
||||
|
||||
export function contextOf(request: FastifyRequest): ActionContext {
|
||||
if (!request.user) throw unauthorized();
|
||||
return {
|
||||
actorId: request.user.id,
|
||||
actorName: request.user.username,
|
||||
ip: request.ip,
|
||||
};
|
||||
}
|
||||
|
||||
export const idParam = z.object({ id: z.coerce.number().int().positive() });
|
||||
|
||||
export const optionalNote = z.string().trim().max(500).optional();
|
||||
Reference in New Issue
Block a user