Browse Source

Task/deprecate auth device and exchange rate endpoints (#8256)

* Deprecate auth device and exchange rate endpoints

* Update changelog
pull/8258/head^2
Thomas Kaul 3 days ago
committed by GitHub
parent
commit
f144c723f4
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      CHANGELOG.md
  2. 16
      apps/api/src/app/__snapshots__/app.module.spec.ts.snap
  3. 8
      apps/api/src/app/app.module.ts
  4. 19
      apps/api/src/app/auth-device/auth-device.module.ts
  5. 4
      apps/api/src/app/auth/auth.module.ts
  6. 2
      apps/api/src/app/auth/web-auth.service.ts
  7. 10
      apps/api/src/app/endpoints/auth-devices/auth-devices.controller.ts
  8. 11
      apps/api/src/app/endpoints/auth-devices/auth-devices.module.ts
  9. 18
      apps/api/src/app/endpoints/exchange-rates/exchange-rates.controller.ts
  10. 13
      apps/api/src/app/endpoints/exchange-rates/exchange-rates.module.ts
  11. 2
      apps/api/src/app/endpoints/exchange-rates/exchange-rates.service.ts
  12. 14
      apps/api/src/app/exchange-rate/exchange-rate.module.ts
  13. 12
      apps/api/src/services/auth-device/auth-device.module.ts
  14. 0
      apps/api/src/services/auth-device/auth-device.service.ts
  15. 2
      apps/client/src/app/services/web-authn.service.ts
  16. 2
      libs/common/src/lib/interfaces/index.ts
  17. 3
      libs/common/src/lib/interfaces/responses/exchange-rate-response.interface.ts

2
CHANGELOG.md

@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Deprecated the `api/v1/auth-device` endpoint in favor of the `api/v1/auth-devices` endpoint
- Deprecated the `api/v1/exchange-rate` endpoint in favor of the `api/v1/exchange-rates` endpoint
- Upgraded `@modelcontextprotocol/core` and `@modelcontextprotocol/server` from version `2.0.0` to `2.3.1`
- Upgraded `@modelcontextprotocol/node` from version `2.0.0` to `2.1.1`
- Upgraded `@rekog/mcp-nest` from version `2.0.7` to `2.0.8`

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

@ -116,6 +116,15 @@ exports[`AppModule should keep the security of each route 1`] = `
"interceptors": [],
"permission": "deleteAuthDevice",
},
"DELETE /auth-devices/:id": {
"allowDuringImpersonation": true,
"guards": [
"AuthGuard('jwt')",
"HasPermissionGuard",
],
"interceptors": [],
"permission": "deleteAuthDevice",
},
"DELETE /benchmarks/:dataSource/:symbol": {
"allowDuringImpersonation": true,
"guards": [
@ -489,6 +498,13 @@ exports[`AppModule should keep the security of each route 1`] = `
],
"interceptors": [],
},
"GET /exchange-rates/:symbol/:dateString": {
"guards": [
"AuthGuard('jwt')",
"HasPermissionGuard",
],
"interceptors": [],
},
"GET /export": {
"guards": [
"AuthGuard('jwt')",

8
apps/api/src/app/app.module.ts

@ -41,15 +41,16 @@ import { ActivitiesModule } from './activities/activities.module';
import { AdminModule } from './admin/admin.module';
import { AppController } from './app.controller';
import { AssetModule } from './asset/asset.module';
import { AuthDeviceModule } from './auth-device/auth-device.module';
import { AuthModule } from './auth/auth.module';
import { CacheModule } from './cache/cache.module';
import { AiModule } from './endpoints/ai/ai.module';
import { ApiKeysModule } from './endpoints/api-keys/api-keys.module';
import { AssetProfilesModule } from './endpoints/asset-profiles/asset-profiles.module';
import { AssetsModule } from './endpoints/assets/assets.module';
import { AuthDevicesModule } from './endpoints/auth-devices/auth-devices.module';
import { BenchmarksModule } from './endpoints/benchmarks/benchmarks.module';
import { GhostfolioModule } from './endpoints/data-providers/ghostfolio/ghostfolio.module';
import { ExchangeRatesModule } from './endpoints/exchange-rates/exchange-rates.module';
import { MarketDataModule } from './endpoints/market-data/market-data.module';
import { McpModule } from './endpoints/mcp/mcp.module';
import { PlatformsModule } from './endpoints/platforms/platforms.module';
@ -57,7 +58,6 @@ import { PublicModule } from './endpoints/public/public.module';
import { SitemapModule } from './endpoints/sitemap/sitemap.module';
import { TagsModule } from './endpoints/tags/tags.module';
import { WatchlistModule } from './endpoints/watchlist/watchlist.module';
import { ExchangeRateModule } from './exchange-rate/exchange-rate.module';
import { ExportModule } from './export/export.module';
import { HealthModule } from './health/health.module';
import { ImportModule } from './import/import.module';
@ -80,7 +80,7 @@ import { UserModule } from './user/user.module';
AssetProfilesModule,
AssetModule,
AssetsModule,
AuthDeviceModule,
AuthDevicesModule,
AuthModule,
BenchmarksModule,
BullBoardModule.forRoot({
@ -119,8 +119,8 @@ import { UserModule } from './user/user.module';
DataProviderModule,
EventEmitterModule.forRoot(),
EventsModule,
ExchangeRateModule,
ExchangeRateDataModule,
ExchangeRatesModule,
ExportModule,
GhostfolioModule,
HealthModule,

19
apps/api/src/app/auth-device/auth-device.module.ts

@ -1,19 +0,0 @@
import { AuthDeviceController } from '@ghostfolio/api/app/auth-device/auth-device.controller';
import { AuthDeviceService } from '@ghostfolio/api/app/auth-device/auth-device.service';
import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module';
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
@Module({
controllers: [AuthDeviceController],
imports: [
JwtModule.register({
secret: process.env.JWT_SECRET_KEY,
signOptions: { expiresIn: '180 days' }
}),
PrismaModule
],
providers: [AuthDeviceService]
})
export class AuthDeviceModule {}

4
apps/api/src/app/auth/auth.module.ts

@ -1,9 +1,9 @@
import { AuthDeviceService } from '@ghostfolio/api/app/auth-device/auth-device.service';
import { WebAuthService } from '@ghostfolio/api/app/auth/web-auth.service';
import { SubscriptionModule } from '@ghostfolio/api/app/subscription/subscription.module';
import { UserModule } from '@ghostfolio/api/app/user/user.module';
import { ApiKeyService } from '@ghostfolio/api/services/api-key/api-key.service';
import { ApiModule } from '@ghostfolio/api/services/api/api.module';
import { AuthDeviceModule } from '@ghostfolio/api/services/auth-device/auth-device.module';
import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { FetchModule } from '@ghostfolio/api/services/fetch/fetch.module';
@ -29,6 +29,7 @@ import { OidcStrategy } from './oidc.strategy';
controllers: [AuthController],
imports: [
ApiModule,
AuthDeviceModule,
ConfigurationModule,
FetchModule,
JwtModule.register({
@ -45,7 +46,6 @@ import { OidcStrategy } from './oidc.strategy';
providers: [
ApiKeyService,
ApiKeyStrategy,
AuthDeviceService,
AuthService,
GoogleStrategy,
JwtStrategy,

2
apps/api/src/app/auth/web-auth.service.ts

@ -1,7 +1,7 @@
import { AuthDeviceService } from '@ghostfolio/api/app/auth-device/auth-device.service';
import { PortfolioSnapshotValue } from '@ghostfolio/api/app/portfolio/interfaces/snapshot-value.interface';
import { UserService } from '@ghostfolio/api/app/user/user.service';
import { ApiService } from '@ghostfolio/api/services/api/api.service';
import { AuthDeviceService } from '@ghostfolio/api/services/auth-device/auth-device.service';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
import { RedisCacheService } from '@ghostfolio/api/services/redis-cache/redis-cache.service';

10
apps/api/src/app/auth-device/auth-device.controller.ts → apps/api/src/app/endpoints/auth-devices/auth-devices.controller.ts

@ -1,7 +1,7 @@
import { AuthDeviceService } from '@ghostfolio/api/app/auth-device/auth-device.service';
import { AllowDuringImpersonation } from '@ghostfolio/api/decorators/allow-during-impersonation.decorator';
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { AuthDeviceService } from '@ghostfolio/api/services/auth-device/auth-device.service';
import { permissions } from '@ghostfolio/common/permissions';
import type { RequestWithUser } from '@ghostfolio/common/types';
@ -18,8 +18,12 @@ import { AuthGuard } from '@nestjs/passport';
import { getReasonPhrase, StatusCodes } from 'http-status-codes';
@AllowDuringImpersonation()
@Controller('auth-device')
export class AuthDeviceController {
@Controller([
'auth-devices',
/** @deprecated */
'auth-device'
])
export class AuthDevicesController {
public constructor(
private readonly authDeviceService: AuthDeviceService,
@Inject(REQUEST) private readonly request: RequestWithUser

11
apps/api/src/app/endpoints/auth-devices/auth-devices.module.ts

@ -0,0 +1,11 @@
import { AuthDeviceModule } from '@ghostfolio/api/services/auth-device/auth-device.module';
import { Module } from '@nestjs/common';
import { AuthDevicesController } from './auth-devices.controller';
@Module({
controllers: [AuthDevicesController],
imports: [AuthDeviceModule]
})
export class AuthDevicesModule {}

18
apps/api/src/app/exchange-rate/exchange-rate.controller.ts → apps/api/src/app/endpoints/exchange-rates/exchange-rates.controller.ts

@ -1,5 +1,5 @@
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { DataProviderHistoricalResponse } from '@ghostfolio/common/interfaces';
import { ExchangeRateResponse } from '@ghostfolio/common/interfaces';
import {
Controller,
@ -12,12 +12,16 @@ import { AuthGuard } from '@nestjs/passport';
import { parseISO } from 'date-fns';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { ExchangeRateService } from './exchange-rate.service';
import { ExchangeRatesService } from './exchange-rates.service';
@Controller('exchange-rate')
export class ExchangeRateController {
@Controller([
'exchange-rates',
/** @deprecated */
'exchange-rate'
])
export class ExchangeRatesController {
public constructor(
private readonly exchangeRateService: ExchangeRateService
private readonly exchangeRatesService: ExchangeRatesService
) {}
@Get(':symbol/:dateString')
@ -25,10 +29,10 @@ export class ExchangeRateController {
public async getExchangeRate(
@Param('dateString') dateString: string,
@Param('symbol') symbol: string
): Promise<DataProviderHistoricalResponse> {
): Promise<ExchangeRateResponse> {
const date = parseISO(dateString);
const exchangeRate = await this.exchangeRateService.getExchangeRate({
const exchangeRate = await this.exchangeRatesService.getExchangeRate({
date,
symbol
});

13
apps/api/src/app/endpoints/exchange-rates/exchange-rates.module.ts

@ -0,0 +1,13 @@
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module';
import { Module } from '@nestjs/common';
import { ExchangeRatesController } from './exchange-rates.controller';
import { ExchangeRatesService } from './exchange-rates.service';
@Module({
controllers: [ExchangeRatesController],
imports: [ExchangeRateDataModule],
providers: [ExchangeRatesService]
})
export class ExchangeRatesModule {}

2
apps/api/src/app/exchange-rate/exchange-rate.service.ts → apps/api/src/app/endpoints/exchange-rates/exchange-rates.service.ts

@ -3,7 +3,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
import { Injectable } from '@nestjs/common';
@Injectable()
export class ExchangeRateService {
export class ExchangeRatesService {
public constructor(
private readonly exchangeRateDataService: ExchangeRateDataService
) {}

14
apps/api/src/app/exchange-rate/exchange-rate.module.ts

@ -1,14 +0,0 @@
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module';
import { Module } from '@nestjs/common';
import { ExchangeRateController } from './exchange-rate.controller';
import { ExchangeRateService } from './exchange-rate.service';
@Module({
controllers: [ExchangeRateController],
exports: [ExchangeRateService],
imports: [ExchangeRateDataModule],
providers: [ExchangeRateService]
})
export class ExchangeRateModule {}

12
apps/api/src/services/auth-device/auth-device.module.ts

@ -0,0 +1,12 @@
import { PrismaModule } from '@ghostfolio/api/services/prisma/prisma.module';
import { Module } from '@nestjs/common';
import { AuthDeviceService } from './auth-device.service';
@Module({
exports: [AuthDeviceService],
imports: [PrismaModule],
providers: [AuthDeviceService]
})
export class AuthDeviceModule {}

0
apps/api/src/app/auth-device/auth-device.service.ts → apps/api/src/services/auth-device/auth-device.service.ts

2
apps/client/src/app/services/web-authn.service.ts

@ -66,7 +66,7 @@ export class WebAuthnService {
const deviceId = this.getDeviceId();
return this.http
.delete<AuthDeviceDto>(`/api/v1/auth-device/${deviceId}`)
.delete<AuthDeviceDto>(`/api/v1/auth-devices/${deviceId}`)
.pipe(
catchError((error) => {
console.warn(`Could not deregister device ${deviceId}`, error);

2
libs/common/src/lib/interfaces/index.ts

@ -67,6 +67,7 @@ import type {
} from './responses/data-provider-response.interface';
import type { DividendsResponse } from './responses/dividends-response.interface';
import type { ResponseError } from './responses/errors.interface';
import type { ExchangeRateResponse } from './responses/exchange-rate-response.interface';
import type { ExportResponse } from './responses/export-response.interface';
import type { HistoricalResponse } from './responses/historical-response.interface';
import type { ImportResponse } from './responses/import-response.interface';
@ -150,6 +151,7 @@ export {
DataProviderResponse,
DividendsResponse,
EnhancedAssetProfile,
ExchangeRateResponse,
ExportResponse,
Filter,
FilterGroup,

3
libs/common/src/lib/interfaces/responses/exchange-rate-response.interface.ts

@ -0,0 +1,3 @@
export interface ExchangeRateResponse {
marketPrice: number;
}
Loading…
Cancel
Save