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,95 @@
|
||||
import type { FastifyInstance } from 'fastify';
|
||||
import { z } from 'zod';
|
||||
import { CreditKind, InactiveReason } from '@prisma/client';
|
||||
import { requireEditor } from '../auth/guard.js';
|
||||
import {
|
||||
createCharacter,
|
||||
deactivateCharacter,
|
||||
reactivateFree,
|
||||
reactivatePaid,
|
||||
redesignCharacter,
|
||||
revertCharacter,
|
||||
updateCharacter,
|
||||
} from '../services/characters.js';
|
||||
import { contextOf, idParam, optionalNote, parseWith } from './helpers.js';
|
||||
|
||||
const redesignKind = z.enum([CreditKind.REDESIGN_PAID, CreditKind.REDESIGN_KULANZ]);
|
||||
const reviveKind = z.enum([CreditKind.CC, CreditKind.REDESIGN_PAID, CreditKind.REDESIGN_KULANZ]);
|
||||
|
||||
export async function characterRoutes(app: FastifyInstance): Promise<void> {
|
||||
app.post('/api/players/:id/characters', { preHandler: requireEditor }, async (request, reply) => {
|
||||
const { id } = parseWith(idParam, request.params);
|
||||
const body = parseWith(
|
||||
z.object({
|
||||
name: z.string().trim().min(1).max(160),
|
||||
loreText: z.string().trim().max(5000).optional(),
|
||||
note: optionalNote,
|
||||
}),
|
||||
request.body,
|
||||
);
|
||||
const result = await createCharacter(id, body, contextOf(request));
|
||||
reply.code(201);
|
||||
return result;
|
||||
});
|
||||
|
||||
app.patch('/api/characters/:id', { preHandler: requireEditor }, async (request) => {
|
||||
const { id } = parseWith(idParam, request.params);
|
||||
const body = parseWith(
|
||||
z.object({
|
||||
name: z.string().trim().min(1).max(160).optional(),
|
||||
loreText: z.string().trim().max(5000).nullable().optional(),
|
||||
}),
|
||||
request.body,
|
||||
);
|
||||
return updateCharacter(id, body, contextOf(request));
|
||||
});
|
||||
|
||||
app.post('/api/characters/:id/redesign', { preHandler: requireEditor }, async (request) => {
|
||||
const { id } = parseWith(idParam, request.params);
|
||||
const body = parseWith(
|
||||
z.object({
|
||||
name: z.string().trim().min(1).max(160),
|
||||
loreText: z.string().trim().max(5000).optional(),
|
||||
useKind: redesignKind,
|
||||
note: optionalNote,
|
||||
}),
|
||||
request.body,
|
||||
);
|
||||
return redesignCharacter(id, body, contextOf(request));
|
||||
});
|
||||
|
||||
app.post('/api/characters/:id/deactivate', { preHandler: requireEditor }, async (request) => {
|
||||
const { id } = parseWith(idParam, request.params);
|
||||
const body = parseWith(
|
||||
z.object({
|
||||
reason: z.enum([InactiveReason.PLAYER_INACTIVITY, InactiveReason.OTHER]),
|
||||
note: optionalNote,
|
||||
}),
|
||||
request.body,
|
||||
);
|
||||
return deactivateCharacter(id, body.reason, contextOf(request), body.note);
|
||||
});
|
||||
|
||||
app.post('/api/characters/:id/reactivate-free', { preHandler: requireEditor }, async (request) => {
|
||||
const { id } = parseWith(idParam, request.params);
|
||||
return reactivateFree(id, contextOf(request));
|
||||
});
|
||||
|
||||
app.post('/api/characters/:id/reactivate-paid', { preHandler: requireEditor }, async (request) => {
|
||||
const { id } = parseWith(idParam, request.params);
|
||||
const body = parseWith(
|
||||
z.object({ useKind: reviveKind, note: optionalNote }),
|
||||
request.body,
|
||||
);
|
||||
return reactivatePaid(id, body.useKind, contextOf(request), body.note);
|
||||
});
|
||||
|
||||
app.post('/api/characters/:id/revert', { preHandler: requireEditor }, async (request) => {
|
||||
const { id } = parseWith(idParam, request.params);
|
||||
const body = parseWith(
|
||||
z.object({ reason: z.string().trim().min(1, 'Eine Begruendung ist Pflicht').max(500) }),
|
||||
request.body,
|
||||
);
|
||||
return revertCharacter(id, body.reason, contextOf(request));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user