Add Turnstile protection to user actions

This commit is contained in:
2026-09-18 00:39:14 +02:00
parent 79cd7f7475
commit 1970be29e7
25 changed files with 406 additions and 39 deletions
+2 -1
View File
@@ -22,6 +22,7 @@ import { resolveRedirect } from "@/lib/seo/redirects";
import { siteConfig } from "@/lib/site";
export const dynamic = "force-dynamic";
const turnstileSiteKey = process.env.TURNSTILE_SITE_KEY ?? "";
type Args = { params: Promise<{ slug: string }> };
const WEEKDAY_LABELS: Record<string, string> = { monday: "Montag", tuesday: "Dienstag", wednesday: "Mittwoch", thursday: "Donnerstag", friday: "Freitag", saturday: "Samstag", sunday: "Sonntag" };
@@ -138,7 +139,7 @@ export default async function OfferDetailPage({ params }: Args) {
)}
{offer.groupCapacity && <p className="mb-2 text-sm text-anouma-plum/75">Plätze: {offer.groupCapacity}</p>}
{offer.registrationDeadline && <p className="mb-6 text-sm text-anouma-plum/75">Anmeldung möglich bis {new Date(offer.registrationDeadline).toLocaleDateString("de-DE")}</p>}
<GroupRegistrationForm offerSlug={offer.slug!} />
<GroupRegistrationForm offerSlug={offer.slug!} siteKey={turnstileSiteKey} />
</div>
</Section>
) : offer.bookable ? (
+2 -1
View File
@@ -14,6 +14,7 @@ import { siteConfig } from "@/lib/site";
export const dynamic = "force-dynamic";
const FALLBACK_DESCRIPTION = "Ich freue mich, von dir zu hören.";
const turnstileSiteKey = process.env.TURNSTILE_SITE_KEY ?? "";
export async function generateMetadata(): Promise<Metadata> {
const [contact, seoSettings] = await Promise.all([getContactGlobal(), getSEOSettingsGlobal()]);
@@ -60,7 +61,7 @@ export default async function KontaktPage({ searchParams }: { searchParams: Prom
<Section tone="plain">
<div className="grid gap-14 lg:grid-cols-[1fr_0.8fr]">
<Reveal>
<ContactForm subjectPrefix={isAppointment ? "Terminanfrage" : "Allgemeine Anfrage"} type={isAppointment ? "appointment" : "contact"} submitLabel={isAppointment ? "Terminanfrage senden" : "Nachricht senden"} />
<ContactForm siteKey={turnstileSiteKey} subjectPrefix={isAppointment ? "Terminanfrage" : "Allgemeine Anfrage"} type={isAppointment ? "appointment" : "contact"} submitLabel={isAppointment ? "Terminanfrage senden" : "Nachricht senden"} />
</Reveal>
<Reveal delay={0.1} className="space-y-8">
+2 -1
View File
@@ -8,6 +8,7 @@ import { LoginForm } from "@/components/auth/LoginForm";
import { getCurrentCustomer } from "@/lib/auth/customer";
export const dynamic = "force-dynamic";
const turnstileSiteKey = process.env.TURNSTILE_SITE_KEY ?? "";
export const metadata: Metadata = {
title: "Anmelden",
@@ -24,7 +25,7 @@ export default async function LoginPage() {
<Section tone="plain">
<div className="mx-auto max-w-md">
<Suspense>
<LoginForm />
<LoginForm siteKey={turnstileSiteKey} />
</Suspense>
<p className="mt-6 text-center text-sm text-anouma-plum">
Noch kein Konto?{" "}
+2 -1
View File
@@ -7,6 +7,7 @@ import { RegisterForm } from "@/components/auth/RegisterForm";
import { getCurrentCustomer } from "@/lib/auth/customer";
export const dynamic = "force-dynamic";
const turnstileSiteKey = process.env.TURNSTILE_SITE_KEY ?? "";
export const metadata: Metadata = {
title: "Konto erstellen",
@@ -28,7 +29,7 @@ export default async function RegisterPage() {
/>
<Section tone="plain">
<div className="mx-auto max-w-md">
<RegisterForm />
<RegisterForm siteKey={turnstileSiteKey} />
<p className="mt-6 text-center text-sm text-anouma-plum">
Schon ein Konto?{" "}
<Link href="/login" className="font-medium text-anouma-mauve-dark underline underline-offset-4">
+2
View File
@@ -17,6 +17,7 @@ import { siteConfig } from "@/lib/site";
export const dynamic = "force-dynamic";
const FALLBACK_DESCRIPTION = "Kennenlernen & Termine vereinbaren.";
const turnstileSiteKey = process.env.TURNSTILE_SITE_KEY ?? "";
export async function generateMetadata(): Promise<Metadata> {
const [booking, seoSettings] = await Promise.all([getBookingGlobal(), getSEOSettingsGlobal()]);
@@ -122,6 +123,7 @@ export default async function TerminBuchenPage() {
/>
<div className="mt-10">
<ContactForm
siteKey={turnstileSiteKey}
subjectPrefix="Terminanfrage über anouma.org"
type="appointment"
submitLabel="Terminanfrage senden"
@@ -8,6 +8,7 @@ import { combineDateAndTime } from "@/lib/meeting/status";
import { formatBerlinDate, formatBerlinTime } from "@/lib/calendar/timezone";
export const dynamic = "force-dynamic";
const turnstileSiteKey = process.env.TURNSTILE_SITE_KEY ?? "";
export const metadata: Metadata = {
title: "Meeting beitreten",
@@ -42,7 +43,7 @@ export default async function BeitretenPage({ params }: Args) {
</p>
<div className="mt-10 rounded-[2rem] bg-white/70 p-8 text-left shadow-sm backdrop-blur">
<JoinForm slug={slug} />
<JoinForm slug={slug} siteKey={turnstileSiteKey} />
</div>
</div>
</section>
+2 -1
View File
@@ -25,6 +25,7 @@ import { resolveRedirect } from "@/lib/seo/redirects";
import { siteConfig } from "@/lib/site";
export const dynamic = "force-dynamic";
const turnstileSiteKey = process.env.TURNSTILE_SITE_KEY ?? "";
type Args = { params: Promise<{ slug: string }> };
@@ -137,7 +138,7 @@ export default async function EventDetailPage({ params }: Args) {
<div>
<h2 className="font-serif text-2xl font-medium text-anouma-plum">Anmeldung</h2>
<div className="mt-4 max-w-sm">
<RegisterForm slug={slug} />
<RegisterForm slug={slug} siteKey={turnstileSiteKey} />
</div>
</div>
)}