diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fd5e538..1094ddec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Extended the benchmarks of the markets overview by the current market condition (bear and bull market) - Extended the twitter bot service by benchmarks +- Added value redaction for the impersonation mode in the API response as an interceptor ### Changed diff --git a/apps/api/src/app/order/order.controller.ts b/apps/api/src/app/order/order.controller.ts index 73c546d8..e61c57ef 100644 --- a/apps/api/src/app/order/order.controller.ts +++ b/apps/api/src/app/order/order.controller.ts @@ -1,5 +1,6 @@ import { UserService } from '@ghostfolio/api/app/user/user.service'; import { nullifyValuesInObjects } from '@ghostfolio/api/helper/object.helper'; +import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor'; import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation.service'; @@ -62,6 +63,7 @@ export class OrderController { @Get() @UseGuards(AuthGuard('jwt')) + @UseInterceptors(RedactValuesInResponseInterceptor) @UseInterceptors(TransformDataSourceInResponseInterceptor) public async getAllOrders( @Headers('impersonation-id') impersonationId diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index f0e75e73..606ce658 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -4,6 +4,7 @@ import { hasNotDefinedValuesInObject, nullifyValuesInObject } from '@ghostfolio/api/helper/object.helper'; +import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor'; import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor'; import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; @@ -106,6 +107,7 @@ export class PortfolioController { @Get('details') @UseGuards(AuthGuard('jwt')) + @UseInterceptors(RedactValuesInResponseInterceptor) @UseInterceptors(TransformDataSourceInResponseInterceptor) public async getDetails( @Headers('impersonation-id') impersonationId: string, diff --git a/apps/api/src/interceptors/redact-values-in-response.interceptor.ts b/apps/api/src/interceptors/redact-values-in-response.interceptor.ts new file mode 100644 index 00000000..b5889328 --- /dev/null +++ b/apps/api/src/interceptors/redact-values-in-response.interceptor.ts @@ -0,0 +1,50 @@ +import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor +} from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +@Injectable() +export class RedactValuesInResponseInterceptor + implements NestInterceptor +{ + public constructor() {} + + public intercept( + context: ExecutionContext, + next: CallHandler + ): Observable { + return next.handle().pipe( + map((data: any) => { + const request = context.switchToHttp().getRequest(); + const hasImpersonationId = !!request.headers?.['impersonation-id']; + + if (hasImpersonationId) { + if (data.accounts) { + for (const accountId of Object.keys(data.accounts)) { + if (data.accounts[accountId]?.balance !== undefined) { + data.accounts[accountId].balance = null; + } + } + } + + if (data.activities) { + data.activities = data.activities.map((activity: Activity) => { + if (activity.Account?.balance !== undefined) { + activity.Account.balance = null; + } + + return activity; + }); + } + } + + return data; + }) + ); + } +}