first commit
Docker-Images bauen und veroeffentlichen / build-and-push (push) Failing after 1m32s

This commit is contained in:
Nick Szaunig committed 2026-09-27 06:06:56 +02:00
commit 59bb5a38a3
132 files changed
+19435

No files matched your search

@@ -0,0 +1,57 @@
/**
* Aktionen der Kundin auf ihrer Statusseite. Zugang nur ueber das
* Statustoken aus Bestaetigungsmail bzw. Stripe-Ruecksprung.
*/
import { z } from "zod";
import { checkSameOrigin, fail, ok, rateLimited, readJson } from "@/lib/api";
import { abandonCheckout, startInstallmentCheckout } from "@/lib/checkout";
import { getDb } from "@/lib/db";
import { requireAppSecret } from "@/lib/env";
import { getGateway } from "@/lib/payment-gateway";
import { RATE_LIMITS } from "@/lib/rate-limit";
import { isWellFormedStatusToken, sha256Hex } from "@/lib/tokens";
const schema = z.discriminatedUnion("action", [
z.object({ action: z.literal("pay_installment"), token: z.string(), installmentId: z.string().min(1).max(64) }),
z.object({ action: z.literal("resume_checkout"), token: z.string() }),
z.object({ action: z.literal("abandon"), token: z.string() }),
]);
export async function POST(request: Request) {
const blocked = checkSameOrigin(request);
if (blocked) return blocked;
const limited = await rateLimited(request, RATE_LIMITS.statusAction);
if (limited) return limited;
const body = await readJson(request, schema);
if (!body.ok) return body.response;
const notFound = fail(404, { code: "NOT_FOUND", message: "Diese Buchung wurde nicht gefunden." });
if (!isWellFormedStatusToken(body.data.token)) return notFound;
const db = getDb();
const booking = await db.booking.findUnique({ where: { statusTokenHash: sha256Hex(body.data.token) } });
if (!booking) return notFound;
const gateway = getGateway();
if (booking.livemode !== (gateway.mode === "live")) return notFound;
const now = new Date();
switch (body.data.action) {
case "pay_installment": {
const result = await startInstallmentCheckout(db, gateway, { bookingId: booking.id, installmentId: body.data.installmentId }, { now, secret: requireAppSecret() });
if (result.ok) return ok({ url: result.url });
return result.error === "NOT_PAYABLE"
? fail(409, { code: "NOT_PAYABLE", message: "Diese Rate kann gerade nicht bezahlt werden. Bitte lade die Seite neu." })
: fail(502, { code: "PAYMENT_PROVIDER", message: "Die Zahlungsseite ist gerade nicht erreichbar. Bitte versuche es später erneut." });
}
case "resume_checkout": {
if (booking.status === "PENDING" && booking.paymentStatus === "UNPAID" && booking.stripeCheckoutUrl && booking.priceLockedUntil > now) {
return ok({ url: booking.stripeCheckoutUrl });
}
return fail(409, { code: "EXPIRED", message: "Die Reservierung ist abgelaufen. Bitte starte eine neue Buchung." });
}
case "abandon": {
await abandonCheckout(db, gateway, booking, { now });
return ok({ abandoned: true });
}
}
}