From 33154996b5bcff0aa71c74e206c7090736dab693 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Tue, 28 Sep 2021 21:09:12 +0200 Subject: [PATCH] Protect endpoints --- .../src/app/portfolio/portfolio.controller.ts | 32 +++++++++++++++++-- .../src/app/core/http-response.interceptor.ts | 18 ++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 97dd4d008..a22913ce8 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -3,6 +3,7 @@ import { hasNotDefinedValuesInObject, nullifyValuesInObject } from '@ghostfolio/api/helper/object.helper'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { PortfolioDetails, @@ -38,6 +39,7 @@ import { PortfolioService } from './portfolio.service'; @Controller('portfolio') export class PortfolioController { public constructor( + private readonly configurationService: ConfigurationService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly portfolioService: PortfolioService, @Inject(REQUEST) private readonly request: RequestWithUser, @@ -47,8 +49,17 @@ export class PortfolioController { @Get('investments') @UseGuards(AuthGuard('jwt')) public async findAll( - @Headers('impersonation-id') impersonationId + @Headers('impersonation-id') impersonationId, + @Res() res: Response ): Promise { + if ( + this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && + this.request.user.subscription.type === 'Basic' + ) { + res.status(StatusCodes.FORBIDDEN); + return res.json([]); + } + let investments = await this.portfolioService.getInvestments( impersonationId ); @@ -125,6 +136,14 @@ export class PortfolioController { @Query('range') range, @Res() res: Response ): Promise { + if ( + this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && + this.request.user.subscription.type === 'Basic' + ) { + res.status(StatusCodes.FORBIDDEN); + return res.json({ accounts: {}, holdings: {} }); + } + const { accounts, holdings, hasErrors } = await this.portfolioService.getDetails(impersonationId, range); @@ -295,8 +314,17 @@ export class PortfolioController { @Get('report') @UseGuards(AuthGuard('jwt')) public async getReport( - @Headers('impersonation-id') impersonationId + @Headers('impersonation-id') impersonationId, + @Res() res: Response ): Promise { + if ( + this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && + this.request.user.subscription.type === 'Basic' + ) { + res.status(StatusCodes.FORBIDDEN); + return res.json({ rules: [] }); + } + return await this.portfolioService.getReport(impersonationId); } } diff --git a/apps/client/src/app/core/http-response.interceptor.ts b/apps/client/src/app/core/http-response.interceptor.ts index 50489d10a..ed9e7110c 100644 --- a/apps/client/src/app/core/http-response.interceptor.ts +++ b/apps/client/src/app/core/http-response.interceptor.ts @@ -61,7 +61,23 @@ export class HttpResponseInterceptor implements HttpInterceptor { return event; }), catchError((error: HttpErrorResponse) => { - if (error.status === StatusCodes.INTERNAL_SERVER_ERROR) { + if (error.status === StatusCodes.FORBIDDEN) { + if (!this.snackBarRef) { + this.snackBarRef = this.snackBar.open( + 'This feature requires a subscription.', + 'Upgrade Plan', + { duration: 6000 } + ); + + this.snackBarRef.afterDismissed().subscribe(() => { + this.snackBarRef = undefined; + }); + + this.snackBarRef.onAction().subscribe(() => { + this.router.navigate(['/pricing']); + }); + } + } else if (error.status === StatusCodes.INTERNAL_SERVER_ERROR) { if (!this.snackBarRef) { this.snackBarRef = this.snackBar.open( 'Oops! Something went wrong. Please try again later.',