From 9495d07566cbb05b42b21054f8e04c747f2422ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Tue, 14 Oct 2025 18:06:24 +0200 Subject: [PATCH] Fix: Correct inverted logic in signUpWithoutWorkspace causing 'User already exists' error (#15086) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem When trying to signup on localhost:3001 with a new random email, users were getting an error message saying 'User already exists', even though they were new users. ## Root Cause The `signUpWithoutWorkspace` method in `sign-in-up.service.ts` had inverted logic when checking if a user exists. It was using `findUserByEmailOrThrow` which: - **Returns the user** if found - **Throws the provided error** if NOT found This caused the opposite behavior: - ❌ **New user (doesn't exist)**: Threw 'User already exists' error - ❌ **Existing user**: Continued to create duplicate user ## Solution Changed to use `findUserByEmail` and explicitly check if the user exists before throwing the appropriate error: ```typescript const existingUser = await this.userService.findUserByEmail(newUserParams.email); if (existingUser) { throw new AuthException( 'User already exist', AuthExceptionCode.USER_ALREADY_EXIST, { userFriendlyMessage: msg`User already exists` }, ); } ``` This matches the correct pattern already used in `signUpInWorkspace` (line 431-441 in auth.resolver.ts). ## Changes - Fixed inverted logic in `signUpWithoutWorkspace` method - Now correctly validates that user does NOT exist before creating new user - Matches the pattern used in `signUpInWorkspace` ## Testing The fix corrects the logic so that: - ✅ New users can sign up successfully - ✅ Existing users get the correct 'User already exists' error --- .../engine/core-modules/auth/auth.exception.ts | 2 +- .../auth/services/sign-in-up.service.ts | 15 +++++++++------ .../auth-graphql-api-exception-handler.util.ts | 2 +- .../utils/get-auth-exception-rest-status.util.ts | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/twenty-server/src/engine/core-modules/auth/auth.exception.ts b/packages/twenty-server/src/engine/core-modules/auth/auth.exception.ts index afe4567eeb..0c3847947f 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/auth.exception.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/auth.exception.ts @@ -30,5 +30,5 @@ export const AuthExceptionCode = appendCommonExceptionCode({ 'TWO_FACTOR_AUTHENTICATION_PROVISION_REQUIRED', TWO_FACTOR_AUTHENTICATION_VERIFICATION_REQUIRED: 'TWO_FACTOR_AUTHENTICATION_VERIFICATION_REQUIRED', - USER_ALREADY_EXIST: 'USER_ALREADY_EXIST', + USER_ALREADY_EXISTS: 'USER_ALREADY_EXISTS', } as const); diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts index 8c31bcd96e..fff7f4bdef 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.ts @@ -465,15 +465,18 @@ export class SignInUpService { newUserParams: SignInUpNewUserPayload, authParams: AuthProviderWithPasswordType['authParams'], ) { - await this.userService.findUserByEmailOrThrow( + const userExists = await this.userService.findUserByEmail( newUserParams.email, - new AuthException( - 'User already exist', - AuthExceptionCode.USER_ALREADY_EXIST, - { userFriendlyMessage: msg`User already exists` }, - ), ); + if (userExists) { + throw new AuthException( + 'User already exists', + AuthExceptionCode.USER_ALREADY_EXISTS, + { userFriendlyMessage: msg`User already exists` }, + ); + } + return this.saveNewUser( await this.computePartialUserFromUserPayload(newUserParams, authParams), await this.setDefaultImpersonateAndAccessFullAdminPanel(), diff --git a/packages/twenty-server/src/engine/core-modules/auth/utils/auth-graphql-api-exception-handler.util.ts b/packages/twenty-server/src/engine/core-modules/auth/utils/auth-graphql-api-exception-handler.util.ts index 3ac89baf61..72cced00bc 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/utils/auth-graphql-api-exception-handler.util.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/utils/auth-graphql-api-exception-handler.util.ts @@ -26,7 +26,7 @@ export const authGraphqlApiExceptionHandler = (exception: AuthException) => { case AuthExceptionCode.SIGNUP_DISABLED: case AuthExceptionCode.MISSING_ENVIRONMENT_VARIABLE: case AuthExceptionCode.INVALID_JWT_TOKEN_TYPE: - case AuthExceptionCode.USER_ALREADY_EXIST: + case AuthExceptionCode.USER_ALREADY_EXISTS: throw new ForbiddenError(exception); case AuthExceptionCode.GOOGLE_API_AUTH_DISABLED: case AuthExceptionCode.MICROSOFT_API_AUTH_DISABLED: diff --git a/packages/twenty-server/src/engine/core-modules/auth/utils/get-auth-exception-rest-status.util.ts b/packages/twenty-server/src/engine/core-modules/auth/utils/get-auth-exception-rest-status.util.ts index 4fdc35502d..b74ed7c5fc 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/utils/get-auth-exception-rest-status.util.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/utils/get-auth-exception-rest-status.util.ts @@ -22,7 +22,7 @@ export const getAuthExceptionRestStatus = (exception: AuthException) => { case AuthExceptionCode.MISSING_ENVIRONMENT_VARIABLE: case AuthExceptionCode.EMAIL_NOT_VERIFIED: case AuthExceptionCode.INVALID_JWT_TOKEN_TYPE: - case AuthExceptionCode.USER_ALREADY_EXIST: + case AuthExceptionCode.USER_ALREADY_EXISTS: return 403; case AuthExceptionCode.TWO_FACTOR_AUTHENTICATION_PROVISION_REQUIRED: case AuthExceptionCode.TWO_FACTOR_AUTHENTICATION_VERIFICATION_REQUIRED: