From ef7df254968dbc90f4ff16e03577aa26c7073bb0 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 21 Apr 2026 20:07:54 +0200 Subject: [PATCH] Task/refactor subscription types (#6735) Refactor subscription types --- apps/api/src/app/access/access.controller.ts | 5 +++-- .../src/app/endpoints/public/public.controller.ts | 3 ++- apps/api/src/app/portfolio/portfolio.controller.ts | 12 +++++++----- apps/api/src/app/user/user.service.ts | 7 ++++--- .../services/data-provider/data-provider.service.ts | 7 ++++--- .../admin-overview/admin-overview.component.ts | 7 +++++-- .../app/pages/portfolio/fire/fire-page.component.ts | 5 +++-- .../pages/portfolio/x-ray/x-ray-page.component.ts | 3 ++- 8 files changed, 30 insertions(+), 19 deletions(-) diff --git a/apps/api/src/app/access/access.controller.ts b/apps/api/src/app/access/access.controller.ts index 5056a6d71..28b459203 100644 --- a/apps/api/src/app/access/access.controller.ts +++ b/apps/api/src/app/access/access.controller.ts @@ -2,6 +2,7 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorat import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { CreateAccessDto, UpdateAccessDto } from '@ghostfolio/common/dtos'; +import { SubscriptionType } from '@ghostfolio/common/enums'; import { Access } from '@ghostfolio/common/interfaces'; import { permissions } from '@ghostfolio/common/permissions'; import type { RequestWithUser } from '@ghostfolio/common/types'; @@ -75,7 +76,7 @@ export class AccessController { ): Promise { if ( this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - this.request.user.subscription.type === 'Basic' + this.request.user.subscription.type === SubscriptionType.Basic ) { throw new HttpException( getReasonPhrase(StatusCodes.FORBIDDEN), @@ -130,7 +131,7 @@ export class AccessController { ): Promise { if ( this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - this.request.user.subscription.type === 'Basic' + this.request.user.subscription.type === SubscriptionType.Basic ) { throw new HttpException( getReasonPhrase(StatusCodes.FORBIDDEN), diff --git a/apps/api/src/app/endpoints/public/public.controller.ts b/apps/api/src/app/endpoints/public/public.controller.ts index b97640cab..33c6052a6 100644 --- a/apps/api/src/app/endpoints/public/public.controller.ts +++ b/apps/api/src/app/endpoints/public/public.controller.ts @@ -7,6 +7,7 @@ import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interc import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { DEFAULT_CURRENCY } from '@ghostfolio/common/config'; +import { SubscriptionType } from '@ghostfolio/common/enums'; import { getSum } from '@ghostfolio/common/helper'; import { PublicPortfolioResponse } from '@ghostfolio/common/interfaces'; import type { RequestWithUser } from '@ghostfolio/common/types'; @@ -58,7 +59,7 @@ export class PublicController { }); if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { - hasDetails = user.subscription.type === 'Premium'; + hasDetails = user.subscription.type === SubscriptionType.Premium; } const [ diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 9c41aecb9..cb6f21e8a 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -17,6 +17,7 @@ import { HEADER_KEY_IMPERSONATION, UNKNOWN_KEY } from '@ghostfolio/common/config'; +import { SubscriptionType } from '@ghostfolio/common/enums'; import { PortfolioDetails, PortfolioDividendsResponse, @@ -92,7 +93,8 @@ export class PortfolioController { let hasError = false; if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { - hasDetails = this.request.user.subscription.type === 'Premium'; + hasDetails = + this.request.user.subscription.type === SubscriptionType.Premium; } const filters = this.apiService.buildFiltersFromQueryParams({ @@ -356,7 +358,7 @@ export class PortfolioController { if ( this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - this.request.user.subscription.type === 'Basic' + this.request.user.subscription.type === SubscriptionType.Basic ) { dividends = dividends.map((item) => { return nullifyValuesInObject(item, ['investment']); @@ -484,7 +486,7 @@ export class PortfolioController { if ( this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - this.request.user.subscription.type === 'Basic' + this.request.user.subscription.type === SubscriptionType.Basic ) { investments = investments.map((item) => { return nullifyValuesInObject(item, ['investment']); @@ -596,7 +598,7 @@ export class PortfolioController { if ( this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - this.request.user.subscription.type === 'Basic' + this.request.user.subscription.type === SubscriptionType.Basic ) { performanceInformation.chart = performanceInformation.chart.map( (item) => { @@ -624,7 +626,7 @@ export class PortfolioController { if ( this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - this.request.user.subscription.type === 'Basic' + this.request.user.subscription.type === SubscriptionType.Basic ) { for (const category of report.xRay.categories) { category.rules = null; diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 370f5d422..0c73833f7 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -32,6 +32,7 @@ import { TAG_ID_EXCLUDE_FROM_ANALYSIS, locale as defaultLocale } from '@ghostfolio/common/config'; +import { SubscriptionType } from '@ghostfolio/common/enums'; import { User as IUser, SystemMessage, @@ -156,7 +157,7 @@ export class UserService { if ( this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - subscription.type === 'Basic' + subscription.type === SubscriptionType.Basic ) { tags = []; } @@ -443,7 +444,7 @@ export class UserService { createdAt: user.createdAt }); - if (user.subscription?.type === 'Basic') { + if (user.subscription?.type === SubscriptionType.Basic) { const daysSinceRegistration = differenceInDays( new Date(), user.createdAt @@ -485,7 +486,7 @@ export class UserService { // Reset holdings view mode user.settings.settings.holdingsViewMode = undefined; - } else if (user.subscription?.type === 'Premium') { + } else if (user.subscription?.type === SubscriptionType.Premium) { if (!hasRole(user, Role.DEMO)) { currentPermissions.push(permissions.createApiKey); currentPermissions.push(permissions.enableDataProviderGhostfolio); diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts index a6b12cce2..e7c7e8a2e 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -12,6 +12,7 @@ import { PROPERTY_DATA_SOURCE_MAPPING } from '@ghostfolio/common/config'; import { CreateOrderDto } from '@ghostfolio/common/dtos'; +import { SubscriptionType } from '@ghostfolio/common/enums'; import { DATE_FORMAT, getAssetProfileIdentifier, @@ -227,7 +228,7 @@ export class DataProviderService implements OnModuleInit { if ( this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - user.subscription.type === 'Basic' + user.subscription.type === SubscriptionType.Basic ) { const dataProvider = this.getDataProvider(DataSource[dataSource]); @@ -591,7 +592,7 @@ export class DataProviderService implements OnModuleInit { } else if ( dataProvider.getDataProviderInfo().isPremium && this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && - user?.subscription.type === 'Basic' + user?.subscription.type === SubscriptionType.Basic ) { // Skip symbols of Premium data providers for users without subscription return false; @@ -780,7 +781,7 @@ export class DataProviderService implements OnModuleInit { }) .map((lookupItem) => { if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { - if (user.subscription.type === 'Premium') { + if (user.subscription.type === SubscriptionType.Premium) { lookupItem.dataProviderInfo.isPremium = false; } diff --git a/apps/client/src/app/components/admin-overview/admin-overview.component.ts b/apps/client/src/app/components/admin-overview/admin-overview.component.ts index 5d4e5268e..ff55bb2bc 100644 --- a/apps/client/src/app/components/admin-overview/admin-overview.component.ts +++ b/apps/client/src/app/components/admin-overview/admin-overview.component.ts @@ -8,7 +8,10 @@ import { PROPERTY_SYSTEM_MESSAGE, ghostfolioPrefix } from '@ghostfolio/common/config'; -import { ConfirmationDialogType } from '@ghostfolio/common/enums'; +import { + ConfirmationDialogType, + SubscriptionType +} from '@ghostfolio/common/enums'; import { getDateFnsLocale } from '@ghostfolio/common/helper'; import { Coupon, @@ -255,7 +258,7 @@ export class GfAdminOverviewComponent implements OnInit { this.systemMessage ?? ({ message: '⚒️ Scheduled maintenance in progress...', - targetGroups: ['Basic', 'Premium'] + targetGroups: [SubscriptionType.Basic, SubscriptionType.Premium] } as SystemMessage) ) ); diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts index 2f7568982..7b5b10c7d 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts @@ -1,5 +1,6 @@ import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; +import { SubscriptionType } from '@ghostfolio/common/enums'; import { FireCalculationCompleteEvent, FireWealth, @@ -80,7 +81,7 @@ export class GfFirePageComponent implements OnInit { : 0 } }; - if (this.user.subscription?.type === 'Basic') { + if (this.user.subscription?.type === SubscriptionType.Basic) { this.fireWealth = { today: { valueInBaseCurrency: 10000 @@ -113,7 +114,7 @@ export class GfFirePageComponent implements OnInit { this.user = state.user; this.hasPermissionToUpdateUserSettings = - this.user.subscription?.type === 'Basic' + this.user.subscription?.type === SubscriptionType.Basic ? false : hasPermission( this.user.permissions, diff --git a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts index e97fd4876..650522896 100644 --- a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts +++ b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.ts @@ -2,6 +2,7 @@ import { GfRulesComponent } from '@ghostfolio/client/components/rules/rules.comp import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; import { UpdateUserSettingDto } from '@ghostfolio/common/dtos'; +import { SubscriptionType } from '@ghostfolio/common/enums'; import { PortfolioReportResponse, PortfolioReportRule @@ -73,7 +74,7 @@ export class GfXRayPageComponent { this.user = state.user; this.hasPermissionToUpdateUserSettings = - this.user.subscription?.type === 'Basic' + this.user.subscription?.type === SubscriptionType.Basic ? false : hasPermission( this.user.permissions,