Browse Source

Merge branch 'main' into task/migrate-market-data-management-to-dedicated-routes

pull/7823/head
Thomas Kaul 3 days ago
committed by GitHub
parent
commit
398dd686f6
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      CHANGELOG.md
  2. 5
      apps/api/src/app/subscription/subscription.controller.ts
  3. 14
      apps/api/src/app/subscription/subscription.service.ts
  4. 2
      apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts
  5. 2
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
  6. 9
      libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html
  7. 4
      package-lock.json
  8. 2
      package.json

2
CHANGELOG.md

@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Migrated the asset profile dialogs of the market data management in the admin control panel to dedicated routes
## 3.67.0 - 2026-09-05
## 3.67.1 - 2026-09-05
### Added

5
apps/api/src/app/subscription/subscription.controller.ts

@ -1,4 +1,5 @@
import { AllowDuringImpersonation } from '@ghostfolio/api/decorators/allow-during-impersonation.decorator';
import { CustomThrottlerGuard } from '@ghostfolio/api/guards/custom-throttler.guard';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
@ -46,7 +47,7 @@ export class SubscriptionController {
@Post('redeem-coupon')
@HttpCode(StatusCodes.OK)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
@UseGuards(AuthGuard('jwt'), CustomThrottlerGuard, HasPermissionGuard)
public async redeemCoupon(@Body() { couponCode }: { couponCode: string }) {
if (!this.request.user) {
throw new HttpException(
@ -119,7 +120,7 @@ export class SubscriptionController {
}
@Post('stripe/checkout-session')
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
@UseGuards(AuthGuard('jwt'), CustomThrottlerGuard, HasPermissionGuard)
public async createStripeCheckoutSession(
@Body() { couponId, priceId }: { couponId?: string; priceId: string }
): Promise<CreateStripeCheckoutSessionResponse> {

14
apps/api/src/app/subscription/subscription.service.ts

@ -17,7 +17,7 @@ import {
UserWithSettings
} from '@ghostfolio/common/types';
import { Injectable, Logger } from '@nestjs/common';
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
import { Prisma, Subscription } from '@prisma/client';
import { addMilliseconds, isBefore } from 'date-fns';
import ms, { StringValue } from 'ms';
@ -64,6 +64,14 @@ export class SubscriptionService {
}
);
if (!subscriptionOffer) {
throw new BadRequestException('Invalid priceId');
}
if (couponId && couponId !== subscriptionOffer.couponId) {
throw new BadRequestException('Invalid couponId');
}
const stripeCheckoutSessionCreateParams: Stripe.Checkout.SessionCreateParams =
{
cancel_url: `${this.configurationService.get('ROOT_URL')}/${
@ -77,9 +85,7 @@ export class SubscriptionService {
}
],
locale: this.getStripeLocale(user.settings?.settings?.language),
metadata: subscriptionOffer
? { subscriptionOffer: JSON.stringify(subscriptionOffer) }
: {},
metadata: { subscriptionOffer: JSON.stringify(subscriptionOffer) },
mode: 'payment',
payment_method_types: ['card'],
success_url: `${this.configurationService.get(

2
apps/api/src/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor.ts

@ -70,6 +70,8 @@ export class TransformDataSourceInResponseInterceptor<
}
}
data.dataProviderInfo = undefined;
if (Object.keys(valueMap).length === 0) {
return data;
}

2
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html

@ -358,7 +358,7 @@
</form>
</div>
@if (dataProviderInfo) {
@if (dataProviderInfo?.name) {
<div class="col-md-12 mb-3 text-center">
<hr />
<gf-data-provider-credits

9
libs/ui/src/lib/data-provider-credits/data-provider-credits.component.html

@ -1,5 +1,5 @@
<small class="text-muted">
<ng-container i18n>Market data provided by</ng-container>&nbsp;
<ng-container i18n>Market data provided by</ng-container>{{ ' ' }}
@for (
dataProviderInfo of dataProviderInfos;
track dataProviderInfo;
@ -7,10 +7,7 @@
) {
<a target="_blank" [href]="dataProviderInfo.url">{{
dataProviderInfo.name
}}</a>
@if (!last) {
,&nbsp;
}
}}</a
>{{ last ? '.' : ', ' }}
}
.
</small>

4
package-lock.json

@ -1,12 +1,12 @@
{
"name": "ghostfolio",
"version": "3.67.0",
"version": "3.67.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ghostfolio",
"version": "3.67.0",
"version": "3.67.1",
"hasInstallScript": true,
"license": "AGPL-3.0",
"dependencies": {

2
package.json

@ -1,6 +1,6 @@
{
"name": "ghostfolio",
"version": "3.67.0",
"version": "3.67.1",
"homepage": "https://ghostfol.io",
"license": "AGPL-3.0",
"repository": "https://github.com/ghostfolio/ghostfolio",

Loading…
Cancel
Save