wait for the captcha to be fetched before allowing form submission
All checks were successful
Deploy / deploy (ubuntu-latest, 2.44.0) (push) Successful in 2m9s
All checks were successful
Deploy / deploy (ubuntu-latest, 2.44.0) (push) Successful in 2m9s
This commit is contained in:
parent
a71502d0b2
commit
338ce3edf1
@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ReactElement, useState } from "react";
|
import { ReactElement, useEffect, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
@ -84,8 +84,14 @@ const inputAnimationVariants = {
|
|||||||
* @return the form jsx
|
* @return the form jsx
|
||||||
*/
|
*/
|
||||||
const AuthForm = (): ReactElement => {
|
const AuthForm = (): ReactElement => {
|
||||||
|
const turnstile: TurnstileObject = useTurnstile();
|
||||||
|
const cookies: Cookies = useCookies();
|
||||||
|
const router: AppRouterInstance = useRouter();
|
||||||
|
|
||||||
const [stage, setStage] = useState<"email" | "register" | "login">("email");
|
const [stage, setStage] = useState<"email" | "register" | "login">("email");
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const [awaitingCaptcha, setAwaitingCaptcha] = useState<boolean>(true);
|
||||||
const [captchaResponse, setCaptchaResponse] = useState<string | undefined>(
|
const [captchaResponse, setCaptchaResponse] = useState<string | undefined>(
|
||||||
undefined
|
undefined
|
||||||
);
|
);
|
||||||
@ -94,9 +100,6 @@ const AuthForm = (): ReactElement => {
|
|||||||
const [tfaPin, setTfaPin] = useState<string | undefined>();
|
const [tfaPin, setTfaPin] = useState<string | undefined>();
|
||||||
|
|
||||||
const [error, setError] = useState<string | undefined>(undefined);
|
const [error, setError] = useState<string | undefined>(undefined);
|
||||||
const turnstile: TurnstileObject = useTurnstile();
|
|
||||||
const cookies: Cookies = useCookies();
|
|
||||||
const router: AppRouterInstance = useRouter();
|
|
||||||
|
|
||||||
// Build the form
|
// Build the form
|
||||||
const {
|
const {
|
||||||
@ -113,6 +116,12 @@ const AuthForm = (): ReactElement => {
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Received the captcha response
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("Received new captcha response");
|
||||||
|
setAwaitingCaptcha(false);
|
||||||
|
}, [captchaResponse]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle submitting the form.
|
* Handle submitting the form.
|
||||||
*/
|
*/
|
||||||
@ -122,6 +131,10 @@ const AuthForm = (): ReactElement => {
|
|||||||
password,
|
password,
|
||||||
passwordConfirmation,
|
passwordConfirmation,
|
||||||
}: any) => {
|
}: any) => {
|
||||||
|
// Prevent submitting when the captcha is being fetched
|
||||||
|
if (awaitingCaptcha) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
if (stage === "email") {
|
if (stage === "email") {
|
||||||
const { data, error } = await apiRequest<{ exists: boolean }>({
|
const { data, error } = await apiRequest<{ exists: boolean }>({
|
||||||
@ -134,6 +147,7 @@ const AuthForm = (): ReactElement => {
|
|||||||
} else {
|
} else {
|
||||||
setStage(data?.exists ? "login" : "register");
|
setStage(data?.exists ? "login" : "register");
|
||||||
}
|
}
|
||||||
|
setAwaitingCaptcha(true);
|
||||||
turnstile.reset();
|
turnstile.reset();
|
||||||
} else {
|
} else {
|
||||||
const registering: boolean = stage === "register";
|
const registering: boolean = stage === "register";
|
||||||
@ -161,6 +175,7 @@ const AuthForm = (): ReactElement => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
setBorderCrossing(true);
|
setBorderCrossing(true);
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
|
setAwaitingCaptcha(true);
|
||||||
turnstile.reset();
|
turnstile.reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -168,6 +183,7 @@ const AuthForm = (): ReactElement => {
|
|||||||
|
|
||||||
// Reset the captcha if auth fails
|
// Reset the captcha if auth fails
|
||||||
if (error) {
|
if (error) {
|
||||||
|
setAwaitingCaptcha(true);
|
||||||
turnstile.reset();
|
turnstile.reset();
|
||||||
} else {
|
} else {
|
||||||
// Otherwise store the session and redirect to the dashboard
|
// Otherwise store the session and redirect to the dashboard
|
||||||
@ -240,6 +256,7 @@ const AuthForm = (): ReactElement => {
|
|||||||
className="pl-8 rounded-lg"
|
className="pl-8 rounded-lg"
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
|
disabled={awaitingCaptcha}
|
||||||
{...register("password")}
|
{...register("password")}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@ -303,7 +320,7 @@ const AuthForm = (): ReactElement => {
|
|||||||
<Button
|
<Button
|
||||||
className="h-11 flex gap-2.5 items-center text-white border border-secondary transition-all transform-gpu group"
|
className="h-11 flex gap-2.5 items-center text-white border border-secondary transition-all transform-gpu group"
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loading || awaitingCaptcha}
|
||||||
>
|
>
|
||||||
{loading && <ArrowPathIcon className="w-4 h-4 animate-spin" />}
|
{loading && <ArrowPathIcon className="w-4 h-4 animate-spin" />}
|
||||||
<span className="-translate-y-0.5">
|
<span className="-translate-y-0.5">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user