Cast typeorm QueryFailedError to BadRequestException for the rest api (#12217)

This commit is contained in:
martmull
2025-05-23 17:00:45 +02:00
committed by GitHub
parent 362d540aac
commit 88b967dfb8
3 changed files with 37 additions and 8 deletions

View File

@ -10,6 +10,7 @@ import {
BillingExceptionCode, BillingExceptionCode,
} from 'src/engine/core-modules/billing/billing.exception'; } from 'src/engine/core-modules/billing/billing.exception';
import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service'; import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service';
import { CustomException } from 'src/utils/custom-exception';
@Catch(BillingException, Stripe.errors.StripeError) @Catch(BillingException, Stripe.errors.StripeError)
export class BillingRestApiExceptionFilter implements ExceptionFilter { export class BillingRestApiExceptionFilter implements ExceptionFilter {
@ -30,7 +31,7 @@ export class BillingRestApiExceptionFilter implements ExceptionFilter {
code: BillingExceptionCode.BILLING_STRIPE_ERROR, code: BillingExceptionCode.BILLING_STRIPE_ERROR,
message: exception.message, message: exception.message,
name: 'StripeError', name: 'StripeError',
}, } as CustomException,
response, response,
400, 400,
); );

View File

@ -1,14 +1,14 @@
import { Inject, Injectable, Scope } from '@nestjs/common'; import { BadRequestException, Inject, Injectable, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core'; import { REQUEST } from '@nestjs/core';
import { Response } from 'express'; import { Response } from 'express';
import { QueryFailedError } from 'typeorm';
import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface'; import { ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface';
import { ExceptionHandlerWorkspace } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-workspace.interface'; import { ExceptionHandlerWorkspace } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-workspace.interface';
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
import { handleException } from 'src/engine/utils/global-exception-handler.util'; import { handleException } from 'src/engine/utils/global-exception-handler.util';
import { CustomException } from 'src/utils/custom-exception';
interface RequestAndParams { interface RequestAndParams {
request: Request | null; request: Request | null;
@ -25,7 +25,7 @@ export class HttpExceptionHandlerService {
) {} ) {}
handleError = ( handleError = (
exception: CustomException, exception: Error,
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
response: Response<any, Record<string, any>>, response: Response<any, Record<string, any>>,
@ -37,11 +37,20 @@ export class HttpExceptionHandlerService {
): Response<any, Record<string, any>> | undefined => { ): Response<any, Record<string, any>> | undefined => {
const params = this.request?.params; const params = this.request?.params;
if (params?.workspaceId) if (params?.workspaceId) {
workspace = { ...workspace, id: params.workspaceId }; workspace = { ...workspace, id: params.workspaceId };
if (params?.userId) user = { ...user, id: params.userId }; }
const statusCode = errorCode || 500; if (params?.userId) {
user = { ...user, id: params.userId };
}
let statusCode = errorCode || 500;
if (exception instanceof QueryFailedError) {
exception = new BadRequestException(exception.message);
statusCode = 400;
}
handleException({ handleException({
exception, exception,
@ -53,7 +62,7 @@ export class HttpExceptionHandlerService {
return response.status(statusCode).send({ return response.status(statusCode).send({
statusCode, statusCode,
error: exception.name || 'Bad Request', error: exception.name || 'BadRequestException',
messages: [exception?.message], messages: [exception?.message],
}); });
}; };

View File

@ -193,4 +193,23 @@ describe('Core REST API Create One endpoint', () => {
expect(res.body.error).toBe('BadRequestException'); expect(res.body.error).toBe('BadRequestException');
}); });
}); });
it('should return a BadRequestException when trying to create an opportunity with an invalid enum', async () => {
const requestBody = {
stage: 'INVALID_ENUM_VALUE',
};
await makeRestAPIRequest({
method: 'post',
path: `/opportunities`,
body: requestBody,
})
.expect(400)
.expect((res) => {
expect(res.body.messages[0]).toMatch(
/invalid input value for enum workspace_[a-z0-9]+\.opportunity_stage_enum: "INVALID_ENUM_VALUE"/,
);
expect(res.body.error).toBe('BadRequestException');
});
});
}); });