From 1b14ebcf00f556cbd31c77cae4167cdfcd96a367 Mon Sep 17 00:00:00 2001 From: stae1102 Date: Sun, 9 Jun 2024 13:54:20 +0900 Subject: [PATCH 1/3] feat: add deletedAt column --- src/common/entities/core.entity.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/entities/core.entity.ts b/src/common/entities/core.entity.ts index 17e911b..40c0198 100644 --- a/src/common/entities/core.entity.ts +++ b/src/common/entities/core.entity.ts @@ -1,6 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { CreateDateColumn, + DeleteDateColumn, PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; @@ -17,4 +18,7 @@ export class CoreEntity { @ApiProperty() @UpdateDateColumn() updatedAt!: Date; + + @DeleteDateColumn({ nullable: true, default: null }) + deletedAt: Date | null; } From 084857e6d4aed22ddd7287f660452f8034e58d69 Mon Sep 17 00:00:00 2001 From: stae1102 Date: Sun, 9 Jun 2024 13:55:28 +0900 Subject: [PATCH 2/3] feat: change hard delete to soft delete to content repository --- src/contents/repository/content.repository.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/contents/repository/content.repository.ts b/src/contents/repository/content.repository.ts index 891e815..5d0cfaa 100644 --- a/src/contents/repository/content.repository.ts +++ b/src/contents/repository/content.repository.ts @@ -60,7 +60,7 @@ export class ContentRepository extends Repository { async deleteOne(contentId: number, entityManager?: EntityManager) { return entityManager - ? entityManager.delete(Content, contentId) - : this.delete({ id: contentId }); + ? entityManager.softDelete(Content, contentId) + : this.softDelete({ id: contentId }); } } From 3a733bf8666f9e69cea9e33936057d4c9ee5f8c1 Mon Sep 17 00:00:00 2001 From: stae1102 Date: Sun, 9 Jun 2024 13:55:53 +0900 Subject: [PATCH 3/3] feat: create restore content api --- src/contents/contents.controller.ts | 32 ++++++++++++++--------------- src/contents/contents.service.ts | 27 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/contents/contents.controller.ts b/src/contents/contents.controller.ts index a40a2e4..f99f590 100644 --- a/src/contents/contents.controller.ts +++ b/src/contents/contents.controller.ts @@ -253,21 +253,19 @@ export class ContentsController { return this.contentsService.summarizeContent(user, contentId); } - // @ApiOperation({ - // summary: '간편 문서 요약', - // description: '성능 테스트를 위해 만든 간편 문서 요약 메서드', - // }) - // @ApiOkResponse({ - // description: '간편 문서 요약 성공 여부를 반환한다.', - // type: SummarizeContentOutput, - // }) - // @ApiBadRequestResponse({ - // description: 'naver 서버에 잘못된 요청을 보냈을 경우', - // }) - // @Post('summarize') - // async testSummarizeContent( - // @Body() content: SummarizeContentBodyDto, - // ): Promise { - // return this.contentsService.testSummarizeContent(content); - // } + @ApiOperation({ + summary: '삭제된 컨텐츠 복원', + description: '삭제된 컨텐츠를 복원합니다.', + }) + @ApiOkResponse({ + description: '삭제된 컨텐츠 복원 성공 여부를 반환합니다.', + }) + @UseGuards(JwtAuthGuard) + @Patch(':contentId/restore') + async restoreContent( + @AuthUser() user: User, + @Param('contentId', new ParseIntPipe()) contentId: number, + ) { + return this.contentsService.restoreContent(user, contentId); + } } diff --git a/src/contents/contents.service.ts b/src/contents/contents.service.ts index 2a450b0..7dca2f7 100644 --- a/src/contents/contents.service.ts +++ b/src/contents/contents.service.ts @@ -425,4 +425,31 @@ export class ContentsService { throw e; } } + + async restoreContent(user: User, contentId: number) { + try { + const content = await this.contentRepository.findOne({ + where: { + id: contentId, + }, + withDeleted: true, + }); + + if (!content) { + throw new NotFoundException('Content not found.'); + } + if (content.userId !== user.id) { + throw new ForbiddenException( + 'You are not allowed to restore this content', + ); + } + + content.deletedAt = null; + await this.contentRepository.save(content); + + return {}; + } catch (e) { + throw e; + } + } }