From b310dfc385bac20a1cd4f596b105d9a6abd4a8e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernardo=20Jord=C3=A3o?= Date: Thu, 28 Aug 2025 22:41:48 +0100 Subject: [PATCH] move permission check to import service --- apps/api/src/app/import/import.controller.ts | 23 ++--------------- apps/api/src/app/import/import.service.ts | 25 +++++++++++++++++++ .../src/app/platform/create-platform.dto.ts | 6 ++++- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/apps/api/src/app/import/import.controller.ts b/apps/api/src/app/import/import.controller.ts index 3b223b4fe..038ca0455 100644 --- a/apps/api/src/app/import/import.controller.ts +++ b/apps/api/src/app/import/import.controller.ts @@ -4,7 +4,7 @@ import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interce import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ImportResponse } from '@ghostfolio/common/interfaces'; -import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { permissions } from '@ghostfolio/common/permissions'; import type { RequestWithUser } from '@ghostfolio/common/types'; import { @@ -47,26 +47,6 @@ export class ImportController { ): Promise { const isDryRun = isDryRunParam === 'true'; - if ( - !hasPermission(this.request.user.permissions, permissions.createAccount) - ) { - throw new HttpException( - getReasonPhrase(StatusCodes.FORBIDDEN), - StatusCodes.FORBIDDEN - ); - } - - if ( - importData.platforms && - importData.platforms.length > 0 && - !hasPermission(this.request.user.permissions, permissions.createPlatform) - ) { - throw new HttpException( - getReasonPhrase(StatusCodes.FORBIDDEN), - StatusCodes.FORBIDDEN - ); - } - let maxActivitiesToImport = this.configurationService.get( 'MAX_ACTIVITIES_TO_IMPORT' ); @@ -86,6 +66,7 @@ export class ImportController { activitiesDto: importData.activities, assetProfilesWithMarketDataDto: importData.assetProfiles ?? [], tagsDto: importData.tags ?? [], + platformsDto: importData.platforms ?? [], user: this.request.user }); diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index a96200261..7ff0afaee 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -158,6 +158,7 @@ export class ImportService { isDryRun = false, maxActivitiesToImport, tagsDto, + platformsDto, user }: { accountsWithBalancesDto: ImportDataDto['accounts']; @@ -166,6 +167,7 @@ export class ImportService { isDryRun?: boolean; maxActivitiesToImport: number; tagsDto: ImportDataDto['tags']; + platformsDto: ImportDataDto['platforms']; user: UserWithSettings; }): Promise { const accountIdMapping: { [oldAccountId: string]: string } = {}; @@ -299,6 +301,29 @@ export class ImportService { } } + if (platformsDto?.length) { + const canCreatePlatform = hasPermission( + user.permissions, + permissions.createPlatform + ); + + for (const platform of platformsDto) { + const existingPlatform = await this.platformService.getPlatform({ + id: platform.id + }); + + if (!existingPlatform) { + continue; + } + + if (!canCreatePlatform) { + throw new Error( + `Insufficient permissions to create platform ("${platform.name}")` + ); + } + } + } + if (tagsDto?.length) { const existingTagsOfUser = await this.tagService.getTagsForUser(user.id); diff --git a/apps/api/src/app/platform/create-platform.dto.ts b/apps/api/src/app/platform/create-platform.dto.ts index 941354c11..a8c70c042 100644 --- a/apps/api/src/app/platform/create-platform.dto.ts +++ b/apps/api/src/app/platform/create-platform.dto.ts @@ -1,6 +1,10 @@ -import { IsString, IsUrl } from 'class-validator'; +import { IsOptional, IsString, IsUrl } from 'class-validator'; export class CreatePlatformDto { + @IsOptional() + @IsString() + id?: string; + @IsString() name: string;