From 301565baca022b9f2a25038de7ce5fb1161b05fb Mon Sep 17 00:00:00 2001 From: nidhal karchoud <114624188+yar01110@users.noreply.github.com> Date: Mon, 28 Sep 2026 18:20:25 +0200 Subject: [PATCH 1/4] Task/migrate historical market data editor dialog from ngModel to form control (#7933) * Migrate from ngModel to form control * Update changelog --- CHANGELOG.md | 1 + ...cal-market-data-editor-dialog.component.ts | 25 ++++++++++---- .../historical-market-data-editor-dialog.html | 34 +++++++++---------- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46ffe1b2ec..c09e057b2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Extended the net performance on the analysis page to include the dividends (experimental) - Extended the net performance in the portfolio summary to include the dividends (experimental) - Improved the get quotes functionality of the _Manual_ service +- Migrated the historical market data editor dialog from `ngModel` to form control - Migrated the _ESLint_ configuration to the flat config format without `FlatCompat` - Upgraded `chartjs-chart-treemap` from version `4.2.0` to `4.2.2` diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts index 1b7b99fa21..17a5a5e612 100644 --- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts +++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts @@ -7,11 +7,15 @@ import { CUSTOM_ELEMENTS_SCHEMA, DestroyRef, OnInit, - inject, - signal + inject } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { + FormControl, + FormGroup, + ReactiveFormsModule, + Validators +} from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; @@ -33,7 +37,6 @@ import { HistoricalMarketDataEditorDialogParams } from './interfaces/interfaces' changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'h-100' }, imports: [ - FormsModule, IonIcon, MatButtonModule, MatDatepickerModule, @@ -51,7 +54,10 @@ export class GfHistoricalMarketDataEditorDialogComponent implements OnInit { public readonly data = inject(MAT_DIALOG_DATA); - protected readonly marketPrice = signal(this.data.marketPrice); + protected readonly historicalMarketDataForm = new FormGroup({ + date: new FormControl({ disabled: true, value: this.data.dateString }), + marketPrice: new FormControl(this.data.marketPrice, Validators.required) + }); private readonly destroyRef = inject(DestroyRef); private readonly locale = @@ -84,14 +90,19 @@ export class GfHistoricalMarketDataEditorDialogComponent implements OnInit { }) .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(({ marketPrice }) => { - this.marketPrice.set(marketPrice); + this.historicalMarketDataForm.controls.marketPrice.setValue( + marketPrice + ); + + this.historicalMarketDataForm.controls.marketPrice.markAsDirty(); this.changeDetectorRef.markForCheck(); }); } public onUpdate() { - const marketPrice = this.marketPrice(); + const marketPrice = + this.historicalMarketDataForm.controls.marketPrice.value; if (isNil(marketPrice)) { return; diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html index 7e81836646..6e52114058 100644 --- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html +++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1,16 +1,14 @@ -
+

Details for {{ data.symbol }}

Date - + Market Price - + {{ data.currency }}
- - +
From d1764863ffeb87dab38415dccd9470be8c262c1d Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 28 Sep 2026 18:28:33 +0200 Subject: [PATCH 2/4] Task/clean up ESLint configuration (#7963) Clean up ESLint configuration --- eslint.config.cjs | 9 +++------ nx.json | 1 + package-lock.json | 2 -- package.json | 2 -- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/eslint.config.cjs b/eslint.config.cjs index 9c1b2024b6..1b4aa6a0c0 100644 --- a/eslint.config.cjs +++ b/eslint.config.cjs @@ -1,6 +1,7 @@ const nxEslintPlugin = require('@nx/eslint-plugin'); const importPlugin = require('eslint-plugin-import'); const storybook = require('eslint-plugin-storybook'); +const { defineConfig } = require('eslint/config'); const typescriptEslint = require('typescript-eslint'); module.exports = [ @@ -25,14 +26,12 @@ module.exports = [ ], enforceBuildableLibDependency: true } - ], - '@typescript-eslint/no-extra-semi': 'error', - 'no-extra-semi': 'off' + ] } }, ...nxEslintPlugin.configs['flat/typescript'], ...nxEslintPlugin.configs['flat/javascript'], - ...typescriptEslint.config({ + ...defineConfig({ files: ['**/*.ts'], plugins: { import: importPlugin }, extends: [ @@ -91,8 +90,6 @@ module.exports = [ } ], '@typescript-eslint/unified-signatures': 'error', - '@typescript-eslint/no-loss-of-precision': 'warn', - '@typescript-eslint/no-var-requires': 'warn', 'arrow-body-style': 'off', 'constructor-super': 'error', eqeqeq: ['error', 'smart'], diff --git a/nx.json b/nx.json index 3b8c3846a1..e0a41e9835 100644 --- a/nx.json +++ b/nx.json @@ -98,6 +98,7 @@ "cache": true }, "lint": { + "inputs": ["default", "^default", "{workspaceRoot}/eslint.config.cjs"], "cache": true }, "@nx/jest:jest": { diff --git a/package-lock.json b/package-lock.json index c4896f0436..22665183a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -152,8 +152,6 @@ "@types/papaparse": "5.5.2", "@types/passport-google-oauth20": "2.0.17", "@types/passport-openidconnect": "0.1.3", - "@typescript-eslint/eslint-plugin": "8.67.0", - "@typescript-eslint/parser": "8.67.0", "eslint": "9.35.0", "eslint-config-prettier": "10.1.8", "eslint-plugin-import": "2.32.0", diff --git a/package.json b/package.json index 3361c354ba..755f661d28 100644 --- a/package.json +++ b/package.json @@ -196,8 +196,6 @@ "@types/papaparse": "5.5.2", "@types/passport-google-oauth20": "2.0.17", "@types/passport-openidconnect": "0.1.3", - "@typescript-eslint/eslint-plugin": "8.67.0", - "@typescript-eslint/parser": "8.67.0", "eslint": "9.35.0", "eslint-config-prettier": "10.1.8", "eslint-plugin-import": "2.32.0", From 68f99609f55b68c353114ee60c6e6240a7b8ed4b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 28 Sep 2026 20:16:55 +0200 Subject: [PATCH 3/4] Bugfix/OIDC discovery with trailing slash (#7886) * Fix OIDC discovery with trailing slash * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/auth/auth.module.ts | 9 ++++++++- apps/api/src/app/auth/oidc.helper.spec.ts | 20 ++++++++++++++++++++ apps/api/src/app/auth/oidc.helper.ts | 4 ++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 apps/api/src/app/auth/oidc.helper.spec.ts create mode 100644 apps/api/src/app/auth/oidc.helper.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index c09e057b2d..91586f2345 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed an issue where holdings without a quote have been valued at the unit price of the latest activity instead of the latest market price +- Fixed the discovery of the _OpenID Connect_ (`OIDC`) configuration for issuer URLs with a trailing slash (experimental) ## 3.74.0 - 2026-09-27 diff --git a/apps/api/src/app/auth/auth.module.ts b/apps/api/src/app/auth/auth.module.ts index e2a71ca843..879463cc13 100644 --- a/apps/api/src/app/auth/auth.module.ts +++ b/apps/api/src/app/auth/auth.module.ts @@ -22,6 +22,7 @@ import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; import { GoogleStrategy } from './google.strategy'; import { JwtStrategy } from './jwt.strategy'; +import { getOidcDiscoveryUrl } from './oidc.helper'; import { OidcStrategy } from './oidc.strategy'; @Module({ @@ -94,9 +95,15 @@ import { OidcStrategy } from './oidc.strategy'; // Fetch OIDC configuration from discovery endpoint try { const response = await fetchService.fetch( - `${issuer}/.well-known/openid-configuration` + getOidcDiscoveryUrl(issuer) ); + if (!response.ok) { + throw new Error( + `OIDC discovery request failed with status ${response.status}` + ); + } + const config = (await response.json()) as { authorization_endpoint: string; token_endpoint: string; diff --git a/apps/api/src/app/auth/oidc.helper.spec.ts b/apps/api/src/app/auth/oidc.helper.spec.ts new file mode 100644 index 0000000000..9234f12c95 --- /dev/null +++ b/apps/api/src/app/auth/oidc.helper.spec.ts @@ -0,0 +1,20 @@ +import { getOidcDiscoveryUrl } from './oidc.helper'; + +describe('getOidcDiscoveryUrl', () => { + it.each([ + [ + 'https://auth.example.com', + 'https://auth.example.com/.well-known/openid-configuration' + ], + [ + 'https://auth.example.com/', + 'https://auth.example.com/.well-known/openid-configuration' + ], + [ + 'https://auth.example.com/application/o/ghostfolio/', + 'https://auth.example.com/application/o/ghostfolio/.well-known/openid-configuration' + ] + ])('creates the discovery URL for %s', (issuer, expected) => { + expect(getOidcDiscoveryUrl(issuer)).toBe(expected); + }); +}); diff --git a/apps/api/src/app/auth/oidc.helper.ts b/apps/api/src/app/auth/oidc.helper.ts new file mode 100644 index 0000000000..4e8de829fc --- /dev/null +++ b/apps/api/src/app/auth/oidc.helper.ts @@ -0,0 +1,4 @@ +export function getOidcDiscoveryUrl(issuer: string) { + // Remove trailing slashes + return `${issuer.replace(/\/+$/, '')}/.well-known/openid-configuration`; +} From bf96d35b5e3932d3e62382b6a1f1791d7b13d3d1 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 28 Sep 2026 20:19:14 +0200 Subject: [PATCH 4/4] Release 3.75.0 (#7968) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91586f2345..e795778177 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 3.75.0 - 2026-09-28 ### Changed diff --git a/package-lock.json b/package-lock.json index 22665183a4..3f8ee0f880 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "3.74.0", + "version": "3.75.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "3.74.0", + "version": "3.75.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 755f661d28..a3f94b74b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "3.74.0", + "version": "3.75.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio",