feat: Integrate Cloudflare Turnstile CAPTCHA

This commit is contained in:
gpt-engineer-app[bot]
2025-09-28 20:01:44 +00:00
parent 5d799241da
commit c88239fc4c
5 changed files with 206 additions and 1 deletions

View File

@@ -11,6 +11,7 @@ import { Separator } from '@/components/ui/separator';
import { Zap, Mail, Lock, User, AlertCircle, Eye, EyeOff } from 'lucide-react';
import { supabase } from '@/integrations/supabase/client';
import { useToast } from '@/hooks/use-toast';
import { TurnstileCaptcha } from '@/components/auth/TurnstileCaptcha';
export default function Auth() {
const [searchParams] = useSearchParams();
const navigate = useNavigate();
@@ -20,6 +21,8 @@ export default function Auth() {
const [loading, setLoading] = useState(false);
const [magicLinkLoading, setMagicLinkLoading] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
const [captchaKey, setCaptchaKey] = useState(0);
const [formData, setFormData] = useState({
email: '',
password: '',
@@ -65,6 +68,8 @@ export default function Auth() {
const handleSignUp = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
// Validate passwords match
if (formData.password !== formData.confirmPassword) {
toast({
variant: "destructive",
@@ -74,6 +79,8 @@ export default function Auth() {
setLoading(false);
return;
}
// Validate password length
if (formData.password.length < 6) {
toast({
variant: "destructive",
@@ -83,6 +90,18 @@ export default function Auth() {
setLoading(false);
return;
}
// Validate CAPTCHA
if (!captchaToken) {
toast({
variant: "destructive",
title: "CAPTCHA required",
description: "Please complete the CAPTCHA verification."
});
setLoading(false);
return;
}
try {
const {
data,
@@ -91,19 +110,26 @@ export default function Auth() {
email: formData.email,
password: formData.password,
options: {
captchaToken,
data: {
username: formData.username,
display_name: formData.displayName
}
}
});
if (error) throw error;
toast({
title: "Welcome to ThrillWiki!",
description: "Please check your email to verify your account."
});
navigate('/');
} catch (error: any) {
// Reset CAPTCHA on error
setCaptchaToken(null);
setCaptchaKey(prev => prev + 1);
toast({
variant: "destructive",
title: "Sign up failed",
@@ -325,7 +351,24 @@ export default function Auth() {
</div>
</div>
<Button type="submit" className="w-full bg-accent hover:bg-accent/90 text-accent-foreground" disabled={loading}>
<div className="space-y-2">
<Label>Security Verification</Label>
<TurnstileCaptcha
key={captchaKey}
onSuccess={setCaptchaToken}
onError={() => setCaptchaToken(null)}
onExpire={() => setCaptchaToken(null)}
siteKey={import.meta.env.VITE_TURNSTILE_SITE_KEY}
theme="auto"
className="flex justify-center"
/>
</div>
<Button
type="submit"
className="w-full bg-accent hover:bg-accent/90 text-accent-foreground"
disabled={loading || !captchaToken}
>
{loading ? "Creating account..." : "Create Account"}
</Button>
</form>