From b12ac1fe8433a636032300e54837728fdb66d754 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 1 Jun 2024 10:02:43 +0200 Subject: [PATCH] Feature/simplify module imports of api (#3443) * Simplify module imports --- .../api/src/app/account/account.controller.ts | 2 +- apps/api/src/app/account/account.module.ts | 8 +-- apps/api/src/app/admin/admin.controller.ts | 2 +- apps/api/src/app/admin/admin.module.ts | 4 +- .../src/app/auth-device/auth-device.module.ts | 2 - .../app/auth-device/auth-device.service.ts | 6 +- .../src/app/benchmark/benchmark.controller.ts | 4 +- .../api/src/app/benchmark/benchmark.module.ts | 8 ++- apps/api/src/app/cache/cache.module.ts | 16 +---- apps/api/src/app/export/export.module.ts | 14 +--- apps/api/src/app/health/health.controller.ts | 2 +- apps/api/src/app/health/health.module.ts | 8 ++- apps/api/src/app/import/import.controller.ts | 4 +- apps/api/src/app/import/import.module.ts | 6 +- apps/api/src/app/info/info.controller.ts | 2 +- apps/api/src/app/info/info.module.ts | 2 + apps/api/src/app/logo/logo.controller.ts | 2 +- apps/api/src/app/logo/logo.module.ts | 7 +- apps/api/src/app/order/order.controller.ts | 6 +- apps/api/src/app/order/order.module.ts | 10 +-- .../src/app/portfolio/portfolio.controller.ts | 70 +++++++++---------- .../api/src/app/portfolio/portfolio.module.ts | 6 ++ apps/api/src/app/sitemap/sitemap.module.ts | 19 +---- apps/api/src/app/symbol/symbol.controller.ts | 4 +- apps/api/src/app/symbol/symbol.module.ts | 8 ++- apps/api/src/app/user/user.service.ts | 22 ------ .../redact-values-in-response.interceptor.ts | 19 ++--- .../redact-values-in-response.module.ts | 4 ++ ...form-data-source-in-request.interceptor.ts | 0 ...transform-data-source-in-request.module.ts | 11 +++ ...orm-data-source-in-response.interceptor.ts | 0 ...ransform-data-source-in-response.module.ts | 11 +++ libs/common/src/lib/permissions.ts | 24 ++++++- 33 files changed, 156 insertions(+), 157 deletions(-) rename apps/api/src/interceptors/{ => redact-values-in-response}/redact-values-in-response.interceptor.ts (85%) create mode 100644 apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.module.ts rename apps/api/src/interceptors/{ => transform-data-source-in-request}/transform-data-source-in-request.interceptor.ts (100%) create mode 100644 apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.module.ts rename apps/api/src/interceptors/{ => transform-data-source-in-response}/transform-data-source-in-response.interceptor.ts (100%) create mode 100644 apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.module.ts diff --git a/apps/api/src/app/account/account.controller.ts b/apps/api/src/app/account/account.controller.ts index 31c2ee76f..594a733f7 100644 --- a/apps/api/src/app/account/account.controller.ts +++ b/apps/api/src/app/account/account.controller.ts @@ -2,7 +2,7 @@ import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/accou import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; -import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor'; +import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.interceptor'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service'; import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; import { diff --git a/apps/api/src/app/account/account.module.ts b/apps/api/src/app/account/account.module.ts index 75be85f5c..1c2d20216 100644 --- a/apps/api/src/app/account/account.module.ts +++ b/apps/api/src/app/account/account.module.ts @@ -1,9 +1,7 @@ import { AccountBalanceModule } from '@ghostfolio/api/app/account-balance/account-balance.module'; import { PortfolioModule } from '@ghostfolio/api/app/portfolio/portfolio.module'; -import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; -import { UserModule } from '@ghostfolio/api/app/user/user.module'; +import { RedactValuesInResponseModule } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; -import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; @@ -19,13 +17,11 @@ import { AccountService } from './account.service'; imports: [ AccountBalanceModule, ConfigurationModule, - DataProviderModule, ExchangeRateDataModule, ImpersonationModule, PortfolioModule, PrismaModule, - RedisCacheModule, - UserModule + RedactValuesInResponseModule ], providers: [AccountService] }) diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index 298a471c3..4494fef7a 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -1,6 +1,6 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; -import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; +import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; import { ApiService } from '@ghostfolio/api/services/api/api.service'; import { DataGatheringService } from '@ghostfolio/api/services/data-gathering/data-gathering.service'; import { ManualService } from '@ghostfolio/api/services/data-provider/manual/manual.service'; diff --git a/apps/api/src/app/admin/admin.module.ts b/apps/api/src/app/admin/admin.module.ts index d0557156a..82d03395b 100644 --- a/apps/api/src/app/admin/admin.module.ts +++ b/apps/api/src/app/admin/admin.module.ts @@ -1,4 +1,5 @@ import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module'; +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; @@ -27,7 +28,8 @@ import { QueueModule } from './queue/queue.module'; PropertyModule, QueueModule, SubscriptionModule, - SymbolProfileModule + SymbolProfileModule, + TransformDataSourceInRequestModule ], controllers: [AdminController], providers: [AdminService], diff --git a/apps/api/src/app/auth-device/auth-device.module.ts b/apps/api/src/app/auth-device/auth-device.module.ts index 89689e5d2..515efa155 100644 --- a/apps/api/src/app/auth-device/auth-device.module.ts +++ b/apps/api/src/app/auth-device/auth-device.module.ts @@ -1,6 +1,5 @@ import { AuthDeviceController } from '@ghostfolio/api/app/auth-device/auth-device.controller'; import { AuthDeviceService } from '@ghostfolio/api/app/auth-device/auth-device.service'; -import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; import { Module } from '@nestjs/common'; @@ -9,7 +8,6 @@ import { JwtModule } from '@nestjs/jwt'; @Module({ controllers: [AuthDeviceController], imports: [ - ConfigurationModule, JwtModule.register({ secret: process.env.JWT_SECRET_KEY, signOptions: { expiresIn: '180 days' } diff --git a/apps/api/src/app/auth-device/auth-device.service.ts b/apps/api/src/app/auth-device/auth-device.service.ts index b24df0ae6..59208a1f3 100644 --- a/apps/api/src/app/auth-device/auth-device.service.ts +++ b/apps/api/src/app/auth-device/auth-device.service.ts @@ -1,4 +1,3 @@ -import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { Injectable } from '@nestjs/common'; @@ -6,10 +5,7 @@ import { AuthDevice, Prisma } from '@prisma/client'; @Injectable() export class AuthDeviceService { - public constructor( - private readonly configurationService: ConfigurationService, - private readonly prismaService: PrismaService - ) {} + public constructor(private readonly prismaService: PrismaService) {} public async authDevice( where: Prisma.AuthDeviceWhereUniqueInput diff --git a/apps/api/src/app/benchmark/benchmark.controller.ts b/apps/api/src/app/benchmark/benchmark.controller.ts index 184214384..7ac0e8c96 100644 --- a/apps/api/src/app/benchmark/benchmark.controller.ts +++ b/apps/api/src/app/benchmark/benchmark.controller.ts @@ -1,8 +1,8 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { getInterval } from '@ghostfolio/api/helper/portfolio.helper'; -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 { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; +import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor'; import type { BenchmarkMarketDataDetails, BenchmarkResponse, diff --git a/apps/api/src/app/benchmark/benchmark.module.ts b/apps/api/src/app/benchmark/benchmark.module.ts index 7371588d1..e7d1e9435 100644 --- a/apps/api/src/app/benchmark/benchmark.module.ts +++ b/apps/api/src/app/benchmark/benchmark.module.ts @@ -1,6 +1,7 @@ import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { SymbolModule } from '@ghostfolio/api/app/symbol/symbol.module'; -import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; +import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; @@ -17,7 +18,6 @@ import { BenchmarkService } from './benchmark.service'; controllers: [BenchmarkController], exports: [BenchmarkService], imports: [ - ConfigurationModule, DataProviderModule, ExchangeRateDataModule, MarketDataModule, @@ -25,7 +25,9 @@ import { BenchmarkService } from './benchmark.service'; PropertyModule, RedisCacheModule, SymbolModule, - SymbolProfileModule + SymbolProfileModule, + TransformDataSourceInRequestModule, + TransformDataSourceInResponseModule ], providers: [BenchmarkService] }) diff --git a/apps/api/src/app/cache/cache.module.ts b/apps/api/src/app/cache/cache.module.ts index 7a82e4366..d435c72a6 100644 --- a/apps/api/src/app/cache/cache.module.ts +++ b/apps/api/src/app/cache/cache.module.ts @@ -1,10 +1,4 @@ import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; -import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; -import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; -import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; -import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; -import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; -import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; import { Module } from '@nestjs/common'; @@ -12,14 +6,6 @@ import { CacheController } from './cache.controller'; @Module({ controllers: [CacheController], - imports: [ - ConfigurationModule, - DataGatheringModule, - DataProviderModule, - ExchangeRateDataModule, - PrismaModule, - RedisCacheModule, - SymbolProfileModule - ] + imports: [RedisCacheModule] }) export class CacheModule {} diff --git a/apps/api/src/app/export/export.module.ts b/apps/api/src/app/export/export.module.ts index 9bc5722a7..048c60359 100644 --- a/apps/api/src/app/export/export.module.ts +++ b/apps/api/src/app/export/export.module.ts @@ -1,10 +1,6 @@ import { AccountModule } from '@ghostfolio/api/app/account/account.module'; import { OrderModule } from '@ghostfolio/api/app/order/order.module'; -import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; -import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; -import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; -import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { Module } from '@nestjs/common'; @@ -12,15 +8,7 @@ import { ExportController } from './export.controller'; import { ExportService } from './export.service'; @Module({ - imports: [ - AccountModule, - ApiModule, - ConfigurationModule, - DataGatheringModule, - DataProviderModule, - OrderModule, - RedisCacheModule - ], + imports: [AccountModule, ApiModule, OrderModule], controllers: [ExportController], providers: [ExportService] }) diff --git a/apps/api/src/app/health/health.controller.ts b/apps/api/src/app/health/health.controller.ts index d899df410..31bdb2e8f 100644 --- a/apps/api/src/app/health/health.controller.ts +++ b/apps/api/src/app/health/health.controller.ts @@ -1,4 +1,4 @@ -import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; +import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; import { Controller, diff --git a/apps/api/src/app/health/health.module.ts b/apps/api/src/app/health/health.module.ts index bce798d16..6ed464401 100644 --- a/apps/api/src/app/health/health.module.ts +++ b/apps/api/src/app/health/health.module.ts @@ -1,4 +1,4 @@ -import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { DataEnhancerModule } from '@ghostfolio/api/services/data-provider/data-enhancer/data-enhancer.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; @@ -9,7 +9,11 @@ import { HealthService } from './health.service'; @Module({ controllers: [HealthController], - imports: [ConfigurationModule, DataEnhancerModule, DataProviderModule], + imports: [ + DataEnhancerModule, + DataProviderModule, + TransformDataSourceInRequestModule + ], providers: [HealthService] }) export class HealthModule {} diff --git a/apps/api/src/app/import/import.controller.ts b/apps/api/src/app/import/import.controller.ts index 29a06fc9f..b276a3c3d 100644 --- a/apps/api/src/app/import/import.controller.ts +++ b/apps/api/src/app/import/import.controller.ts @@ -1,7 +1,7 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; -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 { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; +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'; diff --git a/apps/api/src/app/import/import.module.ts b/apps/api/src/app/import/import.module.ts index ae8318044..47a4b5db3 100644 --- a/apps/api/src/app/import/import.module.ts +++ b/apps/api/src/app/import/import.module.ts @@ -4,6 +4,8 @@ import { OrderModule } from '@ghostfolio/api/app/order/order.module'; import { PlatformModule } from '@ghostfolio/api/app/platform/platform.module'; import { PortfolioModule } from '@ghostfolio/api/app/portfolio/portfolio.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; +import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; @@ -30,7 +32,9 @@ import { ImportService } from './import.service'; PortfolioModule, PrismaModule, RedisCacheModule, - SymbolProfileModule + SymbolProfileModule, + TransformDataSourceInRequestModule, + TransformDataSourceInResponseModule ], providers: [ImportService] }) diff --git a/apps/api/src/app/info/info.controller.ts b/apps/api/src/app/info/info.controller.ts index 4890a444e..67d4101a3 100644 --- a/apps/api/src/app/info/info.controller.ts +++ b/apps/api/src/app/info/info.controller.ts @@ -1,4 +1,4 @@ -import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor'; +import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor'; import { InfoItem } from '@ghostfolio/common/interfaces'; import { Controller, Get, UseInterceptors } from '@nestjs/common'; diff --git a/apps/api/src/app/info/info.module.ts b/apps/api/src/app/info/info.module.ts index c28ef5869..ba58bc36f 100644 --- a/apps/api/src/app/info/info.module.ts +++ b/apps/api/src/app/info/info.module.ts @@ -2,6 +2,7 @@ import { BenchmarkModule } from '@ghostfolio/api/app/benchmark/benchmark.module' import { PlatformModule } from '@ghostfolio/api/app/platform/platform.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module'; +import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; @@ -34,6 +35,7 @@ import { InfoService } from './info.service'; RedisCacheModule, SymbolProfileModule, TagModule, + TransformDataSourceInResponseModule, UserModule ], providers: [InfoService] diff --git a/apps/api/src/app/logo/logo.controller.ts b/apps/api/src/app/logo/logo.controller.ts index 2ef65936e..0982a793f 100644 --- a/apps/api/src/app/logo/logo.controller.ts +++ b/apps/api/src/app/logo/logo.controller.ts @@ -1,4 +1,4 @@ -import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; +import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; import { Controller, diff --git a/apps/api/src/app/logo/logo.module.ts b/apps/api/src/app/logo/logo.module.ts index fe1a46ef6..1f59df1c8 100644 --- a/apps/api/src/app/logo/logo.module.ts +++ b/apps/api/src/app/logo/logo.module.ts @@ -1,3 +1,4 @@ +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; @@ -8,7 +9,11 @@ import { LogoService } from './logo.service'; @Module({ controllers: [LogoController], - imports: [ConfigurationModule, SymbolProfileModule], + imports: [ + ConfigurationModule, + SymbolProfileModule, + TransformDataSourceInRequestModule + ], providers: [LogoService] }) export class LogoModule {} diff --git a/apps/api/src/app/order/order.controller.ts b/apps/api/src/app/order/order.controller.ts index e97fb1c11..f3709abae 100644 --- a/apps/api/src/app/order/order.controller.ts +++ b/apps/api/src/app/order/order.controller.ts @@ -1,9 +1,9 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { getInterval } from '@ghostfolio/api/helper/portfolio.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 { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.interceptor'; +import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; +import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor'; import { ApiService } from '@ghostfolio/api/services/api/api.service'; import { DataGatheringService } from '@ghostfolio/api/services/data-gathering/data-gathering.service'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service'; diff --git a/apps/api/src/app/order/order.module.ts b/apps/api/src/app/order/order.module.ts index d125bb62b..55b4cce82 100644 --- a/apps/api/src/app/order/order.module.ts +++ b/apps/api/src/app/order/order.module.ts @@ -2,9 +2,10 @@ import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/accou import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { CacheModule } from '@ghostfolio/api/app/cache/cache.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; -import { UserModule } from '@ghostfolio/api/app/user/user.module'; +import { RedactValuesInResponseModule } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.module'; +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; +import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; -import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; @@ -23,15 +24,16 @@ import { OrderService } from './order.service'; imports: [ ApiModule, CacheModule, - ConfigurationModule, DataGatheringModule, DataProviderModule, ExchangeRateDataModule, ImpersonationModule, PrismaModule, + RedactValuesInResponseModule, RedisCacheModule, SymbolProfileModule, - UserModule + TransformDataSourceInRequestModule, + TransformDataSourceInResponseModule ], providers: [AccountBalanceService, AccountService, OrderService] }) diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 66419c578..5cdaa1641 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -7,9 +7,9 @@ import { nullifyValuesInObject } from '@ghostfolio/api/helper/object.helper'; import { getInterval } from '@ghostfolio/api/helper/portfolio.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 { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.interceptor'; +import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; +import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor'; import { ApiService } from '@ghostfolio/api/services/api/api.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; @@ -27,6 +27,10 @@ import { PortfolioPublicDetails, PortfolioReport } from '@ghostfolio/common/interfaces'; +import { + hasReadRestrictedAccessPermission, + isRestrictedView +} from '@ghostfolio/common/permissions'; import type { DateRange, GroupBy, @@ -84,11 +88,6 @@ export class PortfolioController { let hasDetails = true; let hasError = false; - const hasReadRestrictedAccessPermission = - this.userService.hasReadRestrictedAccessPermission({ - impersonationId, - user: this.request.user - }); if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { hasDetails = this.request.user.subscription.type === 'Premium'; @@ -117,8 +116,11 @@ export class PortfolioController { let portfolioSummary = summary; if ( - hasReadRestrictedAccessPermission || - this.userService.isRestrictedView(this.request.user) + hasReadRestrictedAccessPermission({ + impersonationId, + user: this.request.user + }) || + isRestrictedView(this.request.user) ) { const totalInvestment = Object.values(holdings) .map(({ investment }) => { @@ -158,8 +160,11 @@ export class PortfolioController { if ( hasDetails === false || - hasReadRestrictedAccessPermission || - this.userService.isRestrictedView(this.request.user) + hasReadRestrictedAccessPermission({ + impersonationId, + user: this.request.user + }) || + isRestrictedView(this.request.user) ) { portfolioSummary = nullifyValuesInObject(summary, [ 'cash', @@ -226,12 +231,6 @@ export class PortfolioController { @Query('range') dateRange: DateRange = 'max', @Query('tags') filterByTags?: string ): Promise { - const hasReadRestrictedAccessPermission = - this.userService.hasReadRestrictedAccessPermission({ - impersonationId, - user: this.request.user - }); - const filters = this.apiService.buildFiltersFromQueryParams({ filterByAccounts, filterByAssetClasses, @@ -259,8 +258,11 @@ export class PortfolioController { }); if ( - hasReadRestrictedAccessPermission || - this.userService.isRestrictedView(this.request.user) + hasReadRestrictedAccessPermission({ + impersonationId, + user: this.request.user + }) || + isRestrictedView(this.request.user) ) { const maxDividend = dividends.reduce( (investment, item) => Math.max(investment, item.investment), @@ -326,12 +328,6 @@ export class PortfolioController { @Query('range') dateRange: DateRange = 'max', @Query('tags') filterByTags?: string ): Promise { - const hasReadRestrictedAccessPermission = - this.userService.hasReadRestrictedAccessPermission({ - impersonationId, - user: this.request.user - }); - const filters = this.apiService.buildFiltersFromQueryParams({ filterByAccounts, filterByAssetClasses, @@ -347,8 +343,11 @@ export class PortfolioController { }); if ( - hasReadRestrictedAccessPermission || - this.userService.isRestrictedView(this.request.user) + hasReadRestrictedAccessPermission({ + impersonationId, + user: this.request.user + }) || + isRestrictedView(this.request.user) ) { const maxInvestment = investments.reduce( (investment, item) => Math.max(investment, item.investment), @@ -397,12 +396,6 @@ export class PortfolioController { ): Promise { const withExcludedAccounts = withExcludedAccountsParam === 'true'; - const hasReadRestrictedAccessPermission = - this.userService.hasReadRestrictedAccessPermission({ - impersonationId, - user: this.request.user - }); - const filters = this.apiService.buildFiltersFromQueryParams({ filterByAccounts, filterByAssetClasses, @@ -418,9 +411,12 @@ export class PortfolioController { }); if ( - hasReadRestrictedAccessPermission || - this.request.user.Settings.settings.viewMode === 'ZEN' || - this.userService.isRestrictedView(this.request.user) + hasReadRestrictedAccessPermission({ + impersonationId, + user: this.request.user + }) || + isRestrictedView(this.request.user) || + this.request.user.Settings.settings.viewMode === 'ZEN' ) { performanceInformation.chart = performanceInformation.chart.map( ({ diff --git a/apps/api/src/app/portfolio/portfolio.module.ts b/apps/api/src/app/portfolio/portfolio.module.ts index 5659f2a7e..7f1f375b1 100644 --- a/apps/api/src/app/portfolio/portfolio.module.ts +++ b/apps/api/src/app/portfolio/portfolio.module.ts @@ -4,6 +4,9 @@ import { AccountService } from '@ghostfolio/api/app/account/account.service'; import { OrderModule } from '@ghostfolio/api/app/order/order.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module'; +import { RedactValuesInResponseModule } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.module'; +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; +import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; @@ -36,8 +39,11 @@ import { RulesService } from './rules.service'; MarketDataModule, OrderModule, PrismaModule, + RedactValuesInResponseModule, RedisCacheModule, SymbolProfileModule, + TransformDataSourceInRequestModule, + TransformDataSourceInResponseModule, UserModule ], providers: [ diff --git a/apps/api/src/app/sitemap/sitemap.module.ts b/apps/api/src/app/sitemap/sitemap.module.ts index ba60d43f6..e04e3f6b3 100644 --- a/apps/api/src/app/sitemap/sitemap.module.ts +++ b/apps/api/src/app/sitemap/sitemap.module.ts @@ -1,25 +1,8 @@ -import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; -import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; -import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; -import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; -import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; -import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; -import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module'; - import { Module } from '@nestjs/common'; import { SitemapController } from './sitemap.controller'; @Module({ - controllers: [SitemapController], - imports: [ - ConfigurationModule, - DataGatheringModule, - DataProviderModule, - ExchangeRateDataModule, - PrismaModule, - RedisCacheModule, - SymbolProfileModule - ] + controllers: [SitemapController] }) export class SitemapModule {} diff --git a/apps/api/src/app/symbol/symbol.controller.ts b/apps/api/src/app/symbol/symbol.controller.ts index 17e0056d6..b3b9dc109 100644 --- a/apps/api/src/app/symbol/symbol.controller.ts +++ b/apps/api/src/app/symbol/symbol.controller.ts @@ -1,6 +1,6 @@ import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; -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 { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; +import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor'; import { IDataProviderHistoricalResponse } from '@ghostfolio/api/services/interfaces/interfaces'; import type { RequestWithUser } from '@ghostfolio/common/types'; diff --git a/apps/api/src/app/symbol/symbol.module.ts b/apps/api/src/app/symbol/symbol.module.ts index 3b5379a62..223a0a832 100644 --- a/apps/api/src/app/symbol/symbol.module.ts +++ b/apps/api/src/app/symbol/symbol.module.ts @@ -1,4 +1,5 @@ -import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module'; +import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module'; @@ -12,10 +13,11 @@ import { SymbolService } from './symbol.service'; controllers: [SymbolController], exports: [SymbolService], imports: [ - ConfigurationModule, DataProviderModule, MarketDataModule, - PrismaModule + PrismaModule, + TransformDataSourceInRequestModule, + TransformDataSourceInResponseModule ], providers: [SymbolService] }) diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 3a370d88a..0ac586671 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -121,28 +121,6 @@ export class UserService { return usersWithAdminRole.length > 0; } - public hasReadRestrictedAccessPermission({ - impersonationId, - user - }: { - impersonationId: string; - user: UserWithSettings; - }) { - if (!impersonationId) { - return false; - } - - const access = user.Access?.find(({ id }) => { - return id === impersonationId; - }); - - return access?.permissions?.includes('READ_RESTRICTED') ?? true; - } - - public isRestrictedView(aUser: UserWithSettings) { - return aUser.Settings.settings.isRestrictedView ?? false; - } - public async user( userWhereUniqueInput: Prisma.UserWhereUniqueInput ): Promise { diff --git a/apps/api/src/interceptors/redact-values-in-response.interceptor.ts b/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts similarity index 85% rename from apps/api/src/interceptors/redact-values-in-response.interceptor.ts rename to apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts index 17d4e3c17..cae4f22ed 100644 --- a/apps/api/src/interceptors/redact-values-in-response.interceptor.ts +++ b/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts @@ -1,6 +1,9 @@ -import { UserService } from '@ghostfolio/api/app/user/user.service'; import { redactAttributes } from '@ghostfolio/api/helper/object.helper'; import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; +import { + hasReadRestrictedAccessPermission, + isRestrictedView +} from '@ghostfolio/common/permissions'; import { UserWithSettings } from '@ghostfolio/common/types'; import { @@ -16,7 +19,7 @@ import { map } from 'rxjs/operators'; export class RedactValuesInResponseInterceptor implements NestInterceptor { - public constructor(private userService: UserService) {} + public constructor() {} public intercept( context: ExecutionContext, @@ -29,15 +32,13 @@ export class RedactValuesInResponseInterceptor const impersonationId = headers?.[HEADER_KEY_IMPERSONATION.toLowerCase()]; - const hasReadRestrictedPermission = - this.userService.hasReadRestrictedAccessPermission({ - impersonationId, - user - }); if ( - hasReadRestrictedPermission || - this.userService.isRestrictedView(user) + hasReadRestrictedAccessPermission({ + impersonationId, + user + }) || + isRestrictedView(user) ) { data = redactAttributes({ object: data, diff --git a/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.module.ts b/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.module.ts new file mode 100644 index 000000000..90cf254b3 --- /dev/null +++ b/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.module.ts @@ -0,0 +1,4 @@ +import { Module } from '@nestjs/common'; + +@Module({}) +export class RedactValuesInResponseModule {} diff --git a/apps/api/src/interceptors/transform-data-source-in-request.interceptor.ts b/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts similarity index 100% rename from apps/api/src/interceptors/transform-data-source-in-request.interceptor.ts rename to apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor.ts diff --git a/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.module.ts b/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.module.ts new file mode 100644 index 000000000..4a7d23803 --- /dev/null +++ b/apps/api/src/interceptors/transform-data-source-in-request/transform-data-source-in-request.module.ts @@ -0,0 +1,11 @@ +import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; + +import { Module } from '@nestjs/common'; + +@Module({ + exports: [ConfigurationService], + imports: [ConfigurationModule], + providers: [ConfigurationService] +}) +export class TransformDataSourceInRequestModule {} diff --git a/apps/api/src/interceptors/transform-data-source-in-response.interceptor.ts b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts similarity index 100% rename from apps/api/src/interceptors/transform-data-source-in-response.interceptor.ts rename to apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts diff --git a/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.module.ts b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.module.ts new file mode 100644 index 000000000..fadf0bd80 --- /dev/null +++ b/apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.module.ts @@ -0,0 +1,11 @@ +import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; + +import { Module } from '@nestjs/common'; + +@Module({ + exports: [ConfigurationService], + imports: [ConfigurationModule], + providers: [ConfigurationService] +}) +export class TransformDataSourceInResponseModule {} diff --git a/libs/common/src/lib/permissions.ts b/libs/common/src/lib/permissions.ts index 890cb8b63..7c8b8ccbe 100644 --- a/libs/common/src/lib/permissions.ts +++ b/libs/common/src/lib/permissions.ts @@ -125,6 +125,28 @@ export function hasPermission( return aPermissions.includes(aPermission); } -export function hasRole(aUser: UserWithSettings, aRole: Role): boolean { +export function hasReadRestrictedAccessPermission({ + impersonationId, + user +}: { + impersonationId: string; + user: UserWithSettings; +}) { + if (!impersonationId) { + return false; + } + + const access = user.Access?.find(({ id }) => { + return id === impersonationId; + }); + + return access?.permissions?.includes('READ_RESTRICTED') ?? true; +} + +export function hasRole(aUser: UserWithSettings, aRole: Role) { return aUser?.role === aRole; } + +export function isRestrictedView(aUser: UserWithSettings) { + return aUser.Settings.settings.isRestrictedView ?? false; +}