Browse Source

Extend create tag endpoint

pull/4308/head
Thomas Kaul 6 months ago
parent
commit
10daf5fa61
  1. 6
      apps/api/src/app/tag/create-tag.dto.ts
  2. 39
      apps/api/src/app/tag/tag.controller.ts
  3. 6
      apps/api/src/app/tag/update-tag.dto.ts
  4. 1
      apps/api/src/app/user/user.service.ts
  5. 10
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
  6. 2
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
  7. 3
      libs/common/src/lib/permissions.ts

6
apps/api/src/app/tag/create-tag.dto.ts

@ -1,6 +1,10 @@
import { IsString } from 'class-validator';
import { IsOptional, IsString } from 'class-validator';
export class CreateTagDto {
@IsString()
name: string;
@IsOptional()
@IsString()
userId?: string;
}

39
apps/api/src/app/tag/tag.controller.ts

@ -1,6 +1,7 @@
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { permissions } from '@ghostfolio/common/permissions';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { RequestWithUser } from '@ghostfolio/common/types';
import {
Body,
@ -8,11 +9,13 @@ import {
Delete,
Get,
HttpException,
Inject,
Param,
Post,
Put,
UseGuards
} from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { Tag } from '@prisma/client';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
@ -23,7 +26,10 @@ import { UpdateTagDto } from './update-tag.dto';
@Controller('tag')
export class TagController {
public constructor(private readonly tagService: TagService) {}
public constructor(
@Inject(REQUEST) private readonly request: RequestWithUser,
private readonly tagService: TagService
) {}
@Get()
@HasPermission(permissions.readTags)
@ -33,9 +39,34 @@ export class TagController {
}
@Post()
@HasPermission(permissions.createTag)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
@UseGuards(AuthGuard('jwt'))
public async createTag(@Body() data: CreateTagDto): Promise<Tag> {
const canCreateOwnTag = hasPermission(
this.request.user.permissions,
permissions.createOwnTag
);
const canCreateTag = hasPermission(
this.request.user.permissions,
permissions.createTag
);
if (!canCreateOwnTag && !canCreateTag) {
throw new HttpException(
getReasonPhrase(StatusCodes.FORBIDDEN),
StatusCodes.FORBIDDEN
);
}
if (canCreateOwnTag && !canCreateTag) {
if (data.userId !== this.request.user.id) {
throw new HttpException(
getReasonPhrase(StatusCodes.BAD_REQUEST),
StatusCodes.BAD_REQUEST
);
}
}
return this.tagService.createTag(data);
}

6
apps/api/src/app/tag/update-tag.dto.ts

@ -1,4 +1,4 @@
import { IsString } from 'class-validator';
import { IsOptional, IsString } from 'class-validator';
export class UpdateTagDto {
@IsString()
@ -6,4 +6,8 @@ export class UpdateTagDto {
@IsString()
name: string;
@IsOptional()
@IsString()
userId?: string;
}

1
apps/api/src/app/user/user.service.ts

@ -347,6 +347,7 @@ export class UserService {
permissions.accessHoldingsChart,
permissions.createAccess,
permissions.createMarketDataOfOwnAssetProfile,
permissions.createOwnTag,
permissions.readAiPrompt,
permissions.readMarketDataOfOwnAssetProfile,
permissions.updateMarketDataOfOwnAssetProfile

10
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts

@ -99,7 +99,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
public dividendYieldPercentWithCurrencyEffect: number;
public feeInBaseCurrency: number;
public firstBuyDate: string;
public hasPermissionToCreateTag: boolean;
public hasPermissionToCreateOwnTag: boolean;
public hasPermissionToReadMarketDataOfOwnAssetProfile: boolean;
public historicalDataItems: LineChartItem[];
public investment: number;
@ -161,9 +161,9 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
return id === undefined;
});
if (newTag && this.hasPermissionToCreateTag) {
if (newTag && this.hasPermissionToCreateOwnTag) {
this.adminService
.postTag(newTag)
.postTag({ ...newTag, userId: this.user.id })
.pipe(
switchMap((createdTag) => {
return this.dataService.putHoldingTags({
@ -448,9 +448,9 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit {
if (state?.user) {
this.user = state.user;
this.hasPermissionToCreateTag = hasPermission(
this.hasPermissionToCreateOwnTag = hasPermission(
this.user.permissions,
permissions.createTag
permissions.createOwnTag
);
this.tagsAvailable =

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

@ -388,7 +388,7 @@
</mat-tab-group>
<gf-tags-selector
[hasPermissionToCreateTag]="hasPermissionToCreateTag"
[hasPermissionToCreateTag]="hasPermissionToCreateOwnTag"
[readonly]="!data.hasPermissionToUpdateOrder"
[tags]="activityForm.get('tags')?.value"
[tagsAvailable]="tagsAvailable"

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

@ -13,6 +13,7 @@ export const permissions = {
createMarketData: 'createMarketData',
createMarketDataOfOwnAssetProfile: 'createMarketDataOfOwnAssetProfile',
createOrder: 'createOrder',
createOwnTag: 'createOwnTag',
createPlatform: 'createPlatform',
createTag: 'createTag',
createUserAccount: 'createUserAccount',
@ -67,6 +68,7 @@ export function getPermissions(aRole: Role): string[] {
permissions.createMarketData,
permissions.createMarketDataOfOwnAssetProfile,
permissions.createOrder,
permissions.createOwnTag,
permissions.createPlatform,
permissions.createTag,
permissions.deleteAccess,
@ -110,6 +112,7 @@ export function getPermissions(aRole: Role): string[] {
permissions.createAccountBalance,
permissions.createMarketDataOfOwnAssetProfile,
permissions.createOrder,
permissions.createOwnTag,
permissions.deleteAccess,
permissions.deleteAccount,
permissions.deleteAccountBalance,

Loading…
Cancel
Save