feat: initialize CalBook project with comprehensive scheduling, admin, and deployment infrastructure
This commit is contained in:
47
app/api/public/stornieren/route.ts
Normal file
47
app/api/public/stornieren/route.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
import { cancelAppointmentByToken } from "@/lib/services/appointments";
|
||||
import { cancelSchema } from "@/lib/validators/public";
|
||||
import { fail, ok } from "@/lib/api";
|
||||
import { enforceRateLimit } from "@/lib/rate-limit";
|
||||
import { readJsonBody, validateMutationRequestOrigin } from "@/lib/security/request";
|
||||
|
||||
export async function GET() {
|
||||
return fail("Bitte verwende POST für die Stornierung.", 405);
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const originError = validateMutationRequestOrigin(req);
|
||||
if (originError) return originError;
|
||||
|
||||
const bodyResult = await readJsonBody(req, { maxBytes: 8 * 1024 });
|
||||
if (!bodyResult.ok) return bodyResult.response;
|
||||
const parsed = cancelSchema.safeParse({
|
||||
token: (bodyResult.data as { token?: string }).token
|
||||
});
|
||||
|
||||
const limit = enforceRateLimit({
|
||||
req,
|
||||
scope: "public-cancel",
|
||||
limit: 30,
|
||||
windowMs: 60_000,
|
||||
...(parsed.success ? { keySuffix: parsed.data.token.slice(0, 12) } : {})
|
||||
});
|
||||
|
||||
if (!limit.ok) {
|
||||
return fail("Zu viele Anfragen. Bitte kurz warten.", 429, {
|
||||
retryAfterSeconds: limit.retryAfterSeconds
|
||||
});
|
||||
}
|
||||
|
||||
if (!parsed.success) {
|
||||
return fail("Token fehlt oder ist ungültig", 400, parsed.error.flatten());
|
||||
}
|
||||
|
||||
const result = await cancelAppointmentByToken(parsed.data.token);
|
||||
if (!result.ok) {
|
||||
return fail(result.message ?? "Stornierung fehlgeschlagen", result.status ?? 400);
|
||||
}
|
||||
|
||||
return ok({ message: "Termin erfolgreich storniert" });
|
||||
}
|
||||
Reference in New Issue
Block a user