Browse Source

Restrict asset endpoint to authenticated users

pull/8270/head
Thomas Kaul 2 days ago
parent
commit
dcb7cf1ef1
  1. 4
      apps/api/src/app/__snapshots__/app.module.spec.ts.snap
  2. 1
      apps/api/src/app/app.module.spec.ts
  3. 10
      apps/api/src/app/endpoints/asset-profiles/asset.controller.ts
  4. 1
      apps/client/src/app/components/markets/markets.html
  5. 2
      libs/ui/src/lib/benchmark/benchmark.component.html
  6. 19
      libs/ui/src/lib/benchmark/benchmark.component.ts

4
apps/api/src/app/__snapshots__/app.module.spec.ts.snap

@ -366,7 +366,9 @@ exports[`AppModule should keep the security of each route 1`] = `
],
},
"GET /asset/:dataSource/:symbol": {
"guards": [],
"guards": [
"AuthGuard('jwt')",
],
"interceptors": [
"TransformDataSourceInResponseInterceptor",
"TransformDataSourceInRequestInterceptor",

1
apps/api/src/app/app.module.spec.ts

@ -52,7 +52,6 @@ const AUTHENTICATION_STRATEGIES = ['api-key', 'google', 'jwt', 'oidc'];
* are not served by a controller
*/
const PUBLIC_ROUTES = [
'GET /asset/:dataSource/:symbol',
'GET /assets/:languageCode/site.webmanifest',
'GET /auth/google',
'GET /auth/google/callback',

10
apps/api/src/app/endpoints/asset-profiles/asset.controller.ts

@ -2,7 +2,14 @@ import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interce
import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.interceptor';
import type { AssetResponse } from '@ghostfolio/common/interfaces';
import { Controller, Get, Param, UseInterceptors } from '@nestjs/common';
import {
Controller,
Get,
Param,
UseGuards,
UseInterceptors
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { DataSource } from '@prisma/client';
import { pick } from 'lodash-es';
@ -15,6 +22,7 @@ export class AssetController {
) {}
@Get(':dataSource/:symbol')
@UseGuards(AuthGuard('jwt'))
@UseInterceptors(TransformDataSourceInRequestInterceptor)
@UseInterceptors(TransformDataSourceInResponseInterceptor)
public async getAsset(

1
apps/client/src/app/components/markets/markets.html

@ -52,6 +52,7 @@
<gf-benchmark
[benchmarks]="benchmarks()"
[deviceType]="deviceType()"
[hasPermissionToOpenDetails]="!!user"
[locale]="user?.settings?.locale ?? DEFAULT_LOCALE"
[showSymbol]="false"
[user]="user"

2
libs/ui/src/lib/benchmark/benchmark.component.html

@ -200,8 +200,8 @@
<tr *matHeaderRowDef="displayedColumns()" mat-header-row></tr>
<tr
*matRowDef="let row; columns: displayedColumns()"
class="cursor-pointer"
mat-row
[class.cursor-pointer]="hasPermissionToOpenDetails()"
(click)="
onOpenBenchmarkDialog({
dataSource: row.dataSource,

19
libs/ui/src/lib/benchmark/benchmark.component.ts

@ -16,6 +16,7 @@ import {
ChangeDetectionStrategy,
Component,
DestroyRef,
OnInit,
computed,
effect,
inject,
@ -62,10 +63,11 @@ import { BenchmarkDetailDialogParams } from './benchmark-detail-dialog/interface
styleUrls: ['./benchmark.component.scss'],
templateUrl: './benchmark.component.html'
})
export class GfBenchmarkComponent {
export class GfBenchmarkComponent implements OnInit {
public readonly benchmarks = input<Benchmark[]>();
public readonly deviceType = input.required<string>();
public readonly hasPermissionToDeleteItem = input<boolean>();
public readonly hasPermissionToOpenDetails = input(true);
public readonly locale = input(getLocale());
public readonly showIcon = input(false);
public readonly showSymbol = input(true);
@ -120,10 +122,15 @@ export class GfBenchmarkComponent {
}
});
addIcons({ ellipsisHorizontal, trashOutline });
}
public ngOnInit() {
this.route.queryParams
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((params) => {
if (
this.hasPermissionToOpenDetails() &&
params['benchmarkDetailDialog'] &&
params['dataSource'] &&
params['symbol']
@ -134,8 +141,6 @@ export class GfBenchmarkComponent {
});
}
});
addIcons({ ellipsisHorizontal, trashOutline });
}
protected onDeleteItem({ dataSource, symbol }: AssetProfileIdentifier) {
@ -152,9 +157,11 @@ export class GfBenchmarkComponent {
dataSource,
symbol
}: AssetProfileIdentifier) {
this.router.navigate([], {
queryParams: { dataSource, symbol, benchmarkDetailDialog: true }
});
if (this.hasPermissionToOpenDetails()) {
this.router.navigate([], {
queryParams: { dataSource, symbol, benchmarkDetailDialog: true }
});
}
}
private openBenchmarkDetailDialog({

Loading…
Cancel
Save