diff --git a/src/modules/content/controllers/comment.controller.ts b/src/modules/content/controllers/comment.controller.ts index 8691b0c..ac2945b 100644 --- a/src/modules/content/controllers/comment.controller.ts +++ b/src/modules/content/controllers/comment.controller.ts @@ -1,16 +1,11 @@ -import { - Body, - Controller, - Delete, - Get, - Param, - ParseUUIDPipe, - Post, - Query, - SerializeOptions, -} from '@nestjs/common'; +import { Body, Controller, Delete, Get, Post, Query, SerializeOptions } from '@nestjs/common'; -import { CreateCommentDto, QueryCommentDto, QueryCommentTreeDto } from '../dtos/comment.dto'; +import { + CreateCommentDto, + DeleteCommentDto, + QueryCommentDto, + QueryCommentTreeDto, +} from '../dtos/comment.dto'; import { CommentService } from '../services'; @Controller('comment') @@ -38,9 +33,9 @@ export class CommentController { return this.service.create(data); } - @Delete(':id') + @Delete() @SerializeOptions({ groups: ['comment-detail'] }) - async delete(@Param('id', new ParseUUIDPipe()) id: string) { - return this.service.delete(id); + async delete(@Body() data: DeleteCommentDto) { + return this.service.delete(data.ids); } } diff --git a/src/modules/content/dtos/comment.dto.ts b/src/modules/content/dtos/comment.dto.ts index 7334817..423173b 100644 --- a/src/modules/content/dtos/comment.dto.ts +++ b/src/modules/content/dtos/comment.dto.ts @@ -46,13 +46,13 @@ export class QueryCommentTreeDto extends PickType(QueryCommentDto, ['post']) {} @DtoValidation() export class CreateCommentDto { - @MaxLength(1000, { message: '' }) - @IsNotEmpty({ message: '' }) + @MaxLength(1000, { message: 'The length of the comment content cannot exceed $constraint1' }) + @IsNotEmpty({ message: 'Comment content cannot be empty' }) body: string; @IsDataExist(PostEntity, { message: 'The post does not exist' }) @IsUUID(undefined, { message: 'The ID format is incorrect' }) - @IsDefined({ message: 'The ID must be specified' }) + @IsDefined({ message: 'The post ID must be specified' }) post: string; @IsDataExist(CommentEntity, { message: 'The parent comment does not exist' }) @@ -62,3 +62,11 @@ export class CreateCommentDto { @Transform(({ value }) => (value === 'null' ? null : value)) parent?: string; } + +@DtoValidation() +export class DeleteCommentDto { + @IsDataExist(CommentEntity) + @IsUUID(undefined, { each: true, always: true, message: 'The ID format is incorrect' }) + @IsDefined({ each: true, message: 'The ID must be specified' }) + ids: string[]; +} diff --git a/src/modules/content/services/comment.service.ts b/src/modules/content/services/comment.service.ts index c67be13..c17fec8 100644 --- a/src/modules/content/services/comment.service.ts +++ b/src/modules/content/services/comment.service.ts @@ -2,7 +2,7 @@ import { ForbiddenException, Injectable } from '@nestjs/common'; import { isNil } from 'lodash'; -import { EntityNotFoundError, SelectQueryBuilder } from 'typeorm'; +import { EntityNotFoundError, In, SelectQueryBuilder } from 'typeorm'; import { CreateCommentDto, @@ -63,9 +63,9 @@ export class CommentService { }); } - async delete(id: string) { - const comment = await this.repository.findOneOrFail({ where: { id: id ?? null } }); - return this.repository.remove(comment); + async delete(ids: string[]) { + const comments = await this.repository.find({ where: { id: In(ids) } }); + return this.repository.remove(comments); } protected async getPost(id: string) { diff --git a/src/modules/database/constraints/data.exist.constraint.ts b/src/modules/database/constraints/data.exist.constraint.ts index e56c52a..e036757 100644 --- a/src/modules/database/constraints/data.exist.constraint.ts +++ b/src/modules/database/constraints/data.exist.constraint.ts @@ -6,6 +6,7 @@ import { ValidationOptions, registerDecorator, } from 'class-validator'; +import { isArray, isNil } from 'lodash'; import { ObjectType, Repository, DataSource } from 'typeorm'; type Condition = { @@ -18,9 +19,11 @@ type Condition = { export class DataExistConstraint implements ValidatorConstraintInterface { constructor(private dataSource: DataSource) {} + errorValues: any[] = []; + async validate(value: any, validationArguments?: ValidationArguments) { let repo: Repository; - if (!value) { + if (isNil(value)) { return true; } let map = 'id'; @@ -30,6 +33,22 @@ export class DataExistConstraint implements ValidatorConstraintInterface { } else { repo = this.dataSource.getRepository(validationArguments.constraints[0]); } + if (isArray(value)) { + const values = value as any[]; + const validationResults = await Promise.all( + values.map(async (val) => { + if (isNil(val)) { + return false; + } + const item = await repo.findOne({ where: { [map]: val } }); + if (isNil(item)) { + this.errorValues.push(val); + } + return !isNil(item); + }), + ); + return validationResults.every((isValid) => isValid); + } const item = await repo.findOne({ where: { [map]: value } }); return !!item; } @@ -37,6 +56,11 @@ export class DataExistConstraint implements ValidatorConstraintInterface { if (!validationArguments.constraints[0]) { return 'Model not been specified!'; } + if (this.errorValues.length > 0) { + return `All instance of ${ + validationArguments.constraints[0].name + } must been exists in databse!Errors are ${this.errorValues.join(',')}`; + } return `All instance of ${validationArguments.constraints[0].name} must been exists in databse!`; } }