diff --git a/apps/core/src/constants/business-event.constant.ts b/apps/core/src/constants/business-event.constant.ts index 2a4bf74f..955b9d20 100644 --- a/apps/core/src/constants/business-event.constant.ts +++ b/apps/core/src/constants/business-event.constant.ts @@ -10,6 +10,7 @@ export enum BusinessEvents { COMMENT_CREATE = 'COMMENT_CREATE', COMMENT_DELETE = 'COMMENT_DELETE', + COMMENT_UPDATE = 'COMMENT_UPDATE', POST_CREATE = 'POST_CREATE', POST_UPDATE = 'POST_UPDATE', diff --git a/apps/core/src/modules/comment/comment.controller.ts b/apps/core/src/modules/comment/comment.controller.ts index bc9fdb7e..37001d4f 100644 --- a/apps/core/src/modules/comment/comment.controller.ts +++ b/apps/core/src/modules/comment/comment.controller.ts @@ -20,7 +20,10 @@ import { import { ApiController } from '~/common/decorators/api-controller.decorator' import { Auth } from '~/common/decorators/auth.decorator' -import { CurrentUser } from '~/common/decorators/current-user.decorator' +import { + CurrentReaderId, + CurrentUser, +} from '~/common/decorators/current-user.decorator' import { HTTPDecorators } from '~/common/decorators/http.decorator' import { IpLocation, IpRecord } from '~/common/decorators/ip.decorator' import { IsAuthenticated } from '~/common/decorators/role.decorator' @@ -43,6 +46,7 @@ import { CommentDto, CommentRefTypesDto, CommentStatePatchDto, + EditCommentDto, TextOnlyDto, } from './comment.dto' import { CommentReplyMailType } from './comment.enum' @@ -451,4 +455,23 @@ export class CommentController { }) return } + + @Patch('/edit/:id') + async editComment( + @Param() params: MongoIdDto, + @Body() body: EditCommentDto, + @IsAuthenticated() isAuthenticated: boolean, + @CurrentReaderId() readerId: string, + ) { + const { id } = params + const { text } = body + const comment = await this.commentService.model.findById(id).lean() + if (!comment) { + throw new CannotFindException() + } + if (comment.readerId !== readerId && !isAuthenticated) { + throw new ForbiddenException() + } + await this.commentService.editComment(id, text) + } } diff --git a/apps/core/src/modules/comment/comment.dto.ts b/apps/core/src/modules/comment/comment.dto.ts index 76b766d8..699d7be0 100644 --- a/apps/core/src/modules/comment/comment.dto.ts +++ b/apps/core/src/modules/comment/comment.dto.ts @@ -55,6 +55,12 @@ export class CommentDto { avatar?: string } +export class EditCommentDto { + @IsString() + @IsNotEmpty() + text: string +} + export class RequiredGuestReaderCommentDto extends CommentDto { @IsString() @IsNotEmpty() diff --git a/apps/core/src/modules/comment/comment.service.ts b/apps/core/src/modules/comment/comment.service.ts index 119e416e..d0110ba8 100644 --- a/apps/core/src/modules/comment/comment.service.ts +++ b/apps/core/src/modules/comment/comment.service.ts @@ -643,4 +643,19 @@ export class CommentService implements OnModuleInit { url: `${adminUrl}#/comments`, }) } + + async editComment(id: string, text: string) { + const comment = await this.commentModel.findById(id).lean() + if (!comment) { + throw new CannotFindException() + } + await this.commentModel.updateOne({ _id: id }, { text }) + await this.eventManager.broadcast( + BusinessEvents.COMMENT_UPDATE, + { id, text }, + { + scope: comment.isWhispers ? EventScope.TO_SYSTEM_ADMIN : EventScope.ALL, + }, + ) + } } diff --git a/packages/webhook/src/types.ts b/packages/webhook/src/types.ts index 2274889e..c4e4ba85 100644 --- a/packages/webhook/src/types.ts +++ b/packages/webhook/src/types.ts @@ -48,6 +48,12 @@ export interface EventPayloadMapping { [BusinessEvents.COMMENT_CREATE]: Omit & { ref: Id | PostModel | PageModel | NoteModel | RecentlyModel } + + [BusinessEvents.COMMENT_UPDATE]: { + id: string + text: string + } + [BusinessEvents.ARTICLE_READ_COUNT_UPDATE]: { count: number type: 'post' | 'note'