From 869d8a5d5f66b443af7453095ad4cdfcb5650fc9 Mon Sep 17 00:00:00 2001 From: nohy6630 Date: Sun, 26 Jan 2025 12:42:59 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../daepiro/domain/community/api/ArticleApiV1.kt | 9 +++++++++ .../community/controller/ArticleControllerV1.kt | 6 ++++++ .../domain/community/service/ArticleService.kt | 11 ++++++++++- .../daepiro/global/exception/CustomErrorContext.kt | 1 + 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/numberone/daepiro/domain/community/api/ArticleApiV1.kt b/src/main/kotlin/com/numberone/daepiro/domain/community/api/ArticleApiV1.kt index db53d53..9ad99eb 100644 --- a/src/main/kotlin/com/numberone/daepiro/domain/community/api/ArticleApiV1.kt +++ b/src/main/kotlin/com/numberone/daepiro/domain/community/api/ArticleApiV1.kt @@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.data.domain.Slice import org.springframework.http.MediaType +import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.ModelAttribute import org.springframework.web.bind.annotation.PathVariable @@ -114,4 +115,12 @@ interface ArticleApiV1 { @RequestBody request: ReportRequest, ): ApiResult + @Operation( + summary = "게시글 삭제", + description = "게시글을 삭제합니다." + ) + @DeleteMapping("/{id}") + fun delete( + @PathVariable("id") id: Long, + ): ApiResult } diff --git a/src/main/kotlin/com/numberone/daepiro/domain/community/controller/ArticleControllerV1.kt b/src/main/kotlin/com/numberone/daepiro/domain/community/controller/ArticleControllerV1.kt index 4c93f14..fb67814 100644 --- a/src/main/kotlin/com/numberone/daepiro/domain/community/controller/ArticleControllerV1.kt +++ b/src/main/kotlin/com/numberone/daepiro/domain/community/controller/ArticleControllerV1.kt @@ -88,4 +88,10 @@ class ArticleController( ) return ApiResult.noContent(path = "/v1/articles/$id/report") } + + override fun delete(id: Long): ApiResult { + val userId = SecurityContextUtils.getUserId() + articleService.delete(userId, id) + return ApiResult.ok(path = "/v1/articles/$id") + } } diff --git a/src/main/kotlin/com/numberone/daepiro/domain/community/service/ArticleService.kt b/src/main/kotlin/com/numberone/daepiro/domain/community/service/ArticleService.kt index 3bc5419..1ec7175 100644 --- a/src/main/kotlin/com/numberone/daepiro/domain/community/service/ArticleService.kt +++ b/src/main/kotlin/com/numberone/daepiro/domain/community/service/ArticleService.kt @@ -186,7 +186,7 @@ class ArticleService( return@let authorVerifiedAddressIds.contains(article.address?.id) } ?: false - roots.forEach { it.children.removeIf { it.deletedAt != null }} + roots.forEach { it.children.removeIf { it.deletedAt != null } } return ArticleDetailResponse.of( article = article, @@ -353,4 +353,13 @@ class ArticleService( article.increaseReportCount() ) } + + @Transactional + fun delete(userId: Long, articleId: Long) { + val article = articleRepository.findByIdOrThrow(articleId) + if (article.authUser?.id != userId) { + throw CustomException(CustomErrorContext.NOT_ARTICLE_AUTHOR) + } + articleRepository.delete(article) + } } diff --git a/src/main/kotlin/com/numberone/daepiro/global/exception/CustomErrorContext.kt b/src/main/kotlin/com/numberone/daepiro/global/exception/CustomErrorContext.kt index ad4f2a3..14ca3fc 100644 --- a/src/main/kotlin/com/numberone/daepiro/global/exception/CustomErrorContext.kt +++ b/src/main/kotlin/com/numberone/daepiro/global/exception/CustomErrorContext.kt @@ -38,6 +38,7 @@ enum class CustomErrorContext( // 26xx: 게시글 관련 오류 NOT_FOUND_ARTICLE(HttpStatus.NOT_FOUND, 2600, "게시글을 찾을 수 없습니다."), + NOT_ARTICLE_AUTHOR(HttpStatus.BAD_REQUEST, 2601, "게시글 작성자가 아닙니다."), // 27xx: 행동요령 관련 오류 NOT_FOUND_TIP_TYPE(HttpStatus.NOT_FOUND, 2700, "행동요령 유형을 찾을 수 없습니다."),