From 4386d22e53047e555bbf3ad1600fd78baa0cb46d Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 7 Aug 2026 09:16:57 +0200 Subject: [PATCH] Bugfix/percentage values in impersonation mode with unrestricted access (#7522) * Fix percentage values in impersonation mode with unrestricted access * Fix savings rate in impersonation mode * Improve savingsRate on FIRE page * Update changelog --- CHANGELOG.md | 6 ++++ .../src/app/portfolio/portfolio.controller.ts | 30 ++++++++-------- .../src/app/portfolio/portfolio.service.ts | 5 +-- .../redact-values-in-response.interceptor.ts | 2 +- apps/client/src/app/app.component.ts | 10 +++--- .../account-detail-dialog.component.ts | 11 ++++-- .../account-detail-dialog.html | 4 +-- .../interfaces/interfaces.ts | 2 +- .../holding-detail-dialog.html | 4 +-- .../interfaces/interfaces.ts | 2 +- .../pages/accounts/accounts-page.component.ts | 12 ++++--- .../allocations/allocations-page.component.ts | 23 +++++++++---- .../analysis/analysis-page.component.ts | 34 ++++++++++++------- .../portfolio/analysis/analysis-page.html | 12 ++----- .../app/pages/portfolio/fire/fire-page.html | 2 +- .../portfolio-investments.interface.ts | 1 + libs/common/src/lib/permissions.ts | 12 +++---- 17 files changed, 103 insertions(+), 69 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4656bdedf..c32f0535b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Migrated the abstract _Material_ form field from a component to a directive - Removed the redundant `balance` attribute of the account in favor of the account balances +### Fixed + +- Fixed the values of the charts and tables in impersonation mode with an unrestricted access to show absolute values instead of percentages +- Fixed the savings rate of the investment timeline chart and the streaks on the analysis page in impersonation mode to be based on the impersonated user +- Fixed the savings rate of the _FIRE_ calculator in impersonation mode to not be based on the impersonating user + ## 3.43.0 - 2026-08-06 ### Added diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index f6e8648d5..953976a4a 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -136,7 +136,7 @@ export class PortfolioController { if ( hasReadRestrictedAccessPermission({ impersonationId, - user: this.request.user + accesses: this.request.user?.accessesGet }) || isRestrictedView(this.request.user) ) { @@ -180,7 +180,7 @@ export class PortfolioController { hasDetails === false || hasReadRestrictedAccessPermission({ impersonationId, - user: this.request.user + accesses: this.request.user?.accessesGet }) || isRestrictedView(this.request.user) ) { @@ -374,7 +374,7 @@ export class PortfolioController { if ( hasReadRestrictedAccessPermission({ impersonationId, - user: this.request.user + accesses: this.request.user?.accessesGet }) || isRestrictedView(this.request.user) ) { @@ -491,19 +491,19 @@ export class PortfolioController { filterByTags: tags }); - let { investments, streaks } = await this.portfolioService.getInvestments({ - filters, - groupBy, - impersonationId, - dateRange: range, - savingsRate: this.request.user?.settings?.settings.savingsRate, - userId: this.request.user.id - }); + let { investments, savingsRate, streaks } = + await this.portfolioService.getInvestments({ + filters, + groupBy, + impersonationId, + dateRange: range, + userId: this.request.user.id + }); if ( hasReadRestrictedAccessPermission({ impersonationId, - user: this.request.user + accesses: this.request.user?.accessesGet }) || isRestrictedView(this.request.user) ) { @@ -521,6 +521,8 @@ export class PortfolioController { 'currentStreak', 'longestStreak' ]); + + savingsRate = null; } if ( @@ -537,7 +539,7 @@ export class PortfolioController { ]); } - return { investments, streaks }; + return { investments, savingsRate, streaks }; } @Get('performance') @@ -578,7 +580,7 @@ export class PortfolioController { if ( hasReadRestrictedAccessPermission({ impersonationId, - user: this.request.user + accesses: this.request.user?.accessesGet }) || isRestrictedView(this.request.user) || this.request.user.settings.settings.viewMode === 'ZEN' diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index ef79fd717..48ea66dac 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -413,19 +413,18 @@ export class PortfolioService { filters, groupBy, impersonationId, - savingsRate, userId }: { dateRange: DateRange; filters?: Filter[]; groupBy?: GroupBy; impersonationId: string; - savingsRate: number; userId: string; }): Promise { userId = await this.getUserId(impersonationId, userId); const user = await this.userService.user({ id: userId }); const userCurrency = this.getUserCurrency(user); + const savingsRate = (user.settings?.settings as UserSettings)?.savingsRate; const { endDate, startDate } = getIntervalFromDateRange({ dateRange }); @@ -438,6 +437,7 @@ export class PortfolioService { if (activities.length === 0) { return { + savingsRate, investments: [], streaks: { currentStreak: 0, longestStreak: 0 } }; @@ -484,6 +484,7 @@ export class PortfolioService { return { investments, + savingsRate, streaks }; } diff --git a/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts b/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts index 60b994cac..6a9596298 100644 --- a/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts +++ b/apps/api/src/interceptors/redact-values-in-response/redact-values-in-response.interceptor.ts @@ -38,7 +38,7 @@ export class RedactValuesInResponseInterceptor implements NestInterceptor< if ( hasReadRestrictedAccessPermission({ impersonationId, - user + accesses: user?.accessesGet }) || isRestrictedView(user) ) { diff --git a/apps/client/src/app/app.component.ts b/apps/client/src/app/app.component.ts index fd17bcd6e..65b5e95b0 100644 --- a/apps/client/src/app/app.component.ts +++ b/apps/client/src/app/app.component.ts @@ -57,12 +57,12 @@ export class GfAppComponent implements OnInit { public currentRoute: string; public currentSubRoute: string; public deviceType: string; - public hasImpersonationId: boolean; public hasInfoMessage: boolean; public hasPermissionToChangeDateRange: boolean; public hasPermissionToChangeFilters: boolean; public hasPromotion = false; public hasTabs = false; + public impersonationId: string | null; public info: InfoItem; public pageTitle: string; public routerLinkRegister = publicRoutes.register.routerLink; @@ -116,7 +116,7 @@ export class GfAppComponent implements OnInit { .onChangeHasImpersonation() .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { - this.hasImpersonationId = !!impersonationId; + this.impersonationId = impersonationId; }); this.router.events @@ -291,13 +291,12 @@ export class GfAppComponent implements OnInit { baseCurrency: this.user?.settings?.baseCurrency, colorScheme: this.user?.settings?.colorScheme, deviceType: this.deviceType, - hasImpersonationId: this.hasImpersonationId, hasPermissionToAccessAdminControl: hasPermission( this.user?.permissions, permissions.accessAdminControl ), hasPermissionToCreateActivity: - !this.hasImpersonationId && + !this.impersonationId && hasPermission( this.user?.permissions, permissions.createActivity @@ -308,12 +307,13 @@ export class GfAppComponent implements OnInit { permissions.reportDataGlitch ), hasPermissionToUpdateActivity: - !this.hasImpersonationId && + !this.impersonationId && hasPermission( this.user?.permissions, permissions.updateActivity ) && !this.user?.settings?.isRestrictedView, + impersonationId: this.impersonationId, locale: this.user?.settings?.locale }, height: this.deviceType === 'mobile' ? '98vh' : '80vh', diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts index e81b8cf06..a0350ee6b 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts @@ -14,7 +14,11 @@ import { PortfolioPosition, User } from '@ghostfolio/common/interfaces'; -import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { + hasPermission, + hasReadRestrictedAccessPermission, + permissions +} from '@ghostfolio/common/permissions'; import { GfAccountBalancesComponent } from '@ghostfolio/ui/account-balances'; import { GfActivitiesTableComponent } from '@ghostfolio/ui/activities-table'; import { GfDialogFooterComponent } from '@ghostfolio/ui/dialog-footer'; @@ -225,7 +229,10 @@ export class GfAccountDetailDialogComponent implements OnInit { protected showValuesInPercentage() { return ( - this.data.hasImpersonationId || this.user?.settings?.isRestrictedView + hasReadRestrictedAccessPermission({ + accesses: this.user?.access, + impersonationId: this.data.impersonationId + }) || this.user?.settings?.isRestrictedView ); } diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html index 485af7500..cb3246c00 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html @@ -158,8 +158,8 @@ [pageSize]="pageSize" [showAccountColumn]="false" [showActions]=" - !data.hasImpersonationId && data.hasPermissionToCreateActivity && + !data.impersonationId && user?.settings?.isExperimentalFeatures && !user?.settings?.isRestrictedView " @@ -183,8 +183,8 @@ [currentBalance]="balance" [locale]="user?.settings?.locale" [showActions]=" - !data.hasImpersonationId && hasPermissionToDeleteAccountBalance && + !data.impersonationId && !user.settings.isRestrictedView " (accountBalanceCreated)="onAddAccountBalance($event)" diff --git a/apps/client/src/app/components/account-detail-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/account-detail-dialog/interfaces/interfaces.ts index 2f80dac36..0e7d04f2c 100644 --- a/apps/client/src/app/components/account-detail-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/account-detail-dialog/interfaces/interfaces.ts @@ -1,8 +1,8 @@ export interface AccountDetailDialogParams { accountId: string; deviceType: string; - hasImpersonationId: boolean; hasPermissionToCreateActivity: boolean; + impersonationId: string | null; } export interface AccountDetailDialogResult { diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html index eccc62b4c..8292ff598 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -382,7 +382,7 @@ [hasPermissionToCreateActivity]="false" [hasPermissionToDeleteActivity]="false" [hasPermissionToExportActivities]=" - !data.hasImpersonationId && !user?.settings?.isRestrictedView + !data.impersonationId && !user?.settings?.isRestrictedView " [hasPermissionToFilter]="false" [hasPermissionToOpenDetails]="false" @@ -390,8 +390,8 @@ [pageIndex]="pageIndex" [pageSize]="pageSize" [showActions]=" - !data.hasImpersonationId && data.hasPermissionToCreateActivity && + !data.impersonationId && user?.settings?.isExperimentalFeatures && !user?.settings?.isRestrictedView " diff --git a/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts index 40c94ca60..efc10d6ac 100644 --- a/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/holding-detail-dialog/interfaces/interfaces.ts @@ -7,11 +7,11 @@ export interface HoldingDetailDialogParams { colorScheme: ColorScheme; dataSource: DataSource; deviceType: string; - hasImpersonationId: boolean; hasPermissionToAccessAdminControl: boolean; hasPermissionToCreateActivity: boolean; hasPermissionToReportDataGlitch: boolean; hasPermissionToUpdateActivity: boolean; + impersonationId: string | null; locale: string; symbol: string; } diff --git a/apps/client/src/app/pages/accounts/accounts-page.component.ts b/apps/client/src/app/pages/accounts/accounts-page.component.ts index e45c1d003..9b10fb222 100644 --- a/apps/client/src/app/pages/accounts/accounts-page.component.ts +++ b/apps/client/src/app/pages/accounts/accounts-page.component.ts @@ -51,9 +51,9 @@ import { GfTransferBalanceDialogComponent } from './transfer-balance/transfer-ba export class GfAccountsPageComponent implements OnInit { protected accounts: AccountWithValue[]; protected activitiesCount = 0; - protected hasImpersonationId: boolean; protected hasPermissionToCreateAccount: boolean; protected hasPermissionToUpdateAccount: boolean; + protected impersonationId: string | null; protected totalBalanceInBaseCurrency = 0; protected totalValueInBaseCurrency = 0; protected user: User; @@ -104,12 +104,16 @@ export class GfAccountsPageComponent implements OnInit { }); } + protected get hasImpersonationId() { + return !!this.impersonationId; + } + public ngOnInit() { this.impersonationStorageService .onChangeHasImpersonation() .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { - this.hasImpersonationId = !!impersonationId; + this.impersonationId = impersonationId; }); this.userService.stateChanged @@ -252,11 +256,11 @@ export class GfAccountsPageComponent implements OnInit { data: { accountId: aAccountId, deviceType: this.deviceType(), - hasImpersonationId: this.hasImpersonationId, hasPermissionToCreateActivity: !this.hasImpersonationId && hasPermission(this.user?.permissions, permissions.createActivity) && - !this.user?.settings?.isRestrictedView + !this.user?.settings?.isRestrictedView, + impersonationId: this.impersonationId }, height: this.deviceType() === 'mobile' ? '98vh' : '80vh', width: this.deviceType() === 'mobile' ? '100vw' : '50rem' diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts index 0931578cf..be7d49bea 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -17,7 +17,11 @@ import { PortfolioPosition, User } from '@ghostfolio/common/interfaces'; -import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { + hasPermission, + hasReadRestrictedAccessPermission, + permissions +} from '@ghostfolio/common/permissions'; import { MarketAdvanced } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; import { GfPortfolioProportionChartComponent } from '@ghostfolio/ui/portfolio-proportion-chart'; @@ -85,7 +89,6 @@ export class GfAllocationsPageComponent implements OnInit { protected readonly deviceType = computed( () => this.deviceDetectorService.deviceInfo().deviceType ); - protected hasImpersonationId: boolean; protected holdings: { [symbol: string]: Pick< PortfolioPosition['assetProfile'], @@ -97,6 +100,7 @@ export class GfAllocationsPageComponent implements OnInit { | 'name' > & { etfProvider: string; value: number }; }; + protected impersonationId: string | null; protected isLoading = false; protected markets: PortfolioDetails['markets']; protected marketsAdvanced: { @@ -169,7 +173,7 @@ export class GfAllocationsPageComponent implements OnInit { .onChangeHasImpersonation() .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { - this.hasImpersonationId = !!impersonationId; + this.impersonationId = impersonationId; this.changeDetectorRef.markForCheck(); }); @@ -224,7 +228,12 @@ export class GfAllocationsPageComponent implements OnInit { } protected showValuesInPercentage() { - return this.hasImpersonationId || this.user?.settings?.isRestrictedView; + return ( + hasReadRestrictedAccessPermission({ + accesses: this.user?.access, + impersonationId: this.impersonationId + }) || this.user?.settings?.isRestrictedView + ); } private extractCurrency({ @@ -618,11 +627,11 @@ export class GfAllocationsPageComponent implements OnInit { data: { accountId: aAccountId, deviceType: this.deviceType(), - hasImpersonationId: this.hasImpersonationId, hasPermissionToCreateActivity: - !this.hasImpersonationId && + !this.impersonationId && hasPermission(this.user?.permissions, permissions.createActivity) && - !this.user?.settings?.isRestrictedView + !this.user?.settings?.isRestrictedView, + impersonationId: this.impersonationId }, height: this.deviceType() === 'mobile' ? '98vh' : '80vh', width: this.deviceType() === 'mobile' ? '100vw' : '50rem' diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index c2d23dbc6..424f1bf5b 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -16,7 +16,11 @@ import { ToggleOption, User } from '@ghostfolio/common/interfaces'; -import { hasPermission, permissions } from '@ghostfolio/common/permissions'; +import { + hasPermission, + hasReadRestrictedAccessPermission, + permissions +} from '@ghostfolio/common/permissions'; import type { AiPromptMode, GroupBy } from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; @@ -79,8 +83,8 @@ export class GfAnalysisPageComponent implements OnInit { protected bottom3: PortfolioPosition[]; protected dividendsByGroup: InvestmentItem[]; protected readonly dividendTimelineDataLabel = $localize`Dividend`; - protected hasImpersonationId: boolean; protected hasPermissionToReadAiPrompt: boolean; + protected impersonationId: string | null; protected investments: InvestmentItem[]; protected readonly investmentTimelineDataLabel = $localize`Invested Capital`; protected investmentsByGroup: InvestmentItem[]; @@ -100,6 +104,7 @@ export class GfAnalysisPageComponent implements OnInit { protected performanceDataItemsInPercentage: HistoricalDataItem[]; protected readonly portfolioEvolutionDataLabel = $localize`Investment`; protected precision = 2; + protected savingsRatePerMonth: number | undefined; protected streaks: PortfolioInvestmentsResponse['streaks']; protected top3: PortfolioPosition[]; protected unitCurrentStreak: string; @@ -131,18 +136,13 @@ export class GfAnalysisPageComponent implements OnInit { } get savingsRate() { - const savingsRatePerMonth = - this.hasImpersonationId || this.user.settings.isRestrictedView - ? undefined - : this.user?.settings?.savingsRate; - - if (savingsRatePerMonth === undefined) { + if (!this.savingsRatePerMonth) { return undefined; } return this.mode() === 'year' - ? savingsRatePerMonth * 12 - : savingsRatePerMonth; + ? this.savingsRatePerMonth * 12 + : this.savingsRatePerMonth; } public ngOnInit() { @@ -150,7 +150,7 @@ export class GfAnalysisPageComponent implements OnInit { .onChangeHasImpersonation() .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe((impersonationId) => { - this.hasImpersonationId = !!impersonationId; + this.impersonationId = impersonationId; this.changeDetectorRef.markForCheck(); }); @@ -241,6 +241,15 @@ export class GfAnalysisPageComponent implements OnInit { }); } + protected showValuesInPercentage() { + return ( + hasReadRestrictedAccessPermission({ + accesses: this.user?.access, + impersonationId: this.impersonationId + }) || this.user?.settings?.isRestrictedView + ); + } + private fetchDividendsAndInvestments() { this.isLoadingDividendTimelineChart = true; this.isLoadingInvestmentTimelineChart = true; @@ -267,8 +276,9 @@ export class GfAnalysisPageComponent implements OnInit { range: this.user?.settings?.dateRange ?? DEFAULT_DATE_RANGE }) .pipe(takeUntilDestroyed(this.destroyRef)) - .subscribe(({ investments, streaks }) => { + .subscribe(({ investments, savingsRate, streaks }) => { this.investmentsByGroup = investments; + this.savingsRatePerMonth = savingsRate; this.streaks = streaks; this.unitCurrentStreak = this.mode() === 'year' diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html index 0fac204f9..82751b882 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -398,9 +398,7 @@ [benchmarkDataLabel]="portfolioEvolutionDataLabel" [currency]="user?.settings?.baseCurrency" [historicalDataItems]="performanceDataItems" - [isInPercentage]=" - hasImpersonationId || user.settings.isRestrictedView - " + [isInPercentage]="showValuesInPercentage()" [isLoading]="isLoadingInvestmentChart" [locale]="user?.settings?.locale" /> @@ -456,9 +454,7 @@ [benchmarkDataLabel]="investmentTimelineDataLabel" [currency]="user?.settings?.baseCurrency" [groupBy]="mode()" - [isInPercentage]=" - hasImpersonationId || user.settings.isRestrictedView - " + [isInPercentage]="showValuesInPercentage()" [isLoading]="isLoadingInvestmentTimelineChart" [locale]="user?.settings?.locale" [savingsRate]="savingsRate" @@ -493,9 +489,7 @@ [benchmarkDataLabel]="dividendTimelineDataLabel" [currency]="user?.settings?.baseCurrency" [groupBy]="mode()" - [isInPercentage]=" - hasImpersonationId || user.settings.isRestrictedView - " + [isInPercentage]="showValuesInPercentage()" [isLoading]="isLoadingDividendTimelineChart" [locale]="user?.settings?.locale" /> diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.html b/apps/client/src/app/pages/portfolio/fire/fire-page.html index 7315f10cb..13693a15a 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.html +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.html @@ -21,7 +21,7 @@ [locale]="user?.settings?.locale" [projectedTotalAmount]="user?.settings?.projectedTotalAmount" [retirementDate]="user?.settings?.retirementDate" - [savingsRate]="user?.settings?.savingsRate" + [savingsRate]="hasImpersonationId ? 0 : user?.settings?.savingsRate" [style.opacity]=" user?.subscription?.type === 'Basic' ? '0.67' : 'initial' " diff --git a/libs/common/src/lib/interfaces/responses/portfolio-investments.interface.ts b/libs/common/src/lib/interfaces/responses/portfolio-investments.interface.ts index 6d0d60002..30ac53765 100644 --- a/libs/common/src/lib/interfaces/responses/portfolio-investments.interface.ts +++ b/libs/common/src/lib/interfaces/responses/portfolio-investments.interface.ts @@ -2,5 +2,6 @@ import { InvestmentItem } from '../investment-item.interface'; export interface PortfolioInvestmentsResponse { investments: InvestmentItem[]; + savingsRate?: number; streaks: { currentStreak: number; longestStreak: number }; } diff --git a/libs/common/src/lib/permissions.ts b/libs/common/src/lib/permissions.ts index 811ded68c..96533a9e7 100644 --- a/libs/common/src/lib/permissions.ts +++ b/libs/common/src/lib/permissions.ts @@ -1,6 +1,6 @@ import { UserWithSettings } from '@ghostfolio/common/types'; -import { Role } from '@prisma/client'; +import { Access, Role } from '@prisma/client'; export const permissions = { accessAdminControl: 'accessAdminControl', @@ -198,17 +198,17 @@ export function hasPermission( } export function hasReadRestrictedAccessPermission({ - impersonationId, - user + accesses = [], + impersonationId }: { - impersonationId: string; - user: UserWithSettings; + accesses?: Pick[]; + impersonationId: string | null; }) { if (!impersonationId) { return false; } - const access = user?.accessesGet?.find(({ id }) => { + const access = accesses.find(({ id }) => { return id === impersonationId; });