Add exceptions for metadata modules (#6070)
Class exception for each metadata module + handler to map on graphql error TODO left : - find a way to call handler on auto-resolvers nestjs query (probably interceptors) - discuss what should be done for pre-hooks errors - discuss what should be done for Unauthorized exception
This commit is contained in:
@ -0,0 +1,16 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export class RemoteServerException extends CustomException {
|
||||
code: RemoteServerExceptionCode;
|
||||
constructor(message: string, code: RemoteServerExceptionCode) {
|
||||
super(message, code);
|
||||
}
|
||||
}
|
||||
|
||||
export enum RemoteServerExceptionCode {
|
||||
REMOTE_SERVER_NOT_FOUND = 'REMOTE_SERVER_NOT_FOUND',
|
||||
REMOTE_SERVER_ALREADY_EXISTS = 'REMOTE_SERVER_ALREADY_EXISTS',
|
||||
REMOTE_SERVER_MUTATION_NOT_ALLOWED = 'REMOTE_SERVER_MUTATION_NOT_ALLOWED',
|
||||
REMOTE_SERVER_CONNECTION_ERROR = 'REMOTE_SERVER_CONNECTION_ERROR',
|
||||
INVALID_REMOTE_SERVER_INPUT = 'INVALID_REMOTE_SERVER_INPUT',
|
||||
}
|
||||
@ -11,6 +11,7 @@ import { RemoteServerDTO } from 'src/engine/metadata-modules/remote-server/dtos/
|
||||
import { UpdateRemoteServerInput } from 'src/engine/metadata-modules/remote-server/dtos/update-remote-server.input';
|
||||
import { RemoteServerType } from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
||||
import { RemoteServerService } from 'src/engine/metadata-modules/remote-server/remote-server.service';
|
||||
import { remoteServerGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/remote-server/utils/remote-server-graphql-api-exception-handler.util';
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Resolver()
|
||||
@ -24,7 +25,11 @@ export class RemoteServerResolver {
|
||||
@Args('input') input: CreateRemoteServerInput<RemoteServerType>,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
return this.remoteServerService.createOneRemoteServer(input, workspaceId);
|
||||
try {
|
||||
return this.remoteServerService.createOneRemoteServer(input, workspaceId);
|
||||
} catch (error) {
|
||||
remoteServerGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => RemoteServerDTO)
|
||||
@ -32,7 +37,11 @@ export class RemoteServerResolver {
|
||||
@Args('input') input: UpdateRemoteServerInput<RemoteServerType>,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
return this.remoteServerService.updateOneRemoteServer(input, workspaceId);
|
||||
try {
|
||||
return this.remoteServerService.updateOneRemoteServer(input, workspaceId);
|
||||
} catch (error) {
|
||||
remoteServerGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => RemoteServerDTO)
|
||||
@ -40,7 +49,11 @@ export class RemoteServerResolver {
|
||||
@Args('input') { id }: RemoteServerIdInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
return this.remoteServerService.deleteOneRemoteServer(id, workspaceId);
|
||||
try {
|
||||
return this.remoteServerService.deleteOneRemoteServer(id, workspaceId);
|
||||
} catch (error) {
|
||||
remoteServerGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Query(() => RemoteServerDTO)
|
||||
@ -48,7 +61,14 @@ export class RemoteServerResolver {
|
||||
@Args('input') { id }: RemoteServerIdInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
return this.remoteServerService.findOneByIdWithinWorkspace(id, workspaceId);
|
||||
try {
|
||||
return this.remoteServerService.findOneByIdWithinWorkspace(
|
||||
id,
|
||||
workspaceId,
|
||||
);
|
||||
} catch (error) {
|
||||
remoteServerGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Query(() => [RemoteServerDTO])
|
||||
@ -57,9 +77,13 @@ export class RemoteServerResolver {
|
||||
{ foreignDataWrapperType }: RemoteServerTypeInput<RemoteServerType>,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
return this.remoteServerService.findManyByTypeWithinWorkspace(
|
||||
foreignDataWrapperType,
|
||||
workspaceId,
|
||||
);
|
||||
try {
|
||||
return this.remoteServerService.findManyByTypeWithinWorkspace(
|
||||
foreignDataWrapperType,
|
||||
workspaceId,
|
||||
);
|
||||
} catch (error) {
|
||||
remoteServerGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
import {
|
||||
ForbiddenException,
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import isEmpty from 'lodash.isempty';
|
||||
@ -27,6 +23,10 @@ import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/work
|
||||
import { buildUpdateRemoteServerRawQuery } from 'src/engine/metadata-modules/remote-server/utils/build-update-remote-server-raw-query.utils';
|
||||
import { validateRemoteServerType } from 'src/engine/metadata-modules/remote-server/utils/validate-remote-server-type.util';
|
||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import {
|
||||
RemoteServerException,
|
||||
RemoteServerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-server.exception';
|
||||
|
||||
@Injectable()
|
||||
export class RemoteServerService<T extends RemoteServerType> {
|
||||
@ -122,7 +122,10 @@ export class RemoteServerService<T extends RemoteServerType> {
|
||||
);
|
||||
|
||||
if (!remoteServer) {
|
||||
throw new NotFoundException('Remote server does not exist');
|
||||
throw new RemoteServerException(
|
||||
'Remote server does not exist',
|
||||
RemoteServerExceptionCode.REMOTE_SERVER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const currentRemoteTablesForServer =
|
||||
@ -132,8 +135,9 @@ export class RemoteServerService<T extends RemoteServerType> {
|
||||
});
|
||||
|
||||
if (currentRemoteTablesForServer.length > 0) {
|
||||
throw new ForbiddenException(
|
||||
throw new RemoteServerException(
|
||||
'Cannot update remote server with synchronized tables',
|
||||
RemoteServerExceptionCode.REMOTE_SERVER_MUTATION_NOT_ALLOWED,
|
||||
);
|
||||
}
|
||||
|
||||
@ -207,7 +211,10 @@ export class RemoteServerService<T extends RemoteServerType> {
|
||||
});
|
||||
|
||||
if (!remoteServer) {
|
||||
throw new NotFoundException('Remote server does not exist');
|
||||
throw new RemoteServerException(
|
||||
'Remote server does not exist',
|
||||
RemoteServerExceptionCode.REMOTE_SERVER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
await this.remoteTableService.unsyncAll(workspaceId, remoteServer);
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export class DistantTableException extends CustomException {
|
||||
code: DistantTableExceptionCode;
|
||||
constructor(message: string, code: DistantTableExceptionCode) {
|
||||
super(message, code);
|
||||
}
|
||||
}
|
||||
|
||||
export enum DistantTableExceptionCode {
|
||||
INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR',
|
||||
TIMEOUT_ERROR = 'TIMEOUT_ERROR',
|
||||
}
|
||||
@ -1,8 +1,4 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
Injectable,
|
||||
RequestTimeoutException,
|
||||
} from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { EntityManager, Repository } from 'typeorm';
|
||||
@ -17,6 +13,10 @@ import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-
|
||||
import { STRIPE_DISTANT_TABLES } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/utils/stripe-distant-tables.util';
|
||||
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||
import { isQueryTimeoutError } from 'src/engine/utils/query-timeout.util';
|
||||
import {
|
||||
DistantTableException,
|
||||
DistantTableExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.exception';
|
||||
|
||||
@Injectable()
|
||||
export class DistantTableService {
|
||||
@ -64,7 +64,10 @@ export class DistantTableService {
|
||||
tableName?: string,
|
||||
): Promise<DistantTables> {
|
||||
if (!remoteServer.schema) {
|
||||
throw new BadRequestException('Remote server schema is not defined');
|
||||
throw new DistantTableException(
|
||||
'Remote server schema is not defined',
|
||||
DistantTableExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
const tmpSchemaId = v4();
|
||||
@ -116,8 +119,9 @@ export class DistantTableService {
|
||||
return distantTables;
|
||||
} catch (error) {
|
||||
if (isQueryTimeoutError(error)) {
|
||||
throw new RequestTimeoutException(
|
||||
throw new DistantTableException(
|
||||
`Could not find distant tables: ${error.message}`,
|
||||
DistantTableExceptionCode.TIMEOUT_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
@ -132,8 +136,9 @@ export class DistantTableService {
|
||||
case RemoteServerType.STRIPE_FDW:
|
||||
return STRIPE_DISTANT_TABLES;
|
||||
default:
|
||||
throw new BadRequestException(
|
||||
throw new DistantTableException(
|
||||
`Type ${remoteServer.foreignDataWrapperType} does not have a static schema.`,
|
||||
DistantTableExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export class ForeignTableException extends CustomException {
|
||||
code: ForeignTableExceptionCode;
|
||||
constructor(message: string, code: ForeignTableExceptionCode) {
|
||||
super(message, code);
|
||||
}
|
||||
}
|
||||
|
||||
export enum ForeignTableExceptionCode {
|
||||
FOREIGN_TABLE_MUTATION_NOT_ALLOWED = 'FOREIGN_TABLE_MUTATION_NOT_ALLOWED',
|
||||
INVALID_FOREIGN_TABLE_INPUT = 'INVALID_FOREIGN_TABLE_INPUT',
|
||||
}
|
||||
@ -1,10 +1,14 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
RemoteServerEntity,
|
||||
RemoteServerType,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
||||
import { RemoteTableStatus } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
|
||||
import {
|
||||
ForeignTableException,
|
||||
ForeignTableExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.exception';
|
||||
import { getForeignTableColumnName } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/utils/get-foreign-table-column-name.util';
|
||||
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
@ -90,8 +94,9 @@ export class ForeignTableService {
|
||||
} catch (exception) {
|
||||
this.workspaceMigrationService.deleteById(workspaceMigration.id);
|
||||
|
||||
throw new BadRequestException(
|
||||
throw new ForeignTableException(
|
||||
'Could not create foreign table. The table may already exists or a column type may not be supported.',
|
||||
ForeignTableExceptionCode.INVALID_FOREIGN_TABLE_INPUT,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -130,7 +135,10 @@ export class ForeignTableService {
|
||||
} catch (exception) {
|
||||
this.workspaceMigrationService.deleteById(workspaceMigration.id);
|
||||
|
||||
throw new BadRequestException('Could not alter foreign table.');
|
||||
throw new ForeignTableException(
|
||||
'Could not alter foreign table.',
|
||||
ForeignTableExceptionCode.FOREIGN_TABLE_MUTATION_NOT_ALLOWED,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,7 +175,10 @@ export class ForeignTableService {
|
||||
case RemoteServerType.STRIPE_FDW:
|
||||
return { object: distantTableName };
|
||||
default:
|
||||
throw new BadRequestException('Foreign data wrapper not supported');
|
||||
throw new ForeignTableException(
|
||||
'Foreign data wrapper not supported',
|
||||
ForeignTableExceptionCode.INVALID_FOREIGN_TABLE_INPUT,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export class RemoteTableException extends CustomException {
|
||||
code: RemoteTableExceptionCode;
|
||||
constructor(message: string, code: RemoteTableExceptionCode) {
|
||||
super(message, code);
|
||||
}
|
||||
}
|
||||
|
||||
export enum RemoteTableExceptionCode {
|
||||
REMOTE_TABLE_NOT_FOUND = 'REMOTE_TABLE_NOT_FOUND',
|
||||
INVALID_REMOTE_TABLE_INPUT = 'INVALID_REMOTE_TABLE_INPUT',
|
||||
REMOTE_TABLE_ALREADY_EXISTS = 'REMOTE_TABLE_ALREADY_EXISTS',
|
||||
NO_FOREIGN_TABLES_FOUND = 'NO_FOREIGN_TABLES_FOUND',
|
||||
NO_OBJECT_METADATA_FOUND = 'NO_OBJECT_METADATA_FOUND',
|
||||
NO_FIELD_METADATA_FOUND = 'NO_FIELD_METADATA_FOUND',
|
||||
}
|
||||
@ -8,6 +8,7 @@ import { FindManyRemoteTablesInput } from 'src/engine/metadata-modules/remote-se
|
||||
import { RemoteTableInput } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table-input';
|
||||
import { RemoteTableDTO } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
|
||||
import { RemoteTableService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.service';
|
||||
import { remoteTableGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/remote-server/remote-table/utils/remote-table-graphql-api-exception-handler.util';
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Resolver()
|
||||
@ -19,11 +20,15 @@ export class RemoteTableResolver {
|
||||
@Args('input') input: FindManyRemoteTablesInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
return this.remoteTableService.findDistantTablesWithStatus(
|
||||
input.id,
|
||||
workspaceId,
|
||||
input.shouldFetchPendingSchemaUpdates,
|
||||
);
|
||||
try {
|
||||
return this.remoteTableService.findDistantTablesWithStatus(
|
||||
input.id,
|
||||
workspaceId,
|
||||
input.shouldFetchPendingSchemaUpdates,
|
||||
);
|
||||
} catch (error) {
|
||||
remoteTableGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => RemoteTableDTO)
|
||||
@ -31,7 +36,11 @@ export class RemoteTableResolver {
|
||||
@Args('input') input: RemoteTableInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
return this.remoteTableService.syncRemoteTable(input, workspaceId);
|
||||
try {
|
||||
return this.remoteTableService.syncRemoteTable(input, workspaceId);
|
||||
} catch (error) {
|
||||
remoteTableGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => RemoteTableDTO)
|
||||
@ -39,7 +48,11 @@ export class RemoteTableResolver {
|
||||
@Args('input') input: RemoteTableInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
return this.remoteTableService.unsyncRemoteTable(input, workspaceId);
|
||||
try {
|
||||
return this.remoteTableService.unsyncRemoteTable(input, workspaceId);
|
||||
} catch (error) {
|
||||
remoteTableGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Mutation(() => RemoteTableDTO)
|
||||
@ -47,9 +60,13 @@ export class RemoteTableResolver {
|
||||
@Args('input') input: RemoteTableInput,
|
||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
||||
) {
|
||||
return this.remoteTableService.syncRemoteTableSchemaChanges(
|
||||
input,
|
||||
workspaceId,
|
||||
);
|
||||
try {
|
||||
return this.remoteTableService.syncRemoteTableSchemaChanges(
|
||||
input,
|
||||
workspaceId,
|
||||
);
|
||||
} catch (error) {
|
||||
remoteTableGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { BadRequestException, Logger, NotFoundException } from '@nestjs/common';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
@ -40,6 +40,10 @@ import {
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import {
|
||||
RemoteTableException,
|
||||
RemoteTableExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.exception';
|
||||
|
||||
export class RemoteTableService {
|
||||
private readonly logger = new Logger(RemoteTableService.name);
|
||||
@ -74,7 +78,10 @@ export class RemoteTableService {
|
||||
});
|
||||
|
||||
if (!remoteServer) {
|
||||
throw new NotFoundException('Remote server does not exist');
|
||||
throw new RemoteTableException(
|
||||
'Remote server does not exist',
|
||||
RemoteTableExceptionCode.INVALID_REMOTE_TABLE_INPUT,
|
||||
);
|
||||
}
|
||||
|
||||
const currentRemoteTables = await this.findRemoteTablesByServerId({
|
||||
@ -148,7 +155,10 @@ export class RemoteTableService {
|
||||
});
|
||||
|
||||
if (!remoteServer) {
|
||||
throw new NotFoundException('Remote server does not exist');
|
||||
throw new RemoteTableException(
|
||||
'Remote server does not exist',
|
||||
RemoteTableExceptionCode.INVALID_REMOTE_TABLE_INPUT,
|
||||
);
|
||||
}
|
||||
|
||||
const currentRemoteTableWithSameDistantName =
|
||||
@ -161,7 +171,10 @@ export class RemoteTableService {
|
||||
});
|
||||
|
||||
if (currentRemoteTableWithSameDistantName) {
|
||||
throw new BadRequestException('Remote table already exists');
|
||||
throw new RemoteTableException(
|
||||
'Remote server does not exist',
|
||||
RemoteTableExceptionCode.REMOTE_TABLE_ALREADY_EXISTS,
|
||||
);
|
||||
}
|
||||
|
||||
const dataSourceMetatada =
|
||||
@ -200,7 +213,10 @@ export class RemoteTableService {
|
||||
);
|
||||
|
||||
if (!distantTableColumns) {
|
||||
throw new BadRequestException('Table not found');
|
||||
throw new RemoteTableException(
|
||||
'Remote server does not exist',
|
||||
RemoteTableExceptionCode.REMOTE_TABLE_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
// We only support remote tables with an id column for now.
|
||||
@ -209,7 +225,10 @@ export class RemoteTableService {
|
||||
);
|
||||
|
||||
if (!distantTableIdColumn) {
|
||||
throw new BadRequestException('Remote table must have an id column');
|
||||
throw new RemoteTableException(
|
||||
'Remote server does not exist',
|
||||
RemoteTableExceptionCode.INVALID_REMOTE_TABLE_INPUT,
|
||||
);
|
||||
}
|
||||
|
||||
await this.foreignTableService.createForeignTable(
|
||||
@ -250,7 +269,10 @@ export class RemoteTableService {
|
||||
});
|
||||
|
||||
if (!remoteServer) {
|
||||
throw new NotFoundException('Remote server does not exist');
|
||||
throw new RemoteTableException(
|
||||
'Remote server does not exist',
|
||||
RemoteTableExceptionCode.INVALID_REMOTE_TABLE_INPUT,
|
||||
);
|
||||
}
|
||||
|
||||
const remoteTable = await this.remoteTableRepository.findOne({
|
||||
@ -262,7 +284,10 @@ export class RemoteTableService {
|
||||
});
|
||||
|
||||
if (!remoteTable) {
|
||||
throw new NotFoundException('Remote table does not exist');
|
||||
throw new RemoteTableException(
|
||||
'Remote table does not exist',
|
||||
RemoteTableExceptionCode.REMOTE_TABLE_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
await this.unsyncOne(workspaceId, remoteTable, remoteServer);
|
||||
@ -302,7 +327,10 @@ export class RemoteTableService {
|
||||
});
|
||||
|
||||
if (!remoteServer) {
|
||||
throw new NotFoundException('Remote server does not exist');
|
||||
throw new RemoteTableException(
|
||||
'Remote server does not exist',
|
||||
RemoteTableExceptionCode.INVALID_REMOTE_TABLE_INPUT,
|
||||
);
|
||||
}
|
||||
|
||||
const remoteTable = await this.remoteTableRepository.findOne({
|
||||
@ -314,7 +342,10 @@ export class RemoteTableService {
|
||||
});
|
||||
|
||||
if (!remoteTable) {
|
||||
throw new NotFoundException('Remote table does not exist');
|
||||
throw new RemoteTableException(
|
||||
'Remote table does not exist',
|
||||
RemoteTableExceptionCode.REMOTE_TABLE_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const distantTableColumns =
|
||||
@ -379,7 +410,10 @@ export class RemoteTableService {
|
||||
);
|
||||
|
||||
if (!currentForeignTableNames.includes(remoteTable.localTableName)) {
|
||||
throw new NotFoundException('Foreign table does not exist');
|
||||
throw new RemoteTableException(
|
||||
'Foreign table does not exist',
|
||||
RemoteTableExceptionCode.NO_FOREIGN_TABLES_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const objectMetadata =
|
||||
@ -507,8 +541,9 @@ export class RemoteTableService {
|
||||
});
|
||||
|
||||
if (!objectMetadata) {
|
||||
throw new NotFoundException(
|
||||
throw new RemoteTableException(
|
||||
`Cannot find associated object for table ${foreignTableName}`,
|
||||
RemoteTableExceptionCode.NO_OBJECT_METADATA_FOUND,
|
||||
);
|
||||
}
|
||||
for (const columnUpdate of columnsUpdates) {
|
||||
@ -547,8 +582,9 @@ export class RemoteTableService {
|
||||
});
|
||||
|
||||
if (!fieldMetadataToDelete) {
|
||||
throw new NotFoundException(
|
||||
throw new RemoteTableException(
|
||||
`Cannot find associated field metadata for column ${columnName}`,
|
||||
RemoteTableExceptionCode.NO_FIELD_METADATA_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { BadRequestException } from '@nestjs/common/exceptions';
|
||||
|
||||
import { singular } from 'pluralize';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { camelCase } from 'src/utils/camel-case';
|
||||
import {
|
||||
RemoteTableException,
|
||||
RemoteTableExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.exception';
|
||||
|
||||
const MAX_SUFFIX = 10;
|
||||
|
||||
@ -55,5 +57,8 @@ export const getRemoteTableLocalName = async (
|
||||
}
|
||||
}
|
||||
|
||||
throw new BadRequestException('Table name is already taken.');
|
||||
throw new RemoteTableException(
|
||||
'Table name is already taken',
|
||||
RemoteTableExceptionCode.INVALID_REMOTE_TABLE_INPUT,
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
import {
|
||||
RemoteTableException,
|
||||
RemoteTableExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.exception';
|
||||
import {
|
||||
UserInputError,
|
||||
ConflictError,
|
||||
InternalServerError,
|
||||
NotFoundError,
|
||||
} from 'src/engine/utils/graphql-errors.util';
|
||||
|
||||
export const remoteTableGraphqlApiExceptionHandler = (error: Error) => {
|
||||
if (error instanceof RemoteTableException) {
|
||||
switch (error.code) {
|
||||
case RemoteTableExceptionCode.REMOTE_TABLE_NOT_FOUND:
|
||||
case RemoteTableExceptionCode.NO_OBJECT_METADATA_FOUND:
|
||||
case RemoteTableExceptionCode.NO_FOREIGN_TABLES_FOUND:
|
||||
case RemoteTableExceptionCode.NO_FIELD_METADATA_FOUND:
|
||||
throw new NotFoundError(error.message);
|
||||
case RemoteTableExceptionCode.INVALID_REMOTE_TABLE_INPUT:
|
||||
throw new UserInputError(error.message);
|
||||
case RemoteTableExceptionCode.REMOTE_TABLE_ALREADY_EXISTS:
|
||||
throw new ConflictError(error.message);
|
||||
default:
|
||||
throw new InternalServerError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
@ -1,10 +1,12 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
ForeignDataWrapperOptions,
|
||||
RemoteServerEntity,
|
||||
RemoteServerType,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
||||
import {
|
||||
RemoteServerException,
|
||||
RemoteServerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-server.exception';
|
||||
import { UserMappingOptions } from 'src/engine/metadata-modules/remote-server/types/user-mapping-options';
|
||||
|
||||
export type DeepPartial<T> = {
|
||||
@ -49,7 +51,10 @@ export const buildUpdateRemoteServerRawQuery = (
|
||||
}
|
||||
|
||||
if (options.length < 1) {
|
||||
throw new BadRequestException('No fields to update');
|
||||
throw new RemoteServerException(
|
||||
'No fields to update',
|
||||
RemoteServerExceptionCode.INVALID_REMOTE_SERVER_INPUT,
|
||||
);
|
||||
}
|
||||
|
||||
const rawQuery = `UPDATE metadata."remoteServer" SET ${options.join(
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
import {
|
||||
RemoteServerException,
|
||||
RemoteServerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-server.exception';
|
||||
import {
|
||||
UserInputError,
|
||||
ForbiddenError,
|
||||
ConflictError,
|
||||
InternalServerError,
|
||||
NotFoundError,
|
||||
} from 'src/engine/utils/graphql-errors.util';
|
||||
|
||||
export const remoteServerGraphqlApiExceptionHandler = (error: any) => {
|
||||
if (error instanceof RemoteServerException) {
|
||||
switch (error.code) {
|
||||
case RemoteServerExceptionCode.REMOTE_SERVER_NOT_FOUND:
|
||||
throw new NotFoundError(error.message);
|
||||
case RemoteServerExceptionCode.INVALID_REMOTE_SERVER_INPUT:
|
||||
throw new UserInputError(error.message);
|
||||
case RemoteServerExceptionCode.REMOTE_SERVER_MUTATION_NOT_ALLOWED:
|
||||
throw new ForbiddenError(error.message);
|
||||
case RemoteServerExceptionCode.REMOTE_SERVER_ALREADY_EXISTS:
|
||||
throw new ConflictError(error.message);
|
||||
default:
|
||||
throw new InternalServerError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
@ -1,7 +1,10 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'class-validator';
|
||||
|
||||
import {
|
||||
RemoteServerException,
|
||||
RemoteServerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-server.exception';
|
||||
|
||||
const INPUT_REGEX = /^([A-Za-z0-9\-_.@]+)$/;
|
||||
|
||||
export const validateObjectAgainstInjections = (input: object) => {
|
||||
@ -21,6 +24,9 @@ export const validateObjectAgainstInjections = (input: object) => {
|
||||
|
||||
export const validateStringAgainstInjections = (input: string) => {
|
||||
if (!INPUT_REGEX.test(input)) {
|
||||
throw new BadRequestException('Invalid remote server input');
|
||||
throw new RemoteServerException(
|
||||
'Invalid remote server input',
|
||||
RemoteServerExceptionCode.INVALID_REMOTE_SERVER_INPUT,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
@ -7,6 +5,10 @@ import {
|
||||
FeatureFlagKeys,
|
||||
} from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import { RemoteServerType } from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
||||
import {
|
||||
RemoteServerException,
|
||||
RemoteServerExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-server.exception';
|
||||
|
||||
export const validateRemoteServerType = async (
|
||||
remoteServerType: RemoteServerType,
|
||||
@ -24,7 +26,10 @@ export const validateRemoteServerType = async (
|
||||
const featureFlagEnabled = featureFlag && featureFlag.value;
|
||||
|
||||
if (!featureFlagEnabled) {
|
||||
throw new BadRequestException(`Type ${remoteServerType} is not supported.`);
|
||||
throw new RemoteServerException(
|
||||
`Type ${remoteServerType} is not supported.`,
|
||||
RemoteServerExceptionCode.INVALID_REMOTE_SERVER_INPUT,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -35,8 +40,9 @@ const getFeatureFlagKey = (remoteServerType: RemoteServerType) => {
|
||||
case RemoteServerType.STRIPE_FDW:
|
||||
return FeatureFlagKeys.IsStripeIntegrationEnabled;
|
||||
default:
|
||||
throw new BadRequestException(
|
||||
throw new RemoteServerException(
|
||||
`Type ${remoteServerType} is not supported.`,
|
||||
RemoteServerExceptionCode.INVALID_REMOTE_SERVER_INPUT,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user