Marie
2025-05-21 14:09:11 +02:00
committed by GitHub
parent 76a8a644a2
commit fdde7651a4
4 changed files with 50 additions and 48 deletions

View File

@ -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')

View File

@ -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;
}
}
}
}

View File

@ -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;
}
}
};

View File

@ -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<ResendEmailVerificationTokenOutput> {
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,
);
}
}