From ddca556d408dd6b5cb4abd32a137162984f5cf40 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 4 Sep 2026 10:47:52 +0200 Subject: [PATCH] Limit length for comment, search query and symbol --- .../asset-profiles.controller.ts | 25 ++++---- .../asset-profiles/get-asset-profiles.dto.ts | 61 +++++++++++++++++++ 2 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 apps/api/src/app/endpoints/asset-profiles/get-asset-profiles.dto.ts diff --git a/apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts b/apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts index e1452c548d..1db09f95e0 100644 --- a/apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts +++ b/apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts @@ -17,7 +17,7 @@ import { } from '@ghostfolio/common/interfaces'; import { hasPermission } from '@ghostfolio/common/permissions'; import { permissions } from '@ghostfolio/common/permissions'; -import { MarketDataPreset, RequestWithUser } from '@ghostfolio/common/types'; +import { RequestWithUser } from '@ghostfolio/common/types'; import { Body, @@ -27,7 +27,6 @@ import { HttpException, Inject, Param, - ParseIntPipe, Patch, Post, Query, @@ -36,11 +35,12 @@ import { } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; -import { AssetProfileSplit, DataSource, Prisma } from '@prisma/client'; +import { AssetProfileSplit, DataSource } from '@prisma/client'; import { parseISO } from 'date-fns'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { AssetProfilesService } from './asset-profiles.service'; +import { GetAssetProfilesDto } from './get-asset-profiles.dto'; @AllowDuringImpersonation() @Controller('asset-profiles') @@ -56,14 +56,17 @@ export class AssetProfilesController { @HasPermission(permissions.accessAdminControl) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async getAssetProfiles( - @Query('assetSubClasses') filterByAssetSubClasses?: string, - @Query('dataSource') filterByDataSource?: string, - @Query('presetId') presetId?: MarketDataPreset, - @Query('query') filterBySearchQuery?: string, - @Query('skip', new ParseIntPipe({ optional: true })) skip?: number, - @Query('sortColumn') sortColumn?: string, - @Query('sortDirection') sortDirection?: Prisma.SortOrder, - @Query('take', new ParseIntPipe({ optional: true })) take?: number + @Query() + { + assetSubClasses: filterByAssetSubClasses, + dataSource: filterByDataSource, + presetId, + query: filterBySearchQuery, + skip, + sortColumn, + sortDirection, + take + }: GetAssetProfilesDto ): Promise { const filters = this.apiService.buildFiltersFromQueryParams({ filterByAssetSubClasses, diff --git a/apps/api/src/app/endpoints/asset-profiles/get-asset-profiles.dto.ts b/apps/api/src/app/endpoints/asset-profiles/get-asset-profiles.dto.ts new file mode 100644 index 0000000000..77696c7795 --- /dev/null +++ b/apps/api/src/app/endpoints/asset-profiles/get-asset-profiles.dto.ts @@ -0,0 +1,61 @@ +import { SEARCH_QUERY_MAXIMUM_LENGTH } from '@ghostfolio/common/config'; +import { MarketDataPreset } from '@ghostfolio/common/types'; + +import { Prisma } from '@prisma/client'; +import { Type } from 'class-transformer'; +import { + IsIn, + IsInt, + IsOptional, + IsString, + MaxLength, + Min +} from 'class-validator'; + +export class GetAssetProfilesDto { + @IsOptional() + @IsString() + assetSubClasses?: string; + + @IsOptional() + @IsString() + dataSource?: string; + + @IsIn([ + 'BENCHMARKS', + 'CURRENCIES', + 'ETF_WITHOUT_COUNTRIES', + 'ETF_WITHOUT_SECTORS', + 'NO_ACTIVITIES' + ] as MarketDataPreset[]) + @IsOptional() + presetId?: MarketDataPreset; + + @IsOptional() + @IsString() + @MaxLength(SEARCH_QUERY_MAXIMUM_LENGTH) + query?: string; + + @IsInt() + @IsOptional() + @Min(0) + @Type(() => Number) + skip?: number; + + @IsIn([ + ...Object.values(Prisma.SymbolProfileScalarFieldEnum), + 'activitiesCount' + ]) + @IsOptional() + sortColumn?: string; + + @IsIn(['asc', 'desc'] as Prisma.SortOrder[]) + @IsOptional() + sortDirection?: Prisma.SortOrder; + + @IsInt() + @IsOptional() + @Min(0) + @Type(() => Number) + take?: number; +}