Fix query runner throwing 500 when pg_graphql detects unique constraint (#5323)

## Context
Since pg_graphql does not return specific error/exception, we have to
map the error message and throw validation errors when needed
This PR adds a check on unicity constraint error returned by pg_graphql
when we are trying to insert duplicate records and returns a 400 instead
of being handled by the exceptionHandler as a 500.
This commit is contained in:
Weiko
2024-05-07 21:03:15 +02:00
committed by GitHub
parent e802cef8f1
commit b691894254
2 changed files with 23 additions and 9 deletions

View File

@ -8,10 +8,24 @@ interface PgGraphQLErrorMapping {
[key: string]: (command: string, objectName: string) => HttpException; [key: string]: (command: string, objectName: string) => HttpException;
} }
const pgGraphQLCommandMapping = {
insertInto: 'insert',
update: 'update',
deleteFrom: 'delete',
};
const pgGraphQLErrorMapping: PgGraphQLErrorMapping = { const pgGraphQLErrorMapping: PgGraphQLErrorMapping = {
'delete impacts too many records': (command, objectName) => 'delete impacts too many records': (command, objectName) =>
new BadRequestException( new BadRequestException(
`Cannot ${command} ${objectName} because it impacts too many records.`, `Cannot ${
pgGraphQLCommandMapping[command] ?? command
} ${objectName} because it impacts too many records.`,
),
'duplicate key value violates unique constraint': (command, objectName) =>
new BadRequestException(
`Cannot ${
pgGraphQLCommandMapping[command] ?? command
} ${objectName} because it violates a uniqueness constraint.`,
), ),
}; };
@ -22,7 +36,14 @@ export const computePgGraphQLError = (
) => { ) => {
const error = errors[0]; const error = errors[0];
const errorMessage = error?.message; const errorMessage = error?.message;
const mappedError = pgGraphQLErrorMapping[errorMessage];
const mappedErrorKey = Object.keys(pgGraphQLErrorMapping).find(
(key) => errorMessage?.startsWith(key),
);
const mappedError = mappedErrorKey
? pgGraphQLErrorMapping[mappedErrorKey]
: null;
if (mappedError) { if (mappedError) {
return mappedError(command, objectName); return mappedError(command, objectName);

View File

@ -599,13 +599,6 @@ export class WorkspaceQueryRunnerService {
const result = graphqlResult?.[0]?.resolve?.data?.[entityKey]; const result = graphqlResult?.[0]?.resolve?.data?.[entityKey];
const errors = graphqlResult?.[0]?.resolve?.errors; const errors = graphqlResult?.[0]?.resolve?.errors;
if (!result) {
this.logger.log(
`No result found for ${entityKey}, graphqlResult: ` +
JSON.stringify(graphqlResult, null, 3),
);
}
if ( if (
result && result &&
['update', 'deleteFrom'].includes(command) && ['update', 'deleteFrom'].includes(command) &&