Sechs Route-Handler (Hinweis-Weiterleitung, E-Mail-Bestaetigung, Newsletter bestaetigen/abmelden, Entra-Login und -Callback) bauten ihr Weiterleitungsziel mit getBaseUrl() absolut zusammen. Ohne gesetztes NEXT_PUBLIC_SITE_URL (lokal, Staging, Vorschau-Host) sprang man damit auf https://wabenhain.com, und die gerade gesetzte Flash-Meldung ging auf dem fremden Host verloren - aufgefallen, als die Admin-Pruefung nach /api/hinweis umleitete. Neuer Helfer lib/redirect.ts (redirectWithinSite) mit relativem Location-Header, analog zu redirect() in Server Actions. Er lehnt alles ausser Pfaden dieser Seite ab ("//host", "/\host", absolute URLs), damit daraus keine offene Weiterleitung werden kann. getSiteUrl() bleibt fuer Adressen, die die Seite verlassen (E-Mails, Stripe, Entra-redirect_uri, Sitemap, Canonicals). proxy.ts bleibt bei new URL("/konto", request.url) (eigener Host): der Proxy verlangt einen absoluten Location-Header, ein relativer endet dort in "Invalid URL" - als Kommentar festgehalten. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
41 lines
1.3 KiB
TypeScript
41 lines
1.3 KiB
TypeScript
import { prisma } from "@/lib/prisma";
|
|
import { hashVerificationToken } from "@/lib/email-verification";
|
|
import { withFlash } from "@/lib/flash";
|
|
import { redirectWithinSite } from "@/lib/redirect";
|
|
|
|
export async function GET(request: Request) {
|
|
const token = new URL(request.url).searchParams.get("token");
|
|
const fail = (message: string) => withFlash(redirectWithinSite("/konto"), "error", message);
|
|
|
|
if (!token) {
|
|
return fail("Dieser Bestätigungslink ist ungültig.");
|
|
}
|
|
|
|
const verificationToken = await prisma.emailVerificationToken.findUnique({
|
|
where: { tokenHash: hashVerificationToken(token) },
|
|
});
|
|
|
|
const isValid =
|
|
verificationToken && verificationToken.usedAt === null && verificationToken.expiresAt > new Date();
|
|
if (!isValid) {
|
|
return fail("Dieser Bestätigungslink ist ungültig oder abgelaufen. Bitte fordere über /konto einen neuen an.");
|
|
}
|
|
|
|
await prisma.$transaction([
|
|
prisma.customer.update({
|
|
where: { id: verificationToken.customerId },
|
|
data: { emailVerifiedAt: new Date() },
|
|
}),
|
|
prisma.emailVerificationToken.update({
|
|
where: { id: verificationToken.id },
|
|
data: { usedAt: new Date() },
|
|
}),
|
|
]);
|
|
|
|
return withFlash(
|
|
redirectWithinSite("/konto"),
|
|
"success",
|
|
"Deine E-Mail-Adresse wurde bestätigt. Du kannst jetzt bestellen."
|
|
);
|
|
}
|