diff --git a/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts b/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts index ea7b3ae6f..2d2e71965 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/auth.resolver.ts @@ -37,6 +37,7 @@ import { RenewTokenService } from 'src/engine/core-modules/auth/token/services/r import { TransientTokenService } from 'src/engine/core-modules/auth/token/services/transient-token.service'; import { CaptchaGuard } from 'src/engine/core-modules/captcha/captcha.guard'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; +import { EmailVerificationExceptionFilter } from 'src/engine/core-modules/email-verification/email-verification-exception-filter.util'; import { EmailVerificationService } from 'src/engine/core-modules/email-verification/services/email-verification.service'; import { I18nContext } from 'src/engine/core-modules/i18n/types/i18n-context.type'; import { SSOService } from 'src/engine/core-modules/sso/services/sso.service'; @@ -66,7 +67,11 @@ import { WorkspaceInviteHashValidInput } from './dto/workspace-invite-hash.input import { AuthService } from './services/auth.service'; @Resolver() -@UseFilters(AuthGraphqlApiExceptionFilter, PermissionsGraphqlApiExceptionFilter) +@UseFilters( + AuthGraphqlApiExceptionFilter, + PermissionsGraphqlApiExceptionFilter, + EmailVerificationExceptionFilter, +) export class AuthResolver { constructor( @InjectRepository(User, 'core') diff --git a/packages/twenty-server/src/engine/core-modules/email-verification/email-verification-exception-filter.util.ts b/packages/twenty-server/src/engine/core-modules/email-verification/email-verification-exception-filter.util.ts new file mode 100644 index 000000000..bfca293d9 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/email-verification/email-verification-exception-filter.util.ts @@ -0,0 +1,32 @@ +import { Catch, ExceptionFilter } from '@nestjs/common'; + +import { + EmailVerificationException, + EmailVerificationExceptionCode, +} from 'src/engine/core-modules/email-verification/email-verification.exception'; +import { + ForbiddenError, + UserInputError, +} from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; + +@Catch(EmailVerificationException) +export class EmailVerificationExceptionFilter implements ExceptionFilter { + catch(exception: EmailVerificationException) { + switch (exception.code) { + case EmailVerificationExceptionCode.INVALID_TOKEN: + case EmailVerificationExceptionCode.INVALID_APP_TOKEN_TYPE: + case EmailVerificationExceptionCode.TOKEN_EXPIRED: + case EmailVerificationExceptionCode.RATE_LIMIT_EXCEEDED: + throw new ForbiddenError(exception.message); + case EmailVerificationExceptionCode.EMAIL_MISSING: + case EmailVerificationExceptionCode.EMAIL_ALREADY_VERIFIED: + case EmailVerificationExceptionCode.EMAIL_VERIFICATION_NOT_REQUIRED: + throw new UserInputError(exception.message); + default: { + const _exhaustiveCheck: never = exception.code; + + throw exception; + } + } + } +} diff --git a/packages/twenty-server/src/engine/core-modules/email-verification/email-verification-exception-handler.util.ts b/packages/twenty-server/src/engine/core-modules/email-verification/email-verification-exception-handler.util.ts deleted file mode 100644 index 367071dbe..000000000 --- a/packages/twenty-server/src/engine/core-modules/email-verification/email-verification-exception-handler.util.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { - EmailVerificationException, - EmailVerificationExceptionCode, -} from 'src/engine/core-modules/email-verification/email-verification.exception'; -import { - ForbiddenError, - UserInputError, -} from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; - -export const emailVerificationGraphqlApiExceptionHandler = ( - error: EmailVerificationException, -) => { - switch (error.code) { - case EmailVerificationExceptionCode.INVALID_TOKEN: - case EmailVerificationExceptionCode.INVALID_APP_TOKEN_TYPE: - case EmailVerificationExceptionCode.TOKEN_EXPIRED: - case EmailVerificationExceptionCode.RATE_LIMIT_EXCEEDED: - throw new ForbiddenError(error.message); - case EmailVerificationExceptionCode.EMAIL_MISSING: - case EmailVerificationExceptionCode.EMAIL_ALREADY_VERIFIED: - case EmailVerificationExceptionCode.EMAIL_VERIFICATION_NOT_REQUIRED: - throw new UserInputError(error.message); - default: { - const _exhaustiveCheck: never = error.code; - - throw error; - } - } -}; diff --git a/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.resolver.ts b/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.resolver.ts index db286c95c..5509d3d3b 100644 --- a/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/email-verification/email-verification.resolver.ts @@ -1,3 +1,4 @@ +import { UseFilters } from '@nestjs/common'; import { Args, Context, Mutation, Resolver } from '@nestjs/graphql'; import { SOURCE_LOCALE } from 'twenty-shared/translations'; @@ -5,13 +6,13 @@ import { SOURCE_LOCALE } from 'twenty-shared/translations'; import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service'; import { ResendEmailVerificationTokenInput } from 'src/engine/core-modules/email-verification/dtos/resend-email-verification-token.input'; import { ResendEmailVerificationTokenOutput } from 'src/engine/core-modules/email-verification/dtos/resend-email-verification-token.output'; -import { emailVerificationGraphqlApiExceptionHandler } from 'src/engine/core-modules/email-verification/email-verification-exception-handler.util'; -import { EmailVerificationException } from 'src/engine/core-modules/email-verification/email-verification.exception'; +import { EmailVerificationExceptionFilter } from 'src/engine/core-modules/email-verification/email-verification-exception-filter.util'; import { EmailVerificationService } from 'src/engine/core-modules/email-verification/services/email-verification.service'; import { I18nContext } from 'src/engine/core-modules/i18n/types/i18n-context.type'; import { OriginHeader } from 'src/engine/decorators/auth/origin-header.decorator'; @Resolver() +@UseFilters(EmailVerificationExceptionFilter) export class EmailVerificationResolver { constructor( private readonly emailVerificationService: EmailVerificationService, @@ -25,22 +26,15 @@ export class EmailVerificationResolver { @OriginHeader() origin: string, @Context() context: I18nContext, ): Promise { - try { - const workspace = - await this.domainManagerService.getWorkspaceByOriginOrDefaultWorkspace( - origin, - ); - - return await this.emailVerificationService.resendEmailVerificationToken( - resendEmailVerificationTokenInput.email, - workspace, - context.req.headers['x-locale'] ?? SOURCE_LOCALE, + const workspace = + await this.domainManagerService.getWorkspaceByOriginOrDefaultWorkspace( + origin, ); - } catch (error) { - if (error instanceof EmailVerificationException) { - return emailVerificationGraphqlApiExceptionHandler(error); - } - throw error; - } + + return await this.emailVerificationService.resendEmailVerificationToken( + resendEmailVerificationTokenInput.email, + workspace, + context.req.headers['x-locale'] ?? SOURCE_LOCALE, + ); } }