Browse Source

Harden validation of accounts and tags in endpoints with filters

pull/7809/head
Thomas Kaul 1 month ago
parent
commit
3d8c64fa9b
  1. 2
      apps/api/src/app/endpoints/mcp/mcp.controller.ts
  2. 16
      apps/api/src/dtos/filter.dto.ts
  3. 12
      apps/api/src/services/api/api.service.ts

2
apps/api/src/app/endpoints/mcp/mcp.controller.ts

@ -175,7 +175,7 @@ export class GhostfolioMcpController {
}: z.infer<typeof GET_ACCOUNTS_PARAMETERS> }: z.infer<typeof GET_ACCOUNTS_PARAMETERS>
) { ) {
const filters = this.apiService.buildFiltersFromQueryParams({ const filters = this.apiService.buildFiltersFromQueryParams({
filterByAccounts: accountIds?.join(','), filterByAccounts: accountIds,
filterByAssetClasses: assetClasses, filterByAssetClasses: assetClasses,
filterByDataSource: holding?.dataSource, filterByDataSource: holding?.dataSource,
filterBySymbol: holding?.symbol filterBySymbol: holding?.symbol

16
apps/api/src/dtos/filter.dto.ts

@ -1,12 +1,15 @@
import { AssetClass, DataSource } from '@prisma/client'; import { AssetClass, DataSource } from '@prisma/client';
import { Transform, TransformFnParams } from 'class-transformer'; import { Transform, TransformFnParams } from 'class-transformer';
import { IsEnum, IsOptional, IsString } from 'class-validator'; import { IsEnum, IsOptional, IsString, IsUUID } from 'class-validator';
import { isString } from 'lodash'; import { isString } from 'lodash';
export class FilterDto { export class FilterDto {
@IsOptional() @IsOptional()
@IsString() @IsUUID(undefined, { each: true })
accounts?: string; @Transform(({ value }: TransformFnParams) => {
return isString(value) ? value.split(',') : value;
})
accounts?: string[];
@IsEnum(AssetClass, { each: true }) @IsEnum(AssetClass, { each: true })
@IsOptional() @IsOptional()
@ -24,6 +27,9 @@ export class FilterDto {
symbol?: string; symbol?: string;
@IsOptional() @IsOptional()
@IsString() @IsUUID(undefined, { each: true })
tags?: string; @Transform(({ value }: TransformFnParams) => {
return isString(value) ? value.split(',') : value;
})
tags?: string[];
} }

12
apps/api/src/services/api/api.service.ts

@ -14,23 +14,23 @@ export class ApiService {
filterBySymbol, filterBySymbol,
filterByTags filterByTags
}: { }: {
filterByAccounts?: string; filterByAccounts?: string[];
filterByAssetClasses?: string[]; filterByAssetClasses?: string[];
filterByAssetSubClasses?: string; filterByAssetSubClasses?: string;
filterByDataSource?: string; filterByDataSource?: string;
filterByHoldingType?: string; filterByHoldingType?: string;
filterBySearchQuery?: string; filterBySearchQuery?: string;
filterBySymbol?: string; filterBySymbol?: string;
filterByTags?: string; filterByTags?: string[];
}): Filter[] { }): Filter[] {
const accountIds = filterByAccounts?.split(',') ?? []; const accountIds = filterByAccounts ?? [];
const assetClasses = filterByAssetClasses ?? []; const assetClasses = filterByAssetClasses ?? [];
const assetSubClasses = filterByAssetSubClasses?.split(',') ?? []; const assetSubClasses = filterByAssetSubClasses?.split(',') ?? [];
const dataSource = filterByDataSource; const dataSource = filterByDataSource;
const holdingType = filterByHoldingType; const holdingType = filterByHoldingType;
const searchQuery = filterBySearchQuery?.toLowerCase(); const searchQuery = filterBySearchQuery?.toLowerCase();
const symbol = filterBySymbol; const symbol = filterBySymbol;
const tagIds = filterByTags?.split(',') ?? []; const tagIds = filterByTags ?? [];
const filters = [ const filters = [
...accountIds.map((accountId) => { ...accountIds.map((accountId) => {
@ -96,11 +96,11 @@ export class ApiService {
userSettings: UserSettings; userSettings: UserSettings;
}): Filter[] { }): Filter[] {
return this.buildFiltersFromQueryParams({ return this.buildFiltersFromQueryParams({
filterByAccounts: userSettings?.['filters.accounts']?.[0], filterByAccounts: userSettings?.['filters.accounts'],
filterByAssetClasses: userSettings?.['filters.assetClasses'], filterByAssetClasses: userSettings?.['filters.assetClasses'],
filterByDataSource: userSettings?.['filters.dataSource'], filterByDataSource: userSettings?.['filters.dataSource'],
filterBySymbol: userSettings?.['filters.symbol'], filterBySymbol: userSettings?.['filters.symbol'],
filterByTags: userSettings?.['filters.tags']?.[0] filterByTags: userSettings?.['filters.tags']
}); });
} }
} }

Loading…
Cancel
Save