fix(email-verification): prevent double email validation (#12250)

Fix #12177 
Fix #12171

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Antoine Moreaux
2025-05-23 18:24:26 +02:00
committed by GitHub
parent 8de85eea61
commit 5428348d7f
14 changed files with 206 additions and 43 deletions

View File

@ -2,6 +2,7 @@ import { useAuth } from '@/auth/hooks/useAuth';
import { AppPath } from '@/types/AppPath';
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { ApolloError } from '@apollo/client';
import { useVerifyLogin } from '@/auth/hooks/useVerifyLogin';
import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain';
@ -41,7 +42,10 @@ export const VerifyEmailEffect = () => {
try {
const { loginToken, workspaceUrls } =
await getLoginTokenFromEmailVerificationToken(emailVerificationToken);
await getLoginTokenFromEmailVerificationToken(
emailVerificationToken,
email,
);
enqueueSnackBar(t`Email verified.`, {
dedupeKey: 'email-verification-dedupe-key',
@ -56,10 +60,23 @@ export const VerifyEmailEffect = () => {
}
verifyLoginToken(loginToken.token);
} catch (error) {
enqueueSnackBar(t`Email verification failed.`, {
const message: string =
error instanceof ApolloError
? error.message
: 'Email verification failed';
enqueueSnackBar(t`${message}`, {
dedupeKey: 'email-verification-error-dedupe-key',
variant: SnackBarVariant.Error,
});
if (
error instanceof ApolloError &&
error.graphQLErrors[0].extensions?.subCode ===
'EMAIL_ALREADY_VERIFIED'
) {
navigate(AppPath.SignInUp);
}
setIsError(true);
}
};

View File

@ -3,11 +3,13 @@ import { gql } from '@apollo/client';
export const GET_LOGIN_TOKEN_FROM_EMAIL_VERIFICATION_TOKEN = gql`
mutation GetLoginTokenFromEmailVerificationToken(
$emailVerificationToken: String!
$email: String!
$captchaToken: String
$origin: String!
) {
getLoginTokenFromEmailVerificationToken(
emailVerificationToken: $emailVerificationToken
email: $email
captchaToken: $captchaToken
origin: $origin
) {

View File

@ -210,9 +210,14 @@ export const useAuth = () => {
);
const handleGetLoginTokenFromEmailVerificationToken = useCallback(
async (emailVerificationToken: string, captchaToken?: string) => {
async (
emailVerificationToken: string,
email: string,
captchaToken?: string,
) => {
const loginTokenResult = await getLoginTokenFromEmailVerificationToken({
variables: {
email,
emailVerificationToken,
captchaToken,
origin,