Browse Source

Extend permissions

pull/4125/head
Thomas Kaul 8 months ago
parent
commit
60253c3a3b
  1. 72
      apps/api/src/app/endpoints/market-data/market-data.controller.ts
  2. 3
      apps/api/src/app/endpoints/market-data/market-data.module.ts
  3. 3
      apps/api/src/app/import/import.service.ts
  4. 1
      libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts
  5. 9
      libs/common/src/lib/permissions.ts

72
apps/api/src/app/endpoints/market-data/market-data.controller.ts

@ -1,5 +1,6 @@
import { AdminService } from '@ghostfolio/api/app/admin/admin.service'; import { AdminService } from '@ghostfolio/api/app/admin/admin.service';
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service';
import { MarketDataDetailsResponse } from '@ghostfolio/common/interfaces'; import { MarketDataDetailsResponse } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { RequestWithUser } from '@ghostfolio/common/types'; import { RequestWithUser } from '@ghostfolio/common/types';
@ -27,7 +28,8 @@ export class MarketDataController {
public constructor( public constructor(
private readonly adminService: AdminService, private readonly adminService: AdminService,
private readonly marketDataService: MarketDataService, private readonly marketDataService: MarketDataService,
@Inject(REQUEST) private readonly request: RequestWithUser @Inject(REQUEST) private readonly request: RequestWithUser,
private readonly symbolProfileService: SymbolProfileService
) {} ) {}
@Get(':dataSource/:symbol') @Get(':dataSource/:symbol')
@ -36,12 +38,35 @@ export class MarketDataController {
@Param('dataSource') dataSource: DataSource, @Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string @Param('symbol') symbol: string
): Promise<MarketDataDetailsResponse> { ): Promise<MarketDataDetailsResponse> {
if ( const [assetProfile] = await this.symbolProfileService.getSymbolProfiles([
!hasPermission(this.request.user.permissions, permissions.readMarketData) { dataSource, symbol }
) { ]);
if (!assetProfile) {
throw new HttpException( throw new HttpException(
getReasonPhrase(StatusCodes.FORBIDDEN), getReasonPhrase(StatusCodes.NOT_FOUND),
StatusCodes.FORBIDDEN StatusCodes.NOT_FOUND
);
}
const canReadAllAssetProfiles = hasPermission(
this.request.user.permissions,
permissions.readMarketData
);
const canReadOwnAssetProfile =
assetProfile.userId === this.request.user.id &&
hasPermission(
this.request.user.permissions,
permissions.readMarketDataOfOwnAssetProfile
);
if (!canReadAllAssetProfiles && !canReadOwnAssetProfile) {
throw new HttpException(
assetProfile.userId
? getReasonPhrase(StatusCodes.NOT_FOUND)
: getReasonPhrase(StatusCodes.FORBIDDEN),
assetProfile.userId ? StatusCodes.NOT_FOUND : StatusCodes.FORBIDDEN
); );
} }
@ -55,16 +80,39 @@ export class MarketDataController {
@Param('dataSource') dataSource: DataSource, @Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string @Param('symbol') symbol: string
) { ) {
if ( const [assetProfile] = await this.symbolProfileService.getSymbolProfiles([
!hasPermission( { dataSource, symbol }
]);
if (!assetProfile) {
throw new HttpException(
getReasonPhrase(StatusCodes.NOT_FOUND),
StatusCodes.NOT_FOUND
);
}
const canUpsertAllAssetProfiles =
hasPermission(
this.request.user.permissions, this.request.user.permissions,
permissions.createMarketData permissions.createMarketData
) || ) &&
!hasPermission( hasPermission(
this.request.user.permissions, this.request.user.permissions,
permissions.updateMarketData permissions.updateMarketData
) );
) {
const canUpsertOwnAssetProfile =
assetProfile.userId === this.request.user.id &&
hasPermission(
this.request.user.permissions,
permissions.createMarketDataOfOwnAssetProfile
) &&
hasPermission(
this.request.user.permissions,
permissions.updateMarketDataOfOwnAssetProfile
);
if (!canUpsertAllAssetProfiles && !canUpsertOwnAssetProfile) {
throw new HttpException( throw new HttpException(
getReasonPhrase(StatusCodes.FORBIDDEN), getReasonPhrase(StatusCodes.FORBIDDEN),
StatusCodes.FORBIDDEN StatusCodes.FORBIDDEN

3
apps/api/src/app/endpoints/market-data/market-data.module.ts

@ -1,5 +1,6 @@
import { AdminModule } from '@ghostfolio/api/app/admin/admin.module'; import { AdminModule } from '@ghostfolio/api/app/admin/admin.module';
import { MarketDataModule as MarketDataServiceModule } from '@ghostfolio/api/services/market-data/market-data.module'; import { MarketDataModule as MarketDataServiceModule } from '@ghostfolio/api/services/market-data/market-data.module';
import { SymbolProfileModule } from '@ghostfolio/api/services/symbol-profile/symbol-profile.module';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
@ -7,6 +8,6 @@ import { MarketDataController } from './market-data.controller';
@Module({ @Module({
controllers: [MarketDataController], controllers: [MarketDataController],
imports: [AdminModule, MarketDataServiceModule] imports: [AdminModule, MarketDataServiceModule, SymbolProfileModule]
}) })
export class MarketDataModule {} export class MarketDataModule {}

3
apps/api/src/app/import/import.service.ts

@ -551,7 +551,8 @@ export class ImportService {
holdings: undefined, holdings: undefined,
id: undefined, id: undefined,
sectors: undefined, sectors: undefined,
updatedAt: undefined updatedAt: undefined,
userId: undefined
} }
}; };
} }

1
libs/common/src/lib/interfaces/enhanced-symbol-profile.interface.ts

@ -30,4 +30,5 @@ export interface EnhancedSymbolProfile {
symbolMapping?: { [key: string]: string }; symbolMapping?: { [key: string]: string };
updatedAt: Date; updatedAt: Date;
url?: string; url?: string;
userId?: string;
} }

9
libs/common/src/lib/permissions.ts

@ -11,6 +11,7 @@ export const permissions = {
createAccountBalance: 'createAccountBalance', createAccountBalance: 'createAccountBalance',
createApiKey: 'createApiKey', createApiKey: 'createApiKey',
createMarketData: 'createMarketData', createMarketData: 'createMarketData',
createMarketDataOfOwnAssetProfile: 'createMarketDataOfOwnAssetProfile',
createOrder: 'createOrder', createOrder: 'createOrder',
createPlatform: 'createPlatform', createPlatform: 'createPlatform',
createTag: 'createTag', createTag: 'createTag',
@ -35,6 +36,7 @@ export const permissions = {
enableSystemMessage: 'enableSystemMessage', enableSystemMessage: 'enableSystemMessage',
impersonateAllUsers: 'impersonateAllUsers', impersonateAllUsers: 'impersonateAllUsers',
readMarketData: 'readMarketData', readMarketData: 'readMarketData',
readMarketDataOfOwnAssetProfile: 'readMarketDataOfOwnAssetProfile',
readPlatforms: 'readPlatforms', readPlatforms: 'readPlatforms',
readTags: 'readTags', readTags: 'readTags',
reportDataGlitch: 'reportDataGlitch', reportDataGlitch: 'reportDataGlitch',
@ -42,6 +44,7 @@ export const permissions = {
updateAccount: 'updateAccount', updateAccount: 'updateAccount',
updateAuthDevice: 'updateAuthDevice', updateAuthDevice: 'updateAuthDevice',
updateMarketData: 'updateMarketData', updateMarketData: 'updateMarketData',
updateMarketDataOfOwnAssetProfile: 'updateMarketDataOfOwnAssetProfile',
updateOrder: 'updateOrder', updateOrder: 'updateOrder',
updatePlatform: 'updatePlatform', updatePlatform: 'updatePlatform',
updateTag: 'updateTag', updateTag: 'updateTag',
@ -61,6 +64,7 @@ export function getPermissions(aRole: Role): string[] {
permissions.createAccountBalance, permissions.createAccountBalance,
permissions.deleteAccountBalance, permissions.deleteAccountBalance,
permissions.createMarketData, permissions.createMarketData,
permissions.createMarketDataOfOwnAssetProfile,
permissions.createOrder, permissions.createOrder,
permissions.createPlatform, permissions.createPlatform,
permissions.createTag, permissions.createTag,
@ -73,11 +77,13 @@ export function getPermissions(aRole: Role): string[] {
permissions.deleteTag, permissions.deleteTag,
permissions.deleteUser, permissions.deleteUser,
permissions.readMarketData, permissions.readMarketData,
permissions.readMarketDataOfOwnAssetProfile,
permissions.readPlatforms, permissions.readPlatforms,
permissions.readTags, permissions.readTags,
permissions.updateAccount, permissions.updateAccount,
permissions.updateAuthDevice, permissions.updateAuthDevice,
permissions.updateMarketData, permissions.updateMarketData,
permissions.updateMarketDataOfOwnAssetProfile,
permissions.updateOrder, permissions.updateOrder,
permissions.updatePlatform, permissions.updatePlatform,
permissions.updateTag, permissions.updateTag,
@ -99,6 +105,7 @@ export function getPermissions(aRole: Role): string[] {
permissions.createAccess, permissions.createAccess,
permissions.createAccount, permissions.createAccount,
permissions.createAccountBalance, permissions.createAccountBalance,
permissions.createMarketDataOfOwnAssetProfile,
permissions.createOrder, permissions.createOrder,
permissions.deleteAccess, permissions.deleteAccess,
permissions.deleteAccount, permissions.deleteAccount,
@ -106,8 +113,10 @@ export function getPermissions(aRole: Role): string[] {
permissions.deleteAuthDevice, permissions.deleteAuthDevice,
permissions.deleteOrder, permissions.deleteOrder,
permissions.deleteOwnUser, permissions.deleteOwnUser,
permissions.readMarketDataOfOwnAssetProfile,
permissions.updateAccount, permissions.updateAccount,
permissions.updateAuthDevice, permissions.updateAuthDevice,
permissions.updateMarketDataOfOwnAssetProfile,
permissions.updateOrder, permissions.updateOrder,
permissions.updateUserSettings, permissions.updateUserSettings,
permissions.updateViewMode permissions.updateViewMode

Loading…
Cancel
Save