From cd85a9fe09fa5b0058ca0b08d7aa6401e703e721 Mon Sep 17 00:00:00 2001 From: guru_sainath Date: Tue, 16 Jul 2024 14:16:10 +0530 Subject: [PATCH] chore: handled the auto form submit for all authenticators (#5139) --- .../account/auth-forms/password.tsx | 32 +++++++++++++++---- .../account/auth-forms/password.tsx | 30 ++++++++++++----- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/space/core/components/account/auth-forms/password.tsx b/space/core/components/account/auth-forms/password.tsx index c3a5e9c31..4d4467d63 100644 --- a/space/core/components/account/auth-forms/password.tsx +++ b/space/core/components/account/auth-forms/password.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useEffect, useMemo, useState } from "react"; +import React, { useEffect, useMemo, useRef, useState } from "react"; import { observer } from "mobx-react"; import { Eye, EyeOff, XCircle } from "lucide-react"; import { Button, Input, Spinner } from "@plane/ui"; @@ -39,8 +39,10 @@ const authService = new AuthService(); export const AuthPasswordForm: React.FC = observer((props: Props) => { const { email, nextPath, isSMTPConfigured, handleAuthStep, handleEmailClear, mode } = props; + // ref + const formRef = useRef(null); // states - const [csrfToken, setCsrfToken] = useState(undefined); + const [csrfPromise, setCsrfPromise] = useState | undefined>(undefined); const [passwordFormData, setPasswordFormData] = useState({ ...defaultValues, email }); const [showPassword, setShowPassword] = useState({ password: false, @@ -57,9 +59,11 @@ export const AuthPasswordForm: React.FC = observer((props: Props) => { setPasswordFormData((prev) => ({ ...prev, [key]: value })); useEffect(() => { - if (csrfToken === undefined) - authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token)); - }, [csrfToken]); + if (csrfPromise === undefined) { + const promise = authService.requestCSRFToken(); + setCsrfPromise(promise); + } + }, [csrfPromise]); const redirectToUniqueCodeSignIn = async () => { handleAuthStep(EAuthSteps.UNIQUE_CODE); @@ -88,15 +92,29 @@ export const AuthPasswordForm: React.FC = observer((props: Props) => { const confirmPassword = passwordFormData.confirm_password ?? ""; const renderPasswordMatchError = !isRetryPasswordInputFocused || confirmPassword.length >= password.length; + const handleCSRFToken = async () => { + if (!formRef || !formRef.current) return; + const token = await csrfPromise; + if (!token?.csrf_token) return; + const csrfElement = formRef.current.querySelector("input[name=csrfmiddlewaretoken]"); + csrfElement?.setAttribute("value", token?.csrf_token); + }; + return (
setIsSubmitting(true)} + onSubmit={async (event) => { + event.preventDefault(); + await handleCSRFToken(); + formRef.current && formRef.current.submit(); + setIsSubmitting(true); + }} onError={() => setIsSubmitting(false)} > - +
diff --git a/web/core/components/account/auth-forms/password.tsx b/web/core/components/account/auth-forms/password.tsx index a4c8b205d..618c578b0 100644 --- a/web/core/components/account/auth-forms/password.tsx +++ b/web/core/components/account/auth-forms/password.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useEffect, useMemo, useState } from "react"; +import React, { useEffect, useMemo, useRef, useState } from "react"; import { observer } from "mobx-react"; import Link from "next/link"; // icons @@ -51,8 +51,10 @@ export const AuthPasswordForm: React.FC = observer((props: Props) => { const { email, isSMTPConfigured, handleAuthStep, handleEmailClear, mode, nextPath } = props; // hooks const { captureEvent } = useEventTracker(); + // ref + const formRef = useRef(null); // states - const [csrfToken, setCsrfToken] = useState(undefined); + const [csrfPromise, setCsrfPromise] = useState | undefined>(undefined); const [passwordFormData, setPasswordFormData] = useState({ ...defaultValues, email }); const [showPassword, setShowPassword] = useState({ password: false, @@ -70,9 +72,11 @@ export const AuthPasswordForm: React.FC = observer((props: Props) => { setPasswordFormData((prev) => ({ ...prev, [key]: value })); useEffect(() => { - if (csrfToken === undefined) - authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token)); - }, [csrfToken]); + if (csrfPromise === undefined) { + const promise = authService.requestCSRFToken(); + setCsrfPromise(promise); + } + }, [csrfPromise]); const redirectToUniqueCodeSignIn = async () => { handleAuthStep(EAuthSteps.UNIQUE_CODE); @@ -115,6 +119,14 @@ export const AuthPasswordForm: React.FC = observer((props: Props) => { const confirmPassword = passwordFormData?.confirm_password ?? ""; const renderPasswordMatchError = !isRetryPasswordInputFocused || confirmPassword.length >= password.length; + const handleCSRFToken = async () => { + if (!formRef || !formRef.current) return; + const token = await csrfPromise; + if (!token?.csrf_token) return; + const csrfElement = formRef.current.querySelector("input[name=csrfmiddlewaretoken]"); + csrfElement?.setAttribute("value", token?.csrf_token); + }; + return ( <> {isBannerMessage && mode === EAuthModes.SIGN_UP && ( @@ -132,11 +144,13 @@ export const AuthPasswordForm: React.FC = observer((props: Props) => {
)} { + onSubmit={async (event) => { event.preventDefault(); // Prevent form from submitting by default + await handleCSRFToken(); const isPasswordValid = mode === EAuthModes.SIGN_UP ? getPasswordStrength(passwordFormData.password) === E_PASSWORD_STRENGTH.STRENGTH_VALID @@ -144,14 +158,14 @@ export const AuthPasswordForm: React.FC = observer((props: Props) => { if (isPasswordValid) { setIsSubmitting(true); captureEvent(mode === EAuthModes.SIGN_IN ? SIGN_IN_WITH_PASSWORD : SIGN_UP_WITH_PASSWORD); - event.currentTarget.submit(); // Manually submit the form if the condition is met + formRef.current && formRef.current.submit(); // Manually submit the form if the condition is met } else { setBannerMessage(true); } }} onError={() => setIsSubmitting(false)} > - + {nextPath && }