From 46d060df1b85b5faedf960ea829c887d82dafd26 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 14 Sep 2026 20:12:21 +0200 Subject: [PATCH 1/4] Bugfix/coupon validation in Stripe checkout session (#7877) Fix coupon validation --- .../api/src/app/subscription/subscription.service.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/api/src/app/subscription/subscription.service.ts b/apps/api/src/app/subscription/subscription.service.ts index 312b8c3aef..f5acbc3e33 100644 --- a/apps/api/src/app/subscription/subscription.service.ts +++ b/apps/api/src/app/subscription/subscription.service.ts @@ -58,17 +58,23 @@ export class SubscriptionService { } = (await this.propertyService.getByKey(PROPERTY_STRIPE_CONFIG)) ?? {}; - const subscriptionOffer = Object.values(subscriptionOffers).find( + const subscriptionOffersForPrice = Object.values(subscriptionOffers).filter( (subscriptionOffer) => { return subscriptionOffer.priceId === priceId; } ); - if (!subscriptionOffer) { + if (subscriptionOffersForPrice.length === 0) { throw new BadRequestException('Invalid priceId'); } - if (couponId && couponId !== subscriptionOffer.couponId) { + const subscriptionOffer = subscriptionOffersForPrice.find( + (subscriptionOffer) => { + return subscriptionOffer.couponId === couponId; + } + ); + + if (!subscriptionOffer) { throw new BadRequestException('Invalid couponId'); } From d27e4de4180c49c6afde055b55f6415a9426a843 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 14 Sep 2026 20:20:37 +0200 Subject: [PATCH 2/4] Task/improve simplified mode in holdings table (#7875) * Improve simplified mode * Update changelog --- CHANGELOG.md | 1 + .../holdings-table.component.html | 31 +++++++++++++++---- .../holdings-table.component.scss | 13 ++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d6779c4c1..ca0d05c146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the style of the activity type filter on the activities page (experimental) - Improved the style of the no activities info component - Improved the style of the selector in the benchmark comparator +- Improved the responsive layout of the holdings table in simplified mode - Improved the language localization for Chinese (`zh`) - Improved the language localization for German (`de`) - Upgraded `@codewithdan/observable-store` from version `2.2.15` to `3.0.0` diff --git a/libs/ui/src/lib/holdings-table/holdings-table.component.html b/libs/ui/src/lib/holdings-table/holdings-table.component.html index 5bc76f646e..69be6f8961 100644 --- a/libs/ui/src/lib/holdings-table/holdings-table.component.html +++ b/libs/ui/src/lib/holdings-table/holdings-table.component.html @@ -3,13 +3,19 @@ class="gf-table w-100" mat-table matSort + [class.simple]="mode() === 'simple'" [dataSource]="dataSource" [matSortActive]="sortActive()" [matSortDirection]="sortDirection()" > - + - + Name - -
+ +
{{ element.assetProfile.name }} @if (element.assetProfile.name === element.assetProfile.symbol) { ({{ element.assetProfile.assetSubClassLabel }}) @@ -160,7 +171,10 @@ - + Performance ± - +
Date: Mon, 14 Sep 2026 23:51:47 +0530 Subject: [PATCH 3/4] Bugfix/harden authentication with OIDC (#7797) * Harden authentication with OIDC * Update changelog --------- Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> --- CHANGELOG.md | 4 ++++ apps/api/src/app/auth/oidc-state.store.ts | 20 ++++++++++++-------- apps/api/src/guards/oauth-callback.guard.ts | 10 +++++++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca0d05c146..8f44c21fe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgraded `papaparse` from version `5.5.3` to `5.7.0` - Upgraded `zone.js` from version `0.16.2` to `0.16.3` +### Fixed + +- Hardened the authentication with _OpenID Connect_ (`OIDC`) (experimental) + ## 3.69.0 - 2026-09-07 ### Changed diff --git a/apps/api/src/app/auth/oidc-state.store.ts b/apps/api/src/app/auth/oidc-state.store.ts index aebd99892f..0131d184d3 100644 --- a/apps/api/src/app/auth/oidc-state.store.ts +++ b/apps/api/src/app/auth/oidc-state.store.ts @@ -1,5 +1,6 @@ import type { Request } from 'express'; import ms from 'ms'; +import { randomBytes } from 'node:crypto'; import type { SessionStore, SessionStoreCallback, @@ -66,13 +67,20 @@ export class OidcStateStore implements SessionStore { const data = this.stateMap.get(handle); if (!data) { - return callback(null, undefined, undefined); + return callback( + new Error('Invalid OIDC state parameter'), + undefined, + undefined + ); } if (Date.now() - data.timestamp > this.STATE_EXPIRY_MS) { - // State has expired this.stateMap.delete(handle); - return callback(null, undefined, undefined); + return callback( + new Error('OIDC state has expired, please try again'), + undefined, + undefined + ); } // Remove state after verification (one-time use) @@ -106,10 +114,6 @@ export class OidcStateStore implements SessionStore { * Generate a cryptographically secure random handle */ private generateHandle() { - return ( - Math.random().toString(36).substring(2, 15) + - Math.random().toString(36).substring(2, 15) + - Date.now().toString(36) - ); + return randomBytes(32).toString('hex'); } } diff --git a/apps/api/src/guards/oauth-callback.guard.ts b/apps/api/src/guards/oauth-callback.guard.ts index cedbccde12..a89d77daa0 100644 --- a/apps/api/src/guards/oauth-callback.guard.ts +++ b/apps/api/src/guards/oauth-callback.guard.ts @@ -5,11 +5,19 @@ export function OAuthCallbackGuard(strategy: string): Type { class OAuthCallbackGuardMixin extends AuthGuard(strategy) { private readonly logger = new Logger(OAuthCallbackGuard.name); - public override handleRequest(error: Error, user: any) { + public override handleRequest( + error: Error | null, + user: any, + info?: { message?: string } + ) { if (error) { this.logger.error( `Authentication with the ${strategy} strategy has failed: ${error.message}` ); + } else if (!user && info?.message) { + this.logger.warn( + `Authentication with the ${strategy} strategy was rejected: ${info.message}` + ); } // Do not throw, the callback handler redirects to the login page instead From 02e74d6e1dfdc77d51a1c971f734ce0b59501885 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 14 Sep 2026 20:23:41 +0200 Subject: [PATCH 4/4] Release 3.70.1 (#7878) --- 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 8f44c21fe8..1437d1bdaf 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). -## 3.70.0 - 2026-09-14 +## 3.70.1 - 2026-09-14 ### Added diff --git a/package-lock.json b/package-lock.json index ebf42dac50..69a7496f86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "3.70.0", + "version": "3.70.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "3.70.0", + "version": "3.70.1", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 7ac8ab8613..830a4f8b79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "3.70.0", + "version": "3.70.1", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio",