From 1732dc92ab3aea7349e14eb47a20cd25f1e0740f Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Wed, 27 Dec 2023 18:58:47 +0900 Subject: [PATCH 01/58] =?UTF-8?q?feat:=20Article=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/gloddy/article/Article.kt | 17 +++++++++++++++++ .../kotlin/gloddy/article/vo/ArticleImage.kt | 18 ++++++++++++++++++ .../src/main/kotlin/gloddy/article/vo/Like.kt | 7 +++++++ 3 files changed, 42 insertions(+) create mode 100644 community-domain/src/main/kotlin/gloddy/article/Article.kt create mode 100644 community-domain/src/main/kotlin/gloddy/article/vo/ArticleImage.kt create mode 100644 community-domain/src/main/kotlin/gloddy/article/vo/Like.kt diff --git a/community-domain/src/main/kotlin/gloddy/article/Article.kt b/community-domain/src/main/kotlin/gloddy/article/Article.kt new file mode 100644 index 0000000..2196dfb --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/article/Article.kt @@ -0,0 +1,17 @@ +package gloddy.article + +import gloddy.article.vo.ArticleImage +import gloddy.article.vo.Like +import gloddy.category.Category +import gloddy.core.ArticleId +import gloddy.core.UserId + +data class Article( + val id: ArticleId?, + val userId: UserId, + val category: Category, + val title: String, + val content: String, + val image: ArticleImage, + val like: Like +) \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/article/vo/ArticleImage.kt b/community-domain/src/main/kotlin/gloddy/article/vo/ArticleImage.kt new file mode 100644 index 0000000..2d55aac --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/article/vo/ArticleImage.kt @@ -0,0 +1,18 @@ +package gloddy.article.vo + +import gloddy.article.exception.ArticleImageSizeOverException + +data class ArticleImage( + val images: List +) { + + init { + verifySize(images) + } + + private fun verifySize(images: List) { + if (images.size > 3) { + throw ArticleImageSizeOverException() + } + } +} \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/article/vo/Like.kt b/community-domain/src/main/kotlin/gloddy/article/vo/Like.kt new file mode 100644 index 0000000..cfdaebc --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/article/vo/Like.kt @@ -0,0 +1,7 @@ +package gloddy.article.vo + +import gloddy.core.UserId + +data class Like( + val likes: List +) \ No newline at end of file From 4f64dd4f208ac755024ad62c415f48ffd10eec8c Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Wed, 27 Dec 2023 18:59:18 +0900 Subject: [PATCH 02/58] =?UTF-8?q?feat:=20Category=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/gloddy/category/Category.kt | 8 ++++++++ .../src/main/kotlin/gloddy/core/Id.kt | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 community-domain/src/main/kotlin/gloddy/category/Category.kt create mode 100644 community-domain/src/main/kotlin/gloddy/core/Id.kt diff --git a/community-domain/src/main/kotlin/gloddy/category/Category.kt b/community-domain/src/main/kotlin/gloddy/category/Category.kt new file mode 100644 index 0000000..e48485c --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/category/Category.kt @@ -0,0 +1,8 @@ +package gloddy.category + +import gloddy.core.CategoryId + +data class Category( + val id: CategoryId?, + val name: String +) diff --git a/community-domain/src/main/kotlin/gloddy/core/Id.kt b/community-domain/src/main/kotlin/gloddy/core/Id.kt new file mode 100644 index 0000000..fcf6f21 --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/core/Id.kt @@ -0,0 +1,16 @@ +package gloddy.core + +@JvmInline +value class UserId( + val value: Long +) + +@JvmInline +value class ArticleId( + val value: Long +) + +@JvmInline +value class CategoryId( + val value: Long +) From 05b589f75b40fc68e822cca02b0356f118b78b2c Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Wed, 27 Dec 2023 18:59:51 +0900 Subject: [PATCH 03/58] =?UTF-8?q?feat:=20=EA=B3=B5=ED=86=B5=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20ErrorCode=20=EB=B0=8F=20Exception=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/gloddy/core/ErrorCode.kt | 7 +++++++ .../kotlin/gloddy/core/GloddyCommunityException.kt | 14 ++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 community-domain/src/main/kotlin/gloddy/core/ErrorCode.kt create mode 100644 community-domain/src/main/kotlin/gloddy/core/GloddyCommunityException.kt diff --git a/community-domain/src/main/kotlin/gloddy/core/ErrorCode.kt b/community-domain/src/main/kotlin/gloddy/core/ErrorCode.kt new file mode 100644 index 0000000..1d7f274 --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/core/ErrorCode.kt @@ -0,0 +1,7 @@ +package gloddy.core + +interface ErrorCode { + val statusCode: Int + val errorCode: String + val message: String +} \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/core/GloddyCommunityException.kt b/community-domain/src/main/kotlin/gloddy/core/GloddyCommunityException.kt new file mode 100644 index 0000000..3c0541e --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/core/GloddyCommunityException.kt @@ -0,0 +1,14 @@ +package gloddy.core + +open class GloddyCommunityException(code: ErrorCode) : RuntimeException() { + + val statusCode: Int + val errorCode: String + override val message: String + + init { + statusCode = code.statusCode + errorCode = code.errorCode + message = code.message + } +} \ No newline at end of file From eba6c397b46d2bfdfa02f06a9c0a419b5eac264c Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Wed, 27 Dec 2023 19:02:06 +0900 Subject: [PATCH 04/58] =?UTF-8?q?feat:=20Article=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=B4=88=EA=B8=B0=20ErrorCode=20=EB=B0=8F=20Except?= =?UTF-8?q?ion=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/gloddy/article/ArticleErrorCode.kt | 12 ++++++++++++ .../exception/ArticleImageSizeOverException.kt | 6 ++++++ .../article/exception/ArticleNotFoundException.kt | 6 ++++++ 3 files changed, 24 insertions(+) create mode 100644 community-domain/src/main/kotlin/gloddy/article/ArticleErrorCode.kt create mode 100644 community-domain/src/main/kotlin/gloddy/article/exception/ArticleImageSizeOverException.kt create mode 100644 community-domain/src/main/kotlin/gloddy/article/exception/ArticleNotFoundException.kt diff --git a/community-domain/src/main/kotlin/gloddy/article/ArticleErrorCode.kt b/community-domain/src/main/kotlin/gloddy/article/ArticleErrorCode.kt new file mode 100644 index 0000000..0536c90 --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/article/ArticleErrorCode.kt @@ -0,0 +1,12 @@ +package gloddy.article + +import gloddy.core.ErrorCode + +enum class ArticleErrorCode( + override val statusCode: Int, + override val errorCode: String, + override val message: String +) : ErrorCode { + NOT_FOUND(400, "ARTICLE_001", "해당 게시글을 찾을 수 없습니다."), + IMAGE_SIZE_OVER(400, "ARTICLE_002", "게시글에 이미지는 최대 3개 입니다.") +} \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/article/exception/ArticleImageSizeOverException.kt b/community-domain/src/main/kotlin/gloddy/article/exception/ArticleImageSizeOverException.kt new file mode 100644 index 0000000..ca6b512 --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/article/exception/ArticleImageSizeOverException.kt @@ -0,0 +1,6 @@ +package gloddy.article.exception + +import gloddy.article.ArticleErrorCode +import gloddy.core.GloddyCommunityException + +class ArticleImageSizeOverException : GloddyCommunityException(ArticleErrorCode.IMAGE_SIZE_OVER) \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/article/exception/ArticleNotFoundException.kt b/community-domain/src/main/kotlin/gloddy/article/exception/ArticleNotFoundException.kt new file mode 100644 index 0000000..fb69e06 --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/article/exception/ArticleNotFoundException.kt @@ -0,0 +1,6 @@ +package gloddy.article.exception + +import gloddy.article.ArticleErrorCode +import gloddy.core.GloddyCommunityException + +class ArticleNotFoundException : GloddyCommunityException(ArticleErrorCode.NOT_FOUND) \ No newline at end of file From d8f7cb7c474bd276feef7fad19ba038a9b170c56 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Wed, 27 Dec 2023 19:02:23 +0900 Subject: [PATCH 05/58] =?UTF-8?q?feat:=20Category=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=B4=88=EA=B8=B0=20ErrorCode=20=EB=B0=8F=20Except?= =?UTF-8?q?ion=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/gloddy/category/CategoryErrorCode.kt | 11 +++++++++++ .../category/exception/CategoryNotFoundException.kt | 6 ++++++ 2 files changed, 17 insertions(+) create mode 100644 community-domain/src/main/kotlin/gloddy/category/CategoryErrorCode.kt create mode 100644 community-domain/src/main/kotlin/gloddy/category/exception/CategoryNotFoundException.kt diff --git a/community-domain/src/main/kotlin/gloddy/category/CategoryErrorCode.kt b/community-domain/src/main/kotlin/gloddy/category/CategoryErrorCode.kt new file mode 100644 index 0000000..56f08ad --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/category/CategoryErrorCode.kt @@ -0,0 +1,11 @@ +package gloddy.category + +import gloddy.core.ErrorCode + +enum class CategoryErrorCode( + override val statusCode: Int, + override val errorCode: String, + override val message: String +): ErrorCode { + NOT_FOUND(400, "CATEGORY_001", "해당 카테고리를 찾을 수 없습니다.") +} \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/category/exception/CategoryNotFoundException.kt b/community-domain/src/main/kotlin/gloddy/category/exception/CategoryNotFoundException.kt new file mode 100644 index 0000000..a8940b1 --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/category/exception/CategoryNotFoundException.kt @@ -0,0 +1,6 @@ +package gloddy.category.exception + +import gloddy.category.CategoryErrorCode +import gloddy.core.GloddyCommunityException + +class CategoryNotFoundException : GloddyCommunityException(CategoryErrorCode.NOT_FOUND) \ No newline at end of file From 2d1ebe33dedfb3fc2780906ae86993efc82149d9 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 29 Dec 2023 23:47:17 +0900 Subject: [PATCH 06/58] =?UTF-8?q?chore:=20jpa=20plugin=20=EB=B0=8F=20allop?= =?UTF-8?q?en=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- community-infrastructure/build.gradle.kts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/community-infrastructure/build.gradle.kts b/community-infrastructure/build.gradle.kts index f31f475..a6596f1 100644 --- a/community-infrastructure/build.gradle.kts +++ b/community-infrastructure/build.gradle.kts @@ -1,5 +1,9 @@ import org.springframework.boot.gradle.tasks.bundling.BootJar +plugins { + kotlin("plugin.jpa") version "1.9.22" +} + val jar: Jar by tasks val bootJar: BootJar by tasks @@ -24,3 +28,10 @@ dependencyManagement { mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}") } } + +allOpen { + annotation("jakarta.persistence.Entity") + annotation("jakarta.persistence.Embeddable") + annotation("jakarta.persistence.MappedSuperclass") +} + From cd1252fb096d928ed1bed94aa74a361dd1394c0e Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sat, 30 Dec 2023 23:54:20 +0900 Subject: [PATCH 07/58] =?UTF-8?q?fix:=20Category=20Domain=20=EC=9E=AC?= =?UTF-8?q?=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- community-domain/src/main/kotlin/gloddy/article/vo/Like.kt | 7 ------- .../src/main/kotlin/gloddy/category/Category.kt | 4 ++-- 2 files changed, 2 insertions(+), 9 deletions(-) delete mode 100644 community-domain/src/main/kotlin/gloddy/article/vo/Like.kt diff --git a/community-domain/src/main/kotlin/gloddy/article/vo/Like.kt b/community-domain/src/main/kotlin/gloddy/article/vo/Like.kt deleted file mode 100644 index cfdaebc..0000000 --- a/community-domain/src/main/kotlin/gloddy/article/vo/Like.kt +++ /dev/null @@ -1,7 +0,0 @@ -package gloddy.article.vo - -import gloddy.core.UserId - -data class Like( - val likes: List -) \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/category/Category.kt b/community-domain/src/main/kotlin/gloddy/category/Category.kt index e48485c..8d381b2 100644 --- a/community-domain/src/main/kotlin/gloddy/category/Category.kt +++ b/community-domain/src/main/kotlin/gloddy/category/Category.kt @@ -3,6 +3,6 @@ package gloddy.category import gloddy.core.CategoryId data class Category( - val id: CategoryId?, - val name: String + var name: String, + val id: CategoryId? = null, ) From 1f26778be6e1830c8a277cce1f7b06b3a786bc9c Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Mon, 1 Jan 2024 21:20:29 +0900 Subject: [PATCH 08/58] =?UTF-8?q?chore:=20Junit=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 6 ++++++ community-application/build.gradle.kts | 8 -------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a193899..fd0bdf1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,6 +30,12 @@ subprojects { dependencies{ implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") + testCompileOnly("org.junit.jupiter:junit-jupiter-params:5.10.1") + testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1") + testImplementation("org.springframework.boot:spring-boot-starter-test") { + exclude("junit") + } } group = "gloddy" diff --git a/community-application/build.gradle.kts b/community-application/build.gradle.kts index 3984d5d..4152bd0 100644 --- a/community-application/build.gradle.kts +++ b/community-application/build.gradle.kts @@ -13,12 +13,4 @@ dependencies { implementation("org.springframework:spring-context") implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") implementation("jakarta.validation:jakarta.validation-api") - - testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") - testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.3") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.9.3") - - testImplementation("org.assertj:assertj-core:3.24.2") - testImplementation("org.mockito:mockito-junit-jupiter:5.3.1") - testImplementation("org.mockito:mockito-core:5.3.1") } From b8d3c3f9778154a4e4c047e129f17145d91dca3d Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Mon, 1 Jan 2024 21:21:00 +0900 Subject: [PATCH 09/58] =?UTF-8?q?fix:=20Article=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=9E=AC=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/gloddy/article/Article.kt | 33 ++++++++++++++----- .../kotlin/gloddy/article/vo/ArticleImage.kt | 6 ++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/community-domain/src/main/kotlin/gloddy/article/Article.kt b/community-domain/src/main/kotlin/gloddy/article/Article.kt index 2196dfb..455f56d 100644 --- a/community-domain/src/main/kotlin/gloddy/article/Article.kt +++ b/community-domain/src/main/kotlin/gloddy/article/Article.kt @@ -1,17 +1,34 @@ package gloddy.article import gloddy.article.vo.ArticleImage -import gloddy.article.vo.Like import gloddy.category.Category import gloddy.core.ArticleId import gloddy.core.UserId data class Article( - val id: ArticleId?, val userId: UserId, - val category: Category, - val title: String, - val content: String, - val image: ArticleImage, - val like: Like -) \ No newline at end of file + var category: Category, + var title: String, + var content: String, + var image: ArticleImage, + val id: ArticleId? = null, +) { + var commentCount: Int = 0 + var likeCount: Int = 0 + + constructor( + userId: UserId, + category: Category, + title: String, + content: String, + imageList: List?, + id: ArticleId? = null + ) : this( + userId = userId, + category = category, + title = title, + content = content, + image = ArticleImage(imageList), + id = id + ) +} \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/article/vo/ArticleImage.kt b/community-domain/src/main/kotlin/gloddy/article/vo/ArticleImage.kt index 2d55aac..34e8cc5 100644 --- a/community-domain/src/main/kotlin/gloddy/article/vo/ArticleImage.kt +++ b/community-domain/src/main/kotlin/gloddy/article/vo/ArticleImage.kt @@ -3,15 +3,15 @@ package gloddy.article.vo import gloddy.article.exception.ArticleImageSizeOverException data class ArticleImage( - val images: List + val images: List? ) { init { verifySize(images) } - private fun verifySize(images: List) { - if (images.size > 3) { + private fun verifySize(images: List?) { + if (!images.isNullOrEmpty() && images.size > 3) { throw ArticleImageSizeOverException() } } From 70b320abe5eb59d731c6213d68f9ef5a0521b31d Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Mon, 1 Jan 2024 21:21:37 +0900 Subject: [PATCH 10/58] =?UTF-8?q?feat:=20ArticleLike=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/gloddy/article/ArticleLike.kt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 community-domain/src/main/kotlin/gloddy/article/ArticleLike.kt diff --git a/community-domain/src/main/kotlin/gloddy/article/ArticleLike.kt b/community-domain/src/main/kotlin/gloddy/article/ArticleLike.kt new file mode 100644 index 0000000..a3ca10d --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/article/ArticleLike.kt @@ -0,0 +1,9 @@ +package gloddy.article + +import gloddy.core.UserId + +data class ArticleLike( + val userId: UserId, + val article: Article, + val id: Long? = null, +) From 3130b251f14cc8406c05db7dfdd97f49b7660ede Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Mon, 1 Jan 2024 21:22:13 +0900 Subject: [PATCH 11/58] =?UTF-8?q?test:=20Article,=20ArticleLike=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gloddy/article/ArticleCreateTest.kt | 62 +++++++++++++++++++ .../gloddy/article/ArticleLikeCreateTest.kt | 25 ++++++++ .../kotlin/gloddy/fixture/ArticleFixture.kt | 37 +++++++++++ .../kotlin/gloddy/fixture/CategoryFixture.kt | 23 +++++++ 4 files changed, 147 insertions(+) create mode 100644 community-domain/src/test/kotlin/gloddy/article/ArticleCreateTest.kt create mode 100644 community-domain/src/test/kotlin/gloddy/article/ArticleLikeCreateTest.kt create mode 100644 community-domain/src/test/kotlin/gloddy/fixture/ArticleFixture.kt create mode 100644 community-domain/src/test/kotlin/gloddy/fixture/CategoryFixture.kt diff --git a/community-domain/src/test/kotlin/gloddy/article/ArticleCreateTest.kt b/community-domain/src/test/kotlin/gloddy/article/ArticleCreateTest.kt new file mode 100644 index 0000000..5638575 --- /dev/null +++ b/community-domain/src/test/kotlin/gloddy/article/ArticleCreateTest.kt @@ -0,0 +1,62 @@ +package gloddy.article + +import gloddy.article.exception.ArticleImageSizeOverException +import gloddy.article.vo.ArticleImage +import gloddy.category.Category +import gloddy.core.CategoryId +import gloddy.core.UserId +import gloddy.fixture.CategoryFixture +import gloddy.fixture.CategoryFixture.* +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource + +@DisplayName("Article 도메인 생성을") +class ArticleCreateTest { + + companion object { + @JvmStatic + fun articleProvider() = listOf( + Arguments.of(listOf("image1")), + Arguments.of(null) + ) + } + + @ParameterizedTest + @MethodSource("articleProvider") + @DisplayName("성공한다.") + fun success(image: List?) { + + val category = K_POP.toPersistDomain(1L) + + val article = Article( + userId = UserId(1L), + category = category, + title = "title", + content = "content", + imageList = image + ) + + assertEquals(article.category, category) + assertEquals(article.image, ArticleImage(image)) + assertEquals(article.commentCount, 0) + assertEquals(article.likeCount, 0) + } + + @Test + @DisplayName("이미지가 3개 초과하여 실패한다.") + fun fail_by_images_size_over() { + assertThrows(ArticleImageSizeOverException::class.java) { + Article( + userId = UserId(1L), + category = K_POP.toPersistDomain(1L), + title = "title", + content = "content", + imageList = listOf("image1", "image2", "image3", "image4") + ) + } + } +} \ No newline at end of file diff --git a/community-domain/src/test/kotlin/gloddy/article/ArticleLikeCreateTest.kt b/community-domain/src/test/kotlin/gloddy/article/ArticleLikeCreateTest.kt new file mode 100644 index 0000000..1d057b9 --- /dev/null +++ b/community-domain/src/test/kotlin/gloddy/article/ArticleLikeCreateTest.kt @@ -0,0 +1,25 @@ +package gloddy.article + +import gloddy.core.UserId +import gloddy.fixture.ArticleFixture.* +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test + +@DisplayName("게시글 좋아요 도메인 생성을") +class ArticleLikeCreateTest { + + @Test + @DisplayName("성공한다.") + fun success() { + + val article = JIHWAN.toPersistDomain(1L, 1L) + + val articleLike = ArticleLike( + userId = UserId(1L), + article = article + ) + + assertEquals(articleLike.article, article) + } +} \ No newline at end of file diff --git a/community-domain/src/test/kotlin/gloddy/fixture/ArticleFixture.kt b/community-domain/src/test/kotlin/gloddy/fixture/ArticleFixture.kt new file mode 100644 index 0000000..2bb08a5 --- /dev/null +++ b/community-domain/src/test/kotlin/gloddy/fixture/ArticleFixture.kt @@ -0,0 +1,37 @@ +package gloddy.fixture + +import gloddy.article.Article +import gloddy.article.vo.ArticleImage +import gloddy.category.Category +import gloddy.core.ArticleId +import gloddy.core.UserId +import gloddy.fixture.CategoryFixture.* + +enum class ArticleFixture( + private val userId: UserId?, + private val category: Category?, + private val title: String, + private val content: String, + private val image: ArticleImage, +) { + JIHWAN(null, QNA.toPersistDomain(1L), "한국 핫플", "요즘 한국 핫플이 어디에용?", ArticleImage(null)); + + fun toDomain(userId: Long): Article = + Article( + userId = UserId(userId), + category = this.category!!, + title = this.title, + content = this.content, + image = this.image + ) + + fun toPersistDomain(userId: Long, id: Long): Article = + Article( + userId = UserId(userId), + category = this.category!!, + title = this.title, + content = this.content, + image = this.image, + id = ArticleId(id) + ) +} \ No newline at end of file diff --git a/community-domain/src/test/kotlin/gloddy/fixture/CategoryFixture.kt b/community-domain/src/test/kotlin/gloddy/fixture/CategoryFixture.kt new file mode 100644 index 0000000..e3b2b6f --- /dev/null +++ b/community-domain/src/test/kotlin/gloddy/fixture/CategoryFixture.kt @@ -0,0 +1,23 @@ +package gloddy.fixture + +import gloddy.category.Category +import gloddy.core.CategoryId + +enum class CategoryFixture( + private val names: String, +) { + K_POP("K-POP"), + QNA("Q&A"), + LANGUAGE("Language"); + + fun toDomain(): Category = + Category( + name = this.names + ) + + fun toPersistDomain(id: Long): Category = + Category( + name = names, + id = CategoryId(id) + ) +} \ No newline at end of file From bd11480e0c555ffb83efda7470fad515aa1a2146 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Tue, 2 Jan 2024 23:39:49 +0900 Subject: [PATCH 12/58] =?UTF-8?q?chore:=20persistence=20yml=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bootstrap/src/main/resources/application.yml | 3 +++ .../{application-jpa.yml => application-persistence.yml} | 0 2 files changed, 3 insertions(+) rename community-infrastructure/src/main/resources/{application-jpa.yml => application-persistence.yml} (100%) diff --git a/bootstrap/src/main/resources/application.yml b/bootstrap/src/main/resources/application.yml index 3f0d280..bd72885 100644 --- a/bootstrap/src/main/resources/application.yml +++ b/bootstrap/src/main/resources/application.yml @@ -1,3 +1,6 @@ +server: + port: {PORT} + spring: config: import: diff --git a/community-infrastructure/src/main/resources/application-jpa.yml b/community-infrastructure/src/main/resources/application-persistence.yml similarity index 100% rename from community-infrastructure/src/main/resources/application-jpa.yml rename to community-infrastructure/src/main/resources/application-persistence.yml From 25d396e0841e047e79b740c39862028c0ed244fa Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Thu, 4 Jan 2024 19:32:12 +0900 Subject: [PATCH 13/58] =?UTF-8?q?chore:=20.gitkeep=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- community-domain/src/main/kotlin/gloddy/.gitkeep | 0 community-domain/src/test/kotlin/gloddy/.gitkeep | 0 community-infrastructure/src/main/kotlin/gloddy/.gitkeep | 0 community-infrastructure/src/test/kotlin/gloddy/.gitkeep | 0 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 community-domain/src/main/kotlin/gloddy/.gitkeep delete mode 100644 community-domain/src/test/kotlin/gloddy/.gitkeep delete mode 100644 community-infrastructure/src/main/kotlin/gloddy/.gitkeep delete mode 100644 community-infrastructure/src/test/kotlin/gloddy/.gitkeep diff --git a/community-domain/src/main/kotlin/gloddy/.gitkeep b/community-domain/src/main/kotlin/gloddy/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/community-domain/src/test/kotlin/gloddy/.gitkeep b/community-domain/src/test/kotlin/gloddy/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/community-infrastructure/src/main/kotlin/gloddy/.gitkeep b/community-infrastructure/src/main/kotlin/gloddy/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/community-infrastructure/src/test/kotlin/gloddy/.gitkeep b/community-infrastructure/src/test/kotlin/gloddy/.gitkeep deleted file mode 100644 index e69de29..0000000 From b47d3780291304daa2f26884481330a5a9f61af3 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Thu, 4 Jan 2024 19:35:43 +0900 Subject: [PATCH 14/58] =?UTF-8?q?chore:=20persistece=20yml=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bootstrap/src/main/resources/application.yml | 2 +- .../main/resources/application-persistence.yml | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/bootstrap/src/main/resources/application.yml b/bootstrap/src/main/resources/application.yml index bd72885..e095c58 100644 --- a/bootstrap/src/main/resources/application.yml +++ b/bootstrap/src/main/resources/application.yml @@ -4,4 +4,4 @@ server: spring: config: import: - - application-jpa.yml + - application-persistence.yml diff --git a/community-infrastructure/src/main/resources/application-persistence.yml b/community-infrastructure/src/main/resources/application-persistence.yml index 8b13789..a48a543 100644 --- a/community-infrastructure/src/main/resources/application-persistence.yml +++ b/community-infrastructure/src/main/resources/application-persistence.yml @@ -1 +1,18 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + username: ${COMMUNITY_DATASOURCE_USERNAME} + password: ${COMMUNITY_DATASOURCE_PASSWORD} + url: ${COMMUNITY_DATASOURCE_URL} + jpa: + hibernate: + ddl-auto: none + naming: + physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl + show-sql: ${SHOW_SQL} + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL8Dialect + default_batch_fetch_size: 50 + format_sql: true From 7fe8681ccd5acb52434ecf550bcc91bb23b12a46 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Thu, 4 Jan 2024 19:36:11 +0900 Subject: [PATCH 15/58] =?UTF-8?q?fix:=20Article=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- community-domain/src/main/kotlin/gloddy/article/Article.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/community-domain/src/main/kotlin/gloddy/article/Article.kt b/community-domain/src/main/kotlin/gloddy/article/Article.kt index 455f56d..c17c6b2 100644 --- a/community-domain/src/main/kotlin/gloddy/article/Article.kt +++ b/community-domain/src/main/kotlin/gloddy/article/Article.kt @@ -11,11 +11,10 @@ data class Article( var title: String, var content: String, var image: ArticleImage, + var commentCount: Int = 0, + var likeCount: Int = 0, val id: ArticleId? = null, ) { - var commentCount: Int = 0 - var likeCount: Int = 0 - constructor( userId: UserId, category: Category, From 4f34a5428d1b2d341768f4dcc32ff4b199a57519 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Thu, 4 Jan 2024 19:38:00 +0900 Subject: [PATCH 16/58] =?UTF-8?q?feat:=20Category=20Jpa=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/category/CategoryJpaEntity.kt | 15 +++++++++++++++ .../category/repository/CategoryJpaRepository.kt | 7 +++++++ 2 files changed, 22 insertions(+) create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/category/CategoryJpaEntity.kt create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/category/repository/CategoryJpaRepository.kt diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/category/CategoryJpaEntity.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/category/CategoryJpaEntity.kt new file mode 100644 index 0000000..dd729d1 --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/category/CategoryJpaEntity.kt @@ -0,0 +1,15 @@ +package gloddy.persistence.category + +import jakarta.persistence.* + +@Entity +@Table(name = "category") +class CategoryJpaEntity( + + var name: String, + + @field:Id + @field:GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long? = null, +) { +} \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/category/repository/CategoryJpaRepository.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/category/repository/CategoryJpaRepository.kt new file mode 100644 index 0000000..6dbeb51 --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/category/repository/CategoryJpaRepository.kt @@ -0,0 +1,7 @@ +package gloddy.persistence.category.repository + +import gloddy.persistence.category.CategoryJpaEntity +import org.springframework.data.jpa.repository.JpaRepository + +interface CategoryJpaRepository : JpaRepository { +} \ No newline at end of file From 603e9ed92dc7ebee242cdb3e5e95206a6c584b1a Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Thu, 4 Jan 2024 19:38:26 +0900 Subject: [PATCH 17/58] =?UTF-8?q?feat:=20Article=20Jpa=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/article/ArticleJpaEntity.kt | 38 +++++++++++++++++++ .../repository/ArticleJpaRepository.kt | 7 ++++ 2 files changed, 45 insertions(+) create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleJpaEntity.kt create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleJpaRepository.kt diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleJpaEntity.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleJpaEntity.kt new file mode 100644 index 0000000..4fd770d --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleJpaEntity.kt @@ -0,0 +1,38 @@ +package gloddy.persistence.article + +import gloddy.persistence.category.CategoryJpaEntity +import gloddy.persistence.util.converter.StringArrayConverter +import jakarta.persistence.* +import org.hibernate.annotations.SQLRestriction + +@Entity +@Table(name = "article") +@SQLRestriction("deleted = false") +class ArticleJpaEntity( + + val userId: Long, + + @field:ManyToOne(fetch = FetchType.LAZY) + @field:JoinColumn(name = "category_id") + var category: CategoryJpaEntity, + + var title: String, + + @field:Column(name = "content", columnDefinition = "longtext") + var content: String, + + @field:Convert(converter = StringArrayConverter::class) + @field:Column(name = "images", columnDefinition = "longtext") + var images: List?, + + var commentCount: Int, + + var likeCount: Int, + + var deleted: Boolean = false, + + @field:Id + @field:GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long? = null, +) { +} \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleJpaRepository.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleJpaRepository.kt new file mode 100644 index 0000000..cb6af88 --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleJpaRepository.kt @@ -0,0 +1,7 @@ +package gloddy.persistence.article.repository + +import gloddy.persistence.article.ArticleJpaEntity +import org.springframework.data.jpa.repository.JpaRepository + +interface ArticleJpaRepository : JpaRepository { +} \ No newline at end of file From 52bf4b7d9bd2f4374e104313c12241e017dd7c50 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Thu, 4 Jan 2024 19:38:57 +0900 Subject: [PATCH 18/58] =?UTF-8?q?feat:=20ArticleLike=20Jpa=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/article/ArticleLikeJpaEntity.kt | 16 ++++++++++++++++ .../repository/ArticleLikeJpaRepository.kt | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleLikeJpaEntity.kt create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleLikeJpaRepository.kt diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleLikeJpaEntity.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleLikeJpaEntity.kt new file mode 100644 index 0000000..2708f84 --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleLikeJpaEntity.kt @@ -0,0 +1,16 @@ +package gloddy.persistence.article + +import jakarta.persistence.* + +@Entity +@Table(name = "article_like") +class ArticleLikeJpaEntity( + val userId: Long, + @field:ManyToOne(fetch = FetchType.LAZY) + @field:JoinColumn(name = "article_id") + val article: ArticleJpaEntity, + @field:Id + @field:GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long? = null +) { +} \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleLikeJpaRepository.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleLikeJpaRepository.kt new file mode 100644 index 0000000..3ae23ad --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleLikeJpaRepository.kt @@ -0,0 +1,7 @@ +package gloddy.persistence.article.repository + +import gloddy.persistence.article.ArticleLikeJpaEntity +import org.springframework.data.jpa.repository.JpaRepository + +interface ArticleLikeJpaRepository : JpaRepository { +} \ No newline at end of file From a930f4060294413b2229b1601d971c982e14c14a Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Thu, 4 Jan 2024 19:39:27 +0900 Subject: [PATCH 19/58] =?UTF-8?q?feat:=20persistence=20util=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EC=9E=91=EC=84=B1(mapper,=20converter)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/converter/StringArrayConverter.kt | 28 +++++++++++ .../persistence/util/mapper/ArticleMapper.kt | 47 +++++++++++++++++++ .../persistence/util/mapper/CategoryMapper.kt | 17 +++++++ 3 files changed, 92 insertions(+) create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/util/converter/StringArrayConverter.kt create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/util/mapper/ArticleMapper.kt create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/util/mapper/CategoryMapper.kt diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/util/converter/StringArrayConverter.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/util/converter/StringArrayConverter.kt new file mode 100644 index 0000000..eeedbda --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/util/converter/StringArrayConverter.kt @@ -0,0 +1,28 @@ +package gloddy.persistence.util.converter + +import jakarta.persistence.AttributeConverter +import jakarta.persistence.Converter + +@Converter +class StringArrayConverter : AttributeConverter, String> { + + companion object { + private const val DELIMITER = "," + } + + override fun convertToDatabaseColumn(attribute: List?): String? { + if (attribute.isNullOrEmpty()) { + return null + } + return attribute.joinToString(DELIMITER) + } + + override fun convertToEntityAttribute(dbData: String?): List { + if (dbData.isNullOrEmpty()) { + return emptyList() + } + return dbData.split(DELIMITER) + .filter { it.isNotEmpty() } + .toList() + } +} \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/util/mapper/ArticleMapper.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/util/mapper/ArticleMapper.kt new file mode 100644 index 0000000..ee4ca61 --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/util/mapper/ArticleMapper.kt @@ -0,0 +1,47 @@ +package gloddy.persistence.util.mapper + +import gloddy.article.Article +import gloddy.article.ArticleLike +import gloddy.article.vo.ArticleImage +import gloddy.core.ArticleId +import gloddy.core.UserId +import gloddy.persistence.article.ArticleJpaEntity +import gloddy.persistence.article.ArticleLikeJpaEntity + +fun Article.toEntity() : ArticleJpaEntity = + ArticleJpaEntity( + userId = this.userId.value, + category = this.category.toEntity(), + title = this.title, + content = this.content, + images = this.image.images, + commentCount = this.commentCount, + likeCount = this.likeCount, + id = this.id?.value + ) + +fun ArticleJpaEntity.toDomain() : Article = + Article( + userId = UserId(this.userId), + category = this.category.toDomain(), + title = this.title, + content = this.content, + image = ArticleImage(this.images), + commentCount = this.commentCount, + likeCount = this.likeCount, + id = ArticleId(this.id!!) + ) + +fun ArticleLike.toEntity() : ArticleLikeJpaEntity = + ArticleLikeJpaEntity( + userId = this.userId.value, + article = this.article.toEntity(), + id = this.id + ) + +fun ArticleLikeJpaEntity.toDomain() : ArticleLike = + ArticleLike( + userId = UserId(this.userId), + article = this.article.toDomain(), + id = this.id + ) \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/util/mapper/CategoryMapper.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/util/mapper/CategoryMapper.kt new file mode 100644 index 0000000..ba5777e --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/util/mapper/CategoryMapper.kt @@ -0,0 +1,17 @@ +package gloddy.persistence.util.mapper + +import gloddy.category.Category +import gloddy.core.CategoryId +import gloddy.persistence.category.CategoryJpaEntity + +fun Category.toEntity() : CategoryJpaEntity = + CategoryJpaEntity( + name = this.name, + id = this.id?.value + ) + +fun CategoryJpaEntity.toDomain() : Category = + Category( + name = this.name, + id = CategoryId(this.id!!) + ) \ No newline at end of file From 1dbbbc0a44bf9c4f92b1feaf09778e1402b85704 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Thu, 4 Jan 2024 19:40:00 +0900 Subject: [PATCH 20/58] =?UTF-8?q?test:=20infrastructure=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=99=98=EA=B2=BD=20?= =?UTF-8?q?=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gloddy/InfrastructureTestContextLoader.kt | 8 ++++++++ .../src/test/resources/application-test.yml | 15 +++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 community-infrastructure/src/test/kotlin/gloddy/InfrastructureTestContextLoader.kt create mode 100644 community-infrastructure/src/test/resources/application-test.yml diff --git a/community-infrastructure/src/test/kotlin/gloddy/InfrastructureTestContextLoader.kt b/community-infrastructure/src/test/kotlin/gloddy/InfrastructureTestContextLoader.kt new file mode 100644 index 0000000..dcb7ec6 --- /dev/null +++ b/community-infrastructure/src/test/kotlin/gloddy/InfrastructureTestContextLoader.kt @@ -0,0 +1,8 @@ +package gloddy + +import org.springframework.boot.autoconfigure.SpringBootApplication + +@SpringBootApplication +class InfrastructureTestContextLoader { + fun contextLoads() {} +} diff --git a/community-infrastructure/src/test/resources/application-test.yml b/community-infrastructure/src/test/resources/application-test.yml new file mode 100644 index 0000000..a51b998 --- /dev/null +++ b/community-infrastructure/src/test/resources/application-test.yml @@ -0,0 +1,15 @@ +spring: + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:community;MODE=MYSQL;DATABASE_TO_UPPER=false + username: sa + password: + + jpa: + hibernate: + ddl-auto: create + properties: + hibernate: + dialect: org.hibernate.dialect.H2Dialect + format_sql: true + show-sql: true \ No newline at end of file From e1f54a6d1e338826ba25fa872feee07afafb92bd Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 15:45:50 +0900 Subject: [PATCH 21/58] =?UTF-8?q?chore:=20.gitkeep=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/test/kotlin/gloddy/.gitkeep | 0 .../kotlin/gloddy}/ArticleFixture.kt | 0 .../kotlin/gloddy}/CategoryFixture.kt | 0 .../src/test/resources/application-test.yml | 15 --------------- 4 files changed, 15 deletions(-) delete mode 100644 community-application/src/test/kotlin/gloddy/.gitkeep rename community-domain/src/{test/kotlin/gloddy/fixture => testFixtures/kotlin/gloddy}/ArticleFixture.kt (100%) rename community-domain/src/{test/kotlin/gloddy/fixture => testFixtures/kotlin/gloddy}/CategoryFixture.kt (100%) delete mode 100644 community-infrastructure/src/test/resources/application-test.yml diff --git a/community-application/src/test/kotlin/gloddy/.gitkeep b/community-application/src/test/kotlin/gloddy/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/community-domain/src/test/kotlin/gloddy/fixture/ArticleFixture.kt b/community-domain/src/testFixtures/kotlin/gloddy/ArticleFixture.kt similarity index 100% rename from community-domain/src/test/kotlin/gloddy/fixture/ArticleFixture.kt rename to community-domain/src/testFixtures/kotlin/gloddy/ArticleFixture.kt diff --git a/community-domain/src/test/kotlin/gloddy/fixture/CategoryFixture.kt b/community-domain/src/testFixtures/kotlin/gloddy/CategoryFixture.kt similarity index 100% rename from community-domain/src/test/kotlin/gloddy/fixture/CategoryFixture.kt rename to community-domain/src/testFixtures/kotlin/gloddy/CategoryFixture.kt diff --git a/community-infrastructure/src/test/resources/application-test.yml b/community-infrastructure/src/test/resources/application-test.yml deleted file mode 100644 index a51b998..0000000 --- a/community-infrastructure/src/test/resources/application-test.yml +++ /dev/null @@ -1,15 +0,0 @@ -spring: - datasource: - driver-class-name: org.h2.Driver - url: jdbc:h2:mem:community;MODE=MYSQL;DATABASE_TO_UPPER=false - username: sa - password: - - jpa: - hibernate: - ddl-auto: create - properties: - hibernate: - dialect: org.hibernate.dialect.H2Dialect - format_sql: true - show-sql: true \ No newline at end of file From ef2f9f590885b8674327a1c3e04adecf4b7dc9b9 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 15:46:56 +0900 Subject: [PATCH 22/58] =?UTF-8?q?chore:=20domain=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=EC=97=90=20testFixture=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- community-application/build.gradle.kts | 1 + community-domain/build.gradle.kts | 3 +++ community-infrastructure/build.gradle.kts | 1 + 3 files changed, 5 insertions(+) diff --git a/community-application/build.gradle.kts b/community-application/build.gradle.kts index 4152bd0..4fd57e4 100644 --- a/community-application/build.gradle.kts +++ b/community-application/build.gradle.kts @@ -13,4 +13,5 @@ dependencies { implementation("org.springframework:spring-context") implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") implementation("jakarta.validation:jakarta.validation-api") + testImplementation(testFixtures(project(":community-domain"))) } diff --git a/community-domain/build.gradle.kts b/community-domain/build.gradle.kts index 121c644..b95847b 100644 --- a/community-domain/build.gradle.kts +++ b/community-domain/build.gradle.kts @@ -6,6 +6,9 @@ val bootJar: BootJar by tasks bootJar.enabled = false jar.enabled = true +plugins { + id("java-test-fixtures") +} dependencies { } diff --git a/community-infrastructure/build.gradle.kts b/community-infrastructure/build.gradle.kts index a6596f1..1f8cff6 100644 --- a/community-infrastructure/build.gradle.kts +++ b/community-infrastructure/build.gradle.kts @@ -20,6 +20,7 @@ dependencies { runtimeOnly("com.h2database:h2") runtimeOnly("com.mysql:mysql-connector-j") implementation("org.springframework.cloud:spring-cloud-starter-openfeign") + testImplementation(testFixtures(project(":community-domain"))) testImplementation("org.springframework.boot:spring-boot-starter-test") } From cbd48deb5d51d4df2f399d8055fd0668bb5b3f7c Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 15:48:41 +0900 Subject: [PATCH 23/58] =?UTF-8?q?feat:=20ArticleCommandPersistenceAdapter?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20save=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/out/ArticleCommandPersistencePort.kt | 7 +++++++ .../ArticleCommandPersistenceAdapter.kt | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt diff --git a/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt new file mode 100644 index 0000000..9fb04ea --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt @@ -0,0 +1,7 @@ +package gloddy.article.port.out + +import gloddy.article.Article + +interface ArticleCommandPersistencePort { + fun save(article: Article) : Article +} \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt new file mode 100644 index 0000000..9a41717 --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt @@ -0,0 +1,18 @@ +package gloddy.persistence.article.adapter + +import gloddy.article.Article +import gloddy.article.port.out.ArticleCommandPersistencePort +import gloddy.persistence.article.repository.ArticleJpaRepository +import gloddy.persistence.util.mapper.toDomain +import gloddy.persistence.util.mapper.toEntity +import org.springframework.stereotype.Component + +@Component +class ArticleCommandPersistenceAdapter( + private val articleJpaRepository: ArticleJpaRepository +) : ArticleCommandPersistencePort { + + override fun save(article: Article): Article { + return articleJpaRepository.save(article.toEntity()).toDomain() + } +} \ No newline at end of file From 0dd026043d1fea8eb3486f8350c04107931ffc54 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 15:49:55 +0900 Subject: [PATCH 24/58] =?UTF-8?q?test:=20ArticleCommandPersistenceAdapter?= =?UTF-8?q?=20save=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/gloddy/article/Article.kt | 4 +- .../gloddy/article/ArticleCreateTest.kt | 9 ++-- .../gloddy/article/ArticleLikeCreateTest.kt | 2 +- .../kotlin/gloddy/ArticleFixture.kt | 14 +++--- .../kotlin/gloddy/CategoryFixture.kt | 2 +- .../src/test/kotlin/gloddy/PersistenceTest.kt | 37 ++++++++++++++++ .../ArticleCommandPersistenceAdapterTest.kt | 43 +++++++++++++++++++ .../src/test/resources/application-test.yml | 15 +++++++ 8 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt create mode 100644 community-infrastructure/src/test/kotlin/gloddy/article/ArticleCommandPersistenceAdapterTest.kt create mode 100644 community-infrastructure/src/test/resources/application-test.yml diff --git a/community-domain/src/main/kotlin/gloddy/article/Article.kt b/community-domain/src/main/kotlin/gloddy/article/Article.kt index c17c6b2..ba839a8 100644 --- a/community-domain/src/main/kotlin/gloddy/article/Article.kt +++ b/community-domain/src/main/kotlin/gloddy/article/Article.kt @@ -20,14 +20,14 @@ data class Article( category: Category, title: String, content: String, - imageList: List?, + images: List?, id: ArticleId? = null ) : this( userId = userId, category = category, title = title, content = content, - image = ArticleImage(imageList), + image = ArticleImage(images), id = id ) } \ No newline at end of file diff --git a/community-domain/src/test/kotlin/gloddy/article/ArticleCreateTest.kt b/community-domain/src/test/kotlin/gloddy/article/ArticleCreateTest.kt index 5638575..98373b2 100644 --- a/community-domain/src/test/kotlin/gloddy/article/ArticleCreateTest.kt +++ b/community-domain/src/test/kotlin/gloddy/article/ArticleCreateTest.kt @@ -2,11 +2,8 @@ package gloddy.article import gloddy.article.exception.ArticleImageSizeOverException import gloddy.article.vo.ArticleImage -import gloddy.category.Category -import gloddy.core.CategoryId import gloddy.core.UserId -import gloddy.fixture.CategoryFixture -import gloddy.fixture.CategoryFixture.* +import gloddy.CategoryFixture.* import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test @@ -37,7 +34,7 @@ class ArticleCreateTest { category = category, title = "title", content = "content", - imageList = image + images = image ) assertEquals(article.category, category) @@ -55,7 +52,7 @@ class ArticleCreateTest { category = K_POP.toPersistDomain(1L), title = "title", content = "content", - imageList = listOf("image1", "image2", "image3", "image4") + images = listOf("image1", "image2", "image3", "image4") ) } } diff --git a/community-domain/src/test/kotlin/gloddy/article/ArticleLikeCreateTest.kt b/community-domain/src/test/kotlin/gloddy/article/ArticleLikeCreateTest.kt index 1d057b9..de383b4 100644 --- a/community-domain/src/test/kotlin/gloddy/article/ArticleLikeCreateTest.kt +++ b/community-domain/src/test/kotlin/gloddy/article/ArticleLikeCreateTest.kt @@ -1,7 +1,7 @@ package gloddy.article import gloddy.core.UserId -import gloddy.fixture.ArticleFixture.* +import gloddy.ArticleFixture.* import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test diff --git a/community-domain/src/testFixtures/kotlin/gloddy/ArticleFixture.kt b/community-domain/src/testFixtures/kotlin/gloddy/ArticleFixture.kt index 2bb08a5..56f3780 100644 --- a/community-domain/src/testFixtures/kotlin/gloddy/ArticleFixture.kt +++ b/community-domain/src/testFixtures/kotlin/gloddy/ArticleFixture.kt @@ -1,11 +1,11 @@ -package gloddy.fixture +package gloddy import gloddy.article.Article import gloddy.article.vo.ArticleImage import gloddy.category.Category import gloddy.core.ArticleId import gloddy.core.UserId -import gloddy.fixture.CategoryFixture.* +import gloddy.CategoryFixture.* enum class ArticleFixture( private val userId: UserId?, @@ -14,21 +14,21 @@ enum class ArticleFixture( private val content: String, private val image: ArticleImage, ) { - JIHWAN(null, QNA.toPersistDomain(1L), "한국 핫플", "요즘 한국 핫플이 어디에용?", ArticleImage(null)); + JIHWAN(null, QNA.toPersistDomain(2L), "한국 핫플", "요즘 한국 핫플이 어디에용?", ArticleImage(null)); - fun toDomain(userId: Long): Article = + fun toDomain(userId: Long, category: Category? = null): Article = Article( userId = UserId(userId), - category = this.category!!, + category = category ?: this.category!!, title = this.title, content = this.content, image = this.image ) - fun toPersistDomain(userId: Long, id: Long): Article = + fun toPersistDomain(userId: Long, id: Long, category: Category? = null): Article = Article( userId = UserId(userId), - category = this.category!!, + category = category ?: this.category!!, title = this.title, content = this.content, image = this.image, diff --git a/community-domain/src/testFixtures/kotlin/gloddy/CategoryFixture.kt b/community-domain/src/testFixtures/kotlin/gloddy/CategoryFixture.kt index e3b2b6f..28cbf18 100644 --- a/community-domain/src/testFixtures/kotlin/gloddy/CategoryFixture.kt +++ b/community-domain/src/testFixtures/kotlin/gloddy/CategoryFixture.kt @@ -1,4 +1,4 @@ -package gloddy.fixture +package gloddy import gloddy.category.Category import gloddy.core.CategoryId diff --git a/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt b/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt new file mode 100644 index 0000000..2bd3cbc --- /dev/null +++ b/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt @@ -0,0 +1,37 @@ +package gloddy + +import gloddy.category.Category +import gloddy.persistence.article.repository.ArticleJpaRepository +import gloddy.persistence.category.repository.CategoryJpaRepository +import gloddy.persistence.util.mapper.toDomain +import gloddy.persistence.util.mapper.toEntity +import jakarta.persistence.EntityManager +import org.junit.jupiter.api.BeforeEach +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.test.context.ActiveProfiles + +@DataJpaTest +@ActiveProfiles("test") +abstract class PersistenceTest { + + protected lateinit var CATEGORY: List + @Autowired + protected lateinit var categoryJpaRepository: CategoryJpaRepository + @Autowired + protected lateinit var articleJpaRepository: ArticleJpaRepository + @Autowired + protected lateinit var em: EntityManager + + @BeforeEach + fun init() { + val categories = categoryJpaRepository.saveAll( + CategoryFixture.values().map { + it.toDomain().toEntity() + } + ) + CATEGORY = categories.map { it.toDomain() } + em.flush() + em.clear() + } +} \ No newline at end of file diff --git a/community-infrastructure/src/test/kotlin/gloddy/article/ArticleCommandPersistenceAdapterTest.kt b/community-infrastructure/src/test/kotlin/gloddy/article/ArticleCommandPersistenceAdapterTest.kt new file mode 100644 index 0000000..c953f96 --- /dev/null +++ b/community-infrastructure/src/test/kotlin/gloddy/article/ArticleCommandPersistenceAdapterTest.kt @@ -0,0 +1,43 @@ +package gloddy.article + +import gloddy.ArticleFixture +import gloddy.PersistenceTest +import gloddy.persistence.article.adapter.ArticleCommandPersistenceAdapter +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +@DisplayName("ArticleCommandPersistenceAdapterTest의") +class ArticleCommandPersistenceAdapterTest : PersistenceTest() { + + private val USER_ID = 1L + private lateinit var article: Article + + private lateinit var articleCommandPersistenceAdapter: ArticleCommandPersistenceAdapter + + @BeforeEach + fun setUp() { + article = ArticleFixture.JIHWAN.toDomain(USER_ID, CATEGORY[0]) + articleCommandPersistenceAdapter = ArticleCommandPersistenceAdapter(articleJpaRepository) + } + + @Nested + @DisplayName("save 메소드는") + inner class Save { + + @Test + @DisplayName("Article 도메인 입력을 받으면 DB에 저장하고 반환한다.") + fun success_save_and_returns() { + //given & when + val savedArticle = articleCommandPersistenceAdapter.save(article) + + //then + assertNotNull(savedArticle.id) + assertEquals(savedArticle.userId.value, USER_ID) + assertEquals(savedArticle.commentCount, 0) + assertEquals(savedArticle.likeCount, 0) + } + } +} \ No newline at end of file diff --git a/community-infrastructure/src/test/resources/application-test.yml b/community-infrastructure/src/test/resources/application-test.yml new file mode 100644 index 0000000..a51b998 --- /dev/null +++ b/community-infrastructure/src/test/resources/application-test.yml @@ -0,0 +1,15 @@ +spring: + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:community;MODE=MYSQL;DATABASE_TO_UPPER=false + username: sa + password: + + jpa: + hibernate: + ddl-auto: create + properties: + hibernate: + dialect: org.hibernate.dialect.H2Dialect + format_sql: true + show-sql: true \ No newline at end of file From f030a941aae09be7fbceb7ab8f7334a7f18bf1a8 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 15:50:31 +0900 Subject: [PATCH 25/58] =?UTF-8?q?feat:=20CategoryQueryPersistenceAdapter?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20findById=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/out/CategoryQueryPersistencePort.kt | 8 ++++++++ .../CategoryQueryPersistenceAdapter.kt | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 community-application/src/main/kotlin/gloddy/category/port/out/CategoryQueryPersistencePort.kt create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/category/adapter/CategoryQueryPersistenceAdapter.kt diff --git a/community-application/src/main/kotlin/gloddy/category/port/out/CategoryQueryPersistencePort.kt b/community-application/src/main/kotlin/gloddy/category/port/out/CategoryQueryPersistencePort.kt new file mode 100644 index 0000000..519ed8a --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/category/port/out/CategoryQueryPersistencePort.kt @@ -0,0 +1,8 @@ +package gloddy.category.port.out + +import gloddy.category.Category +import gloddy.core.CategoryId + +interface CategoryQueryPersistencePort { + fun findById(id: CategoryId): Category +} \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/category/adapter/CategoryQueryPersistenceAdapter.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/category/adapter/CategoryQueryPersistenceAdapter.kt new file mode 100644 index 0000000..bdf7a75 --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/category/adapter/CategoryQueryPersistenceAdapter.kt @@ -0,0 +1,20 @@ +package gloddy.persistence.category.adapter + +import gloddy.category.Category +import gloddy.category.exception.CategoryNotFoundException +import gloddy.category.port.out.CategoryQueryPersistencePort +import gloddy.core.CategoryId +import gloddy.persistence.category.repository.CategoryJpaRepository +import gloddy.persistence.util.mapper.toDomain +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Component + +@Component +class CategoryQueryPersistenceAdapter( + private val categoryJpaRepository: CategoryJpaRepository, +) : CategoryQueryPersistencePort { + + override fun findById(id: CategoryId): Category { + return (categoryJpaRepository.findByIdOrNull(id.value) ?: throw CategoryNotFoundException()).toDomain() + } +} \ No newline at end of file From ad2bdb96481dce257b7e41f24e62d61269d9e423 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 15:51:20 +0900 Subject: [PATCH 26/58] =?UTF-8?q?feat:=20ArticleCommandService=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20create=20=EB=A9=94=EC=86=8C=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/command/ArticleCreateCommand.kt | 12 +++++++ .../article/dto/response/ArticleIdResponse.kt | 7 ++++ .../article/port/in/ArticleCommandUseCase.kt | 9 ++++++ .../article/service/ArticleCommandService.kt | 32 +++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 community-application/src/main/kotlin/gloddy/article/dto/command/ArticleCreateCommand.kt create mode 100644 community-application/src/main/kotlin/gloddy/article/dto/response/ArticleIdResponse.kt create mode 100644 community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt create mode 100644 community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt diff --git a/community-application/src/main/kotlin/gloddy/article/dto/command/ArticleCreateCommand.kt b/community-application/src/main/kotlin/gloddy/article/dto/command/ArticleCreateCommand.kt new file mode 100644 index 0000000..8c89b91 --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/article/dto/command/ArticleCreateCommand.kt @@ -0,0 +1,12 @@ +package gloddy.article.dto.command + +import gloddy.core.CategoryId +import gloddy.core.UserId + +data class ArticleCreateCommand( + val userId: UserId, + val categoryId: CategoryId, + val title: String, + val content: String, + val images: List, +) diff --git a/community-application/src/main/kotlin/gloddy/article/dto/response/ArticleIdResponse.kt b/community-application/src/main/kotlin/gloddy/article/dto/response/ArticleIdResponse.kt new file mode 100644 index 0000000..c7dc991 --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/article/dto/response/ArticleIdResponse.kt @@ -0,0 +1,7 @@ +package gloddy.article.dto.response + +import gloddy.core.ArticleId + +data class ArticleIdResponse( + val articleId: ArticleId +) \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt new file mode 100644 index 0000000..8114b8e --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt @@ -0,0 +1,9 @@ +package gloddy.article.port.`in` + +import gloddy.article.dto.command.ArticleCreateCommand +import gloddy.article.dto.response.ArticleIdResponse +import gloddy.core.UserId + +interface ArticleCommandUseCase { + fun create(command: ArticleCreateCommand): ArticleIdResponse +} \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt new file mode 100644 index 0000000..adecb7f --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt @@ -0,0 +1,32 @@ +package gloddy.article.service + +import gloddy.article.Article +import gloddy.article.dto.command.ArticleCreateCommand +import gloddy.article.dto.response.ArticleIdResponse +import gloddy.article.port.`in`.ArticleCommandUseCase +import gloddy.article.port.out.ArticleCommandPersistencePort +import gloddy.category.port.out.CategoryQueryPersistencePort +import gloddy.core.ArticleId +import gloddy.core.UserId +import org.springframework.stereotype.Service + +@Service +class ArticleCommandService( + private val categoryQueryPersistencePort: CategoryQueryPersistencePort, + private val articleCommandPersistencePort: ArticleCommandPersistencePort, +) : ArticleCommandUseCase { + + override fun create(command: ArticleCreateCommand) : ArticleIdResponse { + + val category = categoryQueryPersistencePort.findById(command.categoryId) + + val article = Article( + userId = command.userId, + category = category, + title = command.title, + content = command.content, + images = command.images, + ).let { articleCommandPersistencePort.save(it) } + return ArticleIdResponse(articleId = article.id!!) + } +} \ No newline at end of file From c213c7a5fcbc669f7b3c6b9b2d479cbe32d6990a Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 15:51:44 +0900 Subject: [PATCH 27/58] =?UTF-8?q?test:=20Application=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=99=98=EA=B2=BD=20=EA=B5=AC?= =?UTF-8?q?=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/test/kotlin/gloddy/ServiceTest.kt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 community-application/src/test/kotlin/gloddy/ServiceTest.kt diff --git a/community-application/src/test/kotlin/gloddy/ServiceTest.kt b/community-application/src/test/kotlin/gloddy/ServiceTest.kt new file mode 100644 index 0000000..c0201c3 --- /dev/null +++ b/community-application/src/test/kotlin/gloddy/ServiceTest.kt @@ -0,0 +1,8 @@ +package gloddy + +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.junit.jupiter.MockitoExtension + +@ExtendWith(MockitoExtension::class) +abstract class ServiceTest { +} \ No newline at end of file From 48a0c5fd3c6086e269466619de5a7bc33187ed83 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 19:05:20 +0900 Subject: [PATCH 28/58] =?UTF-8?q?feat:=20ArticleQueryPersistenceAdapter=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20findById=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/out/ArticleQueryPersistencePort.kt | 7 +++++++ .../adapter/ArticleQueryPersistenceAdapter.kt | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 community-application/src/main/kotlin/gloddy/article/port/out/ArticleQueryPersistencePort.kt create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleQueryPersistenceAdapter.kt diff --git a/community-application/src/main/kotlin/gloddy/article/port/out/ArticleQueryPersistencePort.kt b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleQueryPersistencePort.kt new file mode 100644 index 0000000..01f2379 --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleQueryPersistencePort.kt @@ -0,0 +1,7 @@ +package gloddy.article.port.out + +import gloddy.article.Article + +interface ArticleQueryPersistencePort { + fun findById(id: Long): Article +} \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleQueryPersistenceAdapter.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleQueryPersistenceAdapter.kt new file mode 100644 index 0000000..8bbe04b --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleQueryPersistenceAdapter.kt @@ -0,0 +1,19 @@ +package gloddy.persistence.article.adapter + +import gloddy.article.Article +import gloddy.article.exception.ArticleNotFoundException +import gloddy.article.port.out.ArticleQueryPersistencePort +import gloddy.persistence.article.repository.ArticleJpaRepository +import gloddy.persistence.util.mapper.toDomain +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Component + +@Component +class ArticleQueryPersistenceAdapter( + private val articleJpaRepository: ArticleJpaRepository, +) : ArticleQueryPersistencePort { + + override fun findById(id: Long): Article { + return (articleJpaRepository.findByIdOrNull(id) ?: throw ArticleNotFoundException()).toDomain() + } +} \ No newline at end of file From 5b159f0e158d0d36085f921b5e9a786ba33a1372 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 19:07:02 +0900 Subject: [PATCH 29/58] =?UTF-8?q?feat:=20BaseTimeEntity=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20Article,=20ArticleLike=20jpa=20?= =?UTF-8?q?=EB=AA=A8=EB=8D=B8=EC=97=90=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/article/ArticleJpaEntity.kt | 6 +++++- .../article/ArticleLikeJpaEntity.kt | 3 ++- .../persistence/common/BaseTimeEntity.kt | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/common/BaseTimeEntity.kt diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleJpaEntity.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleJpaEntity.kt index 4fd770d..1c20eec 100644 --- a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleJpaEntity.kt +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleJpaEntity.kt @@ -1,6 +1,7 @@ package gloddy.persistence.article import gloddy.persistence.category.CategoryJpaEntity +import gloddy.persistence.common.BaseTimeEntity import gloddy.persistence.util.converter.StringArrayConverter import jakarta.persistence.* import org.hibernate.annotations.SQLRestriction @@ -34,5 +35,8 @@ class ArticleJpaEntity( @field:Id @field:GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long? = null, -) { +) : BaseTimeEntity() { + fun changeDeletedToTrue() { + this.deleted = true + } } \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleLikeJpaEntity.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleLikeJpaEntity.kt index 2708f84..931504a 100644 --- a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleLikeJpaEntity.kt +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/ArticleLikeJpaEntity.kt @@ -1,5 +1,6 @@ package gloddy.persistence.article +import gloddy.persistence.common.BaseTimeEntity import jakarta.persistence.* @Entity @@ -12,5 +13,5 @@ class ArticleLikeJpaEntity( @field:Id @field:GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long? = null -) { +) : BaseTimeEntity() { } \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/common/BaseTimeEntity.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/common/BaseTimeEntity.kt new file mode 100644 index 0000000..0489782 --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/common/BaseTimeEntity.kt @@ -0,0 +1,18 @@ +package gloddy.persistence.common + +import jakarta.persistence.Column +import jakarta.persistence.MappedSuperclass +import org.springframework.data.annotation.CreatedDate +import org.springframework.data.annotation.LastModifiedDate +import java.time.LocalDateTime + +@MappedSuperclass +open class BaseTimeEntity( + @Column(name = "created_at") + @CreatedDate + var createdAt: LocalDateTime? = null, + @Column(name = "updated_at") + @LastModifiedDate + var updatedAt: LocalDateTime? = null +) { +} \ No newline at end of file From 9f3375cbdb533febb6787b476298ff2704c1efee Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 19:07:55 +0900 Subject: [PATCH 30/58] =?UTF-8?q?feat:=20Article=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B6=8C=ED=95=9C=20=EA=B4=80=EB=A0=A8=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EB=B0=8F=20=EC=98=88=EC=99=B8=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/gloddy/article/ArticleErrorCode.kt | 3 ++- .../article/exception/ArticleNoAuthorizationException.kt | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 community-domain/src/main/kotlin/gloddy/article/exception/ArticleNoAuthorizationException.kt diff --git a/community-domain/src/main/kotlin/gloddy/article/ArticleErrorCode.kt b/community-domain/src/main/kotlin/gloddy/article/ArticleErrorCode.kt index 0536c90..b545490 100644 --- a/community-domain/src/main/kotlin/gloddy/article/ArticleErrorCode.kt +++ b/community-domain/src/main/kotlin/gloddy/article/ArticleErrorCode.kt @@ -8,5 +8,6 @@ enum class ArticleErrorCode( override val message: String ) : ErrorCode { NOT_FOUND(400, "ARTICLE_001", "해당 게시글을 찾을 수 없습니다."), - IMAGE_SIZE_OVER(400, "ARTICLE_002", "게시글에 이미지는 최대 3개 입니다.") + IMAGE_SIZE_OVER(400, "ARTICLE_002", "게시글에 이미지는 최대 3개 입니다."), + NO_AUTHORIZATION(401, "ARTICLE_003", "해당 게시글에 권한이 없습니다.") } \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/article/exception/ArticleNoAuthorizationException.kt b/community-domain/src/main/kotlin/gloddy/article/exception/ArticleNoAuthorizationException.kt new file mode 100644 index 0000000..be68c5a --- /dev/null +++ b/community-domain/src/main/kotlin/gloddy/article/exception/ArticleNoAuthorizationException.kt @@ -0,0 +1,6 @@ +package gloddy.article.exception + +import gloddy.article.ArticleErrorCode +import gloddy.core.GloddyCommunityException + +class ArticleNoAuthorizationException : GloddyCommunityException(ArticleErrorCode.NO_AUTHORIZATION) \ No newline at end of file From dd814492f470e1ee5a7e273dc86658e5d2f64703 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 19:08:35 +0900 Subject: [PATCH 31/58] =?UTF-8?q?feat:=20Article=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B6=8C=ED=95=9C=20=EA=B2=80=EC=82=AC=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- community-domain/src/main/kotlin/gloddy/article/Article.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/community-domain/src/main/kotlin/gloddy/article/Article.kt b/community-domain/src/main/kotlin/gloddy/article/Article.kt index ba839a8..137524e 100644 --- a/community-domain/src/main/kotlin/gloddy/article/Article.kt +++ b/community-domain/src/main/kotlin/gloddy/article/Article.kt @@ -1,5 +1,6 @@ package gloddy.article +import gloddy.article.exception.ArticleNoAuthorizationException import gloddy.article.vo.ArticleImage import gloddy.category.Category import gloddy.core.ArticleId @@ -30,4 +31,10 @@ data class Article( image = ArticleImage(images), id = id ) + + fun validateAuthorization(userId: Long) { + if (this.userId.value != userId) { + throw ArticleNoAuthorizationException() + } + } } \ No newline at end of file From d8f9e048792694ae8c81f7aa32eb4f597fa62710 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 19:09:06 +0900 Subject: [PATCH 32/58] =?UTF-8?q?feat:=20ArticleCommandPersistenceAdapter?= =?UTF-8?q?=EC=97=90=20delete=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/out/ArticleCommandPersistencePort.kt | 1 + .../adapter/ArticleCommandPersistenceAdapter.kt | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt index 9fb04ea..155a266 100644 --- a/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt +++ b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt @@ -4,4 +4,5 @@ import gloddy.article.Article interface ArticleCommandPersistencePort { fun save(article: Article) : Article + fun delete(id: Long) } \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt index 9a41717..bdaca04 100644 --- a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt @@ -1,13 +1,18 @@ package gloddy.persistence.article.adapter import gloddy.article.Article +import gloddy.article.exception.ArticleNotFoundException import gloddy.article.port.out.ArticleCommandPersistencePort +import gloddy.persistence.article.ArticleJpaEntity import gloddy.persistence.article.repository.ArticleJpaRepository import gloddy.persistence.util.mapper.toDomain import gloddy.persistence.util.mapper.toEntity +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional @Component +@Transactional class ArticleCommandPersistenceAdapter( private val articleJpaRepository: ArticleJpaRepository ) : ArticleCommandPersistencePort { @@ -15,4 +20,13 @@ class ArticleCommandPersistenceAdapter( override fun save(article: Article): Article { return articleJpaRepository.save(article.toEntity()).toDomain() } + + override fun delete(id: Long) { + val articleJpaEntity = find(id) + articleJpaEntity.changeDeletedToTrue() + } + + fun find(id: Long): ArticleJpaEntity { + return articleJpaRepository.findByIdOrNull(id) ?: throw ArticleNotFoundException() + } } \ No newline at end of file From af0fe5150ebe0f44871148841a5a1f6085553c12 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 19:09:32 +0900 Subject: [PATCH 33/58] =?UTF-8?q?test:=20ArticleCommandPersistenceAdapter?= =?UTF-8?q?=20delete=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/test/kotlin/gloddy/PersistenceTest.kt | 4 +++ .../ArticleCommandPersistenceAdapterTest.kt | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt b/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt index 2bd3cbc..7689f59 100644 --- a/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt +++ b/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt @@ -31,6 +31,10 @@ abstract class PersistenceTest { } ) CATEGORY = categories.map { it.toDomain() } + flushAndClear() + } + + protected fun flushAndClear() { em.flush() em.clear() } diff --git a/community-infrastructure/src/test/kotlin/gloddy/article/ArticleCommandPersistenceAdapterTest.kt b/community-infrastructure/src/test/kotlin/gloddy/article/ArticleCommandPersistenceAdapterTest.kt index c953f96..be5d6b4 100644 --- a/community-infrastructure/src/test/kotlin/gloddy/article/ArticleCommandPersistenceAdapterTest.kt +++ b/community-infrastructure/src/test/kotlin/gloddy/article/ArticleCommandPersistenceAdapterTest.kt @@ -2,12 +2,16 @@ package gloddy.article import gloddy.ArticleFixture import gloddy.PersistenceTest +import gloddy.article.exception.ArticleNotFoundException import gloddy.persistence.article.adapter.ArticleCommandPersistenceAdapter +import gloddy.persistence.util.mapper.toEntity import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test +import org.springframework.data.repository.findByIdOrNull +import kotlin.properties.Delegates @DisplayName("ArticleCommandPersistenceAdapterTest의") class ArticleCommandPersistenceAdapterTest : PersistenceTest() { @@ -40,4 +44,29 @@ class ArticleCommandPersistenceAdapterTest : PersistenceTest() { assertEquals(savedArticle.likeCount, 0) } } + + @Nested + @DisplayName("delete 메소드는") + inner class Delete { + + private var articleId by Delegates.notNull() + + @BeforeEach + fun given() { + val saveArticle = articleJpaRepository.save(article.toEntity()) + articleId = saveArticle.id!! + flushAndClear() + } + + @Test + @DisplayName("articleId를 입력 받으면 해당 Article을 DB에서 조회하고 deleted 필드를 true로 변경 후 DB에 반영한다.") + fun success_delete() { + //when + articleCommandPersistenceAdapter.delete(articleId) + flushAndClear() + + //then + assertThrows(ArticleNotFoundException::class.java) { articleCommandPersistenceAdapter.find(articleId) } + } + } } \ No newline at end of file From b3fc1c5320c14b13c3b211270ae7f0da4dc7616d Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 19:10:04 +0900 Subject: [PATCH 34/58] =?UTF-8?q?feat:=20ArticleCommandService=EC=97=90=20?= =?UTF-8?q?delete=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gloddy/article/port/in/ArticleCommandUseCase.kt | 1 + .../gloddy/article/service/ArticleCommandService.kt | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt index 8114b8e..c50c2d5 100644 --- a/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt +++ b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt @@ -6,4 +6,5 @@ import gloddy.core.UserId interface ArticleCommandUseCase { fun create(command: ArticleCreateCommand): ArticleIdResponse + fun delete(userId: Long, articleId: Long) } \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt index adecb7f..77e77d0 100644 --- a/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt +++ b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt @@ -5,6 +5,7 @@ import gloddy.article.dto.command.ArticleCreateCommand import gloddy.article.dto.response.ArticleIdResponse import gloddy.article.port.`in`.ArticleCommandUseCase import gloddy.article.port.out.ArticleCommandPersistencePort +import gloddy.article.port.out.ArticleQueryPersistencePort import gloddy.category.port.out.CategoryQueryPersistencePort import gloddy.core.ArticleId import gloddy.core.UserId @@ -13,6 +14,7 @@ import org.springframework.stereotype.Service @Service class ArticleCommandService( private val categoryQueryPersistencePort: CategoryQueryPersistencePort, + private val articleQueryPersistencePort: ArticleQueryPersistencePort, private val articleCommandPersistencePort: ArticleCommandPersistencePort, ) : ArticleCommandUseCase { @@ -29,4 +31,10 @@ class ArticleCommandService( ).let { articleCommandPersistencePort.save(it) } return ArticleIdResponse(articleId = article.id!!) } + + override fun delete(userId: Long, articleId: Long) { + val article = articleQueryPersistencePort.findById(articleId) + article.validateAuthorization(userId) + articleCommandPersistencePort.delete(article.id!!.value) + } } \ No newline at end of file From 8487bc072277fe9c3910ce80a33048e48fb1db64 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 20:50:30 +0900 Subject: [PATCH 35/58] =?UTF-8?q?chore:=20.gitkeep=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- community-application/src/main/kotlin/gloddy/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 community-application/src/main/kotlin/gloddy/.gitkeep diff --git a/community-application/src/main/kotlin/gloddy/.gitkeep b/community-application/src/main/kotlin/gloddy/.gitkeep deleted file mode 100644 index e69de29..0000000 From 5e6842753cbb2b95d1e88de4ea81f7277b61bf9f Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 20:53:51 +0900 Subject: [PATCH 36/58] =?UTF-8?q?feat:=20ArticleLikeCommandPersistencAdapt?= =?UTF-8?q?er=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20save,=20delete=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/ArticleLikeCommandPersistencePort.kt | 8 +++++++ .../ArticleLikeCommandPersistenceAdapter.kt | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 community-application/src/main/kotlin/gloddy/article/port/out/ArticleLikeCommandPersistencePort.kt create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleLikeCommandPersistenceAdapter.kt diff --git a/community-application/src/main/kotlin/gloddy/article/port/out/ArticleLikeCommandPersistencePort.kt b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleLikeCommandPersistencePort.kt new file mode 100644 index 0000000..5ee5eb4 --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleLikeCommandPersistencePort.kt @@ -0,0 +1,8 @@ +package gloddy.article.port.out + +import gloddy.article.ArticleLike + +interface ArticleLikeCommandPersistencePort { + fun save(articleLike: ArticleLike): ArticleLike + fun delete(articleLike: ArticleLike) +} \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleLikeCommandPersistenceAdapter.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleLikeCommandPersistenceAdapter.kt new file mode 100644 index 0000000..a0522fb --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleLikeCommandPersistenceAdapter.kt @@ -0,0 +1,24 @@ +package gloddy.persistence.article.adapter + +import gloddy.article.ArticleLike +import gloddy.article.port.out.ArticleLikeCommandPersistencePort +import gloddy.persistence.article.repository.ArticleLikeJpaRepository +import gloddy.persistence.util.mapper.toDomain +import gloddy.persistence.util.mapper.toEntity +import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional + +@Component +@Transactional +class ArticleLikeCommandPersistenceAdapter( + private val articleLikeJpaRepository: ArticleLikeJpaRepository +) : ArticleLikeCommandPersistencePort { + + override fun save(articleLike: ArticleLike): ArticleLike { + return articleLikeJpaRepository.save(articleLike.toEntity()).toDomain() + } + + override fun delete(articleLike: ArticleLike) { + articleLikeJpaRepository.delete(articleLike.toEntity()) + } +} \ No newline at end of file From 060c9ec5e9c4d8cf46215eaf026f7397614eabee Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 20:57:21 +0900 Subject: [PATCH 37/58] =?UTF-8?q?test:=20ArticleLikeCommandPersistence=20s?= =?UTF-8?q?ave,=20delete=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...rticleLikeCommandPersistenceAdapterTest.kt | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 community-infrastructure/src/test/kotlin/gloddy/article/ArticleLikeCommandPersistenceAdapterTest.kt diff --git a/community-infrastructure/src/test/kotlin/gloddy/article/ArticleLikeCommandPersistenceAdapterTest.kt b/community-infrastructure/src/test/kotlin/gloddy/article/ArticleLikeCommandPersistenceAdapterTest.kt new file mode 100644 index 0000000..f682d2d --- /dev/null +++ b/community-infrastructure/src/test/kotlin/gloddy/article/ArticleLikeCommandPersistenceAdapterTest.kt @@ -0,0 +1,80 @@ +package gloddy.article + +import gloddy.ArticleFixture.* +import gloddy.PersistenceTest +import gloddy.core.UserId +import gloddy.persistence.article.adapter.ArticleLikeCommandPersistenceAdapter +import gloddy.persistence.util.mapper.toDomain +import gloddy.persistence.util.mapper.toEntity +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.springframework.data.repository.findByIdOrNull + +@DisplayName("ArticleLikeCommandPersistenceAdapter 클래스의") +class ArticleLikeCommandPersistenceAdapterTest: PersistenceTest() { + + private val USER_ID = 1L + private lateinit var persistedArticle: Article + + private lateinit var articleLikeCommandPersistenceAdapter: ArticleLikeCommandPersistenceAdapter + + @BeforeEach + fun setUp() { + persistedArticle = articleJpaRepository.save(JIHWAN.toDomain(USER_ID, CATEGORY[0]).toEntity()).toDomain() + articleLikeCommandPersistenceAdapter = ArticleLikeCommandPersistenceAdapter(articleLikeJpaRepository) + } + + @Nested + @DisplayName("save 메소드는") + inner class Save { + + @Test + @DisplayName("ArticleLike 도메인을 입력받고 DB에 저장하고 Id가 존재하는 ArticleLike를 반환한다.") + fun success_save_and_returns() { + //given + val articleLike = ArticleLike( + userId = UserId(USER_ID), + article = persistedArticle + ) + + //when + val saveArticleLike = articleLikeCommandPersistenceAdapter.save(articleLike) + + //then + assertNotNull(saveArticleLike.id) + assertEquals(saveArticleLike.userId.value, USER_ID) + assertEquals(saveArticleLike.article, persistedArticle) + } + } + + @Nested + @DisplayName("delete 메소드는") + inner class Delete { + + private lateinit var persistedArticleLike: ArticleLike + + @BeforeEach + fun given() { + persistedArticleLike = articleLikeCommandPersistenceAdapter.save( + ArticleLike( + userId = UserId(USER_ID), + article = persistedArticle + ) + ) + flushAndClear() + } + + @Test + @DisplayName("영속화 된 ArticleLike를 입력받고 DB에서 삭제한다.") + fun success_delete() { + //when + articleLikeCommandPersistenceAdapter.delete(persistedArticleLike) + + //then + assertNull(articleLikeJpaRepository.findByIdOrNull(persistedArticleLike.id!!)) + } + } +} \ No newline at end of file From 0334a45e041224caeba7a3a7ee3001aef0902a88 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 20:58:13 +0900 Subject: [PATCH 38/58] =?UTF-8?q?feat:=20ArticleLikeQueryPersistenceAdapte?= =?UTF-8?q?r=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20findByUserIdAndArticleOrNu?= =?UTF-8?q?ll=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArticleLikeQueryPersistenceAdapter.kt | 19 +++++++++++++++++++ .../repository/ArticleLikeJpaRepository.kt | 2 ++ 2 files changed, 21 insertions(+) create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleLikeQueryPersistenceAdapter.kt diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleLikeQueryPersistenceAdapter.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleLikeQueryPersistenceAdapter.kt new file mode 100644 index 0000000..cb63c8e --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleLikeQueryPersistenceAdapter.kt @@ -0,0 +1,19 @@ +package gloddy.persistence.article.adapter + +import gloddy.article.Article +import gloddy.article.ArticleLike +import gloddy.article.port.out.ArticleLikeQueryPersistencePort +import gloddy.persistence.article.repository.ArticleLikeJpaRepository +import gloddy.persistence.util.mapper.toDomain +import gloddy.persistence.util.mapper.toEntity +import org.springframework.stereotype.Component + +@Component +class ArticleLikeQueryPersistenceAdapter( + private val articleLikeJpaRepository: ArticleLikeJpaRepository, +) : ArticleLikeQueryPersistencePort { + + override fun findByUserIdAndArticleOrNull(userId: Long, article: Article): ArticleLike? { + return articleLikeJpaRepository.findByUserIdAndArticle(userId, article.toEntity())?.toDomain() + } +} \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleLikeJpaRepository.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleLikeJpaRepository.kt index 3ae23ad..a171c3d 100644 --- a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleLikeJpaRepository.kt +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/repository/ArticleLikeJpaRepository.kt @@ -1,7 +1,9 @@ package gloddy.persistence.article.repository +import gloddy.persistence.article.ArticleJpaEntity import gloddy.persistence.article.ArticleLikeJpaEntity import org.springframework.data.jpa.repository.JpaRepository interface ArticleLikeJpaRepository : JpaRepository { + fun findByUserIdAndArticle(userId: Long, article: ArticleJpaEntity): ArticleLikeJpaEntity? } \ No newline at end of file From 2794854d838f1ee4e685be0bf7f592ada19421ee Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 20:58:41 +0900 Subject: [PATCH 39/58] =?UTF-8?q?test:=20ArticleLikeQueryPersistence=20fin?= =?UTF-8?q?dByUserIdAndArticle=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArticleLikeQueryPersistenceTest.kt | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 community-infrastructure/src/test/kotlin/gloddy/article/ArticleLikeQueryPersistenceTest.kt diff --git a/community-infrastructure/src/test/kotlin/gloddy/article/ArticleLikeQueryPersistenceTest.kt b/community-infrastructure/src/test/kotlin/gloddy/article/ArticleLikeQueryPersistenceTest.kt new file mode 100644 index 0000000..f73705e --- /dev/null +++ b/community-infrastructure/src/test/kotlin/gloddy/article/ArticleLikeQueryPersistenceTest.kt @@ -0,0 +1,62 @@ +package gloddy.article + +import gloddy.ArticleFixture +import gloddy.PersistenceTest +import gloddy.core.UserId +import gloddy.persistence.article.adapter.ArticleLikeQueryPersistenceAdapter +import gloddy.persistence.util.mapper.toDomain +import gloddy.persistence.util.mapper.toEntity +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +@DisplayName("ArticleLikeQueryPersistence 클래스의") +class ArticleLikeQueryPersistenceTest: PersistenceTest() { + + private val USER_ID = 1L + private lateinit var persistedArticle: Article + + private lateinit var articleLikeQueryPersistenceAdapter: ArticleLikeQueryPersistenceAdapter + + @BeforeEach + fun setUp() { + persistedArticle = articleJpaRepository.save(ArticleFixture.JIHWAN.toDomain(USER_ID, CATEGORY[0]).toEntity()).toDomain() + articleLikeQueryPersistenceAdapter = ArticleLikeQueryPersistenceAdapter(articleLikeJpaRepository) + } + + @Nested + @DisplayName("findByUserIdAndArticleOrNull 메소드는") + inner class FindByUserIdAndArticleOrNull { + + @Test + @DisplayName("ArticleLike가 DB에 존재하면 반환한다.") + fun success_returns_domain_when_exist() { + //given + articleLikeJpaRepository.save(ArticleLike( + userId = UserId(USER_ID), + article = persistedArticle + ).toEntity()) + + //when + val articleLike = + articleLikeQueryPersistenceAdapter.findByUserIdAndArticleOrNull(USER_ID, persistedArticle) + + //then + assertNotNull(articleLike) + assertEquals(articleLike!!.article, persistedArticle) + } + + @Test + @DisplayName("ArticleLike가 DB에 존재하지 않으면 null을 반환한다.") + fun success_returns_null_when_no_exist() { + //when + val articleLike = + articleLikeQueryPersistenceAdapter.findByUserIdAndArticleOrNull(USER_ID, persistedArticle) + + //then + assertNull(articleLike) + } + } +} \ No newline at end of file From 13b7f6e50c5185e06bb76cab4d9fea09c292c0a4 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 20:59:18 +0900 Subject: [PATCH 40/58] =?UTF-8?q?test:=20PersistenceTest=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/test/kotlin/gloddy/PersistenceTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt b/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt index 7689f59..cf35018 100644 --- a/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt +++ b/community-infrastructure/src/test/kotlin/gloddy/PersistenceTest.kt @@ -2,6 +2,7 @@ package gloddy import gloddy.category.Category import gloddy.persistence.article.repository.ArticleJpaRepository +import gloddy.persistence.article.repository.ArticleLikeJpaRepository import gloddy.persistence.category.repository.CategoryJpaRepository import gloddy.persistence.util.mapper.toDomain import gloddy.persistence.util.mapper.toEntity @@ -21,6 +22,8 @@ abstract class PersistenceTest { @Autowired protected lateinit var articleJpaRepository: ArticleJpaRepository @Autowired + protected lateinit var articleLikeJpaRepository: ArticleLikeJpaRepository + @Autowired protected lateinit var em: EntityManager @BeforeEach From 454163b11b4dcc7d9e3227fef0b3666fb6ce3564 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 20:59:58 +0900 Subject: [PATCH 41/58] =?UTF-8?q?fix:=20ArticeLike=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=83=9D=EC=84=B1=20=EA=B2=80=EC=A6=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80(Article=EC=9D=98=20=EC=98=81=EC=86=8D=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/gloddy/article/ArticleLike.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/community-domain/src/main/kotlin/gloddy/article/ArticleLike.kt b/community-domain/src/main/kotlin/gloddy/article/ArticleLike.kt index a3ca10d..2239da2 100644 --- a/community-domain/src/main/kotlin/gloddy/article/ArticleLike.kt +++ b/community-domain/src/main/kotlin/gloddy/article/ArticleLike.kt @@ -6,4 +6,14 @@ data class ArticleLike( val userId: UserId, val article: Article, val id: Long? = null, -) +) { + init { + verifyArticle(article) + } + + private fun verifyArticle(article: Article) { + if (article.id == null) { + throw RuntimeException("ArticleLike 생성 오류 : 영속화 되지 않은 Article을 입력으로 받았습니다.") + } + } +} From 26f7d9b18a9b069c9262035e34138bc93ee50ce4 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Fri, 5 Jan 2024 21:00:30 +0900 Subject: [PATCH 42/58] =?UTF-8?q?feat:=20ArticleCommandService=EC=97=90=20?= =?UTF-8?q?like=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../article/port/in/ArticleCommandUseCase.kt | 1 + .../out/ArticleLikeQueryPersistencePort.kt | 8 ++++++++ .../article/service/ArticleCommandService.kt | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 community-application/src/main/kotlin/gloddy/article/port/out/ArticleLikeQueryPersistencePort.kt diff --git a/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt index c50c2d5..5f68a07 100644 --- a/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt +++ b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt @@ -7,4 +7,5 @@ import gloddy.core.UserId interface ArticleCommandUseCase { fun create(command: ArticleCreateCommand): ArticleIdResponse fun delete(userId: Long, articleId: Long) + fun like(userId: Long, articleId: Long) } \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/port/out/ArticleLikeQueryPersistencePort.kt b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleLikeQueryPersistencePort.kt new file mode 100644 index 0000000..c710d2c --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleLikeQueryPersistencePort.kt @@ -0,0 +1,8 @@ +package gloddy.article.port.out + +import gloddy.article.Article +import gloddy.article.ArticleLike + +interface ArticleLikeQueryPersistencePort { + fun findByUserIdAndArticleOrNull(userId: Long, article: Article): ArticleLike? +} \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt index 77e77d0..26745a0 100644 --- a/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt +++ b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt @@ -1,10 +1,13 @@ package gloddy.article.service import gloddy.article.Article +import gloddy.article.ArticleLike import gloddy.article.dto.command.ArticleCreateCommand import gloddy.article.dto.response.ArticleIdResponse import gloddy.article.port.`in`.ArticleCommandUseCase import gloddy.article.port.out.ArticleCommandPersistencePort +import gloddy.article.port.out.ArticleLikeCommandPersistencePort +import gloddy.article.port.out.ArticleLikeQueryPersistencePort import gloddy.article.port.out.ArticleQueryPersistencePort import gloddy.category.port.out.CategoryQueryPersistencePort import gloddy.core.ArticleId @@ -16,6 +19,8 @@ class ArticleCommandService( private val categoryQueryPersistencePort: CategoryQueryPersistencePort, private val articleQueryPersistencePort: ArticleQueryPersistencePort, private val articleCommandPersistencePort: ArticleCommandPersistencePort, + private val articleLikeCommandPersistencePort: ArticleLikeCommandPersistencePort, + private val articleLikeQueryPersistencePort: ArticleLikeQueryPersistencePort ) : ArticleCommandUseCase { override fun create(command: ArticleCreateCommand) : ArticleIdResponse { @@ -37,4 +42,18 @@ class ArticleCommandService( article.validateAuthorization(userId) articleCommandPersistencePort.delete(article.id!!.value) } + + override fun like(userId: Long, articleId: Long) { + + val article = articleQueryPersistencePort.findById(articleId) + + articleLikeQueryPersistencePort.findByUserIdAndArticleOrNull(userId, article) + ?.run { articleLikeCommandPersistencePort.delete(this) } + ?: articleLikeCommandPersistencePort.save( + ArticleLike( + userId = UserId(userId), + article = article + ) + ) + } } \ No newline at end of file From b65ef05f532bf257a9e6d6db95caf3291cb63015 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sat, 6 Jan 2024 19:42:52 +0900 Subject: [PATCH 43/58] =?UTF-8?q?feat:=20Jpa=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/gloddy/persistence/config/JpaConfig.kt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 community-infrastructure/src/main/kotlin/gloddy/persistence/config/JpaConfig.kt diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/config/JpaConfig.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/config/JpaConfig.kt new file mode 100644 index 0000000..b406d23 --- /dev/null +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/config/JpaConfig.kt @@ -0,0 +1,9 @@ +package gloddy.persistence.config + +import org.springframework.context.annotation.Configuration +import org.springframework.data.jpa.repository.config.EnableJpaAuditing + +@Configuration +@EnableJpaAuditing +class JpaConfig { +} \ No newline at end of file From 2a9504cdc21056e6dd5e09be63a222a781411e5b Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sat, 6 Jan 2024 20:46:50 +0900 Subject: [PATCH 44/58] =?UTF-8?q?chore:=20mysqldialect=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-persistence.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/community-infrastructure/src/main/resources/application-persistence.yml b/community-infrastructure/src/main/resources/application-persistence.yml index a48a543..1bc562f 100644 --- a/community-infrastructure/src/main/resources/application-persistence.yml +++ b/community-infrastructure/src/main/resources/application-persistence.yml @@ -13,6 +13,6 @@ spring: show-sql: ${SHOW_SQL} properties: hibernate: - dialect: org.hibernate.dialect.MySQL8Dialect + dialect: org.hibernate.dialect.MySQLDialect default_batch_fetch_size: 50 format_sql: true From 315bbdae6298d9145f077f4d8288cb57a11bf7c0 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sat, 6 Jan 2024 20:47:12 +0900 Subject: [PATCH 45/58] =?UTF-8?q?feat:=20Cors=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/gloddy/config/WebConfig.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 community-in-api/src/main/kotlin/gloddy/config/WebConfig.kt diff --git a/community-in-api/src/main/kotlin/gloddy/config/WebConfig.kt b/community-in-api/src/main/kotlin/gloddy/config/WebConfig.kt new file mode 100644 index 0000000..e5c2cef --- /dev/null +++ b/community-in-api/src/main/kotlin/gloddy/config/WebConfig.kt @@ -0,0 +1,21 @@ +package gloddy.config + +import org.springframework.context.annotation.Configuration +import org.springframework.web.servlet.config.annotation.CorsRegistry +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer + +@Configuration +class WebConfig : WebMvcConfigurer { + + override fun addCorsMappings(registry: CorsRegistry) { + registry.addMapping("/**") + .allowCredentials(true) + .allowedOrigins( + "http://localhost:3000", + "https://gloddy.vercel.app", + "https://gloddy-git-develop-gueit214.vercel.app" + ) + .allowedMethods("*") + .allowedHeaders("*") + } +} \ No newline at end of file From 3043a73418b064d757a0d43e13b03a9f1b77c0e6 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sat, 6 Jan 2024 20:49:30 +0900 Subject: [PATCH 46/58] =?UTF-8?q?feat:=20=EA=B3=B5=ED=86=B5=20Response=20?= =?UTF-8?q?=EB=B0=8F=20ResponseEntityWrapper=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/gloddy/response/ApiResponse.kt | 11 +++++++++ .../response/ApiResponseEntityWrapper.kt | 23 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 community-in-api/src/main/kotlin/gloddy/response/ApiResponse.kt create mode 100644 community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt diff --git a/community-in-api/src/main/kotlin/gloddy/response/ApiResponse.kt b/community-in-api/src/main/kotlin/gloddy/response/ApiResponse.kt new file mode 100644 index 0000000..12fb36a --- /dev/null +++ b/community-in-api/src/main/kotlin/gloddy/response/ApiResponse.kt @@ -0,0 +1,11 @@ +package gloddy.response + +data class ApiResponse( + val meta: Meta, + val data: T? +) { + data class Meta( + val statusCode: Int, + val message: String? + ) +} \ No newline at end of file diff --git a/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt b/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt new file mode 100644 index 0000000..2888140 --- /dev/null +++ b/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt @@ -0,0 +1,23 @@ +package gloddy.response + +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity + +class ApiResponseEntityWrapper( + val data: T? +) { + fun getResponseEntity(statusCode: Int, message: String? = null): ResponseEntity> = + ResponseEntity.status(statusCode) + .body(ApiResponse( + meta = ApiResponse.Meta( + statusCode = statusCode, + message = message + ), + data = this.data + )) +} + +fun ApiResponseEntityWrapper.ok(): ResponseEntity> = this.getResponseEntity(HttpStatus.OK.value()) +fun ApiResponseEntityWrapper.created(): ResponseEntity> = this.getResponseEntity(HttpStatus.CREATED.value()) +fun ApiResponseEntityWrapper.noContent(): ResponseEntity> = this.getResponseEntity(HttpStatus.NO_CONTENT.value()) +fun ApiResponseEntityWrapper.fail(statusCode: Int, message: String) = this.getResponseEntity(statusCode, message) From 10978db44baf3a22d68af4a78a1a132c6ff83555 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sat, 6 Jan 2024 20:50:14 +0900 Subject: [PATCH 47/58] =?UTF-8?q?feat:=20findAll=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1(CategoryQueryPersistenceAdapter)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gloddy/category/port/out/CategoryQueryPersistencePort.kt | 1 + .../category/adapter/CategoryQueryPersistenceAdapter.kt | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/community-application/src/main/kotlin/gloddy/category/port/out/CategoryQueryPersistencePort.kt b/community-application/src/main/kotlin/gloddy/category/port/out/CategoryQueryPersistencePort.kt index 519ed8a..da61348 100644 --- a/community-application/src/main/kotlin/gloddy/category/port/out/CategoryQueryPersistencePort.kt +++ b/community-application/src/main/kotlin/gloddy/category/port/out/CategoryQueryPersistencePort.kt @@ -5,4 +5,5 @@ import gloddy.core.CategoryId interface CategoryQueryPersistencePort { fun findById(id: CategoryId): Category + fun findAll(): List } \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/category/adapter/CategoryQueryPersistenceAdapter.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/category/adapter/CategoryQueryPersistenceAdapter.kt index bdf7a75..eead95f 100644 --- a/community-infrastructure/src/main/kotlin/gloddy/persistence/category/adapter/CategoryQueryPersistenceAdapter.kt +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/category/adapter/CategoryQueryPersistenceAdapter.kt @@ -17,4 +17,9 @@ class CategoryQueryPersistenceAdapter( override fun findById(id: CategoryId): Category { return (categoryJpaRepository.findByIdOrNull(id.value) ?: throw CategoryNotFoundException()).toDomain() } + + override fun findAll(): List { + return categoryJpaRepository.findAll() + .map { it.toDomain() } + } } \ No newline at end of file From e97a4683f2ad763b825eb9f81ea1a76b6183b698 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sat, 6 Jan 2024 20:51:30 +0900 Subject: [PATCH 48/58] =?UTF-8?q?feat:=20Category=20getAll=20UseCase=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/port/dto/CategoryReadData.kt | 6 +++++ .../category/port/in/CategoryQueryUseCase.kt | 7 ++++++ .../port/service/CategoryQueryService.kt | 22 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 community-application/src/main/kotlin/gloddy/category/port/dto/CategoryReadData.kt create mode 100644 community-application/src/main/kotlin/gloddy/category/port/in/CategoryQueryUseCase.kt create mode 100644 community-application/src/main/kotlin/gloddy/category/port/service/CategoryQueryService.kt diff --git a/community-application/src/main/kotlin/gloddy/category/port/dto/CategoryReadData.kt b/community-application/src/main/kotlin/gloddy/category/port/dto/CategoryReadData.kt new file mode 100644 index 0000000..0ac7168 --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/category/port/dto/CategoryReadData.kt @@ -0,0 +1,6 @@ +package gloddy.category.port.dto + +data class CategoryReadData( + val id: Long, + val name: String +) \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/category/port/in/CategoryQueryUseCase.kt b/community-application/src/main/kotlin/gloddy/category/port/in/CategoryQueryUseCase.kt new file mode 100644 index 0000000..febc50a --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/category/port/in/CategoryQueryUseCase.kt @@ -0,0 +1,7 @@ +package gloddy.category.port.`in` + +import gloddy.category.port.dto.CategoryReadData + +interface CategoryQueryUseCase { + fun getAll(): List +} \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/category/port/service/CategoryQueryService.kt b/community-application/src/main/kotlin/gloddy/category/port/service/CategoryQueryService.kt new file mode 100644 index 0000000..e8e37b8 --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/category/port/service/CategoryQueryService.kt @@ -0,0 +1,22 @@ +package gloddy.category.port.service + +import gloddy.category.port.dto.CategoryReadData +import gloddy.category.port.`in`.CategoryQueryUseCase +import gloddy.category.port.out.CategoryQueryPersistencePort +import org.springframework.stereotype.Service + +@Service +class CategoryQueryService( + private val categoryQueryPersistencePort: CategoryQueryPersistencePort, +) : CategoryQueryUseCase { + + override fun getAll(): List { + val categories = categoryQueryPersistencePort.findAll() + return categories.map { + CategoryReadData( + id = it.id!!.value, + name = it.name + ) + } + } +} \ No newline at end of file From 6bbc3911262eff2bedd637c0f3c2c61110e6dda4 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sat, 6 Jan 2024 20:53:25 +0900 Subject: [PATCH 49/58] =?UTF-8?q?feat:=20CategoryQueryController=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20getAll=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/CategoryQueryController.kt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryController.kt diff --git a/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryController.kt b/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryController.kt new file mode 100644 index 0000000..90844be --- /dev/null +++ b/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryController.kt @@ -0,0 +1,25 @@ +package gloddy.controller.category + +import gloddy.category.port.dto.CategoryReadData +import gloddy.category.port.`in`.CategoryQueryUseCase +import gloddy.response.ApiResponse +import gloddy.response.ApiResponseEntityWrapper +import gloddy.response.ok +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestHeader +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/api/v1/communities") +class CategoryQueryController( + private val categoryQueryUseCase: CategoryQueryUseCase +) { + + @GetMapping("/categories") + fun getAll(@RequestHeader("USER_ID") userId: Long): ResponseEntity>> { + val data = categoryQueryUseCase.getAll() + return ApiResponseEntityWrapper(data).ok() + } +} \ No newline at end of file From 61055a6542cc94b637e29ddd950ea9c76fc5a06b Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sun, 7 Jan 2024 00:53:34 +0900 Subject: [PATCH 50/58] =?UTF-8?q?fix:=20Article=20create=20usecase=20?= =?UTF-8?q?=EC=88=98=EC=A0=95(=EC=9E=85=EB=A0=A5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../article/dto/command/ArticleCreateCommand.kt | 8 ++------ .../gloddy/article/dto/read/ArticleIdReadData.kt | 5 +++++ .../gloddy/article/dto/response/ArticleIdResponse.kt | 7 ------- .../gloddy/article/port/in/ArticleCommandUseCase.kt | 5 ++--- .../gloddy/article/service/ArticleCommandService.kt | 12 ++++++------ 5 files changed, 15 insertions(+), 22 deletions(-) create mode 100644 community-application/src/main/kotlin/gloddy/article/dto/read/ArticleIdReadData.kt delete mode 100644 community-application/src/main/kotlin/gloddy/article/dto/response/ArticleIdResponse.kt diff --git a/community-application/src/main/kotlin/gloddy/article/dto/command/ArticleCreateCommand.kt b/community-application/src/main/kotlin/gloddy/article/dto/command/ArticleCreateCommand.kt index 8c89b91..c488ef8 100644 --- a/community-application/src/main/kotlin/gloddy/article/dto/command/ArticleCreateCommand.kt +++ b/community-application/src/main/kotlin/gloddy/article/dto/command/ArticleCreateCommand.kt @@ -1,12 +1,8 @@ package gloddy.article.dto.command -import gloddy.core.CategoryId -import gloddy.core.UserId - data class ArticleCreateCommand( - val userId: UserId, - val categoryId: CategoryId, + val categoryId: Long, val title: String, val content: String, - val images: List, + val images: List?, ) diff --git a/community-application/src/main/kotlin/gloddy/article/dto/read/ArticleIdReadData.kt b/community-application/src/main/kotlin/gloddy/article/dto/read/ArticleIdReadData.kt new file mode 100644 index 0000000..a9da087 --- /dev/null +++ b/community-application/src/main/kotlin/gloddy/article/dto/read/ArticleIdReadData.kt @@ -0,0 +1,5 @@ +package gloddy.article.dto.read + +data class ArticleIdReadData( + val articleId: Long +) \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/dto/response/ArticleIdResponse.kt b/community-application/src/main/kotlin/gloddy/article/dto/response/ArticleIdResponse.kt deleted file mode 100644 index c7dc991..0000000 --- a/community-application/src/main/kotlin/gloddy/article/dto/response/ArticleIdResponse.kt +++ /dev/null @@ -1,7 +0,0 @@ -package gloddy.article.dto.response - -import gloddy.core.ArticleId - -data class ArticleIdResponse( - val articleId: ArticleId -) \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt index 5f68a07..ded8688 100644 --- a/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt +++ b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt @@ -1,11 +1,10 @@ package gloddy.article.port.`in` import gloddy.article.dto.command.ArticleCreateCommand -import gloddy.article.dto.response.ArticleIdResponse -import gloddy.core.UserId +import gloddy.article.dto.read.ArticleIdReadData interface ArticleCommandUseCase { - fun create(command: ArticleCreateCommand): ArticleIdResponse + fun create(userId: Long, command: ArticleCreateCommand): ArticleIdReadData fun delete(userId: Long, articleId: Long) fun like(userId: Long, articleId: Long) } \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt index 26745a0..1e730e9 100644 --- a/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt +++ b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt @@ -3,14 +3,14 @@ package gloddy.article.service import gloddy.article.Article import gloddy.article.ArticleLike import gloddy.article.dto.command.ArticleCreateCommand -import gloddy.article.dto.response.ArticleIdResponse +import gloddy.article.dto.read.ArticleIdReadData import gloddy.article.port.`in`.ArticleCommandUseCase import gloddy.article.port.out.ArticleCommandPersistencePort import gloddy.article.port.out.ArticleLikeCommandPersistencePort import gloddy.article.port.out.ArticleLikeQueryPersistencePort import gloddy.article.port.out.ArticleQueryPersistencePort import gloddy.category.port.out.CategoryQueryPersistencePort -import gloddy.core.ArticleId +import gloddy.core.CategoryId import gloddy.core.UserId import org.springframework.stereotype.Service @@ -23,18 +23,18 @@ class ArticleCommandService( private val articleLikeQueryPersistencePort: ArticleLikeQueryPersistencePort ) : ArticleCommandUseCase { - override fun create(command: ArticleCreateCommand) : ArticleIdResponse { + override fun create(userId: Long, command: ArticleCreateCommand) : ArticleIdReadData { - val category = categoryQueryPersistencePort.findById(command.categoryId) + val category = categoryQueryPersistencePort.findById(CategoryId(command.categoryId)) val article = Article( - userId = command.userId, + userId = UserId(userId), category = category, title = command.title, content = command.content, images = command.images, ).let { articleCommandPersistencePort.save(it) } - return ArticleIdResponse(articleId = article.id!!) + return ArticleIdReadData(articleId = article.id!!.value) } override fun delete(userId: Long, articleId: Long) { From 8193d5428475889c6932ae1abf79e3ef27d73a65 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sun, 7 Jan 2024 00:54:07 +0900 Subject: [PATCH 51/58] =?UTF-8?q?fix:=20Jpa=20naming=20=EC=A0=84=EB=9E=B5?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/gloddy/persistence/common/BaseTimeEntity.kt | 3 +++ .../src/main/resources/application-persistence.yml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/common/BaseTimeEntity.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/common/BaseTimeEntity.kt index 0489782..b32dc5e 100644 --- a/community-infrastructure/src/main/kotlin/gloddy/persistence/common/BaseTimeEntity.kt +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/common/BaseTimeEntity.kt @@ -1,12 +1,15 @@ package gloddy.persistence.common import jakarta.persistence.Column +import jakarta.persistence.EntityListeners import jakarta.persistence.MappedSuperclass import org.springframework.data.annotation.CreatedDate import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener import java.time.LocalDateTime @MappedSuperclass +@EntityListeners(AuditingEntityListener::class) open class BaseTimeEntity( @Column(name = "created_at") @CreatedDate diff --git a/community-infrastructure/src/main/resources/application-persistence.yml b/community-infrastructure/src/main/resources/application-persistence.yml index 1bc562f..24ff877 100644 --- a/community-infrastructure/src/main/resources/application-persistence.yml +++ b/community-infrastructure/src/main/resources/application-persistence.yml @@ -9,7 +9,7 @@ spring: hibernate: ddl-auto: none naming: - physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl + physical-strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy show-sql: ${SHOW_SQL} properties: hibernate: From 349f81500ac43ecb0be44566ea2062763bd45e62 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Sun, 7 Jan 2024 00:54:30 +0900 Subject: [PATCH 52/58] =?UTF-8?q?feat:=20Article=20create=20Contoller=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../article/ArticleCommandController.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt diff --git a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt new file mode 100644 index 0000000..9824266 --- /dev/null +++ b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt @@ -0,0 +1,30 @@ +package gloddy.controller.article + +import gloddy.article.dto.command.ArticleCreateCommand +import gloddy.article.dto.read.ArticleIdReadData +import gloddy.article.port.`in`.ArticleCommandUseCase +import gloddy.response.ApiResponse +import gloddy.response.ApiResponseEntityWrapper +import gloddy.response.created +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestHeader +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/api/v1/communities") +class ArticleCommandController( + private val articleCommandUseCase: ArticleCommandUseCase +) { + + @PostMapping("/articles/create") + fun create( + @RequestHeader("USER_ID") userId: Long, + @RequestBody command: ArticleCreateCommand, + ): ResponseEntity> { + val data = articleCommandUseCase.create(userId, command) + return ApiResponseEntityWrapper(data).created() + } +} \ No newline at end of file From bb4a2307f353c50a0972264920583d9f0b767154 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Tue, 9 Jan 2024 01:37:58 +0900 Subject: [PATCH 53/58] =?UTF-8?q?chore:=20in-api=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=EC=97=90=20swagger=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- community-in-api/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/community-in-api/build.gradle.kts b/community-in-api/build.gradle.kts index 4dae864..7caad09 100644 --- a/community-in-api/build.gradle.kts +++ b/community-in-api/build.gradle.kts @@ -12,6 +12,8 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-validation") implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0") + implementation("com.fasterxml.jackson.module:jackson-module-kotlin") testImplementation("org.springframework.boot:spring-boot-starter-test") } From 960b8753224291f64ff5cb49791d52f3b59fe766 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Tue, 9 Jan 2024 01:38:25 +0900 Subject: [PATCH 54/58] =?UTF-8?q?feat:=20swagger=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/gloddy/config/SwaggerConfig.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 community-in-api/src/main/kotlin/gloddy/config/SwaggerConfig.kt diff --git a/community-in-api/src/main/kotlin/gloddy/config/SwaggerConfig.kt b/community-in-api/src/main/kotlin/gloddy/config/SwaggerConfig.kt new file mode 100644 index 0000000..6265e0d --- /dev/null +++ b/community-in-api/src/main/kotlin/gloddy/config/SwaggerConfig.kt @@ -0,0 +1,33 @@ +package gloddy.config + +import io.swagger.v3.oas.models.Components +import io.swagger.v3.oas.models.OpenAPI +import io.swagger.v3.oas.models.security.SecurityRequirement +import io.swagger.v3.oas.models.security.SecurityScheme +import io.swagger.v3.oas.models.servers.Server +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class SwaggerConfig { + + @Bean + fun communityOpenAPI(): OpenAPI { + return OpenAPI() + .components(Components() + .addSecuritySchemes("JWT", securityScheme())) + .addSecurityItem(SecurityRequirement().addList("JWT")) + .addServersItem(serversItem()) + } + + private fun securityScheme(): SecurityScheme { + return SecurityScheme() + .type(SecurityScheme.Type.APIKEY) + .`in`(SecurityScheme.In.HEADER) + .name("X-AUTH-TOKEN") + } + + private fun serversItem(): Server { + return Server().url("/api/v1/communities") + } +} From 7dfd28f0676c3b445ea60f7c83cad51795726bfb Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Tue, 9 Jan 2024 01:52:48 +0900 Subject: [PATCH 55/58] =?UTF-8?q?feat:=20=EA=B5=AC=ED=98=84=EB=90=9C=20Con?= =?UTF-8?q?troller=EC=97=90=20swagger=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../article/ArticleCommandController.kt | 11 +++++----- .../article/ArticleCommandControllerDocs.kt | 20 +++++++++++++++++++ .../category/CategoryQueryController.kt | 9 +++++---- .../category/CategoryQueryControllerDocs.kt | 17 ++++++++++++++++ .../response/ApiResponseEntityWrapper.kt | 12 +++++------ ...ApiResponse.kt => CommunityApiResponse.kt} | 2 +- 6 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandControllerDocs.kt create mode 100644 community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryControllerDocs.kt rename community-in-api/src/main/kotlin/gloddy/response/{ApiResponse.kt => CommunityApiResponse.kt} (80%) diff --git a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt index 9824266..b963794 100644 --- a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt +++ b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt @@ -3,7 +3,7 @@ package gloddy.controller.article import gloddy.article.dto.command.ArticleCreateCommand import gloddy.article.dto.read.ArticleIdReadData import gloddy.article.port.`in`.ArticleCommandUseCase -import gloddy.response.ApiResponse +import gloddy.response.CommunityApiResponse import gloddy.response.ApiResponseEntityWrapper import gloddy.response.created import org.springframework.http.ResponseEntity @@ -16,14 +16,15 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/api/v1/communities") class ArticleCommandController( - private val articleCommandUseCase: ArticleCommandUseCase -) { + private val articleCommandUseCase: ArticleCommandUseCase, +) : ArticleCommandControllerDocs { + @PostMapping("/articles/create") - fun create( + override fun create( @RequestHeader("USER_ID") userId: Long, @RequestBody command: ArticleCreateCommand, - ): ResponseEntity> { + ): ResponseEntity> { val data = articleCommandUseCase.create(userId, command) return ApiResponseEntityWrapper(data).created() } diff --git a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandControllerDocs.kt b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandControllerDocs.kt new file mode 100644 index 0000000..ef7b19a --- /dev/null +++ b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandControllerDocs.kt @@ -0,0 +1,20 @@ +package gloddy.controller.article + +import gloddy.article.dto.command.ArticleCreateCommand +import gloddy.article.dto.read.ArticleIdReadData +import gloddy.response.CommunityApiResponse +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.Parameter +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.RequestBody + +@Tag(name = "게시글") +interface ArticleCommandControllerDocs { + + @Operation(summary = "게시글 생성") + @ApiResponse(responseCode = "201", description = "게시글 생성 성공") + fun create(@Parameter(hidden = true) userId: Long, @RequestBody command: ArticleCreateCommand) + : ResponseEntity> +} \ No newline at end of file diff --git a/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryController.kt b/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryController.kt index 90844be..e199d18 100644 --- a/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryController.kt +++ b/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryController.kt @@ -2,7 +2,7 @@ package gloddy.controller.category import gloddy.category.port.dto.CategoryReadData import gloddy.category.port.`in`.CategoryQueryUseCase -import gloddy.response.ApiResponse +import gloddy.response.CommunityApiResponse import gloddy.response.ApiResponseEntityWrapper import gloddy.response.ok import org.springframework.http.ResponseEntity @@ -14,11 +14,12 @@ import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/api/v1/communities") class CategoryQueryController( - private val categoryQueryUseCase: CategoryQueryUseCase -) { + private val categoryQueryUseCase: CategoryQueryUseCase, +) : CategoryQueryControllerDocs { + @GetMapping("/categories") - fun getAll(@RequestHeader("USER_ID") userId: Long): ResponseEntity>> { + override fun getAll(@RequestHeader("USER_ID") userId: Long): ResponseEntity>> { val data = categoryQueryUseCase.getAll() return ApiResponseEntityWrapper(data).ok() } diff --git a/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryControllerDocs.kt b/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryControllerDocs.kt new file mode 100644 index 0000000..4650fc0 --- /dev/null +++ b/community-in-api/src/main/kotlin/gloddy/controller/category/CategoryQueryControllerDocs.kt @@ -0,0 +1,17 @@ +package gloddy.controller.category + +import gloddy.category.port.dto.CategoryReadData +import gloddy.response.CommunityApiResponse +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.Parameter +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.http.ResponseEntity + +@Tag(name = "카테고리") +interface CategoryQueryControllerDocs { + + @Operation(summary = "카테고리 전체 조회") + @ApiResponse(responseCode = "200", description = "카테고리 전체 조회 성공") + fun getAll(@Parameter(hidden = true) userId: Long) : ResponseEntity>> +} \ No newline at end of file diff --git a/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt b/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt index 2888140..f9c3a77 100644 --- a/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt +++ b/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt @@ -6,10 +6,10 @@ import org.springframework.http.ResponseEntity class ApiResponseEntityWrapper( val data: T? ) { - fun getResponseEntity(statusCode: Int, message: String? = null): ResponseEntity> = + fun getResponseEntity(statusCode: Int, message: String? = null): ResponseEntity> = ResponseEntity.status(statusCode) - .body(ApiResponse( - meta = ApiResponse.Meta( + .body(CommunityApiResponse( + meta = CommunityApiResponse.Meta( statusCode = statusCode, message = message ), @@ -17,7 +17,7 @@ class ApiResponseEntityWrapper( )) } -fun ApiResponseEntityWrapper.ok(): ResponseEntity> = this.getResponseEntity(HttpStatus.OK.value()) -fun ApiResponseEntityWrapper.created(): ResponseEntity> = this.getResponseEntity(HttpStatus.CREATED.value()) -fun ApiResponseEntityWrapper.noContent(): ResponseEntity> = this.getResponseEntity(HttpStatus.NO_CONTENT.value()) +fun ApiResponseEntityWrapper.ok(): ResponseEntity> = this.getResponseEntity(HttpStatus.OK.value()) +fun ApiResponseEntityWrapper.created(): ResponseEntity> = this.getResponseEntity(HttpStatus.CREATED.value()) +fun ApiResponseEntityWrapper.noContent(): ResponseEntity> = this.getResponseEntity(HttpStatus.NO_CONTENT.value()) fun ApiResponseEntityWrapper.fail(statusCode: Int, message: String) = this.getResponseEntity(statusCode, message) diff --git a/community-in-api/src/main/kotlin/gloddy/response/ApiResponse.kt b/community-in-api/src/main/kotlin/gloddy/response/CommunityApiResponse.kt similarity index 80% rename from community-in-api/src/main/kotlin/gloddy/response/ApiResponse.kt rename to community-in-api/src/main/kotlin/gloddy/response/CommunityApiResponse.kt index 12fb36a..3b51d74 100644 --- a/community-in-api/src/main/kotlin/gloddy/response/ApiResponse.kt +++ b/community-in-api/src/main/kotlin/gloddy/response/CommunityApiResponse.kt @@ -1,6 +1,6 @@ package gloddy.response -data class ApiResponse( +data class CommunityApiResponse( val meta: Meta, val data: T? ) { From 6e14fbe7e604fd6d47dcf87a38108ff38bfe4eb5 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Tue, 9 Jan 2024 02:04:40 +0900 Subject: [PATCH 56/58] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C,=20=EC=A2=8B=EC=95=84=EC=9A=94=20controller?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../article/ArticleCommandController.kt | 21 ++++++++++++++----- .../article/ArticleCommandControllerDocs.kt | 11 ++++++++++ .../response/ApiResponseEntityWrapper.kt | 2 +- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt index b963794..8859345 100644 --- a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt +++ b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt @@ -6,12 +6,9 @@ import gloddy.article.port.`in`.ArticleCommandUseCase import gloddy.response.CommunityApiResponse import gloddy.response.ApiResponseEntityWrapper import gloddy.response.created +import gloddy.response.noContent import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestHeader -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* @RestController @RequestMapping("/api/v1/communities") @@ -28,4 +25,18 @@ class ArticleCommandController( val data = articleCommandUseCase.create(userId, command) return ApiResponseEntityWrapper(data).created() } + + @PostMapping("/articles/{articleId}/delete") + override fun delete(@RequestHeader("USER_ID") userId: Long, @PathVariable("articleId") articleId: Long) + : ResponseEntity> { + articleCommandUseCase.delete(userId, articleId) + return ApiResponseEntityWrapper().noContent() + } + + @PostMapping("/articles/{articleId}/like") + override fun like(@RequestHeader("USER_ID") userId: Long, @PathVariable("articleId") articleId: Long) + : ResponseEntity> { + articleCommandUseCase.like(userId, articleId) + return ApiResponseEntityWrapper().noContent() + } } \ No newline at end of file diff --git a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandControllerDocs.kt b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandControllerDocs.kt index ef7b19a..380a55e 100644 --- a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandControllerDocs.kt +++ b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandControllerDocs.kt @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.Parameter import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestBody @Tag(name = "게시글") @@ -17,4 +18,14 @@ interface ArticleCommandControllerDocs { @ApiResponse(responseCode = "201", description = "게시글 생성 성공") fun create(@Parameter(hidden = true) userId: Long, @RequestBody command: ArticleCreateCommand) : ResponseEntity> + + @Operation(summary = "게시글 삭제") + @ApiResponse(responseCode = "204", description = "게시글 삭제 성공") + fun delete(@Parameter(hidden = true) userId: Long, @PathVariable("articleId") articleId: Long) + : ResponseEntity> + + @Operation(summary = "게시글 좋아요 및 좋아요 취소") + @ApiResponse(responseCode = "204", description = "게시글 좋아요 및 좋아요 취소 성공") + fun like(@Parameter(hidden = true) userId: Long, @PathVariable("articleId") articleId: Long) + : ResponseEntity> } \ No newline at end of file diff --git a/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt b/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt index f9c3a77..5954275 100644 --- a/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt +++ b/community-in-api/src/main/kotlin/gloddy/response/ApiResponseEntityWrapper.kt @@ -4,7 +4,7 @@ import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity class ApiResponseEntityWrapper( - val data: T? + val data: T? = null ) { fun getResponseEntity(statusCode: Int, message: String? = null): ResponseEntity> = ResponseEntity.status(statusCode) From 7e549e9b7ff74bdc2b78cf5a93ecc2308e1985f2 Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Tue, 9 Jan 2024 02:53:30 +0900 Subject: [PATCH 57/58] =?UTF-8?q?chore:=20logback=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20gradle=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/kotlin/gloddy/CommunityApplicationTests.kt | 13 ------------- build.gradle.kts | 2 ++ 2 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 bootstrap/src/test/kotlin/gloddy/CommunityApplicationTests.kt diff --git a/bootstrap/src/test/kotlin/gloddy/CommunityApplicationTests.kt b/bootstrap/src/test/kotlin/gloddy/CommunityApplicationTests.kt deleted file mode 100644 index 1361480..0000000 --- a/bootstrap/src/test/kotlin/gloddy/CommunityApplicationTests.kt +++ /dev/null @@ -1,13 +0,0 @@ -package gloddy - -import org.junit.jupiter.api.Test -import org.springframework.boot.test.context.SpringBootTest - -@SpringBootTest -class CommunityApplicationTests { - - @Test - fun contextLoads() { - } - -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index fd0bdf1..6a7c313 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,6 +30,8 @@ subprojects { dependencies{ implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") + implementation("org.slf4j:slf4j-api:2.0.10") + implementation("ch.qos.logback:logback-core:1.4.14") testCompileOnly("org.junit.jupiter:junit-jupiter-params:5.10.1") testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1") From b020bf72e9f289510e071aecc40cb64d9326958b Mon Sep 17 00:00:00 2001 From: jihwan2da Date: Tue, 9 Jan 2024 02:53:49 +0900 Subject: [PATCH 58/58] =?UTF-8?q?feat:=20CommunityControllerAdvice=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bootstrap/src/test/kotlin/gloddy/.gitkeep | 0 .../exception/CommunityControllerAdvice.kt | 32 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 bootstrap/src/test/kotlin/gloddy/.gitkeep create mode 100644 community-in-api/src/main/kotlin/gloddy/exception/CommunityControllerAdvice.kt diff --git a/bootstrap/src/test/kotlin/gloddy/.gitkeep b/bootstrap/src/test/kotlin/gloddy/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/community-in-api/src/main/kotlin/gloddy/exception/CommunityControllerAdvice.kt b/community-in-api/src/main/kotlin/gloddy/exception/CommunityControllerAdvice.kt new file mode 100644 index 0000000..df8923e --- /dev/null +++ b/community-in-api/src/main/kotlin/gloddy/exception/CommunityControllerAdvice.kt @@ -0,0 +1,32 @@ +package gloddy.exception + +import gloddy.core.GloddyCommunityException +import gloddy.response.ApiResponseEntityWrapper +import gloddy.response.CommunityApiResponse +import gloddy.response.fail +import org.slf4j.LoggerFactory +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.ExceptionHandler +import org.springframework.web.bind.annotation.RestControllerAdvice + +@RestControllerAdvice(basePackages = ["gloddy"]) +class CommunityControllerAdvice { + + companion object { + private const val INTERNAL_SERVER_ERROR_CODE = 500 + private const val INTERNAL_SERVER_ERROR_MESSAGE = "서버 내부 오류입니다." + private val logger = LoggerFactory.getLogger(CommunityControllerAdvice::class.java) + } + + @ExceptionHandler(GloddyCommunityException::class) + fun handleGloddyCummunityException(e: GloddyCommunityException): ResponseEntity> { + logger.error("Community Error\n{}", e.message, e) + return ApiResponseEntityWrapper().fail(e.statusCode, e.message) + } + + @ExceptionHandler(Exception::class) + fun handleInternalServerError(e: Exception): ResponseEntity> { + logger.error("Community Internal Error\n{}", e.message, e) + return ApiResponseEntityWrapper().fail(INTERNAL_SERVER_ERROR_CODE, INTERNAL_SERVER_ERROR_MESSAGE) + } +} \ No newline at end of file