diff --git a/packages/twenty-server/src/engine/core-modules/exception-handler/http-exception-handler.service.ts b/packages/twenty-server/src/engine/core-modules/exception-handler/http-exception-handler.service.ts index f064c58206..e3034fc3eb 100644 --- a/packages/twenty-server/src/engine/core-modules/exception-handler/http-exception-handler.service.ts +++ b/packages/twenty-server/src/engine/core-modules/exception-handler/http-exception-handler.service.ts @@ -14,6 +14,8 @@ import { QueryFailedError } from 'typeorm'; import { type ExceptionHandlerUser } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-user.interface'; import { type ExceptionHandlerWorkspace } from 'src/engine/core-modules/exception-handler/interfaces/exception-handler-workspace.interface'; +import { CustomError } from 'twenty-shared/utils'; + import { PostgresException } from 'src/engine/api/graphql/workspace-query-runner/utils/postgres-exception'; import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { @@ -21,7 +23,6 @@ import { TwentyORMExceptionCode, } from 'src/engine/twenty-orm/exceptions/twenty-orm.exception'; import { handleException } from 'src/engine/utils/global-exception-handler.util'; -import { CustomException } from 'src/utils/custom-exception'; interface RequestAndParams { request: Request | null; @@ -121,7 +122,7 @@ export class HttpExceptionHandlerService { statusCode, error: exception.name ?? getErrorNameFromStatusCode(statusCode), messages: [exception?.message], - code: exception instanceof CustomException ? exception.code : undefined, + code: exception instanceof CustomError ? exception.code : undefined, }); }; } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter.ts new file mode 100644 index 0000000000..645da1d20e --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter.ts @@ -0,0 +1,49 @@ +import { + type ArgumentsHost, + Catch, + type ExceptionFilter, + Injectable, +} from '@nestjs/common'; + +import { type Response } from 'express'; + +import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service'; +import { + FlatEntityMapsException, + FlatEntityMapsExceptionCode, +} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception'; +import { type CustomException } from 'src/utils/custom-exception'; + +@Injectable() +@Catch(FlatEntityMapsException) +export class FlatEntityMapsRestApiExceptionFilter implements ExceptionFilter { + constructor( + private readonly httpExceptionHandlerService: HttpExceptionHandlerService, + ) {} + + catch(exception: FlatEntityMapsException, host: ArgumentsHost) { + const response = host.switchToHttp().getResponse(); + + switch (exception.code) { + case FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND: + case FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND: + return this.httpExceptionHandlerService.handleError( + exception as CustomException, + response, + 404, + ); + case FlatEntityMapsExceptionCode.ENTITY_ALREADY_EXISTS: + return this.httpExceptionHandlerService.handleError( + exception as CustomException, + response, + 409, + ); + default: + return this.httpExceptionHandlerService.handleError( + exception as CustomException, + response, + 500, + ); + } + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/front-component/controllers/front-component.controller.ts b/packages/twenty-server/src/engine/metadata-modules/front-component/controllers/front-component.controller.ts index 3bf53404aa..d74c06d603 100644 --- a/packages/twenty-server/src/engine/metadata-modules/front-component/controllers/front-component.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/front-component/controllers/front-component.controller.ts @@ -20,16 +20,22 @@ import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.ent import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { FrontComponentRestApiExceptionFilter } from 'src/engine/metadata-modules/front-component/filters/front-component-rest-api-exception.filter'; import { FrontComponentException, FrontComponentExceptionCode, } from 'src/engine/metadata-modules/front-component/front-component.exception'; import { FrontComponentService } from 'src/engine/metadata-modules/front-component/front-component.service'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller('rest/front-components') @UseGuards(WorkspaceAuthGuard) -@UseFilters(FrontComponentRestApiExceptionFilter) +@UseFilters( + FrontComponentRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class FrontComponentController { constructor(private readonly frontComponentService: FrontComponentService) {} diff --git a/packages/twenty-server/src/engine/metadata-modules/page-layout-tab/controllers/page-layout-tab.controller.ts b/packages/twenty-server/src/engine/metadata-modules/page-layout-tab/controllers/page-layout-tab.controller.ts index d6131f69bf..6a9f9d965b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/page-layout-tab/controllers/page-layout-tab.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/page-layout-tab/controllers/page-layout-tab.controller.ts @@ -19,6 +19,7 @@ import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorat import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard'; import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { CreatePageLayoutTabInput } from 'src/engine/metadata-modules/page-layout-tab/dtos/inputs/create-page-layout-tab.input'; import { UpdatePageLayoutTabInput } from 'src/engine/metadata-modules/page-layout-tab/dtos/inputs/update-page-layout-tab.input'; import { type PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout-tab/dtos/page-layout-tab.dto'; @@ -30,10 +31,15 @@ import { } from 'src/engine/metadata-modules/page-layout-tab/exceptions/page-layout-tab.exception'; import { PageLayoutTabRestApiExceptionFilter } from 'src/engine/metadata-modules/page-layout-tab/filters/page-layout-tab-rest-api-exception.filter'; import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout-tab/services/page-layout-tab.service'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller('rest/metadata/pageLayoutTabs') @UseGuards(WorkspaceAuthGuard) -@UseFilters(PageLayoutTabRestApiExceptionFilter) +@UseFilters( + PageLayoutTabRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class PageLayoutTabController { constructor(private readonly pageLayoutTabService: PageLayoutTabService) {} diff --git a/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/controllers/page-layout-widget.controller.ts b/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/controllers/page-layout-widget.controller.ts index a1e776063b..54b0fd642b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/controllers/page-layout-widget.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/controllers/page-layout-widget.controller.ts @@ -19,6 +19,7 @@ import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorat import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard'; import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/create-page-layout-widget.input'; import { UpdatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/update-page-layout-widget.input'; import { type PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/page-layout-widget.dto'; @@ -30,10 +31,15 @@ import { } from 'src/engine/metadata-modules/page-layout-widget/exceptions/page-layout-widget.exception'; import { PageLayoutWidgetRestApiExceptionFilter } from 'src/engine/metadata-modules/page-layout-widget/filters/page-layout-widget-rest-api-exception.filter'; import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout-widget/services/page-layout-widget.service'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller('rest/metadata/pageLayoutWidgets') @UseGuards(WorkspaceAuthGuard) -@UseFilters(PageLayoutWidgetRestApiExceptionFilter) +@UseFilters( + PageLayoutWidgetRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class PageLayoutWidgetController { constructor( private readonly pageLayoutWidgetService: PageLayoutWidgetService, diff --git a/packages/twenty-server/src/engine/metadata-modules/page-layout/controllers/page-layout.controller.ts b/packages/twenty-server/src/engine/metadata-modules/page-layout/controllers/page-layout.controller.ts index a5d9570e40..5282c8fd0e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/page-layout/controllers/page-layout.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/page-layout/controllers/page-layout.controller.ts @@ -19,16 +19,22 @@ import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorat import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard'; import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { CreatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout.input'; import { UpdatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout.input'; import { type PageLayoutDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout.dto'; import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum'; import { PageLayoutRestApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/filters/page-layout-rest-api-exception.filter'; import { PageLayoutService } from 'src/engine/metadata-modules/page-layout/services/page-layout.service'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller('rest/metadata/pageLayouts') @UseGuards(WorkspaceAuthGuard) -@UseFilters(PageLayoutRestApiExceptionFilter) +@UseFilters( + PageLayoutRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class PageLayoutController { constructor(private readonly pageLayoutService: PageLayoutService) {} diff --git a/packages/twenty-server/src/engine/metadata-modules/view-field/controllers/view-field.controller.ts b/packages/twenty-server/src/engine/metadata-modules/view-field/controllers/view-field.controller.ts index d51ef794b9..0df3400bed 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-field/controllers/view-field.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-field/controllers/view-field.controller.ts @@ -17,6 +17,7 @@ import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.ent import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { CreateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/create-view-field.input'; import { UpdateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/update-view-field.input'; import { ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto'; @@ -32,10 +33,15 @@ import { ViewFieldService } from 'src/engine/metadata-modules/view-field/service import { CreateViewFieldPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/create-view-field-permission.guard'; import { DeleteViewFieldPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/delete-view-field-permission.guard'; import { UpdateViewFieldPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/update-view-field-permission.guard'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller('rest/metadata/viewFields') @UseGuards(WorkspaceAuthGuard) -@UseFilters(ViewFieldRestApiExceptionFilter) +@UseFilters( + ViewFieldRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class ViewFieldController { constructor(private readonly viewFieldService: ViewFieldService) {} diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter-group/controllers/view-filter-group.controller.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter-group/controllers/view-filter-group.controller.ts index 81081de711..c0efac25a5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter-group/controllers/view-filter-group.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter-group/controllers/view-filter-group.controller.ts @@ -17,6 +17,7 @@ import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspac import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { type CreateViewFilterGroupInput } from 'src/engine/metadata-modules/view-filter-group/dtos/inputs/create-view-filter-group.input'; import { type UpdateViewFilterGroupInput } from 'src/engine/metadata-modules/view-filter-group/dtos/inputs/update-view-filter-group.input'; import { type ViewFilterGroupDTO } from 'src/engine/metadata-modules/view-filter-group/dtos/view-filter-group.dto'; @@ -32,10 +33,15 @@ import { ViewFilterGroupService } from 'src/engine/metadata-modules/view-filter- import { CreateViewFilterGroupPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/create-view-filter-group-permission.guard'; import { DeleteViewFilterGroupPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/delete-view-filter-group-permission.guard'; import { UpdateViewFilterGroupPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/update-view-filter-group-permission.guard'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller('rest/metadata/viewFilterGroups') @UseGuards(WorkspaceAuthGuard) -@UseFilters(ViewFilterGroupRestApiExceptionFilter) +@UseFilters( + ViewFilterGroupRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class ViewFilterGroupController { constructor( private readonly viewFilterGroupService: ViewFilterGroupService, diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/controllers/view-filter.controller.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/controllers/view-filter.controller.ts index 643fbfbff7..37670a45a1 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter/controllers/view-filter.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/controllers/view-filter.controller.ts @@ -17,6 +17,7 @@ import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.ent import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { CreateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input'; import { UpdateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input'; import { ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; @@ -32,10 +33,15 @@ import { ViewFilterService } from 'src/engine/metadata-modules/view-filter/servi import { CreateViewFilterPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/create-view-filter-permission.guard'; import { DeleteViewFilterPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/delete-view-filter-permission.guard'; import { UpdateViewFilterPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/update-view-filter-permission.guard'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller('rest/metadata/viewFilters') @UseGuards(WorkspaceAuthGuard) -@UseFilters(ViewFilterRestApiExceptionFilter) +@UseFilters( + ViewFilterRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class ViewFilterController { constructor(private readonly viewFilterService: ViewFilterService) {} diff --git a/packages/twenty-server/src/engine/metadata-modules/view-group/controllers/view-group.controller.ts b/packages/twenty-server/src/engine/metadata-modules/view-group/controllers/view-group.controller.ts index 6e3fea8e97..59e11c29c4 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-group/controllers/view-group.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-group/controllers/view-group.controller.ts @@ -17,6 +17,7 @@ import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.ent import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { CreateViewGroupInput } from 'src/engine/metadata-modules/view-group/dtos/inputs/create-view-group.input'; import { UpdateViewGroupInput } from 'src/engine/metadata-modules/view-group/dtos/inputs/update-view-group.input'; import { type ViewGroupDTO } from 'src/engine/metadata-modules/view-group/dtos/view-group.dto'; @@ -32,10 +33,15 @@ import { ViewGroupService } from 'src/engine/metadata-modules/view-group/service import { CreateViewGroupPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/create-view-group-permission.guard'; import { DeleteViewGroupPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/delete-view-group-permission.guard'; import { UpdateViewGroupPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/update-view-group-permission.guard'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller('rest/metadata/viewGroups') @UseGuards(WorkspaceAuthGuard) -@UseFilters(ViewGroupRestApiExceptionFilter) +@UseFilters( + ViewGroupRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class ViewGroupController { constructor(private readonly viewGroupService: ViewGroupService) {} diff --git a/packages/twenty-server/src/engine/metadata-modules/view-sort/controllers/view-sort.controller.ts b/packages/twenty-server/src/engine/metadata-modules/view-sort/controllers/view-sort.controller.ts index 1768c23809..8cc314a1f5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-sort/controllers/view-sort.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-sort/controllers/view-sort.controller.ts @@ -17,6 +17,7 @@ import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.ent import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { CreateViewSortPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/create-view-sort-permission.guard'; import { DeleteViewSortPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/delete-view-sort-permission.guard'; import { UpdateViewSortPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/update-view-sort-permission.guard'; @@ -31,11 +32,16 @@ import { } from 'src/engine/metadata-modules/view-sort/exceptions/view-sort.exception'; import { ViewSortRestApiExceptionFilter } from 'src/engine/metadata-modules/view-sort/filters/view-sort-rest-api-exception.filter'; import { ViewSortService } from 'src/engine/metadata-modules/view-sort/services/view-sort.service'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; import { ViewSortDirection } from 'twenty-shared/types'; @Controller('rest/metadata/viewSorts') @UseGuards(WorkspaceAuthGuard) -@UseFilters(ViewSortRestApiExceptionFilter) +@UseFilters( + ViewSortRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class ViewSortController { constructor(private readonly viewSortService: ViewSortService) {} diff --git a/packages/twenty-server/src/engine/metadata-modules/view/controllers/view.controller.ts b/packages/twenty-server/src/engine/metadata-modules/view/controllers/view.controller.ts index 1b638029b2..9d1aefe3c6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view/controllers/view.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view/controllers/view.controller.ts @@ -40,10 +40,16 @@ import { } from 'src/engine/metadata-modules/view/exceptions/view.exception'; import { ViewRestApiExceptionFilter } from 'src/engine/metadata-modules/view/filters/view-rest-api-exception.filter'; import { ViewService } from 'src/engine/metadata-modules/view/services/view.service'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller('rest/metadata/views') @UseGuards(WorkspaceAuthGuard) -@UseFilters(ViewRestApiExceptionFilter) +@UseFilters( + ViewRestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class ViewController { constructor( private readonly viewService: ViewService, diff --git a/packages/twenty-server/src/engine/metadata-modules/webhook/controllers/webhook.controller.ts b/packages/twenty-server/src/engine/metadata-modules/webhook/controllers/webhook.controller.ts index 2bb2486f24..b817a3d2bb 100644 --- a/packages/twenty-server/src/engine/metadata-modules/webhook/controllers/webhook.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/webhook/controllers/webhook.controller.ts @@ -18,10 +18,12 @@ import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorat import { JwtAuthGuard } from 'src/engine/guards/jwt-auth.guard'; import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; +import { FlatEntityMapsRestApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-rest-api-exception.filter'; import { CreateWebhookInput } from 'src/engine/metadata-modules/webhook/dtos/create-webhook.input'; import { UpdateWebhookInput } from 'src/engine/metadata-modules/webhook/dtos/update-webhook.input'; import { type WebhookDTO } from 'src/engine/metadata-modules/webhook/dtos/webhook.dto'; import { WebhookService } from 'src/engine/metadata-modules/webhook/webhook.service'; +import { WorkspaceMigrationRunnerRestApiExceptionFilter } from 'src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter'; @Controller(['rest/webhooks', 'rest/metadata/webhooks']) @UseGuards( @@ -29,7 +31,11 @@ import { WebhookService } from 'src/engine/metadata-modules/webhook/webhook.serv WorkspaceAuthGuard, SettingsPermissionGuard(PermissionFlagType.API_KEYS_AND_WEBHOOKS), ) -@UseFilters(RestApiExceptionFilter) +@UseFilters( + RestApiExceptionFilter, + FlatEntityMapsRestApiExceptionFilter, + WorkspaceMigrationRunnerRestApiExceptionFilter, +) export class WebhookController { constructor(private readonly webhookService: WebhookService) {} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter.ts new file mode 100644 index 0000000000..b31d043bb9 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/filters/workspace-migration-runner-rest-api-exception.filter.ts @@ -0,0 +1,47 @@ +import { + type ArgumentsHost, + Catch, + type ExceptionFilter, + Injectable, +} from '@nestjs/common'; + +import { type Response } from 'express'; +import { QueryFailedError } from 'typeorm'; + +import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service'; +import { + WorkspaceMigrationRunnerException, + WorkspaceMigrationRunnerExceptionCode, +} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/exceptions/workspace-migration-runner.exception'; + +@Injectable() +@Catch(WorkspaceMigrationRunnerException) +export class WorkspaceMigrationRunnerRestApiExceptionFilter + implements ExceptionFilter +{ + constructor( + private readonly httpExceptionHandlerService: HttpExceptionHandlerService, + ) {} + + catch(exception: WorkspaceMigrationRunnerException, host: ArgumentsHost) { + const response = host.switchToHttp().getResponse(); + + if ( + exception.code === WorkspaceMigrationRunnerExceptionCode.EXECUTION_FAILED + ) { + const underlyingError = + exception.errors?.metadata ?? + exception.errors?.workspaceSchema ?? + exception.errors?.actionTranspilation; + + if (underlyingError instanceof QueryFailedError) { + return this.httpExceptionHandlerService.handleError( + underlyingError, + response, + ); + } + } + + return this.httpExceptionHandlerService.handleError(exception, response); + } +}