From 6a1cbccc4391eec81a3e4481e128e6bab3a24c2e Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 10 Oct 2026 20:33:47 +0200 Subject: [PATCH] Bugfix/AI prompt in impersonation mode (#8115) * Fix AI prompt in impersonation mode * Update changelog --- CHANGELOG.md | 4 ++++ .../api/src/app/endpoints/ai/ai.controller.ts | 19 ++++++++++++------- apps/api/src/app/endpoints/ai/ai.module.ts | 2 ++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5216b1726a..a5aea753b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Extended the access to share the portfolio with the Model Context Protocol (MCP) to support the _View_ and the _View and manage_ permissions (experimental) - Improved the performance of getting the historical market data by selecting only the required columns +### Fixed + +- Fixed the _Copy AI prompt to clipboard_ actions on the analysis page in impersonation mode to be based on the impersonated user (experimental) + ## 3.83.0 - 2026-10-10 ### Added diff --git a/apps/api/src/app/endpoints/ai/ai.controller.ts b/apps/api/src/app/endpoints/ai/ai.controller.ts index 9691e211de..3c7f6661d7 100644 --- a/apps/api/src/app/endpoints/ai/ai.controller.ts +++ b/apps/api/src/app/endpoints/ai/ai.controller.ts @@ -1,11 +1,17 @@ import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; +import { Impersonation } from '@ghostfolio/api/decorators/impersonation.decorator'; +import { RequiresScope } from '@ghostfolio/api/decorators/requires-scope.decorator'; import { FilterDto } from '@ghostfolio/api/dtos/filter.dto'; -import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; 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 { AiPromptResponse } from '@ghostfolio/common/interfaces'; import { permissions } from '@ghostfolio/common/permissions'; -import type { AiPromptMode, RequestWithUser } from '@ghostfolio/common/types'; +import { scopes } from '@ghostfolio/common/scopes'; +import type { + AiPromptMode, + ImpersonationContext, + RequestWithUser +} from '@ghostfolio/common/types'; import { Controller, @@ -13,11 +19,9 @@ import { Inject, Param, Query, - UseGuards, UseInterceptors } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; -import { AuthGuard } from '@nestjs/passport'; import { AiService } from './ai.service'; @@ -31,9 +35,10 @@ export class AiController { @Get('prompt/:mode') @HasPermission(permissions.readAiPrompt) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + @RequiresScope(scopes.portfolioRead) @UseInterceptors(TransformDataSourceInRequestInterceptor) public async getPrompt( + @Impersonation() { userId, userSettings }: ImpersonationContext, @Param('mode') mode: AiPromptMode, @Query() { accounts, assetClasses, dataSource, symbol, tags }: FilterDto @@ -49,9 +54,9 @@ export class AiController { const prompt = await this.aiService.getPrompt({ filters, mode, + userId, languageCode: this.request.user.settings.settings.language, - userCurrency: this.request.user.settings.settings.baseCurrency, - userId: this.request.user.id + userCurrency: userSettings.baseCurrency }); return { prompt }; diff --git a/apps/api/src/app/endpoints/ai/ai.module.ts b/apps/api/src/app/endpoints/ai/ai.module.ts index f46ed1df88..756f6914fd 100644 --- a/apps/api/src/app/endpoints/ai/ai.module.ts +++ b/apps/api/src/app/endpoints/ai/ai.module.ts @@ -1,6 +1,7 @@ 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 { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module'; import { PortfolioTableModule } from '@ghostfolio/api/services/portfolio-table/portfolio-table.module'; import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; @@ -15,6 +16,7 @@ import { AiService } from './ai.service'; imports: [ ApiModule, ConfigurationModule, + ImpersonationModule, PortfolioTableModule, PropertyModule, TransformDataSourceInRequestModule