提交 Turnstile 集成源文件改动

This commit is contained in:
2569718930@qq.com
2026-06-16 03:49:49 +08:00
parent e896ffa7ac
commit a94e6ecaf9
8 changed files with 147 additions and 7 deletions
+29 -1
View File
@@ -1,6 +1,6 @@
"use client";
import { FormEvent, useEffect, useState } from "react";
import { FormEvent, useCallback, useEffect, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import {
@@ -18,6 +18,8 @@ import {
} from "@/lib/supabase/client";
import { getConfiguredSiteUrl, PRODUCTION_SITE_URL } from "@/lib/site-url";
import { useI18n } from "@/hooks/useI18n";
import { TurnstileWidget } from "@/components/security/TurnstileWidget";
import { getTurnstileTokenForAction } from "@/lib/turnstile-client";
type Mode = "login" | "signup";
@@ -72,6 +74,8 @@ export function LoginClient({ nextPath, initialError, initialMode }: LoginClient
const [infoText, setInfoText] = useState("");
const [resetSent, setResetSent] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const [turnstileToken, setTurnstileToken] = useState("");
const [turnstileResetKey, setTurnstileResetKey] = useState(0);
const supabaseReady = hasSupabasePublicEnv();
const isLogin = mode === "login";
@@ -173,6 +177,11 @@ export function LoginClient({ nextPath, initialError, initialMode }: LoginClient
setErrorText(initialError || "");
}, [initialError]);
const resetTurnstile = useCallback(() => {
setTurnstileToken("");
setTurnstileResetKey((value) => value + 1);
}, []);
const onResetPassword = async () => {
setErrorText("");
setInfoText("");
@@ -247,13 +256,19 @@ export function LoginClient({ nextPath, initialError, initialMode }: LoginClient
setLoading(true);
try {
const supabase = getSupabaseBrowserClient();
const captchaToken = getTurnstileTokenForAction(
turnstileToken,
isLogin ? "login" : "signup",
);
if (mode === "login") {
const { data, error } = await supabase.auth.signInWithPassword({
email: email.trim(),
password,
options: captchaToken ? { captchaToken } : undefined,
});
if (error) {
setErrorText(error.message);
resetTurnstile();
return;
}
const redirectPath = await resolvePostLoginRedirect({
@@ -272,10 +287,12 @@ export function LoginClient({ nextPath, initialError, initialMode }: LoginClient
password,
options: {
emailRedirectTo,
...(captchaToken ? { captchaToken } : {}),
},
});
if (error) {
setErrorText(error.message);
resetTurnstile();
return;
}
if (data.session?.user) {
@@ -287,6 +304,10 @@ export function LoginClient({ nextPath, initialError, initialMode }: LoginClient
return;
}
setInfoText(copy.signupCheckEmail);
resetTurnstile();
} catch (error) {
setErrorText(error instanceof Error ? error.message : String(error));
resetTurnstile();
} finally {
setLoading(false);
}
@@ -407,6 +428,7 @@ export function LoginClient({ nextPath, initialError, initialMode }: LoginClient
setErrorText("");
setInfoText("");
setMode(isLogin ? "signup" : "login");
resetTurnstile();
}}
className="whitespace-nowrap rounded-xl border border-slate-300 bg-white px-4 py-2 text-xs font-bold text-slate-700 shadow-sm transition hover:border-blue-300 hover:text-blue-700 active:scale-[0.98]"
>
@@ -495,6 +517,12 @@ export function LoginClient({ nextPath, initialError, initialMode }: LoginClient
</div>
</div>
<TurnstileWidget
action={isLogin ? "login" : "signup"}
onToken={setTurnstileToken}
resetKey={turnstileResetKey}
/>
{!isLogin ? (
<p className="text-[11px] leading-relaxed text-slate-500">
{copy.termsAgreement}