From 005d8514d4efdd2daa5273bff960b2e9050e2a99 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:15:24 +0900 Subject: [PATCH 01/81] =?UTF-8?q?feat:=20ktlint=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20editorconfig=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..56e1ef63 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset=utf-8 +end_of_line=lf +indent_style=space +indent_size=4 +insert_final_newline=true +disabled_rules=no-wildcard-imports,import-ordering,comment-spacing + +[*.{kt,kts}] +insert_final_newline=false \ No newline at end of file From 4206334b0589f11723bedc5e9bf4f9221f038353 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:16:27 +0900 Subject: [PATCH 02/81] =?UTF-8?q?feat:=20=EC=BD=94=ED=8A=B8=EB=A6=B0=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EB=B0=8F=20?= =?UTF-8?q?=ED=94=8C=EB=9F=AC=EA=B7=B8=EC=9D=B8=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chore: http client, minio 관련 변수를 추가합니다 --- build.gradle | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/build.gradle b/build.gradle index cff56fb5..724c10fa 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,12 @@ buildscript { springBootVersion = '2.7.5' dependencyManagementVersion = '1.0.15.RELEASE' + // kotlin version + kotlinVersion = '1.5.31' + + // ktlint version + ktlintVersion = '11.3.2' + // jwt jsonwebtokenVersion = '0.11.5' @@ -24,6 +30,12 @@ buildscript { // spotless spotlessVersion = '6.8.0' + // HTTP client + httpclientVersion = '4.5.13' + + // Minio + minioVersion = '8.5.5' + // spring cloud set('springCloudVersion', "2021.0.1") } @@ -32,6 +44,19 @@ buildscript { plugins { id 'java' + // kotlin + id 'org.jetbrains.kotlin.jvm' version "${kotlinVersion}" + + // plugin kotlin spring + id 'org.jetbrains.kotlin.plugin.spring' version "${kotlinVersion}" + + // plugin kotlin jpa + id 'org.jetbrains.kotlin.plugin.jpa' version "${kotlinVersion}" + + // plugin kotlin ktlint + id 'org.jlleitschuh.gradle.ktlint' version "${ktlintVersion}" + id 'org.jlleitschuh.gradle.ktlint-idea' version "${ktlintVersion}" + // spring id 'org.springframework.boot' version "${springBootVersion}" id 'io.spring.dependency-management' version "${dependencyManagementVersion}" From 7e4715273038cba59c3ebd4885817913eff4deda Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:17:01 +0900 Subject: [PATCH 03/81] =?UTF-8?q?feat:=20member-api,=20api-repository,=20i?= =?UTF-8?q?mage-store=20=EB=AA=A8=EB=93=88=EC=9D=84=20settings.gradle?= =?UTF-8?q?=EC=97=90=20=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/settings.gradle b/settings.gradle index 8b52eaa2..2102586b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,9 +1,14 @@ rootProject.name = 'walking-be' // api include 'api' +include 'member-api' // data include 'data' +include 'api-repository' + +// image-store +include 'image-store' // batch include 'batch' From 1f15957d49be57f0a94e7b269345e43c50d8637c Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:17:24 +0900 Subject: [PATCH 04/81] =?UTF-8?q?feat:=20=EB=A1=9C=EC=BB=AC=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=97=90=20minio=20=ED=99=98=EA=B2=BD=EC=9D=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../docker-compose.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/resources/local-develop-environment/docker-compose.yml b/resources/local-develop-environment/docker-compose.yml index 5266543f..c01e73ba 100644 --- a/resources/local-develop-environment/docker-compose.yml +++ b/resources/local-develop-environment/docker-compose.yml @@ -21,4 +21,19 @@ services: environment: - ADMINER_DEFAULT_SERVER=walking-mysql8 - ADMINER_DESIGN=nette - - ADMINER_PLUGINS=tables-filter tinymce \ No newline at end of file + - ADMINER_PLUGINS=tables-filter tinymce + + walking-minio: + container_name: walking-minio + image: minio/minio + ports: + - "9000:9000" + - "9001:9001" + shm_size: '1gb' + environment: + - MINIO_ACCESS_KEY=thisisroot + - MINIO_SECRET_KEY=thisisroot + - MINIO_ROOT_USER=thisisroot + - MINIO_ROOT_PASSWORD=thisisroot + - MINIO_REGION_NAME=ap-northeast-2 + command: server /data --console-address ":9001" From 23c1bcadb650d270bc35b50569d8f35296943fdc Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:17:48 +0900 Subject: [PATCH 05/81] =?UTF-8?q?feat:=20image-store=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20build.gradle=EC=9D=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- image-store/build.gradle | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 image-store/build.gradle diff --git a/image-store/build.gradle b/image-store/build.gradle new file mode 100644 index 00000000..76289a8c --- /dev/null +++ b/image-store/build.gradle @@ -0,0 +1,21 @@ +bootJar { + enabled = false +} + +jar { + enabled = true +} + +apply plugin: 'org.jlleitschuh.gradle.ktlint' +apply plugin: 'org.jlleitschuh.gradle.ktlint-idea' +apply plugin: 'org.jetbrains.kotlin.jvm' +apply plugin: 'org.jetbrains.kotlin.plugin.spring' + +dependencies { + // kotlin reflect + runtimeOnly "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + + // minio + implementation "io.minio:minio:${minioVersion}" +} From ae7c0083aee93d03ebe1dbed1625ed48e0307fa1 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:18:05 +0900 Subject: [PATCH 06/81] =?UTF-8?q?feat:=20image-store=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EA=B5=AC=EC=84=B1=20=EC=84=A4=EC=A0=95=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- image-store/src/main/resources/application-iamge-store.yml | 5 +++++ .../src/main/resources/application-image-store-dev.yml | 5 +++++ .../src/main/resources/application-image-store-local.yml | 5 +++++ .../src/main/resources/application-image-store-prod.yml | 5 +++++ 4 files changed, 20 insertions(+) create mode 100644 image-store/src/main/resources/application-iamge-store.yml create mode 100644 image-store/src/main/resources/application-image-store-dev.yml create mode 100644 image-store/src/main/resources/application-image-store-local.yml create mode 100644 image-store/src/main/resources/application-image-store-prod.yml diff --git a/image-store/src/main/resources/application-iamge-store.yml b/image-store/src/main/resources/application-iamge-store.yml new file mode 100644 index 00000000..8e3058fa --- /dev/null +++ b/image-store/src/main/resources/application-iamge-store.yml @@ -0,0 +1,5 @@ +minio: + url: ${MINIO_URL} + access-key: ${MINIO_ACCESS_KEY} + secret-key: ${MINIO_SECRET_KEY} + bucket-name: ${MINIO_BUCKET_NAME} diff --git a/image-store/src/main/resources/application-image-store-dev.yml b/image-store/src/main/resources/application-image-store-dev.yml new file mode 100644 index 00000000..8e3058fa --- /dev/null +++ b/image-store/src/main/resources/application-image-store-dev.yml @@ -0,0 +1,5 @@ +minio: + url: ${MINIO_URL} + access-key: ${MINIO_ACCESS_KEY} + secret-key: ${MINIO_SECRET_KEY} + bucket-name: ${MINIO_BUCKET_NAME} diff --git a/image-store/src/main/resources/application-image-store-local.yml b/image-store/src/main/resources/application-image-store-local.yml new file mode 100644 index 00000000..b81d17c0 --- /dev/null +++ b/image-store/src/main/resources/application-image-store-local.yml @@ -0,0 +1,5 @@ +minio: + url: http://localhost:9000 + access-key: thisisroot + secret-key: thisisroot + bucket-name: picture diff --git a/image-store/src/main/resources/application-image-store-prod.yml b/image-store/src/main/resources/application-image-store-prod.yml new file mode 100644 index 00000000..8e3058fa --- /dev/null +++ b/image-store/src/main/resources/application-image-store-prod.yml @@ -0,0 +1,5 @@ +minio: + url: ${MINIO_URL} + access-key: ${MINIO_ACCESS_KEY} + secret-key: ${MINIO_SECRET_KEY} + bucket-name: ${MINIO_BUCKET_NAME} From b44400464a644c8affaffbfe943e8ef9451e70ae Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:18:36 +0900 Subject: [PATCH 07/81] =?UTF-8?q?feat:=20ImageStoreConfig=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/image/config/ImageStoreConfig.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/config/ImageStoreConfig.kt diff --git a/image-store/src/main/kotlin/com/walking/image/config/ImageStoreConfig.kt b/image-store/src/main/kotlin/com/walking/image/config/ImageStoreConfig.kt new file mode 100644 index 00000000..4d746ef3 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/config/ImageStoreConfig.kt @@ -0,0 +1,16 @@ +package com.walking.image.config + +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration + +@Configuration +@ComponentScan(basePackages = [ImageStoreConfig.BASE_PACKAGE]) +class ImageStoreConfig { + companion object { + const val BASE_PACKAGE = "com.walking.image" + const val SERVICE_NAME = "walking" + const val MODULE_NAME = "image-store" + const val BEAN_NAME_PREFIX = "imageStore" + const val PROPERTY_PREFIX = SERVICE_NAME + "." + MODULE_NAME + } +} \ No newline at end of file From 79281886d6f7b4b92731e2f3eaf5c283dca20213 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:18:46 +0900 Subject: [PATCH 08/81] =?UTF-8?q?feat:=20MinioImageStoreClientConfig=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/MinioImageStoreClientConfig.kt | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/config/MinioImageStoreClientConfig.kt diff --git a/image-store/src/main/kotlin/com/walking/image/config/MinioImageStoreClientConfig.kt b/image-store/src/main/kotlin/com/walking/image/config/MinioImageStoreClientConfig.kt new file mode 100644 index 00000000..78261c0c --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/config/MinioImageStoreClientConfig.kt @@ -0,0 +1,57 @@ +package com.walking.image.config + +import com.walking.image.MinioImageStoreClient +import io.minio.BucketExistsArgs +import io.minio.MakeBucketArgs +import io.minio.MinioClient +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.ApplicationListener +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Profile +import org.springframework.context.event.ContextRefreshedEvent + +@Profile("minio") +@Configuration +class MinioImageStoreClientConfig( + @Value("\${minio.url}") val url: String, + @Value("\${minio.access-key}") val accessKey: String, + @Value("\${minio.secret-key}") val secretKey: String, + @Value("\${minio.bucket-name}") val bucket: String +) : ApplicationListener { + + val log: Logger = LoggerFactory.getLogger(MinioImageStoreClientConfig::class.java) + + private var client: MinioClient? = null + + override fun onApplicationEvent(event: ContextRefreshedEvent) { + client?.bucketExists( + BucketExistsArgs.builder() + .bucket(bucket) + .build() + )?.let { exist -> + if (!exist) { + client?.makeBucket( + MakeBucketArgs.builder() + .bucket(bucket) + .build() + ) + log.info("Create bucket $bucket") + } + log.info("Bucket $bucket already exists") + } + } + + @Bean + fun minioImageStoreClient(): MinioImageStoreClient { + MinioClient.builder() + .endpoint(url) + .credentials(accessKey, secretKey) + .build().let { client -> + this.client = client + return MinioImageStoreClient(client) + } + } +} \ No newline at end of file From e25607126131ca74bee6083c13b2c4a521137367 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:19:00 +0900 Subject: [PATCH 09/81] =?UTF-8?q?feat:=20ImageObjectArgs.kt=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/image/ImageObjectArgs.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/ImageObjectArgs.kt diff --git a/image-store/src/main/kotlin/com/walking/image/ImageObjectArgs.kt b/image-store/src/main/kotlin/com/walking/image/ImageObjectArgs.kt new file mode 100644 index 00000000..77ce8686 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/ImageObjectArgs.kt @@ -0,0 +1,23 @@ +package com.walking.image + +import java.io.InputStream + +data class ImageGetPresignedObjectUrlArgs( + val bucket: String, + val `object`: String, + val method: String +) + +data class ImagePutObjectArgs( + val bucket: String, + val `object`: String, + val stream: InputStream, + val objectSize: Long, + val partSize: Long, + val contentType: String = "image/jpg" +) + +data class ImageRemoveObjectArgs( + val bucket: String, + val `object`: String +) \ No newline at end of file From a348154cb5abe4fb9ef00aa39a014e00e2370051 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:19:12 +0900 Subject: [PATCH 10/81] =?UTF-8?q?feat:=20ImageWriteResponse=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/walking/image/ImageWriteResponse.kt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/ImageWriteResponse.kt diff --git a/image-store/src/main/kotlin/com/walking/image/ImageWriteResponse.kt b/image-store/src/main/kotlin/com/walking/image/ImageWriteResponse.kt new file mode 100644 index 00000000..219cd4b0 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/ImageWriteResponse.kt @@ -0,0 +1,9 @@ +package com.walking.image + +data class ImageWriteResponse( + val bucket: String, + val region: String, + val `object`: String, + val etag: String, + val versionId: String +) \ No newline at end of file From b90606c33515ccd95c94bcc3711757c543135bc6 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:19:25 +0900 Subject: [PATCH 11/81] =?UTF-8?q?feat:=20ImageStoreClient=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/walking/image/ImageStoreClient.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/ImageStoreClient.kt diff --git a/image-store/src/main/kotlin/com/walking/image/ImageStoreClient.kt b/image-store/src/main/kotlin/com/walking/image/ImageStoreClient.kt new file mode 100644 index 00000000..590ca2d3 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/ImageStoreClient.kt @@ -0,0 +1,10 @@ +package com.walking.image + +interface ImageStoreClient { + + fun getPresignedObjectUrl(fileName: ImageGetPresignedObjectUrlArgs): String + + fun removeObject(fileName: ImageRemoveObjectArgs) + + fun putObject(fileName: ImagePutObjectArgs): ImageWriteResponse +} \ No newline at end of file From c29ae23bd6c91493e47abd4a397ef9a485c30087 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:19:35 +0900 Subject: [PATCH 12/81] =?UTF-8?q?feat:=20MinioImageStoreClient=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../walking/image/MinioImageStoreClient.kt | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/MinioImageStoreClient.kt diff --git a/image-store/src/main/kotlin/com/walking/image/MinioImageStoreClient.kt b/image-store/src/main/kotlin/com/walking/image/MinioImageStoreClient.kt new file mode 100644 index 00000000..b9c3515b --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/MinioImageStoreClient.kt @@ -0,0 +1,53 @@ +package com.walking.image + +import io.minio.GetPresignedObjectUrlArgs +import io.minio.MinioClient +import io.minio.PutObjectArgs +import io.minio.RemoveObjectArgs +import io.minio.http.Method + +class MinioImageStoreClient( + private val minIoClient: MinioClient +) : ImageStoreClient { + + override fun getPresignedObjectUrl(fileName: ImageGetPresignedObjectUrlArgs): String { + GetPresignedObjectUrlArgs.builder() + .bucket(fileName.bucket) + .`object`(fileName.`object`) + .method(Method.valueOf(fileName.method)) + .build() + .let { args -> + return minIoClient.getPresignedObjectUrl(args) + } + } + + override fun removeObject(fileName: ImageRemoveObjectArgs) { + RemoveObjectArgs.builder() + .bucket(fileName.bucket) + .`object`(fileName.`object`) + .build() + .let { args -> + minIoClient.removeObject(args) + } + } + + override fun putObject(fileName: ImagePutObjectArgs): ImageWriteResponse { + PutObjectArgs.builder() + .bucket(fileName.bucket) + .`object`(fileName.`object`) + .stream(fileName.stream, fileName.objectSize, fileName.partSize) + .contentType(fileName.contentType) + .build() + .let { args -> + minIoClient.putObject(args).let { owr -> + return ImageWriteResponse( + owr.bucket(), + owr.region(), + owr.`object`(), + owr.etag(), + owr.versionId() + ) + } + } + } +} \ No newline at end of file From e7d45b272ce21cbb9a73e902808ae7b3634975fa Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:19:55 +0900 Subject: [PATCH 13/81] =?UTF-8?q?feat:=20ImageArgsGenerator=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../walking/image/util/ImageArgsGenerator.kt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/util/ImageArgsGenerator.kt diff --git a/image-store/src/main/kotlin/com/walking/image/util/ImageArgsGenerator.kt b/image-store/src/main/kotlin/com/walking/image/util/ImageArgsGenerator.kt new file mode 100644 index 00000000..ede3e79d --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/util/ImageArgsGenerator.kt @@ -0,0 +1,25 @@ +package com.walking.image.util + +import com.walking.image.ImageGetPresignedObjectUrlArgs +import com.walking.image.ImagePutObjectArgs +import com.walking.image.ImageRemoveObjectArgs +import io.minio.http.Method +import java.io.BufferedInputStream +import java.io.File +import java.io.FileInputStream + +class ImageArgsGenerator { + companion object { + fun preSignedUrl(bucket: String, image: String): ImageGetPresignedObjectUrlArgs { + return ImageGetPresignedObjectUrlArgs(bucket, image, Method.GET.toString()) + } + + fun putImage(bucket: String, name: String, image: File, contentType: String = "image/jpg"): ImagePutObjectArgs { + return ImagePutObjectArgs(bucket, name, BufferedInputStream(FileInputStream(image)), image.length(), -1, contentType) + } + + fun remove(bucket: String, image: String): ImageRemoveObjectArgs { + return ImageRemoveObjectArgs(bucket, image) + } + } +} \ No newline at end of file From c4f7bb171fc06d3f7241a0d82dd3d31f3fb4025f Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:20:17 +0900 Subject: [PATCH 14/81] =?UTF-8?q?feat:=20GetPreSignedImageUrlService=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/image/service/GetPreSignedImageUrlService.kt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/service/GetPreSignedImageUrlService.kt diff --git a/image-store/src/main/kotlin/com/walking/image/service/GetPreSignedImageUrlService.kt b/image-store/src/main/kotlin/com/walking/image/service/GetPreSignedImageUrlService.kt new file mode 100644 index 00000000..9fda3390 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/service/GetPreSignedImageUrlService.kt @@ -0,0 +1,5 @@ +package com.walking.image.service + +fun interface GetPreSignedImageUrlService { + fun execute(image: String): String +} \ No newline at end of file From b30fc431db6f420aaa28da211ddf8d1397472f36 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:20:25 +0900 Subject: [PATCH 15/81] =?UTF-8?q?feat:=20RemoveImageService=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/walking/image/service/RemoveImageService.kt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/service/RemoveImageService.kt diff --git a/image-store/src/main/kotlin/com/walking/image/service/RemoveImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/RemoveImageService.kt new file mode 100644 index 00000000..c6b248b7 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/service/RemoveImageService.kt @@ -0,0 +1,5 @@ +package com.walking.image.service + +fun interface RemoveImageService { + fun execute(image: String): Boolean +} \ No newline at end of file From f2c017e5271ee05803760564c7cb6560af30b108 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:20:32 +0900 Subject: [PATCH 16/81] =?UTF-8?q?feat:=20UploadImageService=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/image/service/UploadImageService.kt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/service/UploadImageService.kt diff --git a/image-store/src/main/kotlin/com/walking/image/service/UploadImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/UploadImageService.kt new file mode 100644 index 00000000..5b180841 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/service/UploadImageService.kt @@ -0,0 +1,8 @@ +package com.walking.image.service + +import com.walking.image.ImageWriteResponse +import java.io.File + +fun interface UploadImageService { + fun execute(name: String, file: File): ImageWriteResponse +} \ No newline at end of file From 1ef431b0fb5efe092e4653bc2a58af1994859d58 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:20:43 +0900 Subject: [PATCH 17/81] =?UTF-8?q?feat:=20MinioGetPreSignedImageUrlService?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../minio/MinioGetPreSignedImageUrlService.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt diff --git a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt new file mode 100644 index 00000000..3623b482 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt @@ -0,0 +1,21 @@ +package com.walking.image.service.minio + +import com.walking.image.MinioImageStoreClient +import com.walking.image.service.GetPreSignedImageUrlService +import com.walking.image.util.ImageArgsGenerator +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Service + +@Profile("minio") +@Service +class MinioGetPreSignedImageUrlService( + @Value("\${minio.bucket-name}") val bucket: String, + private val imageStoreClient: MinioImageStoreClient +) : GetPreSignedImageUrlService { + override fun execute(image: String): String { + ImageArgsGenerator.preSignedUrl(bucket, image).let { args -> + return imageStoreClient.getPresignedObjectUrl(args) + } + } +} \ No newline at end of file From c64018dd3b1c99d686a1b984fe70565ec7ed5dd5 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:20:55 +0900 Subject: [PATCH 18/81] =?UTF-8?q?feat:=20MinioRemoveImageService=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/minio/MinioRemoveImageService.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt diff --git a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt new file mode 100644 index 00000000..9aa12c60 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt @@ -0,0 +1,26 @@ +package com.walking.image.service.minio + +import com.walking.image.MinioImageStoreClient +import com.walking.image.service.RemoveImageService +import com.walking.image.util.ImageArgsGenerator +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Service + +@Profile("minio") +@Service +class MinioRemoveImageService( + @Value("\${minio.bucket-name}") val bucket: String, + private val imageStoreClient: MinioImageStoreClient +) : RemoveImageService { + override fun execute(image: String): Boolean { + try { + ImageArgsGenerator.remove(bucket, image).let { args -> + imageStoreClient.removeObject(args) + return true + } + } catch (e: Exception) { + return false + } + } +} \ No newline at end of file From e6a7793eaa1615fab6af0351f0037d242669da18 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:21:11 +0900 Subject: [PATCH 19/81] =?UTF-8?q?feat:=20MinioUploadImageService=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/minio/MinioUploadImageService.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt diff --git a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt new file mode 100644 index 00000000..b370da7d --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt @@ -0,0 +1,23 @@ +package com.walking.image.service.minio + +import com.walking.image.ImageWriteResponse +import com.walking.image.MinioImageStoreClient +import com.walking.image.service.UploadImageService +import com.walking.image.util.ImageArgsGenerator +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Service +import java.io.File + +@Profile("minio") +@Service +class MinioUploadImageService( + @Value("\${minio.bucket-name}") val bucket: String, + private val imageStoreClient: MinioImageStoreClient +) : UploadImageService { + override fun execute(name: String, file: File): ImageWriteResponse { + ImageArgsGenerator.putImage(bucket, name, file).let { args -> + return imageStoreClient.putObject(args) + } + } +} \ No newline at end of file From 80ce679af71d41c822e92e6d4061d5eed39cc3a8 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:22:52 +0900 Subject: [PATCH 20/81] =?UTF-8?q?refactor:=20MemberEntity=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9E=90=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: withDrawn, updateProfile 메서드를 추가합니다 --- .../walking/data/entity/member/MemberEntity.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/data/src/main/java/com/walking/data/entity/member/MemberEntity.java b/data/src/main/java/com/walking/data/entity/member/MemberEntity.java index b1346ee9..ddadff74 100644 --- a/data/src/main/java/com/walking/data/entity/member/MemberEntity.java +++ b/data/src/main/java/com/walking/data/entity/member/MemberEntity.java @@ -51,4 +51,20 @@ public class MemberEntity extends BaseEntity { @Builder.Default @Column(nullable = false, columnDefinition = "json") private String resource = "{}"; + + public MemberEntity(String nickName, String profile, String certificationId) { + this.nickName = nickName; + this.profile = profile; + this.certificationId = certificationId; + } + + public MemberEntity withDrawn() { + this.status = MemberStatus.WITHDRAWN; + return this; + } + + public MemberEntity updateProfile(String profile) { + this.profile = profile; + return this; + } } From d84f40d8373f97b02841b9fa3c4c36bc1e66c207 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:23:19 +0900 Subject: [PATCH 21/81] =?UTF-8?q?feat:=20member-api=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20build.gradle=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- member-api/build.gradle | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 member-api/build.gradle diff --git a/member-api/build.gradle b/member-api/build.gradle new file mode 100644 index 00000000..b7c2d0cc --- /dev/null +++ b/member-api/build.gradle @@ -0,0 +1,36 @@ +bootJar { + enabled = false +} + +jar { + enabled = true +} + +apply plugin: 'org.jlleitschuh.gradle.ktlint' +apply plugin: 'org.jlleitschuh.gradle.ktlint-idea' +apply plugin: 'org.jetbrains.kotlin.jvm' +apply plugin: 'org.jetbrains.kotlin.plugin.jpa' +apply plugin: 'org.jetbrains.kotlin.plugin.spring' + +dependencies { + api project(':api-repository') + implementation project(':image-store') + + // kotlin reflect + runtimeOnly "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + + // spring + implementation 'org.springframework.boot:spring-boot-starter-web' + + // jackson + implementation 'com.fasterxml.jackson.module:jackson-module-kotlin' + implementation 'com.fasterxml.jackson.core:jackson-databind' + implementation 'com.fasterxml.jackson.core:jackson-core' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' + implementation group: 'com.google.code.findbugs', name: 'jsr305', version: "${jsr305Version}" + + // retry + implementation "org.apache.httpcomponents:httpclient:${httpclientVersion}" + implementation 'org.springframework.retry:spring-retry:1.2.5.RELEASE' +} From 89dbf29807741e8a9d0e908d346771ba801daf6c Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:23:37 +0900 Subject: [PATCH 22/81] =?UTF-8?q?feat:=20member-api=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EA=B5=AC=EC=84=B1=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/application-member-api-dev.yml | 23 +++++++++++++++++++ .../application-member-api-local.yml | 22 ++++++++++++++++++ .../resources/application-member-api-prod.yml | 22 ++++++++++++++++++ .../main/resources/application-member-api.yml | 22 ++++++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 member-api/src/main/resources/application-member-api-dev.yml create mode 100644 member-api/src/main/resources/application-member-api-local.yml create mode 100644 member-api/src/main/resources/application-member-api-prod.yml create mode 100644 member-api/src/main/resources/application-member-api.yml diff --git a/member-api/src/main/resources/application-member-api-dev.yml b/member-api/src/main/resources/application-member-api-dev.yml new file mode 100644 index 00000000..c909e4f6 --- /dev/null +++ b/member-api/src/main/resources/application-member-api-dev.yml @@ -0,0 +1,23 @@ +client: + max-attempts: ${CLIENT_MAX_ATTEMPTS:3} + pool: + max-connect: ${CLIENT_MAX_CONNECT:100} + max-connect-per-route: ${CLIENT_MAX_CONNECT_PER_ROUTE:5} + timeout: + connect: ${CLIENT_CONNECT_TIMEOUT:5000} + read: ${CLIENT_READ_TIMEOUT:5000} + retry: + maxAttempts: ${MAX_ATTEMPTS} + backOffPeriod: ${BACK_OFF_PERIOD} + +kakao: + host: ${KAKO_HOST} + adminKey: ${KAKO_ADMIN_KEY} + uri: + token: ${KAKO_TOKEN_URI} + token_info: ${KAKO_TOKEN_INFO_URI} + me_info: ${KAKO_ME_INFO_URI} + unlink: ${KAKO_UNLINK_URI} + redirect_uri: ${KAKO_APP_REDIRECT_URI} + client_id: ${KAKO_APP_CLIENT_ID} + diff --git a/member-api/src/main/resources/application-member-api-local.yml b/member-api/src/main/resources/application-member-api-local.yml new file mode 100644 index 00000000..7624fa3e --- /dev/null +++ b/member-api/src/main/resources/application-member-api-local.yml @@ -0,0 +1,22 @@ +client: + max-attempts: 3 + pool: + max-connect: 100 + max-connect-per-route: 5 + timeout: + connect: 5000 + read: 5000 + retry: + maxAttempts: 3 + backOffPeriod: 2000 + +kakao: + host: https://kauth.kakao.com + adminKey: adminKey + uri: + token: https://kauth.kakao.com/oauth/token + token_info: https://kapi.kakao.com/v1/user/access_token_info + me_info: https://kapi.kakao.com/v2/user/me + unlink: https://kapi.kakao.com/v1/user/unlink + redirect_uri: http://localhost:8080/api/v1/social/kakao + client_id: thisIsKaKaoClientId diff --git a/member-api/src/main/resources/application-member-api-prod.yml b/member-api/src/main/resources/application-member-api-prod.yml new file mode 100644 index 00000000..fe646adb --- /dev/null +++ b/member-api/src/main/resources/application-member-api-prod.yml @@ -0,0 +1,22 @@ +client: + max-attempts: ${CLIENT_MAX_ATTEMPTS:3} + pool: + max-connect: ${CLIENT_MAX_CONNECT:100} + max-connect-per-route: ${CLIENT_MAX_CONNECT_PER_ROUTE:5} + timeout: + connect: ${CLIENT_CONNECT_TIMEOUT:5000} + read: ${CLIENT_READ_TIMEOUT:5000} + retry: + maxAttempts: ${MAX_ATTEMPTS} + backOffPeriod: ${BACK_OFF_PERIOD} + +kakao: + host: ${KAKO_HOST} + adminKey: ${KAKO_ADMIN_KEY} + uri: + token: ${KAKO_TOKEN_URI} + token_info: ${KAKO_TOKEN_INFO_URI} + me_info: ${KAKO_ME_INFO_URI} + unlink: ${KAKO_UNLINK_URI} + redirect_uri: ${KAKO_APP_REDIRECT_URI} + client_id: ${KAKO_APP_CLIENT_ID} diff --git a/member-api/src/main/resources/application-member-api.yml b/member-api/src/main/resources/application-member-api.yml new file mode 100644 index 00000000..fe646adb --- /dev/null +++ b/member-api/src/main/resources/application-member-api.yml @@ -0,0 +1,22 @@ +client: + max-attempts: ${CLIENT_MAX_ATTEMPTS:3} + pool: + max-connect: ${CLIENT_MAX_CONNECT:100} + max-connect-per-route: ${CLIENT_MAX_CONNECT_PER_ROUTE:5} + timeout: + connect: ${CLIENT_CONNECT_TIMEOUT:5000} + read: ${CLIENT_READ_TIMEOUT:5000} + retry: + maxAttempts: ${MAX_ATTEMPTS} + backOffPeriod: ${BACK_OFF_PERIOD} + +kakao: + host: ${KAKO_HOST} + adminKey: ${KAKO_ADMIN_KEY} + uri: + token: ${KAKO_TOKEN_URI} + token_info: ${KAKO_TOKEN_INFO_URI} + me_info: ${KAKO_ME_INFO_URI} + unlink: ${KAKO_UNLINK_URI} + redirect_uri: ${KAKO_APP_REDIRECT_URI} + client_id: ${KAKO_APP_CLIENT_ID} From b62de5db42f90668f05583a225e4a84e208a18d0 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:23:51 +0900 Subject: [PATCH 23/81] =?UTF-8?q?feat:=20MemberApiConfig=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/config/MemberApiConfig.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/config/MemberApiConfig.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/config/MemberApiConfig.kt b/member-api/src/main/kotlin/com/walking/member/api/config/MemberApiConfig.kt new file mode 100644 index 00000000..364d5f90 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/config/MemberApiConfig.kt @@ -0,0 +1,22 @@ +package com.walking.member.api.config + +import com.walking.api.repository.config.ApiRepositoryConfig +import com.walking.image.config.ImageStoreConfig +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Import + +@Import( + value = [ApiRepositoryConfig::class, ImageStoreConfig::class] +) +@Configuration +@ComponentScan(basePackages = [MemberApiConfig.BASE_PACKAGE]) +class MemberApiConfig { + companion object { + const val BASE_PACKAGE = "com.walking.member.api" + const val SERVICE_NAME = "walking" + const val MODULE_NAME = "member-api" + const val BEAN_NAME_PREFIX = "memberApi" + const val PROPERTY_PREFIX = SERVICE_NAME + "." + MODULE_NAME + } +} \ No newline at end of file From b893eae56f4775212e2647f703394a7331e586f3 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:24:35 +0900 Subject: [PATCH 24/81] =?UTF-8?q?feat:=20social=20client=20exception?= =?UTF-8?q?=EC=9D=84=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/client/exception/SocialClientException.kt | 3 +++ .../member/api/client/exception/SocialIntegrationException.kt | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/exception/SocialClientException.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/exception/SocialIntegrationException.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/exception/SocialClientException.kt b/member-api/src/main/kotlin/com/walking/member/api/client/exception/SocialClientException.kt new file mode 100644 index 00000000..17d554bb --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/exception/SocialClientException.kt @@ -0,0 +1,3 @@ +package com.walking.member.api.client.exception + +class SocialClientException(message: String = "클라이언트 에러가 발생하였습니다.") : RuntimeException(message) \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/exception/SocialIntegrationException.kt b/member-api/src/main/kotlin/com/walking/member/api/client/exception/SocialIntegrationException.kt new file mode 100644 index 00000000..e51ba26d --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/exception/SocialIntegrationException.kt @@ -0,0 +1,4 @@ +package com.walking.member.api.client.exception + +class SocialIntegrationException(message: String = "소셜 연동 중 오류가 발생했습니다.") : + RuntimeException(message) \ No newline at end of file From 773910ad8ca66b528f63fff2ac517082ede5e0b5 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:25:07 +0900 Subject: [PATCH 25/81] =?UTF-8?q?feat:=20social=20client=20interceptor=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LogClientHttpRequestInterceptor.kt | 60 +++++++++++++++++++ ...RetryPolicyClientHttpRequestInterceptor.kt | 37 ++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/config/interceptor/LogClientHttpRequestInterceptor.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/config/interceptor/RetryPolicyClientHttpRequestInterceptor.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/config/interceptor/LogClientHttpRequestInterceptor.kt b/member-api/src/main/kotlin/com/walking/member/api/client/config/interceptor/LogClientHttpRequestInterceptor.kt new file mode 100644 index 00000000..dcc12852 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/config/interceptor/LogClientHttpRequestInterceptor.kt @@ -0,0 +1,60 @@ +package com.walking.member.api.client.config.interceptor + +import org.slf4j.Logger +import org.springframework.http.HttpRequest +import org.springframework.http.client.ClientHttpRequestExecution +import org.springframework.http.client.ClientHttpRequestInterceptor +import org.springframework.http.client.ClientHttpResponse +import org.springframework.stereotype.Component +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader +import java.nio.charset.StandardCharsets +import java.util.stream.Collectors + +@Component +class LogClientHttpRequestInterceptor : ClientHttpRequestInterceptor { + val log: Logger = org.slf4j.LoggerFactory.getLogger(LogClientHttpRequestInterceptor::class.java) + + @Throws(IOException::class) + override fun intercept( + request: HttpRequest, + body: ByteArray, + execution: ClientHttpRequestExecution + ): ClientHttpResponse { + val uuid = clientHttpRequestUUID() + doLogRequest(uuid, request, body) + val response = execution.execute(request, body) + doLogResponse(uuid, response) + return response + } + + private fun clientHttpRequestUUID(): String { + return (Math.random() * 1000000).toInt().toString() + } + + private fun doLogRequest(sessionNumber: String, req: HttpRequest, body: ByteArray) { + log.info( + "[{}] URI: {}, Method: {}, Headers:{}, Body:{} ", + sessionNumber, + req.uri, + req.method, + req.headers, + String(body, StandardCharsets.UTF_8) + ) + } + + @Throws(IOException::class) + private fun doLogResponse(sessionNumber: String, res: ClientHttpResponse) { + val body = BufferedReader(InputStreamReader(res.body, StandardCharsets.UTF_8)) + .lines() + .collect(Collectors.joining("\n")) + log.info( + "[{}] Status: {}, Headers:{}, Body:{} ", + sessionNumber, + res.statusCode, + res.headers, + body + ) + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/config/interceptor/RetryPolicyClientHttpRequestInterceptor.kt b/member-api/src/main/kotlin/com/walking/member/api/client/config/interceptor/RetryPolicyClientHttpRequestInterceptor.kt new file mode 100644 index 00000000..1593249f --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/config/interceptor/RetryPolicyClientHttpRequestInterceptor.kt @@ -0,0 +1,37 @@ +package com.walking.member.api.client.config.interceptor + +import org.springframework.beans.factory.annotation.Value +import org.springframework.http.HttpRequest +import org.springframework.http.client.ClientHttpRequestExecution +import org.springframework.http.client.ClientHttpRequestInterceptor +import org.springframework.http.client.ClientHttpResponse +import org.springframework.retry.policy.SimpleRetryPolicy +import org.springframework.retry.support.RetryTemplate +import org.springframework.stereotype.Component +import java.io.IOException + +@Component +class RetryPolicyClientHttpRequestInterceptor( + @Value("\${client.max-attempts:3}") private val maxAttempts: Int +) : ClientHttpRequestInterceptor { + @Throws(IOException::class) + override fun intercept( + request: HttpRequest, + body: ByteArray, + execution: ClientHttpRequestExecution + ): ClientHttpResponse { + val retryTemplate = RetryTemplate() + retryTemplate.setRetryPolicy(SimpleRetryPolicy(maxAttempts)) + + return try { + retryTemplate.execute { + execution.execute( + request, + body + ) + } + } catch (e: Exception) { + throw RuntimeException(e) + } + } +} \ No newline at end of file From 190d96f26f37e1a3255fd1c7bb89a19826f67982 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:25:28 +0900 Subject: [PATCH 26/81] =?UTF-8?q?feat:=20ClientListener=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/config/listener/ClientListener.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/config/listener/ClientListener.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/config/listener/ClientListener.kt b/member-api/src/main/kotlin/com/walking/member/api/client/config/listener/ClientListener.kt new file mode 100644 index 00000000..f8a9ee91 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/config/listener/ClientListener.kt @@ -0,0 +1,37 @@ +package com.walking.member.api.client.config.listener + +import org.springframework.retry.RetryCallback +import org.springframework.retry.RetryContext +import org.springframework.retry.listener.RetryListenerSupport +import org.springframework.stereotype.Component + +@Component +class ClientListener : RetryListenerSupport() { + private val log = org.slf4j.LoggerFactory.getLogger(ClientListener::class.java) + + override fun open( + context: RetryContext, + callback: RetryCallback + ): Boolean { + log.debug("request to kakao api") + return super.open(context, callback) + } + + override fun close( + context: RetryContext, + callback: RetryCallback, + throwable: Throwable + ) { + log.debug("success get response kakao api") + super.close(context, callback, throwable) + } + + override fun onError( + context: RetryContext, + callback: RetryCallback, + throwable: Throwable + ) { + log.error("fail get response kakao api : {}", throwable.message) + super.onError(context, callback, throwable) + } +} \ No newline at end of file From 1b85c6b9ffdb24ba3e3f49c27bea0da8e884c9bd Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:25:47 +0900 Subject: [PATCH 27/81] =?UTF-8?q?feat:=20social=20client=20properties=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/config/property/KaKaoApiProperties.kt | 16 ++++++++++++++++ .../config/property/KaKaoIdTokenProperties.kt | 10 ++++++++++ 2 files changed, 26 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/config/property/KaKaoApiProperties.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/config/property/KaKaoIdTokenProperties.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/config/property/KaKaoApiProperties.kt b/member-api/src/main/kotlin/com/walking/member/api/client/config/property/KaKaoApiProperties.kt new file mode 100644 index 00000000..1038b9f1 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/config/property/KaKaoApiProperties.kt @@ -0,0 +1,16 @@ +package com.walking.member.api.client.config.property + +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Component + +@Component +data class KaKaoApiProperties( + @Value("\${kakao.host}") val host: String, + @Value("\${kakao.adminKey}") val adminKey: String, + @Value("\${kakao.uri.token}") val uriToken: String, + @Value("\${kakao.uri.token_info}") val uriTokenInfo: String, + @Value("\${kakao.uri.me_info}") val uriMeInfo: String, + @Value("\${kakao.uri.unlink}") val unlink: String, + @Value("\${kakao.redirect_uri}") val redirectUri: String, + @Value("\${kakao.client_id}") val clientId: String +) \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/config/property/KaKaoIdTokenProperties.kt b/member-api/src/main/kotlin/com/walking/member/api/client/config/property/KaKaoIdTokenProperties.kt new file mode 100644 index 00000000..51fd906f --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/config/property/KaKaoIdTokenProperties.kt @@ -0,0 +1,10 @@ +package com.walking.member.api.client.config.property + +data class +KaKaoIdTokenProperties( + val iss: String, + val aud: String, + val sub: String, + val nickname: String, + val picture: String +) \ No newline at end of file From 817c61bc42cc73d090e526c1a3cd16792e59184c Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:26:02 +0900 Subject: [PATCH 28/81] =?UTF-8?q?feat:=20RestTemplateConfig=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/client/config/RestTemplateConfig.kt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/config/RestTemplateConfig.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/config/RestTemplateConfig.kt b/member-api/src/main/kotlin/com/walking/member/api/client/config/RestTemplateConfig.kt new file mode 100644 index 00000000..45052df6 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/config/RestTemplateConfig.kt @@ -0,0 +1,47 @@ +package com.walking.member.api.client.config + +import com.walking.member.api.client.config.interceptor.LogClientHttpRequestInterceptor +import com.walking.member.api.client.config.interceptor.RetryPolicyClientHttpRequestInterceptor +import org.apache.http.client.HttpClient +import org.apache.http.impl.client.HttpClientBuilder +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.http.client.BufferingClientHttpRequestFactory +import org.springframework.http.client.ClientHttpRequestInterceptor +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory +import org.springframework.web.client.RestTemplate + +@Configuration +class RestTemplateConfig( + private val retryPolicyClientHttpRequestInterceptor: RetryPolicyClientHttpRequestInterceptor, + private val logClientHttpRequestInterceptor: LogClientHttpRequestInterceptor +) { + @Bean + fun restTemplate( + @Value("\${client.timeout.connect}") connectTimeout: Int, + @Value("\${client.timeout.read}") readTimeout: Int, + @Value("\${client.pool.max-connect}") maxConnectPool: Int, + @Value("\${client.pool.max-connect-per-route}") maxPerRouteConnectPool: Int + ): RestTemplate { + val factory = HttpComponentsClientHttpRequestFactory() + factory.setReadTimeout(readTimeout) + factory.setConnectTimeout(connectTimeout) + val httpClient: HttpClient = HttpClientBuilder.create() + .setMaxConnTotal(maxConnectPool) + .setMaxConnPerRoute(maxPerRouteConnectPool) + .build() + factory.setHttpClient(httpClient) + + val restTemplate = RestTemplate(BufferingClientHttpRequestFactory(factory)) + var interceptors: MutableList = + restTemplate.getInterceptors() + if (interceptors.isEmpty()) { + interceptors = ArrayList() + } + interceptors.add(retryPolicyClientHttpRequestInterceptor) + interceptors.add(logClientHttpRequestInterceptor) + restTemplate.setInterceptors(interceptors) + return restTemplate + } +} \ No newline at end of file From d7175c064fa463d2f03051aa78439366d3d4f0d3 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:26:16 +0900 Subject: [PATCH 29/81] =?UTF-8?q?feat:=20RetryTemplateConfig=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/client/config/RetryTemplateConfig.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/config/RetryTemplateConfig.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/config/RetryTemplateConfig.kt b/member-api/src/main/kotlin/com/walking/member/api/client/config/RetryTemplateConfig.kt new file mode 100644 index 00000000..f289107e --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/config/RetryTemplateConfig.kt @@ -0,0 +1,34 @@ +package com.walking.member.api.client.config + +import com.walking.member.api.client.config.listener.ClientListener +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.retry.annotation.EnableRetry +import org.springframework.retry.backoff.FixedBackOffPolicy +import org.springframework.retry.policy.SimpleRetryPolicy +import org.springframework.retry.support.RetryTemplate + +@Configuration +@EnableRetry +class RetryTemplateConfig( + private val clientListener: ClientListener +) { + @Bean + fun retryTemplate( + @Value("\${client.retry.maxAttempts}") maxAttempts: Int, + @Value("\${client.retry.backOffPeriod}") backOffPeriod: Int + ): RetryTemplate { + val backOffPolicy = FixedBackOffPolicy() + backOffPolicy.backOffPeriod = backOffPeriod.toLong() + + val retryPolicy = SimpleRetryPolicy() + retryPolicy.maxAttempts = maxAttempts + + val retryTemplate = RetryTemplate() + retryTemplate.setBackOffPolicy(backOffPolicy) + retryTemplate.setRetryPolicy(retryPolicy) + retryTemplate.registerListener(clientListener) + return retryTemplate + } +} \ No newline at end of file From 953a2b0972fb1aab0eb84c69c3ed9a4315135d52 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:29:03 +0900 Subject: [PATCH 30/81] =?UTF-8?q?feat:=20HeaderUtils=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../walking/member/api/client/util/HeaderUtils.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt b/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt new file mode 100644 index 00000000..0865efaa --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt @@ -0,0 +1,13 @@ +package com.walking.member.api.client.util + +import org.springframework.http.HttpHeaders + +class HeaderUtils { + companion object { + fun generateBearerHeaders(token: String): HttpHeaders { + val headers = HttpHeaders() + headers.add("Authorization", "Bearer $token") + return headers + } + } +} \ No newline at end of file From b2ffd079e4e4b2c840e13781d14ecc79410c9609 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:29:21 +0900 Subject: [PATCH 31/81] =?UTF-8?q?feat:=20TokenPropertiesMapper=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/client/util/TokenPropertiesMapper.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/util/TokenPropertiesMapper.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/util/TokenPropertiesMapper.kt b/member-api/src/main/kotlin/com/walking/member/api/client/util/TokenPropertiesMapper.kt new file mode 100644 index 00000000..21315ad5 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/util/TokenPropertiesMapper.kt @@ -0,0 +1,23 @@ +package com.walking.member.api.client.util + +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.databind.ObjectMapper +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Component + +@Component +class TokenPropertiesMapper( + private val objectMapper: ObjectMapper +) { + val log: Logger = LoggerFactory.getLogger(TokenPropertiesMapper::class.java) + fun read(info: String?, clazz: Class): T { + var properties: T? = null + try { + properties = objectMapper.readValue(info, clazz) + } catch (e: JsonProcessingException) { + log.error("error read token properties", e) + } + return properties!! + } +} \ No newline at end of file From f3757b540c41f63031fc83f2ab03b1102cf1fb1b Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:26:42 +0900 Subject: [PATCH 32/81] =?UTF-8?q?feat:=20social=20member=20client=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/client/member/KaKaoMemberClient.kt | 43 +++++++++++++++++++ .../api/client/member/SocialMemberClient.kt | 8 ++++ .../api/client/member/dto/KaKaoMemberData.kt | 15 +++++++ .../api/client/member/dto/SocialMemberData.kt | 6 +++ 4 files changed, 72 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/member/dto/KaKaoMemberData.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/member/dto/SocialMemberData.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt new file mode 100644 index 00000000..0212fe70 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt @@ -0,0 +1,43 @@ +package com.walking.member.api.client.member + +import com.walking.member.api.client.config.property.KaKaoApiProperties +import com.walking.member.api.client.exception.SocialClientException +import com.walking.member.api.client.member.dto.KaKaoMemberData +import com.walking.member.api.client.member.dto.SocialMemberData +import com.walking.member.api.client.token.dto.SocialIdToken +import com.walking.member.api.client.util.HeaderUtils +import lombok.RequiredArgsConstructor +import lombok.extern.slf4j.Slf4j +import org.springframework.http.HttpEntity +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod +import org.springframework.http.ResponseEntity +import org.springframework.stereotype.Component +import org.springframework.web.client.RestTemplate + +@Slf4j +@Component +@RequiredArgsConstructor +class KaKaoMemberClient( + private val restTemplate: RestTemplate, + private val properties: KaKaoApiProperties +) : SocialMemberClient { + override fun execute(token: SocialIdToken): SocialMemberData { + val accessToken: String = token.getToken() + + val headers: HttpHeaders = HeaderUtils.generateBearerHeaders(accessToken) + headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=utf-8") + val response: ResponseEntity = restTemplate.exchange( + properties.uriMeInfo, + HttpMethod.POST, + HttpEntity(null, headers), + KaKaoMemberData::class.java + ) + + val statusCode = response.statusCode + if (statusCode.is4xxClientError) { + throw SocialClientException() + } + return response.body!! + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt new file mode 100644 index 00000000..37482946 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt @@ -0,0 +1,8 @@ +package com.walking.member.api.client.member + +import com.walking.member.api.client.member.dto.SocialMemberData +import com.walking.member.api.client.token.dto.SocialIdToken + +fun interface SocialMemberClient { + fun execute(token: SocialIdToken): SocialMemberData +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/KaKaoMemberData.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/KaKaoMemberData.kt new file mode 100644 index 00000000..c70527a9 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/KaKaoMemberData.kt @@ -0,0 +1,15 @@ +package com.walking.member.api.client.member.dto + +data class KaKaoMemberData(private val id: String) : SocialMemberData { + private val properties: Properties? = null + + private data class Properties(val nickname: String) + + override fun getName(): String { + return properties?.nickname ?: "" + } + + override fun getId(): Long { + return id.toLong() + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/SocialMemberData.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/SocialMemberData.kt new file mode 100644 index 00000000..ebe46415 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/SocialMemberData.kt @@ -0,0 +1,6 @@ +package com.walking.member.api.client.member.dto + +interface SocialMemberData { + fun getName(): String + fun getId(): Long +} \ No newline at end of file From 615bc80631c1cce1af85230d9475a1cdaeec0ea8 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:28:26 +0900 Subject: [PATCH 33/81] =?UTF-8?q?feat:=20social=20token=20client=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/client/token/KaKaoIdTokenClient.kt | 59 +++++++++++++++++++ .../api/client/token/KaKaoTokenClient.kt | 40 +++++++++++++ .../client/token/RetryAbleKaKaoTokenClient.kt | 40 +++++++++++++ .../api/client/token/SocialIdTokenClient.kt | 5 ++ .../api/client/token/SocialTokenClient.kt | 9 +++ .../api/client/token/dto/KaKaoIdTokenData.kt | 7 +++ .../api/client/token/dto/KaKaoTokenData.kt | 7 +++ .../api/client/token/dto/SocialIdToken.kt | 5 ++ .../api/client/token/dto/SocialToken.kt | 5 ++ 9 files changed, 177 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoIdTokenClient.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenClient.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/token/RetryAbleKaKaoTokenClient.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/token/SocialIdTokenClient.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/token/SocialTokenClient.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoIdTokenData.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoTokenData.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/token/dto/SocialIdToken.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/token/dto/SocialToken.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoIdTokenClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoIdTokenClient.kt new file mode 100644 index 00000000..5aff70af --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoIdTokenClient.kt @@ -0,0 +1,59 @@ +package com.walking.member.api.client.token + +import SocialIdTokenClient +import com.walking.member.api.client.config.property.KaKaoApiProperties +import com.walking.member.api.client.exception.SocialClientException +import com.walking.member.api.client.token.dto.KaKaoIdTokenData +import com.walking.member.api.client.token.dto.SocialIdToken +import lombok.RequiredArgsConstructor +import lombok.extern.slf4j.Slf4j +import org.springframework.http.HttpEntity +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod +import org.springframework.http.ResponseEntity +import org.springframework.stereotype.Component +import org.springframework.util.LinkedMultiValueMap +import org.springframework.util.MultiValueMap +import org.springframework.web.client.RestClientException +import org.springframework.web.client.RestTemplate + +@Slf4j +@Component +@RequiredArgsConstructor +class KaKaoIdTokenClient( + private val restTemplate: RestTemplate, + private val properties: KaKaoApiProperties +) : SocialIdTokenClient { + override fun execute(code: String): SocialIdToken { + val headers = HttpHeaders() + headers.add("Accept", "application/json") + headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=utf-8") + + val params: MultiValueMap = LinkedMultiValueMap() + params.add("grant_type", "authorization_code") + params.add("client_id", properties.clientId) + params.add("redirect_uri", properties.redirectUri) + params.add("code", code) + + val httpEntity = HttpEntity(params, headers) + + val response: ResponseEntity + try { + response = restTemplate.exchange( + properties.uriToken, + HttpMethod.POST, + httpEntity, + KaKaoIdTokenData::class.java + ) + } catch (e: RestClientException) { + throw SocialClientException() + } + + val statusCode = response.statusCode + if (statusCode.is4xxClientError) { + throw SocialClientException() + } + + return response.body as SocialIdToken + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenClient.kt new file mode 100644 index 00000000..b7f3e7ad --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenClient.kt @@ -0,0 +1,40 @@ +import com.walking.member.api.client.config.property.KaKaoApiProperties +import com.walking.member.api.client.exception.SocialClientException +import com.walking.member.api.client.token.SocialTokenClient +import com.walking.member.api.client.token.dto.KaKaoTokenData +import com.walking.member.api.client.token.dto.SocialIdToken +import com.walking.member.api.client.token.dto.SocialToken +import com.walking.member.api.client.util.HeaderUtils +import lombok.RequiredArgsConstructor +import lombok.extern.slf4j.Slf4j +import org.springframework.http.* +import org.springframework.stereotype.Component +import org.springframework.web.client.RestTemplate + +@Slf4j +@Component +@RequiredArgsConstructor +class KaKaoTokenClient( + private val restTemplate: RestTemplate, + private val properties: KaKaoApiProperties +) : SocialTokenClient { + override fun execute(token: SocialIdToken): SocialToken { + val accessToken: String = token.getToken() + val headers: HttpHeaders = HeaderUtils.generateBearerHeaders(accessToken) + headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=utf-8") + + val response: ResponseEntity = restTemplate.exchange( + properties.uriTokenInfo, + HttpMethod.GET, + HttpEntity(null, headers), + KaKaoTokenData::class.java + ) + + val statusCode: HttpStatus = response.statusCode + if (statusCode.is4xxClientError) { + throw SocialClientException() + } + + return response.body!! + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/RetryAbleKaKaoTokenClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/RetryAbleKaKaoTokenClient.kt new file mode 100644 index 00000000..a4a397ae --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/RetryAbleKaKaoTokenClient.kt @@ -0,0 +1,40 @@ +package com.walking.member.api.client.token + +import SocialIdTokenClient +import com.walking.member.api.client.exception.SocialClientException +import com.walking.member.api.client.token.dto.SocialIdToken +import lombok.RequiredArgsConstructor +import lombok.extern.slf4j.Slf4j +import org.slf4j.Logger +import org.springframework.retry.RecoveryCallback +import org.springframework.retry.RetryCallback +import org.springframework.retry.support.RetryTemplate +import org.springframework.stereotype.Component + +@Slf4j +@Component +@RequiredArgsConstructor +class RetryAbleKaKaoTokenClient( + private val retryTemplate: RetryTemplate, + private val kaKaoIdTokenClient: KaKaoIdTokenClient +) : SocialIdTokenClient { + val log: Logger = org.slf4j.LoggerFactory.getLogger(RetryAbleKaKaoTokenClient::class.java) + + override fun execute(code: String): SocialIdToken { + return retryTemplate.execute( + RetryCallback { retryContext -> + log.error("something wrong at KaKao api") + log.error( + "KaKao get token retry count: {}", + retryContext.retryCount + ) + kaKaoIdTokenClient.execute(code) + }, + // todo 실패 기록 + RecoveryCallback { + log.error("fail get token KaKao api") + null + } + ) + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialIdTokenClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialIdTokenClient.kt new file mode 100644 index 00000000..37cae0b7 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialIdTokenClient.kt @@ -0,0 +1,5 @@ +import com.walking.member.api.client.token.dto.SocialIdToken + +fun interface SocialIdTokenClient { + fun execute(code: String): SocialIdToken +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialTokenClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialTokenClient.kt new file mode 100644 index 00000000..aea01125 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialTokenClient.kt @@ -0,0 +1,9 @@ +package com.walking.member.api.client.token + +import com.walking.member.api.client.token.dto.SocialIdToken +import com.walking.member.api.client.token.dto.SocialToken + +fun interface SocialTokenClient { + + fun execute(token: SocialIdToken): SocialToken +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoIdTokenData.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoIdTokenData.kt new file mode 100644 index 00000000..26e5d9f7 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoIdTokenData.kt @@ -0,0 +1,7 @@ +package com.walking.member.api.client.token.dto + +data class KaKaoIdTokenData(private val id_token: String) : SocialIdToken { + override fun getToken(): String { + return id_token + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoTokenData.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoTokenData.kt new file mode 100644 index 00000000..c65e3c13 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoTokenData.kt @@ -0,0 +1,7 @@ +package com.walking.member.api.client.token.dto + +data class KaKaoTokenData(val id: String) : SocialToken { + override fun getInfo(): String { + return id + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/SocialIdToken.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/SocialIdToken.kt new file mode 100644 index 00000000..45c1161d --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/SocialIdToken.kt @@ -0,0 +1,5 @@ +package com.walking.member.api.client.token.dto + +fun interface SocialIdToken { + fun getToken(): String +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/SocialToken.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/SocialToken.kt new file mode 100644 index 00000000..0de875eb --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/SocialToken.kt @@ -0,0 +1,5 @@ +package com.walking.member.api.client.token.dto + +fun interface SocialToken { + fun getInfo(): String +} \ No newline at end of file From 016044c1c30a49f02d29cce778bb21fb3975ebe1 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:28:43 +0900 Subject: [PATCH 34/81] =?UTF-8?q?feat:=20social=20unlink=20client=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/client/unlink/KaKaoUnlinkClient.kt | 52 +++++++++++++++++++ .../api/client/unlink/SocialUnlinkClient.kt | 8 +++ .../api/client/unlink/dto/KaKaoUnlinkData.kt | 7 +++ .../api/client/unlink/dto/SocialUnlinkData.kt | 5 ++ 4 files changed, 72 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/unlink/KaKaoUnlinkClient.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/unlink/dto/KaKaoUnlinkData.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/unlink/dto/SocialUnlinkData.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/KaKaoUnlinkClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/KaKaoUnlinkClient.kt new file mode 100644 index 00000000..8a1ba306 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/KaKaoUnlinkClient.kt @@ -0,0 +1,52 @@ +package com.walking.member.api.client.unlink + +import com.walking.member.api.client.config.property.KaKaoApiProperties +import com.walking.member.api.client.exception.SocialClientException +import com.walking.member.api.client.unlink.dto.KaKaoUnlinkData +import com.walking.member.api.client.unlink.dto.SocialUnlinkData +import org.springframework.http.HttpEntity +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod +import org.springframework.http.ResponseEntity +import org.springframework.stereotype.Component +import org.springframework.util.LinkedMultiValueMap +import org.springframework.util.MultiValueMap +import org.springframework.web.client.RestClientException +import org.springframework.web.client.RestTemplate + +@Component +class KaKaoUnlinkClient( + private val restTemplate: RestTemplate, + private val properties: KaKaoApiProperties +) : SocialUnlinkClient { + override fun execute(targetId: String): SocialUnlinkData { + val adminKey: String = properties.adminKey + + val headers = HttpHeaders() + headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded") + headers.add(HttpHeaders.AUTHORIZATION, "KakaoAK $adminKey") + + val params: MultiValueMap = LinkedMultiValueMap() + params.add("target_id_type", "user_id") + params.add("target_id", targetId.toLong()) + + val response: ResponseEntity + try { + response = restTemplate.exchange( + properties.unlink, + HttpMethod.POST, + HttpEntity(params, headers), + KaKaoUnlinkData::class.java + ) + } catch (e: RestClientException) { + throw SocialClientException() + } + + val statusCode = response.statusCode + if (statusCode.is4xxClientError) { + throw SocialClientException() + } + + return response.body!! + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt new file mode 100644 index 00000000..586a2175 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt @@ -0,0 +1,8 @@ +package com.walking.member.api.client.unlink + +import com.walking.member.api.client.unlink.dto.SocialUnlinkData + +fun interface SocialUnlinkClient { + + fun execute(targetId: String): SocialUnlinkData +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/dto/KaKaoUnlinkData.kt b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/dto/KaKaoUnlinkData.kt new file mode 100644 index 00000000..a96fbf0b --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/dto/KaKaoUnlinkData.kt @@ -0,0 +1,7 @@ +package com.walking.member.api.client.unlink.dto + +data class KaKaoUnlinkData(val id: String) : SocialUnlinkData { + override fun getUnlinkInfo(): String { + return id + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/dto/SocialUnlinkData.kt b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/dto/SocialUnlinkData.kt new file mode 100644 index 00000000..32a99343 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/dto/SocialUnlinkData.kt @@ -0,0 +1,5 @@ +package com.walking.member.api.client.unlink.dto + +fun interface SocialUnlinkData { + fun getUnlinkInfo(): String +} \ No newline at end of file From db3fa89adb904b57ab83c2512d03d05367ad55d5 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:29:55 +0900 Subject: [PATCH 35/81] =?UTF-8?q?feat:=20KaKoIdTokenParser=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/client/support/KaKoIdTokenParser.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/support/KaKoIdTokenParser.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/support/KaKoIdTokenParser.kt b/member-api/src/main/kotlin/com/walking/member/api/client/support/KaKoIdTokenParser.kt new file mode 100644 index 00000000..d1194ce6 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/support/KaKoIdTokenParser.kt @@ -0,0 +1,30 @@ +package com.walking.member.api.client.support + +import com.walking.member.api.client.config.property.KaKaoApiProperties +import com.walking.member.api.client.config.property.KaKaoIdTokenProperties +import com.walking.member.api.client.exception.SocialIntegrationException +import com.walking.member.api.client.util.TokenPropertiesMapper +import org.springframework.stereotype.Component +import java.util.* + +@Component +class KaKoIdTokenParser( + private val kaKaoApiProperties: KaKaoApiProperties, + private val tokenPropertiesMapper: TokenPropertiesMapper +) { + val payloadIndex = 1 + fun parse(idToken: String): KaKaoIdTokenProperties { + val payload = idToken.split("\\.".toRegex()).dropLastWhile { it.isEmpty() } + .toTypedArray()[payloadIndex] + val source = String(Base64.getDecoder().decode(payload)) + val idProperties: KaKaoIdTokenProperties = + tokenPropertiesMapper.read(source, KaKaoIdTokenProperties::class.java) + if (idProperties.iss != kaKaoApiProperties.host) { + throw SocialIntegrationException() + } + if (idProperties.aud != kaKaoApiProperties.clientId) { + throw SocialIntegrationException() + } + return idProperties + } +} \ No newline at end of file From 255322e77cb9bbe4553b6409a1ac563aadfeffcc Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:30:22 +0900 Subject: [PATCH 36/81] =?UTF-8?q?feat:=20SocialMemberServiceDto=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/service/kakao/dto/SocialMemberServiceDto.kt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/service/kakao/dto/SocialMemberServiceDto.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/service/kakao/dto/SocialMemberServiceDto.kt b/member-api/src/main/kotlin/com/walking/member/api/service/kakao/dto/SocialMemberServiceDto.kt new file mode 100644 index 00000000..533f8d03 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/service/kakao/dto/SocialMemberServiceDto.kt @@ -0,0 +1,8 @@ +package com.walking.member.api.service.kakao.dto + +data class SocialMemberServiceDto( + val nickName: String, + val profile: String, + val certificationId: String, + val certificationSubject: String +) \ No newline at end of file From 56e1d17d66639705b93fb133604aa6881f479855 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:30:40 +0900 Subject: [PATCH 37/81] =?UTF-8?q?feat:=20PostKaKaoMemberService=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/kakao/PostKaKaoMemberService.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/service/kakao/PostKaKaoMemberService.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/service/kakao/PostKaKaoMemberService.kt b/member-api/src/main/kotlin/com/walking/member/api/service/kakao/PostKaKaoMemberService.kt new file mode 100644 index 00000000..697c5347 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/service/kakao/PostKaKaoMemberService.kt @@ -0,0 +1,29 @@ +package com.walking.member.api.service.kakao + +import com.walking.member.api.client.support.KaKoIdTokenParser +import com.walking.member.api.client.token.KaKaoIdTokenClient +import com.walking.member.api.service.kakao.dto.SocialMemberServiceDto +import org.springframework.stereotype.Service + +@Service +class PostKaKaoMemberService(private val kaKaoIdTokenClient: KaKaoIdTokenClient, private val kaKoIdTokenParser: KaKoIdTokenParser) { + + companion object { + private const val SUBJECT = "KAKAO" + } + fun execute(code: String): SocialMemberServiceDto { + val token = kaKaoIdTokenClient.execute(code) + + val idTokenProperties = kaKoIdTokenParser.parse(token.getToken()) + val nickname = idTokenProperties.nickname + val certificationId = idTokenProperties.sub + val profile = idTokenProperties.picture + + return SocialMemberServiceDto( + nickname, + profile, + certificationId, + SUBJECT + ) + } +} \ No newline at end of file From 1eb854a926200f20c7f2ab0e2fa0b537fa627639 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:30:52 +0900 Subject: [PATCH 38/81] =?UTF-8?q?feat:=20MemberDao=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/member/api/dao/MemberDao.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/dao/MemberDao.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/dao/MemberDao.kt b/member-api/src/main/kotlin/com/walking/member/api/dao/MemberDao.kt new file mode 100644 index 00000000..4ad81081 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/dao/MemberDao.kt @@ -0,0 +1,37 @@ +package com.walking.member.api.dao + +import com.walking.api.repository.dao.member.MemberRepository +import com.walking.data.entity.member.MemberEntity +import org.springframework.stereotype.Repository + +@Repository +class MemberDao(private val memberRepository: MemberRepository) { + + fun save(memberEntity: MemberEntity): MemberEntity { + return memberRepository.save(memberEntity) + } + + fun findByCertificationId(certificationId: String): MemberEntity? { + return memberRepository.findByCertificationIdAndDeletedFalse(certificationId).let { + if (it.isPresent) { + it.get() + } else { + null + } + } + } + + fun findById(id: Long): MemberEntity? { + return memberRepository.findByIdAndDeletedFalse(id).let { + if (it.isPresent) { + it.get() + } else { + null + } + } + } + + fun exist(id: Long): Boolean { + return memberRepository.existsByIdAndDeletedFalse(id) + } +} \ No newline at end of file From 030343d3d0ff74dc15ee562c24a07a619d3bbb28 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:31:10 +0900 Subject: [PATCH 39/81] =?UTF-8?q?feat:=20DeleteMemberUseCase=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/usecase/DeleteMemberUseCase.kt | 28 +++++++++++++++++++ .../response/DeleteMemberUseCaseResponse.kt | 8 ++++++ 2 files changed, 36 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/DeleteMemberUseCaseResponse.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt new file mode 100644 index 00000000..394750eb --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt @@ -0,0 +1,28 @@ +package com.walking.member.api.usecase + +import com.walking.data.entity.member.MemberEntity +import com.walking.image.service.minio.MinioRemoveImageService +import com.walking.member.api.dao.MemberDao +import com.walking.member.api.usecase.dto.response.DeleteMemberUseCaseResponse +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class DeleteMemberUseCase( + private val memberRepository: MemberDao, + private val removeImageService: MinioRemoveImageService +) { + @Transactional + fun execute(id: Long): DeleteMemberUseCaseResponse { + val member = memberRepository.findById(id) ?: throw IllegalArgumentException("Member not found") + val deletedMember = withdrawMember(member) + removeImageService.execute(deletedMember.profile) + + return DeleteMemberUseCaseResponse(deletedMember.id, deletedMember.updatedAt) + } + + private fun withdrawMember(member: MemberEntity): MemberEntity { + member.withDrawn() + return memberRepository.save(member) + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/DeleteMemberUseCaseResponse.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/DeleteMemberUseCaseResponse.kt new file mode 100644 index 00000000..e8196c45 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/DeleteMemberUseCaseResponse.kt @@ -0,0 +1,8 @@ +package com.walking.member.api.usecase.dto.response + +import java.time.LocalDateTime + +data class DeleteMemberUseCaseResponse( + val id: Long, + val deletedAt: LocalDateTime +) \ No newline at end of file From df46396f57e30f6a131bf05039547c7d49dc3e9a Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:31:31 +0900 Subject: [PATCH 40/81] =?UTF-8?q?feat:=20GetMemberDetailUseCase=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/usecase/GetMemberDetailUseCase.kt | 32 +++++++++++++++++++ .../GetMemberDetailUseCaseResponse.kt | 9 ++++++ 2 files changed, 41 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/GetMemberDetailUseCaseResponse.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt new file mode 100644 index 00000000..52ab2b06 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt @@ -0,0 +1,32 @@ +package com.walking.member.api.usecase + +import com.walking.image.service.GetPreSignedImageUrlService +import com.walking.member.api.dao.MemberDao + +import com.walking.member.api.usecase.dto.response.GetMemberDetailUseCaseResponse +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class GetMemberDetailUseCase( + private val memberRepository: MemberDao, + private val getPreSignedImageUrlService: GetPreSignedImageUrlService +) { + @Transactional + fun execute(id: Long): GetMemberDetailUseCaseResponse { + val member = memberRepository.findById(id) ?: throw IllegalArgumentException("Member not found") + val id = member.id + val nickName = member.nickName + val certificationSubject = member.certificationSubject.name + val status = member.status.name + val profile = getPreSignedImageUrlService.execute(member.profile) + + return GetMemberDetailUseCaseResponse( + id, + nickName, + profile, + certificationSubject, + status + ) + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/GetMemberDetailUseCaseResponse.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/GetMemberDetailUseCaseResponse.kt new file mode 100644 index 00000000..1edc55fa --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/GetMemberDetailUseCaseResponse.kt @@ -0,0 +1,9 @@ +package com.walking.member.api.usecase.dto.response + +data class GetMemberDetailUseCaseResponse( + val id: Long, + val nickName: String, + val profile: String, + val certificationSubject: String, + val status: String +) \ No newline at end of file From d0bd0498bbb3c4886b905cfc8e038f11b31226fb Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:31:45 +0900 Subject: [PATCH 41/81] =?UTF-8?q?feat:=20GetMemberTokenDetailUseCase=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/usecase/GetMemberTokenDetailUseCase.kt | 15 +++++++++++++++ .../GetMemberTokenDetailUseCaseResponse.kt | 5 +++++ 2 files changed, 20 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberTokenDetailUseCase.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/GetMemberTokenDetailUseCaseResponse.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberTokenDetailUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberTokenDetailUseCase.kt new file mode 100644 index 00000000..7a2151f5 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberTokenDetailUseCase.kt @@ -0,0 +1,15 @@ +package com.walking.member.api.usecase + +import com.walking.member.api.dao.MemberDao +import com.walking.member.api.usecase.dto.response.GetMemberTokenDetailUseCaseResponse +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class GetMemberTokenDetailUseCase(private val memberRepository: MemberDao) { + @Transactional + fun execute(id: Long): GetMemberTokenDetailUseCaseResponse { + val member = memberRepository.findById(id) ?: throw IllegalArgumentException("Member not found") + return GetMemberTokenDetailUseCaseResponse(member.id) + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/GetMemberTokenDetailUseCaseResponse.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/GetMemberTokenDetailUseCaseResponse.kt new file mode 100644 index 00000000..85789bb3 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/GetMemberTokenDetailUseCaseResponse.kt @@ -0,0 +1,5 @@ +package com.walking.member.api.usecase.dto.response + +data class GetMemberTokenDetailUseCaseResponse( + val id: Long +) \ No newline at end of file From dbe0c74b758deae42acb32d294838332b2b258c9 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:32:02 +0900 Subject: [PATCH 42/81] =?UTF-8?q?feat:=20PostMemberUseCase=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/usecase/PostMemberUseCase.kt | 38 +++++++++++++++++++ .../dto/response/PostMemberUseCaseResponse.kt | 7 ++++ 2 files changed, 45 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/PostMemberUseCase.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/PostMemberUseCaseResponse.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/PostMemberUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/PostMemberUseCase.kt new file mode 100644 index 00000000..eb4f4e06 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/PostMemberUseCase.kt @@ -0,0 +1,38 @@ +package com.walking.member.api.usecase + +import com.walking.data.entity.member.MemberEntity +import com.walking.member.api.dao.MemberDao +import com.walking.member.api.service.kakao.dto.SocialMemberServiceDto +import com.walking.member.api.usecase.dto.response.PostMemberUseCaseResponse +import com.walking.member.api.service.kakao.PostKaKaoMemberService +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class PostMemberUseCase( + private val createKaKaoMemberService: PostKaKaoMemberService, + private val memberRepository: MemberDao +) { + @Transactional + fun execute(code: String): PostMemberUseCaseResponse { + val socialMember = createKaKaoMemberService.execute(code) + + memberRepository.findByCertificationId(socialMember.certificationId) + ?.let { member -> + return PostMemberUseCaseResponse(member.id, member.nickName, member.profile) + } + + val newMember = createMemberEntity(socialMember) + memberRepository.save(newMember).let { member -> + return PostMemberUseCaseResponse(member.id, member.nickName, member.profile) + } + } + + private fun createMemberEntity(socialMember: SocialMemberServiceDto): MemberEntity { + return MemberEntity( + socialMember.nickName, + socialMember.profile, + socialMember.certificationId + ) + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/PostMemberUseCaseResponse.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/PostMemberUseCaseResponse.kt new file mode 100644 index 00000000..f73733b7 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/PostMemberUseCaseResponse.kt @@ -0,0 +1,7 @@ +package com.walking.member.api.usecase.dto.response + +data class PostMemberUseCaseResponse( + val id: Long, + val nickname: String, + val profile: String +) \ No newline at end of file From bbf514a560af6f59221e777cdbcd3612f94de322 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:32:33 +0900 Subject: [PATCH 43/81] =?UTF-8?q?feat:=20PatchProfileImageUseCase=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/usecase/PatchProfileImageUseCase.kt | 41 +++++++++++++++++++ .../PatchProfileImageUseCaseResponse.kt | 7 ++++ 2 files changed, 48 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/PatchProfileImageUseCase.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/PatchProfileImageUseCaseResponse.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/PatchProfileImageUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/PatchProfileImageUseCase.kt new file mode 100644 index 00000000..bee9de60 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/PatchProfileImageUseCase.kt @@ -0,0 +1,41 @@ +package com.walking.member.api.usecase + +import com.walking.image.service.UploadImageService +import com.walking.member.api.dao.MemberDao +import com.walking.member.api.usecase.dto.response.PatchProfileImageUseCaseResponse +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.io.File +import java.time.LocalDate +import kotlin.random.Random + +@Service +class PatchProfileImageUseCase( + private val memberDao: MemberDao, + private val uploadImageService: UploadImageService +) { + @Transactional + fun execute(id: Long, image: File): PatchProfileImageUseCaseResponse { + val member = memberDao.findById(id) ?: throw IllegalArgumentException("Member not found") + val imageName = generateImageName() + + uploadImageService.execute(imageName, image).let { + member.updateProfile(imageName).let { member -> + memberDao.save(member) + return PatchProfileImageUseCaseResponse(member.id, member.nickName, imageName) + } + } + } + + private fun generateImageName(): String { + val now = LocalDate.now() + return "${now.year}${now.monthValue}${now.dayOfMonth}_${randomString()}" + } + + private fun randomString(): String { + val charPool: List = ('a'..'z') + ('A'..'Z') + ('0'..'9') + return (1..16) + .map { Random.nextInt(0, charPool.size).let { charPool[it] } } + .joinToString("") + } +} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/PatchProfileImageUseCaseResponse.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/PatchProfileImageUseCaseResponse.kt new file mode 100644 index 00000000..c62c5f52 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/dto/response/PatchProfileImageUseCaseResponse.kt @@ -0,0 +1,7 @@ +package com.walking.member.api.usecase.dto.response + +data class PatchProfileImageUseCaseResponse( + val id: Long, + val nickName: String, + val profile: String +) \ No newline at end of file From a78369f58bdc4ab224d486f7b857d39b66f03407 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:32:45 +0900 Subject: [PATCH 44/81] =?UTF-8?q?feat:=20ExistMemberService=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/usecase/ExistMemberService.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/usecase/ExistMemberService.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/ExistMemberService.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/ExistMemberService.kt new file mode 100644 index 00000000..bcbdc253 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/ExistMemberService.kt @@ -0,0 +1,15 @@ +package com.walking.member.api.usecase + +import com.walking.member.api.dao.MemberDao +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class ExistMemberService( + private val memberDao: MemberDao +) { + @Transactional(readOnly = true) + fun execute(id: Long): Boolean { + return memberDao.exist(id) + } +} \ No newline at end of file From b68c3f7e6d401faedbfaf66e225904a8a2097f21 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:41:31 +0900 Subject: [PATCH 45/81] =?UTF-8?q?refactor:=20repository=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A5=BC=20api-reposito?= =?UTF-8?q?ry=20=EB=AA=A8=EB=93=88=EB=A1=9C=20=EC=9D=B4=EB=8F=99=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api-repository/build.gradle | 12 ++++++++++++ .../repository/config/ApiRepositoryConfig.java | 15 +++++++++++++++ .../config/ApiRepositoryDataConfig.java | 4 ++-- .../config/ApiRepositoryDataSourceConfig.java | 8 ++++---- .../config/ApiRepositoryEntityConfig.java | 11 ++++++----- .../config/ApiRepositoryJpaConfig.java | 12 ++++++------ .../repository/dao/member/MemberRepository.java | 16 ++++++++++++++++ .../dao}/member/PathFavoritesRepository.java | 2 +- .../dao}/member/TrafficFavoritesRepository.java | 2 +- .../dao}/traffic/TrafficRepository.java | 2 +- .../resources/application-api-repository-dev.yml | 6 ++++++ .../application-api-repository-local.yml | 6 ++++++ .../application-api-repository-prod.yml | 6 ++++++ .../resources/application-api-repository.yml | 6 ++++++ .../api/repository/member/MemberRepository.java | 8 -------- 15 files changed, 88 insertions(+), 28 deletions(-) create mode 100644 api-repository/build.gradle create mode 100644 api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryConfig.java rename api/src/main/java/com/walking/api/config/ApiDataConfig.java => api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryDataConfig.java (70%) rename api/src/main/java/com/walking/api/config/ApiDataSourceConfig.java => api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryDataSourceConfig.java (76%) rename api/src/main/java/com/walking/api/config/ApiEntityConfig.java => api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryEntityConfig.java (80%) rename api/src/main/java/com/walking/api/config/ApiJpaConfig.java => api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryJpaConfig.java (69%) create mode 100644 api-repository/src/main/java/com/walking/api/repository/dao/member/MemberRepository.java rename {api/src/main/java/com/walking/api/repository => api-repository/src/main/java/com/walking/api/repository/dao}/member/PathFavoritesRepository.java (85%) rename {api/src/main/java/com/walking/api/repository => api-repository/src/main/java/com/walking/api/repository/dao}/member/TrafficFavoritesRepository.java (85%) rename {api/src/main/java/com/walking/api/repository => api-repository/src/main/java/com/walking/api/repository/dao}/traffic/TrafficRepository.java (84%) create mode 100644 api-repository/src/main/resources/application-api-repository-dev.yml create mode 100644 api-repository/src/main/resources/application-api-repository-local.yml create mode 100644 api-repository/src/main/resources/application-api-repository-prod.yml create mode 100644 api-repository/src/main/resources/application-api-repository.yml delete mode 100644 api/src/main/java/com/walking/api/repository/member/MemberRepository.java diff --git a/api-repository/build.gradle b/api-repository/build.gradle new file mode 100644 index 00000000..0ea26ded --- /dev/null +++ b/api-repository/build.gradle @@ -0,0 +1,12 @@ +bootJar { + enabled = false +} + +jar { + enabled = true +} + + +dependencies { + api project(':data') +} diff --git a/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryConfig.java b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryConfig.java new file mode 100644 index 00000000..78a08d6a --- /dev/null +++ b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryConfig.java @@ -0,0 +1,15 @@ +package com.walking.api.repository.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = ApiRepositoryConfig.BASE_PACKAGE) +public class ApiRepositoryConfig { + + public static final String BASE_PACKAGE = "com.walking.api.repository"; + public static final String SERVICE_NAME = "walking"; + public static final String MODULE_NAME = "api-repository"; + public static final String BEAN_NAME_PREFIX = "apiRepository"; + public static final String PROPERTY_PREFIX = SERVICE_NAME + "." + MODULE_NAME; +} diff --git a/api/src/main/java/com/walking/api/config/ApiDataConfig.java b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryDataConfig.java similarity index 70% rename from api/src/main/java/com/walking/api/config/ApiDataConfig.java rename to api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryDataConfig.java index 47d43fff..cecf5ec9 100644 --- a/api/src/main/java/com/walking/api/config/ApiDataConfig.java +++ b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryDataConfig.java @@ -1,4 +1,4 @@ -package com.walking.api.config; +package com.walking.api.repository.config; import com.walking.data.DataConfig; import org.springframework.context.annotation.Configuration; @@ -6,4 +6,4 @@ @Configuration @Import({DataConfig.class}) -public class ApiDataConfig {} +public class ApiRepositoryDataConfig {} diff --git a/api/src/main/java/com/walking/api/config/ApiDataSourceConfig.java b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryDataSourceConfig.java similarity index 76% rename from api/src/main/java/com/walking/api/config/ApiDataSourceConfig.java rename to api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryDataSourceConfig.java index eb3ececa..74434629 100644 --- a/api/src/main/java/com/walking/api/config/ApiDataSourceConfig.java +++ b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryDataSourceConfig.java @@ -1,4 +1,4 @@ -package com.walking.api.config; +package com.walking.api.repository.config; import javax.sql.DataSource; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -15,12 +15,12 @@ DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, }) -public class ApiDataSourceConfig { +public class ApiRepositoryDataSourceConfig { - public static final String DATASOURCE_NAME = ApiAppConfig.BEAN_NAME_PREFIX + "DataSource"; + public static final String DATASOURCE_NAME = ApiRepositoryConfig.BEAN_NAME_PREFIX + "DataSource"; @Bean(name = DATASOURCE_NAME) - @ConfigurationProperties(prefix = "spring.datasource") + @ConfigurationProperties(prefix = "api.datasource") public DataSource dataSource() { return DataSourceBuilder.create().build(); } diff --git a/api/src/main/java/com/walking/api/config/ApiEntityConfig.java b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryEntityConfig.java similarity index 80% rename from api/src/main/java/com/walking/api/config/ApiEntityConfig.java rename to api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryEntityConfig.java index cd28c925..4ad6bee4 100644 --- a/api/src/main/java/com/walking/api/config/ApiEntityConfig.java +++ b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryEntityConfig.java @@ -1,6 +1,6 @@ -package com.walking.api.config; +package com.walking.api.repository.config; -import static com.walking.api.config.ApiDataSourceConfig.DATASOURCE_NAME; +import static com.walking.api.repository.config.ApiRepositoryDataSourceConfig.DATASOURCE_NAME; import com.walking.data.DataConfig; import com.walking.data.config.HibernatePropertyMapProvider; @@ -17,10 +17,11 @@ @Configuration @RequiredArgsConstructor -public class ApiEntityConfig { +public class ApiRepositoryEntityConfig { public static final String ENTITY_MANAGER_FACTORY_NAME = - ApiAppConfig.BEAN_NAME_PREFIX + "EntityManagerFactory"; - private static final String PERSIST_UNIT = ApiAppConfig.BEAN_NAME_PREFIX + "PersistenceUnit"; + ApiRepositoryConfig.BEAN_NAME_PREFIX + "EntityManagerFactory"; + private static final String PERSIST_UNIT = + ApiRepositoryConfig.BEAN_NAME_PREFIX + "PersistenceUnit"; private final HibernatePropertyMapProvider hibernatePropertyMapProvider; diff --git a/api/src/main/java/com/walking/api/config/ApiJpaConfig.java b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryJpaConfig.java similarity index 69% rename from api/src/main/java/com/walking/api/config/ApiJpaConfig.java rename to api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryJpaConfig.java index f7b776e2..6d29622d 100644 --- a/api/src/main/java/com/walking/api/config/ApiJpaConfig.java +++ b/api-repository/src/main/java/com/walking/api/repository/config/ApiRepositoryJpaConfig.java @@ -1,4 +1,4 @@ -package com.walking.api.config; +package com.walking.api.repository.config; import javax.persistence.EntityManagerFactory; import org.springframework.context.annotation.Bean; @@ -13,13 +13,13 @@ @EnableJpaAuditing @EnableTransactionManagement @EnableJpaRepositories( - basePackages = ApiAppConfig.BASE_PACKAGE, - transactionManagerRef = ApiJpaConfig.TRANSACTION_MANAGER_NAME, - entityManagerFactoryRef = ApiEntityConfig.ENTITY_MANAGER_FACTORY_NAME) -public class ApiJpaConfig { + basePackages = ApiRepositoryConfig.BASE_PACKAGE, + transactionManagerRef = ApiRepositoryJpaConfig.TRANSACTION_MANAGER_NAME, + entityManagerFactoryRef = ApiRepositoryEntityConfig.ENTITY_MANAGER_FACTORY_NAME) +public class ApiRepositoryJpaConfig { public static final String TRANSACTION_MANAGER_NAME = - ApiAppConfig.BEAN_NAME_PREFIX + "TransactionalManager"; + ApiRepositoryConfig.BEAN_NAME_PREFIX + "TransactionalManager"; @Bean(name = TRANSACTION_MANAGER_NAME) public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { diff --git a/api-repository/src/main/java/com/walking/api/repository/dao/member/MemberRepository.java b/api-repository/src/main/java/com/walking/api/repository/dao/member/MemberRepository.java new file mode 100644 index 00000000..489f0e53 --- /dev/null +++ b/api-repository/src/main/java/com/walking/api/repository/dao/member/MemberRepository.java @@ -0,0 +1,16 @@ +package com.walking.api.repository.dao.member; + +import com.walking.data.entity.member.MemberEntity; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface MemberRepository extends JpaRepository { + + boolean existsByIdAndDeletedFalse(Long id); + + Optional findByIdAndDeletedFalse(Long id); + + Optional findByCertificationIdAndDeletedFalse(String certificationId); +} diff --git a/api/src/main/java/com/walking/api/repository/member/PathFavoritesRepository.java b/api-repository/src/main/java/com/walking/api/repository/dao/member/PathFavoritesRepository.java similarity index 85% rename from api/src/main/java/com/walking/api/repository/member/PathFavoritesRepository.java rename to api-repository/src/main/java/com/walking/api/repository/dao/member/PathFavoritesRepository.java index e4f8c070..396606ed 100644 --- a/api/src/main/java/com/walking/api/repository/member/PathFavoritesRepository.java +++ b/api-repository/src/main/java/com/walking/api/repository/dao/member/PathFavoritesRepository.java @@ -1,4 +1,4 @@ -package com.walking.api.repository.member; +package com.walking.api.repository.dao.member; import com.walking.data.entity.member.PathFavoritesEntity; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/api/src/main/java/com/walking/api/repository/member/TrafficFavoritesRepository.java b/api-repository/src/main/java/com/walking/api/repository/dao/member/TrafficFavoritesRepository.java similarity index 85% rename from api/src/main/java/com/walking/api/repository/member/TrafficFavoritesRepository.java rename to api-repository/src/main/java/com/walking/api/repository/dao/member/TrafficFavoritesRepository.java index 15ea6239..23ed0cbd 100644 --- a/api/src/main/java/com/walking/api/repository/member/TrafficFavoritesRepository.java +++ b/api-repository/src/main/java/com/walking/api/repository/dao/member/TrafficFavoritesRepository.java @@ -1,4 +1,4 @@ -package com.walking.api.repository.member; +package com.walking.api.repository.dao.member; import com.walking.data.entity.member.TrafficFavoritesEntity; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/api/src/main/java/com/walking/api/repository/traffic/TrafficRepository.java b/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficRepository.java similarity index 84% rename from api/src/main/java/com/walking/api/repository/traffic/TrafficRepository.java rename to api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficRepository.java index 93b2781a..04d42dd2 100644 --- a/api/src/main/java/com/walking/api/repository/traffic/TrafficRepository.java +++ b/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficRepository.java @@ -1,4 +1,4 @@ -package com.walking.api.repository.traffic; +package com.walking.api.repository.dao.traffic; import com.walking.data.entity.traffic.TrafficEntity; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/api-repository/src/main/resources/application-api-repository-dev.yml b/api-repository/src/main/resources/application-api-repository-dev.yml new file mode 100644 index 00000000..f321aa37 --- /dev/null +++ b/api-repository/src/main/resources/application-api-repository-dev.yml @@ -0,0 +1,6 @@ +api: + datasource: + jdbc-url: ${DB_HOSTNAME}/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true + username: ${DB_USERNAME} + password: ${DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/api-repository/src/main/resources/application-api-repository-local.yml b/api-repository/src/main/resources/application-api-repository-local.yml new file mode 100644 index 00000000..559dd252 --- /dev/null +++ b/api-repository/src/main/resources/application-api-repository-local.yml @@ -0,0 +1,6 @@ +api: + datasource: + jdbc-url: jdbc:mysql://localhost:13306/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true + username: root + password: root + driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/api-repository/src/main/resources/application-api-repository-prod.yml b/api-repository/src/main/resources/application-api-repository-prod.yml new file mode 100644 index 00000000..f321aa37 --- /dev/null +++ b/api-repository/src/main/resources/application-api-repository-prod.yml @@ -0,0 +1,6 @@ +api: + datasource: + jdbc-url: ${DB_HOSTNAME}/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true + username: ${DB_USERNAME} + password: ${DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/api-repository/src/main/resources/application-api-repository.yml b/api-repository/src/main/resources/application-api-repository.yml new file mode 100644 index 00000000..f321aa37 --- /dev/null +++ b/api-repository/src/main/resources/application-api-repository.yml @@ -0,0 +1,6 @@ +api: + datasource: + jdbc-url: ${DB_HOSTNAME}/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true + username: ${DB_USERNAME} + password: ${DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/api/src/main/java/com/walking/api/repository/member/MemberRepository.java b/api/src/main/java/com/walking/api/repository/member/MemberRepository.java deleted file mode 100644 index b69c76d8..00000000 --- a/api/src/main/java/com/walking/api/repository/member/MemberRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.walking.api.repository.member; - -import com.walking.data.entity.member.MemberEntity; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface MemberRepository extends JpaRepository {} From d9a016685f7982acf62309b00c582bfe2b8fbf71 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:41:54 +0900 Subject: [PATCH 46/81] =?UTF-8?q?feat:=20implementation=20project=EB=A5=BC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/build.gradle b/api/build.gradle index 3afbb328..11e93ed1 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -8,7 +8,8 @@ dependencyManagement { } dependencies { - implementation project(':data') + implementation project(':api-repository') + implementation project(':member-api') // web implementation 'org.springframework.boot:spring-boot-starter-web' From eeebf2d1500c6b0b87638588434d906f5cd19f27 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:42:08 +0900 Subject: [PATCH 47/81] =?UTF-8?q?feat:=20ApiConfig=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/main/java/com/walking/api/config/ApiConfig.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 api/src/main/java/com/walking/api/config/ApiConfig.java diff --git a/api/src/main/java/com/walking/api/config/ApiConfig.java b/api/src/main/java/com/walking/api/config/ApiConfig.java new file mode 100644 index 00000000..113cf121 --- /dev/null +++ b/api/src/main/java/com/walking/api/config/ApiConfig.java @@ -0,0 +1,7 @@ +package com.walking.api.config; + +import com.walking.member.api.config.MemberApiConfig; +import org.springframework.context.annotation.Import; + +@Import({MemberApiConfig.class}) +public class ApiConfig {} From cc3a2a7081a1ae1bf3945c7837a5cfbf7f5056c7 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:42:30 +0900 Subject: [PATCH 48/81] =?UTF-8?q?feat:=20member-api=20req,=20res=EB=A5=BC?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/member/PatchProfileBody.java | 23 ++++++++++++++++++ .../dto/request/member/PostMemberBody.java | 21 ++++++++++++++++ .../member/RefreshMemberAuthTokenBody.java | 20 ++++++++++++++++ .../response/member/DeleteMemberResponse.java | 22 +++++++++++++++++ .../response/member/GetMemberResponse.java | 22 +++++++++++++++++ .../response/member/MemberTokenResponse.java | 21 ++++++++++++++++ .../response/member/PatchProfileResponse.java | 21 ++++++++++++++++ .../response/member/PostMemberResponse.java | 24 +++++++++++++++++++ 8 files changed, 174 insertions(+) create mode 100644 api/src/main/java/com/walking/api/web/dto/request/member/PatchProfileBody.java create mode 100644 api/src/main/java/com/walking/api/web/dto/request/member/PostMemberBody.java create mode 100644 api/src/main/java/com/walking/api/web/dto/request/member/RefreshMemberAuthTokenBody.java create mode 100644 api/src/main/java/com/walking/api/web/dto/response/member/DeleteMemberResponse.java create mode 100644 api/src/main/java/com/walking/api/web/dto/response/member/GetMemberResponse.java create mode 100644 api/src/main/java/com/walking/api/web/dto/response/member/MemberTokenResponse.java create mode 100644 api/src/main/java/com/walking/api/web/dto/response/member/PatchProfileResponse.java create mode 100644 api/src/main/java/com/walking/api/web/dto/response/member/PostMemberResponse.java diff --git a/api/src/main/java/com/walking/api/web/dto/request/member/PatchProfileBody.java b/api/src/main/java/com/walking/api/web/dto/request/member/PatchProfileBody.java new file mode 100644 index 00000000..2c2a70aa --- /dev/null +++ b/api/src/main/java/com/walking/api/web/dto/request/member/PatchProfileBody.java @@ -0,0 +1,23 @@ +package com.walking.api.web.dto.request.member; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import javax.validation.constraints.NotEmpty; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.springframework.web.multipart.MultipartFile; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +public class PatchProfileBody { + + @JsonIgnore @NotEmpty private MultipartFile profile; +} diff --git a/api/src/main/java/com/walking/api/web/dto/request/member/PostMemberBody.java b/api/src/main/java/com/walking/api/web/dto/request/member/PostMemberBody.java new file mode 100644 index 00000000..d84e3aaf --- /dev/null +++ b/api/src/main/java/com/walking/api/web/dto/request/member/PostMemberBody.java @@ -0,0 +1,21 @@ +package com.walking.api.web.dto.request.member; + +import javax.validation.constraints.NotEmpty; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +public class PostMemberBody { + + @NotEmpty private String code; +} diff --git a/api/src/main/java/com/walking/api/web/dto/request/member/RefreshMemberAuthTokenBody.java b/api/src/main/java/com/walking/api/web/dto/request/member/RefreshMemberAuthTokenBody.java new file mode 100644 index 00000000..5ef803c6 --- /dev/null +++ b/api/src/main/java/com/walking/api/web/dto/request/member/RefreshMemberAuthTokenBody.java @@ -0,0 +1,20 @@ +package com.walking.api.web.dto.request.member; + +import javax.validation.constraints.NotEmpty; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +public class RefreshMemberAuthTokenBody { + @NotEmpty private String refreshToken; +} diff --git a/api/src/main/java/com/walking/api/web/dto/response/member/DeleteMemberResponse.java b/api/src/main/java/com/walking/api/web/dto/response/member/DeleteMemberResponse.java new file mode 100644 index 00000000..eafe9282 --- /dev/null +++ b/api/src/main/java/com/walking/api/web/dto/response/member/DeleteMemberResponse.java @@ -0,0 +1,22 @@ +package com.walking.api.web.dto.response.member; + +import java.time.LocalDateTime; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +public class DeleteMemberResponse { + + private Long id; + private LocalDateTime deletedAt; +} diff --git a/api/src/main/java/com/walking/api/web/dto/response/member/GetMemberResponse.java b/api/src/main/java/com/walking/api/web/dto/response/member/GetMemberResponse.java new file mode 100644 index 00000000..cbf29382 --- /dev/null +++ b/api/src/main/java/com/walking/api/web/dto/response/member/GetMemberResponse.java @@ -0,0 +1,22 @@ +package com.walking.api.web.dto.response.member; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +public class GetMemberResponse { + + private Long id; + private String nickname; + private String profile; +} diff --git a/api/src/main/java/com/walking/api/web/dto/response/member/MemberTokenResponse.java b/api/src/main/java/com/walking/api/web/dto/response/member/MemberTokenResponse.java new file mode 100644 index 00000000..581346ab --- /dev/null +++ b/api/src/main/java/com/walking/api/web/dto/response/member/MemberTokenResponse.java @@ -0,0 +1,21 @@ +package com.walking.api.web.dto.response.member; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +public class MemberTokenResponse { + + private String accessToken; + private String refreshToken; +} diff --git a/api/src/main/java/com/walking/api/web/dto/response/member/PatchProfileResponse.java b/api/src/main/java/com/walking/api/web/dto/response/member/PatchProfileResponse.java new file mode 100644 index 00000000..3ae85598 --- /dev/null +++ b/api/src/main/java/com/walking/api/web/dto/response/member/PatchProfileResponse.java @@ -0,0 +1,21 @@ +package com.walking.api.web.dto.response.member; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +public class PatchProfileResponse { + private Long id; + private String nickname; + private String profile; +} diff --git a/api/src/main/java/com/walking/api/web/dto/response/member/PostMemberResponse.java b/api/src/main/java/com/walking/api/web/dto/response/member/PostMemberResponse.java new file mode 100644 index 00000000..2e50ea45 --- /dev/null +++ b/api/src/main/java/com/walking/api/web/dto/response/member/PostMemberResponse.java @@ -0,0 +1,24 @@ +package com.walking.api.web.dto.response.member; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +public class PostMemberResponse { + + private Long id; + private String nickname; + private String profile; + private String accessToken; + private String refreshToken; +} From 7f9b74871b5884c692cff28b78128fda78235553 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:42:42 +0900 Subject: [PATCH 49/81] =?UTF-8?q?feat:=20MemberController=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/member/MemberController.java | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 api/src/main/java/com/walking/api/web/controller/member/MemberController.java diff --git a/api/src/main/java/com/walking/api/web/controller/member/MemberController.java b/api/src/main/java/com/walking/api/web/controller/member/MemberController.java new file mode 100644 index 00000000..5e14ed9e --- /dev/null +++ b/api/src/main/java/com/walking/api/web/controller/member/MemberController.java @@ -0,0 +1,140 @@ +package com.walking.api.web.controller.member; + +import com.walking.api.security.authentication.authority.Roles; +import com.walking.api.security.authentication.token.TokenUserDetails; +import com.walking.api.security.token.AuthToken; +import com.walking.api.security.token.TokenGenerator; +import com.walking.api.security.token.TokenResolver; +import com.walking.api.web.dto.request.member.PatchProfileBody; +import com.walking.api.web.dto.request.member.PostMemberBody; +import com.walking.api.web.dto.request.member.RefreshMemberAuthTokenBody; +import com.walking.api.web.dto.response.member.DeleteMemberResponse; +import com.walking.api.web.dto.response.member.GetMemberResponse; +import com.walking.api.web.dto.response.member.MemberTokenResponse; +import com.walking.api.web.dto.response.member.PatchProfileResponse; +import com.walking.api.web.dto.response.member.PostMemberResponse; +import com.walking.api.web.support.ApiResponse; +import com.walking.api.web.support.ApiResponseGenerator; +import com.walking.api.web.support.MessageCode; +import com.walking.member.api.usecase.DeleteMemberUseCase; +import com.walking.member.api.usecase.GetMemberDetailUseCase; +import com.walking.member.api.usecase.GetMemberTokenDetailUseCase; +import com.walking.member.api.usecase.PatchProfileImageUseCase; +import com.walking.member.api.usecase.PostMemberUseCase; +import com.walking.member.api.usecase.dto.response.DeleteMemberUseCaseResponse; +import com.walking.member.api.usecase.dto.response.GetMemberDetailUseCaseResponse; +import com.walking.member.api.usecase.dto.response.GetMemberTokenDetailUseCaseResponse; +import com.walking.member.api.usecase.dto.response.PatchProfileImageUseCaseResponse; +import com.walking.member.api.usecase.dto.response.PostMemberUseCaseResponse; +import java.io.IOException; +import java.util.List; +import javax.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@Validated +@RestController +@RequestMapping("/api/v1/members") +@RequiredArgsConstructor +public class MemberController { + + private final TokenGenerator tokenGenerator; + private final TokenResolver tokenResolver; + + private final PostMemberUseCase postMemberUseCase; + private final DeleteMemberUseCase deleteMemberUseCase; + private final GetMemberDetailUseCase getMemberDetailUseCase; + private final GetMemberTokenDetailUseCase getMemberTokenDetailUseCase; + private final PatchProfileImageUseCase patchProfileImageUseCase; + + @PostMapping() + public ApiResponse> postMember( + @Valid @RequestBody PostMemberBody postMemberBody) { + PostMemberUseCaseResponse useCaseResponse = postMemberUseCase.execute(postMemberBody.getCode()); + AuthToken authToken = + tokenGenerator.generateAuthToken(useCaseResponse.getId(), List.of(Roles.ROLE_USER)); + PostMemberResponse response = + PostMemberResponse.builder() + .id(useCaseResponse.getId()) + .nickname(useCaseResponse.getNickname()) + .profile(useCaseResponse.getProfile()) + .accessToken(authToken.getAccessToken()) + .refreshToken(authToken.getRefreshToken()) + .build(); + return ApiResponseGenerator.success(response, HttpStatus.CREATED, MessageCode.RESOURCE_CREATED); + } + + @DeleteMapping() + public ApiResponse> deleteMember( + @AuthenticationPrincipal TokenUserDetails userDetails) { + Long memberId = Long.valueOf(userDetails.getUsername()); + DeleteMemberUseCaseResponse useCaseResponse = deleteMemberUseCase.execute(memberId); + DeleteMemberResponse response = + DeleteMemberResponse.builder() + .id(useCaseResponse.getId()) + .deletedAt(useCaseResponse.getDeletedAt()) + .build(); + return ApiResponseGenerator.success(response, HttpStatus.OK, MessageCode.RESOURCE_DELETED); + } + + @GetMapping() + public ApiResponse> getMember( + @AuthenticationPrincipal TokenUserDetails userDetails) { + Long memberId = Long.valueOf(userDetails.getUsername()); + GetMemberDetailUseCaseResponse useCaseResponse = getMemberDetailUseCase.execute(memberId); + GetMemberResponse response = + GetMemberResponse.builder() + .id(useCaseResponse.getId()) + .nickname(useCaseResponse.getNickName()) + .profile(useCaseResponse.getProfile()) + .build(); + return ApiResponseGenerator.success(response, HttpStatus.OK, MessageCode.SUCCESS); + } + + @PostMapping("/token") + public ApiResponse> refreshMemberAuthToken( + @Valid @RequestBody RefreshMemberAuthTokenBody memberAuthTokenBody) { + Long memberId = + tokenResolver + .resolveId(memberAuthTokenBody.getRefreshToken()) + .orElseThrow(() -> new IllegalArgumentException("Invalid token")); + GetMemberTokenDetailUseCaseResponse useCaseResponse = + getMemberTokenDetailUseCase.execute(memberId); + AuthToken authToken = + tokenGenerator.generateAuthToken(useCaseResponse.getId(), List.of(Roles.ROLE_USER)); + MemberTokenResponse response = + MemberTokenResponse.builder() + .accessToken(authToken.getAccessToken()) + .refreshToken(authToken.getRefreshToken()) + .build(); + return ApiResponseGenerator.success(response, HttpStatus.OK, MessageCode.SUCCESS); + } + + @PatchMapping("/profile") + public ApiResponse> patchProfileImage( + @AuthenticationPrincipal TokenUserDetails userDetails, PatchProfileBody patchProfileBody) + throws IOException { + Long memberId = Long.valueOf(userDetails.getUsername()); + PatchProfileImageUseCaseResponse useCaseResponse = + patchProfileImageUseCase.execute( + memberId, patchProfileBody.getProfile().getResource().getFile()); + PatchProfileResponse response = + PatchProfileResponse.builder() + .id(useCaseResponse.getId()) + .nickname(useCaseResponse.getNickName()) + .profile(useCaseResponse.getProfile()) + .build(); + return ApiResponseGenerator.success(response, HttpStatus.OK, MessageCode.RESOURCE_MODIFIED); + } +} From 99609c87112b946f69184647d4d15d68b7899e90 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:43:13 +0900 Subject: [PATCH 50/81] =?UTF-8?q?refactor:=20api=20=EA=B5=AC=EC=84=B1=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=EC=9D=84=20=EB=B3=80=EA=B2=BD=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/main/resources/application-dev.yml | 11 +++++------ api/src/main/resources/application-local.yml | 11 +++++------ api/src/main/resources/application-prod.yml | 11 +++++------ api/src/main/resources/application.yml | 11 +++++------ 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/api/src/main/resources/application-dev.yml b/api/src/main/resources/application-dev.yml index fff2996a..081637e8 100644 --- a/api/src/main/resources/application-dev.yml +++ b/api/src/main/resources/application-dev.yml @@ -9,11 +9,10 @@ spring: # add import modules profile include: - data-dev - datasource: - jdbc-url: ${DB_HOSTNAME}/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true - username: ${DB_USERNAME} - password: ${DB_PASSWORD} - driver-class-name: com.mysql.cj.jdbc.Driver + - api-repository-dev + - member-api-dev + - image-store-dev + - minio # logging config logging: @@ -71,4 +70,4 @@ log: springdoc: swagger-ui: url: /docs/openapi3.yaml - path: /swagger \ No newline at end of file + path: /swagger diff --git a/api/src/main/resources/application-local.yml b/api/src/main/resources/application-local.yml index 3a054b29..04aba982 100644 --- a/api/src/main/resources/application-local.yml +++ b/api/src/main/resources/application-local.yml @@ -9,11 +9,10 @@ spring: # add import modules profile include: - data-local - datasource: - jdbc-url: jdbc:mysql://localhost:13306/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true - username: root - password: root - driver-class-name: com.mysql.cj.jdbc.Driver + - api-repository-local + - member-api-local + - image-store-local + - minio # logging config logging: @@ -71,4 +70,4 @@ log: springdoc: swagger-ui: url: /docs/openapi3.yaml - path: /swagger \ No newline at end of file + path: /swagger diff --git a/api/src/main/resources/application-prod.yml b/api/src/main/resources/application-prod.yml index e1427b1b..85fb76e0 100644 --- a/api/src/main/resources/application-prod.yml +++ b/api/src/main/resources/application-prod.yml @@ -9,11 +9,10 @@ spring: # add import modules profile include: - data-prod - datasource: - jdbc-url: ${DB_HOSTNAME}/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true - username: ${DB_USERNAME} - password: ${DB_PASSWORD} - driver-class-name: com.mysql.cj.jdbc.Driver + - api-repository-prod + - member-api-prod + - image-store-prod + - minio # prometheus config management: @@ -60,4 +59,4 @@ log: springdoc: swagger-ui: url: /docs/openapi3.yaml - path: /swagger \ No newline at end of file + path: /swagger diff --git a/api/src/main/resources/application.yml b/api/src/main/resources/application.yml index a3fbafb5..169a8a1c 100644 --- a/api/src/main/resources/application.yml +++ b/api/src/main/resources/application.yml @@ -9,11 +9,10 @@ spring: # add import modules profile include: - data - datasource: - jdbc-url: ${DB_HOSTNAME}/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true - username: ${DB_USERNAME} - password: ${DB_PASSWORD} - driver-class-name: com.mysql.cj.jdbc.Driver + - api-repository + - member-api + - image-store + - minio # prometheus config management: @@ -59,4 +58,4 @@ log: springdoc: swagger-ui: url: /docs/openapi3.yaml - path: /swagger \ No newline at end of file + path: /swagger From 9d9dea43acf7664ffc1736713fe3f4b07c16feba Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:43:39 +0900 Subject: [PATCH 51/81] =?UTF-8?q?remove:=20RepositoryTest=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/repository/RepositoryTest.java | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 api/src/test/java/com/walking/api/repository/RepositoryTest.java diff --git a/api/src/test/java/com/walking/api/repository/RepositoryTest.java b/api/src/test/java/com/walking/api/repository/RepositoryTest.java deleted file mode 100644 index 1306d0f3..00000000 --- a/api/src/test/java/com/walking/api/repository/RepositoryTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.walking.api.repository; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.walking.api.config.ApiDataSourceConfig; -import com.walking.api.config.ApiEntityConfig; -import com.walking.api.config.ApiJpaConfig; -import com.walking.data.config.DataJpaConfig; -import com.walking.data.config.HibernatePropertyMapProvider; -import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; -import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestPropertySource; - -@Slf4j -@ActiveProfiles(profiles = {"test"}) -@DataJpaTest( - excludeAutoConfiguration = { - DataSourceAutoConfiguration.class, - DataSourceTransactionManagerAutoConfiguration.class, - HibernateJpaAutoConfiguration.class, - }) -@TestPropertySource(locations = "classpath:application-test.yml") -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -@ContextConfiguration( - classes = { - ApiDataSourceConfig.class, - ApiEntityConfig.class, - ApiJpaConfig.class, - DataJpaConfig.class, - HibernatePropertyMapProvider.class, - ObjectMapper.class, - }) -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -abstract class RepositoryTest {} From 478419e4c4b72990a3667ea7fc973b2d5250aba2 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:43:52 +0900 Subject: [PATCH 52/81] =?UTF-8?q?chore:=20test=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/test/resources/images/test.png | Bin 0 -> 20369 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 api/src/test/resources/images/test.png diff --git a/api/src/test/resources/images/test.png b/api/src/test/resources/images/test.png new file mode 100644 index 0000000000000000000000000000000000000000..2af0681102e3c6aa81d3dc5906cc0df98887fc51 GIT binary patch literal 20369 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 literal 0 HcmV?d00001 From ab9aaf87684d06c1b5d9e7181df7bf2042422989 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 00:47:33 +0900 Subject: [PATCH 53/81] =?UTF-8?q?fix:=20MemberApiConfig=20=EC=9E=84?= =?UTF-8?q?=ED=8F=AC=ED=8A=B8=20=EC=9C=84=EC=B9=98=EB=A5=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/main/java/com/walking/api/config/ApiAppConfig.java | 3 +++ api/src/main/java/com/walking/api/config/ApiConfig.java | 7 ------- 2 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 api/src/main/java/com/walking/api/config/ApiConfig.java diff --git a/api/src/main/java/com/walking/api/config/ApiAppConfig.java b/api/src/main/java/com/walking/api/config/ApiAppConfig.java index e47e17f3..bd561e84 100644 --- a/api/src/main/java/com/walking/api/config/ApiAppConfig.java +++ b/api/src/main/java/com/walking/api/config/ApiAppConfig.java @@ -1,8 +1,11 @@ package com.walking.api.config; +import com.walking.member.api.config.MemberApiConfig; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +@Import({MemberApiConfig.class}) @Configuration @ComponentScan(basePackages = ApiAppConfig.BASE_PACKAGE) public class ApiAppConfig { diff --git a/api/src/main/java/com/walking/api/config/ApiConfig.java b/api/src/main/java/com/walking/api/config/ApiConfig.java deleted file mode 100644 index 113cf121..00000000 --- a/api/src/main/java/com/walking/api/config/ApiConfig.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.walking.api.config; - -import com.walking.member.api.config.MemberApiConfig; -import org.springframework.context.annotation.Import; - -@Import({MemberApiConfig.class}) -public class ApiConfig {} From 02d5f5ab19c32dd7aa4d72d262bebae3c76ce380 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 01:15:01 +0900 Subject: [PATCH 54/81] =?UTF-8?q?fix:=20patchProfileImageUseCase=EC=97=90?= =?UTF-8?q?=20=EC=9E=84=EC=8B=9C=20=ED=8C=8C=EC=9D=BC=EC=9D=84=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=ED=95=98=EC=97=AC=20=EC=A0=84=EB=8B=AC=20=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/web/controller/member/MemberController.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/walking/api/web/controller/member/MemberController.java b/api/src/main/java/com/walking/api/web/controller/member/MemberController.java index 5e14ed9e..fd1c774a 100644 --- a/api/src/main/java/com/walking/api/web/controller/member/MemberController.java +++ b/api/src/main/java/com/walking/api/web/controller/member/MemberController.java @@ -26,6 +26,7 @@ import com.walking.member.api.usecase.dto.response.GetMemberTokenDetailUseCaseResponse; import com.walking.member.api.usecase.dto.response.PatchProfileImageUseCaseResponse; import com.walking.member.api.usecase.dto.response.PostMemberUseCaseResponse; +import java.io.File; import java.io.IOException; import java.util.List; import javax.validation.Valid; @@ -126,9 +127,12 @@ public ApiResponse> patchProfileIm @AuthenticationPrincipal TokenUserDetails userDetails, PatchProfileBody patchProfileBody) throws IOException { Long memberId = Long.valueOf(userDetails.getUsername()); + String suffix = patchProfileBody.getProfile().getOriginalFilename().split("\\.")[1]; + File tempFile = File.createTempFile("temp_", "." + suffix); + patchProfileBody.getProfile().transferTo(tempFile); PatchProfileImageUseCaseResponse useCaseResponse = - patchProfileImageUseCase.execute( - memberId, patchProfileBody.getProfile().getResource().getFile()); + patchProfileImageUseCase.execute(memberId, tempFile); + tempFile.deleteOnExit(); PatchProfileResponse response = PatchProfileResponse.builder() .id(useCaseResponse.getId()) From 7334e3b04197f3b17b6d1a1551a839b2f77df2f8 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 01:15:24 +0900 Subject: [PATCH 55/81] =?UTF-8?q?feat:=20test=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20security=20=EC=84=A4=EC=A0=95=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/web/security/TestSecurityConfig.java | 13 +++++++++++++ .../security/TestTokenUserDetailsService.java | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 api/src/test/java/com/walking/api/web/security/TestSecurityConfig.java create mode 100644 api/src/test/java/com/walking/api/web/security/TestTokenUserDetailsService.java diff --git a/api/src/test/java/com/walking/api/web/security/TestSecurityConfig.java b/api/src/test/java/com/walking/api/web/security/TestSecurityConfig.java new file mode 100644 index 00000000..959edd88 --- /dev/null +++ b/api/src/test/java/com/walking/api/web/security/TestSecurityConfig.java @@ -0,0 +1,13 @@ +package com.walking.api.web.security; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class TestSecurityConfig { + + @Bean + public TestTokenUserDetailsService testTokenUserDetailsService() { + return new TestTokenUserDetailsService(); + } +} diff --git a/api/src/test/java/com/walking/api/web/security/TestTokenUserDetailsService.java b/api/src/test/java/com/walking/api/web/security/TestTokenUserDetailsService.java new file mode 100644 index 00000000..2d98ab14 --- /dev/null +++ b/api/src/test/java/com/walking/api/web/security/TestTokenUserDetailsService.java @@ -0,0 +1,19 @@ +package com.walking.api.web.security; + +import com.walking.api.security.authentication.authority.Roles; +import com.walking.api.security.authentication.token.TokenUserDetails; +import java.util.List; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +public class TestTokenUserDetailsService implements UserDetailsService { + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return TokenUserDetails.builder() + .id("1") + .authorities(List.of(Roles.ROLE_USER.getAuthority())) + .build(); + } +} From bf459f2dc37f5f2ae5049c4f353db63fb375cd79 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sat, 18 May 2024 01:15:38 +0900 Subject: [PATCH 56/81] =?UTF-8?q?test:=20MemberControllerTest=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/MemberControllerTest.java | 347 ++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 api/src/test/java/com/walking/api/web/controller/member/MemberControllerTest.java diff --git a/api/src/test/java/com/walking/api/web/controller/member/MemberControllerTest.java b/api/src/test/java/com/walking/api/web/controller/member/MemberControllerTest.java new file mode 100644 index 00000000..47efaf74 --- /dev/null +++ b/api/src/test/java/com/walking/api/web/controller/member/MemberControllerTest.java @@ -0,0 +1,347 @@ +package com.walking.api.web.controller.member; + +import static com.epages.restdocs.apispec.ResourceDocumentation.resource; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.when; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.multipart; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.epages.restdocs.apispec.ResourceSnippetParameters; +import com.epages.restdocs.apispec.Schema; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.walking.api.ApiApp; +import com.walking.api.security.token.AuthToken; +import com.walking.api.security.token.TokenGenerator; +import com.walking.api.security.token.TokenResolver; +import com.walking.api.web.controller.description.Description; +import com.walking.api.web.dto.request.member.PatchProfileBody; +import com.walking.api.web.dto.request.member.PostMemberBody; +import com.walking.api.web.dto.request.member.RefreshMemberAuthTokenBody; +import com.walking.member.api.usecase.DeleteMemberUseCase; +import com.walking.member.api.usecase.GetMemberDetailUseCase; +import com.walking.member.api.usecase.GetMemberTokenDetailUseCase; +import com.walking.member.api.usecase.PatchProfileImageUseCase; +import com.walking.member.api.usecase.PostMemberUseCase; +import com.walking.member.api.usecase.dto.response.DeleteMemberUseCaseResponse; +import com.walking.member.api.usecase.dto.response.GetMemberDetailUseCaseResponse; +import com.walking.member.api.usecase.dto.response.GetMemberTokenDetailUseCaseResponse; +import com.walking.member.api.usecase.dto.response.PatchProfileImageUseCaseResponse; +import com.walking.member.api.usecase.dto.response.PostMemberUseCaseResponse; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Optional; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.restdocs.payload.FieldDescriptor; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.security.test.context.support.WithUserDetails; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + +@ActiveProfiles(value = "test") +@AutoConfigureRestDocs +@AutoConfigureMockMvc(addFilters = false) +@SpringBootTest(classes = ApiApp.class) +class MemberControllerTest { + + @Autowired private MockMvc mockMvc; + @Autowired private ObjectMapper objectMapper; + private static final String TAG = "MemberControllerTest"; + private static final String BASE_URL = "/api/v1/members"; + + @MockBean TokenGenerator tokenGenerator; + @MockBean TokenResolver tokenResolver; + + @MockBean PostMemberUseCase postMemberUseCase; + @MockBean DeleteMemberUseCase deleteMemberUseCase; + @MockBean GetMemberDetailUseCase getMemberDetailUseCase; + @MockBean GetMemberTokenDetailUseCase getMemberTokenDetailUseCase; + @MockBean PatchProfileImageUseCase patchProfileImageUseCase; + + @Test + @DisplayName("POST /api/v1/members 회원 가입을 한다.") + @WithUserDetails(userDetailsServiceBeanName = "testTokenUserDetailsService") + void postMember() throws Exception { + when(postMemberUseCase.execute(any())) + .thenReturn(new PostMemberUseCaseResponse(1L, "nickname", "profile")); + when(tokenGenerator.generateAuthToken(any(), any())) + .thenReturn(new AuthToken("accessToken", "refreshToken")); + + PostMemberBody postMemberBody = PostMemberBody.builder().code("dsakfjdsakfj").build(); + + String content = objectMapper.writeValueAsString(postMemberBody); + + mockMvc + .perform( + post(BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .content(content) + .header("Authorization", "Bearer {{ accessToken }}")) + .andExpect(status().is2xxSuccessful()) + .andDo( + document( + "postMember", + resource( + ResourceSnippetParameters.builder() + .description("회원 가입을 한다.") + .tag(TAG) + .requestSchema(Schema.schema("PostMemberRequest")) + .requestHeaders(Description.authHeader()) + .responseSchema(Schema.schema("PostMemberResponse")) + .responseFields( + Description.common( + new FieldDescriptor[] { + fieldWithPath("data") + .type(JsonFieldType.OBJECT) + .description("데이터"), + fieldWithPath("data.id") + .type(JsonFieldType.NUMBER) + .description("회원 ID"), + fieldWithPath("data.nickname") + .type(JsonFieldType.STRING) + .description("닉네임"), + fieldWithPath("data.profile") + .type(JsonFieldType.STRING) + .description("프로필 이미지"), + fieldWithPath("data.accessToken") + .type(JsonFieldType.STRING) + .description("액세스 토큰"), + fieldWithPath("data.refreshToken") + .type(JsonFieldType.STRING) + .description("리프레시 토큰") + })) + .build()))); + } + + @Test + @DisplayName("DELETE /api/v1/members 회원 탈퇴를 한다.") + @WithUserDetails(userDetailsServiceBeanName = "testTokenUserDetailsService") + void deleteMember() throws Exception { + when(deleteMemberUseCase.execute(anyLong())) + .thenReturn(new DeleteMemberUseCaseResponse(1L, LocalDateTime.now())); + + mockMvc + .perform( + delete(BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer {{ accessToken }}")) + .andExpect(status().is2xxSuccessful()) + .andDo( + document( + "deleteMember", + resource( + ResourceSnippetParameters.builder() + .description("회원 탈퇴를 한다.") + .tag(TAG) + .requestSchema(Schema.schema("DeleteMemberRequest")) + .requestHeaders(Description.authHeader()) + .responseSchema(Schema.schema("DeleteMemberResponse")) + .responseFields( + Description.common( + new FieldDescriptor[] { + fieldWithPath("data") + .type(JsonFieldType.OBJECT) + .description("데이터"), + fieldWithPath("data.id") + .type(JsonFieldType.NUMBER) + .description("회원 ID"), + fieldWithPath("data.deletedAt") + .type(JsonFieldType.STRING) + .description("삭제 시간") + })) + .build()))); + } + + @Test + @DisplayName("GET /api/v1/members 회원 정보를 조회한다.") + @WithUserDetails(userDetailsServiceBeanName = "testTokenUserDetailsService") + void getMember() throws Exception { + when(getMemberDetailUseCase.execute(anyLong())) + .thenReturn(new GetMemberDetailUseCaseResponse(1L, "nickname", "profile", "KAKAO", "정회원")); + + mockMvc + .perform( + get(BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer {{ accessToken }}")) + .andExpect(status().is2xxSuccessful()) + .andDo( + document( + "getMember", + resource( + ResourceSnippetParameters.builder() + .description("회원 정보를 조회한다.") + .tag(TAG) + .requestSchema(Schema.schema("GetMemberRequest")) + .requestHeaders(Description.authHeader()) + .responseSchema(Schema.schema("GetMemberResponse")) + .responseFields( + Description.common( + new FieldDescriptor[] { + fieldWithPath("data") + .type(JsonFieldType.OBJECT) + .description("데이터"), + fieldWithPath("data.id") + .type(JsonFieldType.NUMBER) + .description("회원 ID"), + fieldWithPath("data.nickname") + .type(JsonFieldType.STRING) + .description("닉네임"), + fieldWithPath("data.profile") + .type(JsonFieldType.STRING) + .description("프로필 이미지") + })) + .build()))); + } + + @Test + @DisplayName("POST /api/v1/members/token 회원 토큰을 갱신한다.") + @WithUserDetails(userDetailsServiceBeanName = "testTokenUserDetailsService") + void getMemberToken() throws Exception { + when(tokenResolver.resolveId(any())).thenReturn(Optional.of(1L)); + + when(getMemberTokenDetailUseCase.execute(anyLong())) + .thenReturn(new GetMemberTokenDetailUseCaseResponse(1L)); + + when(tokenGenerator.generateAuthToken(any(), any())) + .thenReturn(new AuthToken("accessToken", "refreshToken")); + + RefreshMemberAuthTokenBody refreshToken = + RefreshMemberAuthTokenBody.builder().refreshToken("refresh").build(); + + String content = objectMapper.writeValueAsString(refreshToken); + + mockMvc + .perform(post(BASE_URL + "/token").contentType(MediaType.APPLICATION_JSON).content(content)) + .andExpect(status().is2xxSuccessful()) + .andDo( + document( + "refreshMemberAuthToken", + resource( + ResourceSnippetParameters.builder() + .description("회원 토큰을 갱신한다.") + .tag(TAG) + .requestSchema(Schema.schema("RefreshMemberAuthTokenRequest")) + .responseSchema(Schema.schema("RefreshMemberAuthTokenResponse")) + .responseFields( + Description.common( + new FieldDescriptor[] { + fieldWithPath("data") + .type(JsonFieldType.OBJECT) + .description("데이터"), + fieldWithPath("data.accessToken") + .type(JsonFieldType.STRING) + .description("액세스 토큰"), + fieldWithPath("data.refreshToken") + .type(JsonFieldType.STRING) + .description("리프레시 토큰") + })) + .build()))); + } + + @Test + @DisplayName("PATCH /api/v1/members/profile 프로필 이미지를 수정한다.") + @WithUserDetails(userDetailsServiceBeanName = "testTokenUserDetailsService") + void patchProfile() throws Exception { + when(patchProfileImageUseCase.execute(anyLong(), any())) + .thenReturn(new PatchProfileImageUseCaseResponse(1L, "nickname", "profile")); + + File file = makeFile("src/test/resources/images", "test", "png"); + PatchProfileBody patchProfileBody = + PatchProfileBody.builder() + .profile( + new MockMultipartFile( + "profile", + file.getName(), + "image/png", + new BufferedInputStream(new FileInputStream(file)))) + .build(); + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\n"); + stringBuilder.append(" \"profile\": \""); + stringBuilder.append(Arrays.toString(patchProfileBody.getProfile().getBytes())); + stringBuilder.append("\"\n"); + stringBuilder.append("}"); + String content = stringBuilder.toString(); + + mockMvc + .perform( + multipart(BASE_URL + "/profile") + .file((MockMultipartFile) patchProfileBody.getProfile()) + .header("Authorization", "Bearer {{ accessToken }}") + .contentType(MediaType.MULTIPART_FORM_DATA) + .content(content) + .with( + request -> { + request.setMethod("PATCH"); + return request; + })) + .andExpect(status().is2xxSuccessful()) + .andDo( + document( + "patchProfileImage", + resource( + ResourceSnippetParameters.builder() + .description("프로필 이미지를 수정한다.") + .tag(TAG) + .requestSchema(Schema.schema("PatchProfileImageRequest")) + .requestHeaders(Description.authHeader()) + .responseSchema(Schema.schema("PatchProfileImageResponse")) + .requestFields( + fieldWithPath("profile") + .type(JsonFieldType.STRING) + .description("프로필 이미지")) + .responseFields( + Description.common( + new FieldDescriptor[] { + fieldWithPath("data") + .type(JsonFieldType.OBJECT) + .description("데이터"), + fieldWithPath("data.id") + .type(JsonFieldType.NUMBER) + .description("회원 ID"), + fieldWithPath("data.nickname") + .type(JsonFieldType.STRING) + .description("닉네임"), + fieldWithPath("data.profile") + .type(JsonFieldType.STRING) + .description("프로필 이미지") + })) + .build()))); + } + + File makeFile(String path, String pictureName, String pictureExtension) { + String picture = combineDot(pictureName, pictureExtension); + File directory = new File(path); + if (!directory.exists()) { + directory.mkdirs(); + } + String testPicturePath = combinePath(path, picture); + return new File(testPicturePath); + } + + String combinePath(String s1, String s2) { + return s1 + "/" + s2; + } + + String combineDot(String s1, String s2) { + return s1 + "." + s2; + } +} From 9d8ddddfbc1d16d71f19d50347d72eb0fa17c65f Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sun, 19 May 2024 23:43:54 +0900 Subject: [PATCH 57/81] =?UTF-8?q?rename:=20KaKaoTokenClient=20->=20KaKaoTo?= =?UTF-8?q?kenInfoClient=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=AA=85?= =?UTF-8?q?=EC=9D=84=20=EC=88=98=EC=A0=95=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../token/{KaKaoTokenClient.kt => KaKaoTokenInfoClient.kt} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename member-api/src/main/kotlin/com/walking/member/api/client/token/{KaKaoTokenClient.kt => KaKaoTokenInfoClient.kt} (98%) diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenInfoClient.kt similarity index 98% rename from member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenClient.kt rename to member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenInfoClient.kt index b7f3e7ad..69980924 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenInfoClient.kt @@ -14,7 +14,7 @@ import org.springframework.web.client.RestTemplate @Slf4j @Component @RequiredArgsConstructor -class KaKaoTokenClient( +class KaKaoTokenInfoClient( private val restTemplate: RestTemplate, private val properties: KaKaoApiProperties ) : SocialTokenClient { From 5c17ecba601630dd11bb400480f1c973ead30d90 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Sun, 19 May 2024 23:44:45 +0900 Subject: [PATCH 58/81] =?UTF-8?q?fix:=20KaKaoIdTokenData=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=EC=9D=B4=20=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8D=98=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/member/api/client/token/dto/KaKaoIdTokenData.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoIdTokenData.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoIdTokenData.kt index 26e5d9f7..db2a046e 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoIdTokenData.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/dto/KaKaoIdTokenData.kt @@ -1,6 +1,6 @@ package com.walking.member.api.client.token.dto -data class KaKaoIdTokenData(private val id_token: String) : SocialIdToken { +data class KaKaoIdTokenData(val id_token: String) : SocialIdToken { override fun getToken(): String { return id_token } From 9263c3d59cba483447bb51f4785f6aa229b8f6ca Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 00:09:54 +0900 Subject: [PATCH 59/81] =?UTF-8?q?feat:=20generateKakaoHeaders=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/member/api/client/util/HeaderUtils.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt b/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt index 0865efaa..2de96f12 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt @@ -9,5 +9,11 @@ class HeaderUtils { headers.add("Authorization", "Bearer $token") return headers } + + fun generateKakaoHeaders(adminKey: String): HttpHeaders { + val headers = HttpHeaders() + headers.add("Authorization", "KakaoAK $adminKey") + return headers + } } } \ No newline at end of file From f46be6cc4430ad3f3ad1fdcc041e7d04648ebbd2 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 00:10:19 +0900 Subject: [PATCH 60/81] =?UTF-8?q?refactor:=20usrId=EB=A1=9C=20SocialMember?= =?UTF-8?q?Client=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/member/api/client/member/SocialMemberClient.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt index 37482946..8da0f7d1 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt @@ -1,8 +1,7 @@ package com.walking.member.api.client.member import com.walking.member.api.client.member.dto.SocialMemberData -import com.walking.member.api.client.token.dto.SocialIdToken fun interface SocialMemberClient { - fun execute(token: SocialIdToken): SocialMemberData + fun execute(userId: String): SocialMemberData } \ No newline at end of file From 4170b7402cf18f1016b81a7be9d870006f5af7d8 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 00:12:05 +0900 Subject: [PATCH 61/81] =?UTF-8?q?refactor:=20KaKaoMemberData=EA=B0=80=20pr?= =?UTF-8?q?ofile=5Fimage=EB=8F=84=20=EB=B0=9B=EC=95=84=EC=98=AC=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/client/member/dto/KaKaoMemberData.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/KaKaoMemberData.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/KaKaoMemberData.kt index c70527a9..f7baaef0 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/KaKaoMemberData.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/dto/KaKaoMemberData.kt @@ -1,9 +1,9 @@ package com.walking.member.api.client.member.dto -data class KaKaoMemberData(private val id: String) : SocialMemberData { - private val properties: Properties? = null +data class KaKaoMemberData(val id: String) : SocialMemberData { + val properties: Properties? = null - private data class Properties(val nickname: String) + data class Properties(val nickname: String, val profile_image: String) override fun getName(): String { return properties?.nickname ?: "" @@ -12,4 +12,8 @@ data class KaKaoMemberData(private val id: String) : SocialMemberData { override fun getId(): Long { return id.toLong() } + + fun getPicture(): String { + return properties?.profile_image ?: "" + } } \ No newline at end of file From 4f205a7fd5fe30ff59a2f45783c06dfa08cdc9de Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 00:10:54 +0900 Subject: [PATCH 62/81] =?UTF-8?q?refactor:=20usrId=EB=A1=9C=20SocialMember?= =?UTF-8?q?Client=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20KaKaoMemberClient=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/client/member/KaKaoMemberClient.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt index 0212fe70..b2f29e79 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt @@ -4,7 +4,6 @@ import com.walking.member.api.client.config.property.KaKaoApiProperties import com.walking.member.api.client.exception.SocialClientException import com.walking.member.api.client.member.dto.KaKaoMemberData import com.walking.member.api.client.member.dto.SocialMemberData -import com.walking.member.api.client.token.dto.SocialIdToken import com.walking.member.api.client.util.HeaderUtils import lombok.RequiredArgsConstructor import lombok.extern.slf4j.Slf4j @@ -22,13 +21,14 @@ class KaKaoMemberClient( private val restTemplate: RestTemplate, private val properties: KaKaoApiProperties ) : SocialMemberClient { - override fun execute(token: SocialIdToken): SocialMemberData { - val accessToken: String = token.getToken() + override fun execute(userId: String): SocialMemberData { + val adminKey = properties.adminKey - val headers: HttpHeaders = HeaderUtils.generateBearerHeaders(accessToken) + val headers = HeaderUtils.generateKakaoHeaders(adminKey) headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=utf-8") + val queryParameter = "?target_id_type=user_id&target_id=$userId" val response: ResponseEntity = restTemplate.exchange( - properties.uriMeInfo, + properties.uriMeInfo + queryParameter, HttpMethod.POST, HttpEntity(null, headers), KaKaoMemberData::class.java From 0f3d2fe875646bc1a2dc161fd126ab9a52322888 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 00:15:53 +0900 Subject: [PATCH 63/81] =?UTF-8?q?refactor:=20HeaderUtils=EC=9D=84=20HttpHe?= =?UTF-8?q?aders=20=ED=99=95=EC=9E=A5=ED=95=A8=EC=88=98=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/client/util/HeaderUtils.kt | 19 ------------------- .../member/api/client/util/HeadersFunction.kt | 13 +++++++++++++ 2 files changed, 13 insertions(+), 19 deletions(-) delete mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/util/HeadersFunction.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt b/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt deleted file mode 100644 index 2de96f12..00000000 --- a/member-api/src/main/kotlin/com/walking/member/api/client/util/HeaderUtils.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.walking.member.api.client.util - -import org.springframework.http.HttpHeaders - -class HeaderUtils { - companion object { - fun generateBearerHeaders(token: String): HttpHeaders { - val headers = HttpHeaders() - headers.add("Authorization", "Bearer $token") - return headers - } - - fun generateKakaoHeaders(adminKey: String): HttpHeaders { - val headers = HttpHeaders() - headers.add("Authorization", "KakaoAK $adminKey") - return headers - } - } -} \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/util/HeadersFunction.kt b/member-api/src/main/kotlin/com/walking/member/api/client/util/HeadersFunction.kt new file mode 100644 index 00000000..f2082d28 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/util/HeadersFunction.kt @@ -0,0 +1,13 @@ +package com.walking.member.api.client.util + +import org.springframework.http.HttpHeaders + +fun HttpHeaders.addBearerHeader(token: String) { + this.add("Authorization", "Bearer $token") +} + +fun HttpHeaders.addKakaoHeader(adminKey: String) { + this.add("Authorization", "KakaoAK $adminKey") +} + +class HeadersFunction \ No newline at end of file From 1b9f0ac94786f572931f4648725916a27d0c0838 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 00:16:09 +0900 Subject: [PATCH 64/81] =?UTF-8?q?refactor:=20HeaderUtils=EC=9D=84=20HttpHe?= =?UTF-8?q?aders=20=ED=99=95=EC=9E=A5=ED=95=A8=EC=88=98=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../walking/member/api/client/member/KaKaoMemberClient.kt | 5 +++-- .../walking/member/api/client/token/KaKaoTokenInfoClient.kt | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt index b2f29e79..63d496b0 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt @@ -4,7 +4,7 @@ import com.walking.member.api.client.config.property.KaKaoApiProperties import com.walking.member.api.client.exception.SocialClientException import com.walking.member.api.client.member.dto.KaKaoMemberData import com.walking.member.api.client.member.dto.SocialMemberData -import com.walking.member.api.client.util.HeaderUtils +import com.walking.member.api.client.util.addKakaoHeader import lombok.RequiredArgsConstructor import lombok.extern.slf4j.Slf4j import org.springframework.http.HttpEntity @@ -24,7 +24,8 @@ class KaKaoMemberClient( override fun execute(userId: String): SocialMemberData { val adminKey = properties.adminKey - val headers = HeaderUtils.generateKakaoHeaders(adminKey) + val headers = HttpHeaders() + headers.addKakaoHeader(adminKey) headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=utf-8") val queryParameter = "?target_id_type=user_id&target_id=$userId" val response: ResponseEntity = restTemplate.exchange( diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenInfoClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenInfoClient.kt index 69980924..ac5648b3 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenInfoClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/KaKaoTokenInfoClient.kt @@ -1,10 +1,11 @@ + import com.walking.member.api.client.config.property.KaKaoApiProperties import com.walking.member.api.client.exception.SocialClientException import com.walking.member.api.client.token.SocialTokenClient import com.walking.member.api.client.token.dto.KaKaoTokenData import com.walking.member.api.client.token.dto.SocialIdToken import com.walking.member.api.client.token.dto.SocialToken -import com.walking.member.api.client.util.HeaderUtils +import com.walking.member.api.client.util.addBearerHeader import lombok.RequiredArgsConstructor import lombok.extern.slf4j.Slf4j import org.springframework.http.* @@ -20,7 +21,8 @@ class KaKaoTokenInfoClient( ) : SocialTokenClient { override fun execute(token: SocialIdToken): SocialToken { val accessToken: String = token.getToken() - val headers: HttpHeaders = HeaderUtils.generateBearerHeaders(accessToken) + val headers = HttpHeaders() + headers.addBearerHeader(accessToken) headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=utf-8") val response: ResponseEntity = restTemplate.exchange( From bbd1b00c6f19807378f4936f1986fad150cfcfe9 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 01:02:30 +0900 Subject: [PATCH 65/81] =?UTF-8?q?refactor:=20ImageStoreClient=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit null을 반환할 수 있도록 수정 --- .../src/main/kotlin/com/walking/image/ImageStoreClient.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/image-store/src/main/kotlin/com/walking/image/ImageStoreClient.kt b/image-store/src/main/kotlin/com/walking/image/ImageStoreClient.kt index 590ca2d3..3da4f87c 100644 --- a/image-store/src/main/kotlin/com/walking/image/ImageStoreClient.kt +++ b/image-store/src/main/kotlin/com/walking/image/ImageStoreClient.kt @@ -2,9 +2,9 @@ package com.walking.image interface ImageStoreClient { - fun getPresignedObjectUrl(fileName: ImageGetPresignedObjectUrlArgs): String + fun getPresignedObjectUrl(fileName: ImageGetPresignedObjectUrlArgs): String? - fun removeObject(fileName: ImageRemoveObjectArgs) + fun removeObject(fileName: ImageRemoveObjectArgs): Boolean - fun putObject(fileName: ImagePutObjectArgs): ImageWriteResponse + fun putObject(fileName: ImagePutObjectArgs): ImageWriteResponse? } \ No newline at end of file From f79b18154b700c53fec02cbf6ffd1c5eb659155e Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 01:02:47 +0900 Subject: [PATCH 66/81] =?UTF-8?q?refactor:=20ImageStoreClient=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=EC=88=98=EC=A0=95=20MinioImageStoreClient=EC=97=90?= =?UTF-8?q?=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../walking/image/MinioImageStoreClient.kt | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/image-store/src/main/kotlin/com/walking/image/MinioImageStoreClient.kt b/image-store/src/main/kotlin/com/walking/image/MinioImageStoreClient.kt index b9c3515b..f9d1ad9a 100644 --- a/image-store/src/main/kotlin/com/walking/image/MinioImageStoreClient.kt +++ b/image-store/src/main/kotlin/com/walking/image/MinioImageStoreClient.kt @@ -5,33 +5,48 @@ import io.minio.MinioClient import io.minio.PutObjectArgs import io.minio.RemoveObjectArgs import io.minio.http.Method +import org.slf4j.Logger +import org.slf4j.LoggerFactory class MinioImageStoreClient( private val minIoClient: MinioClient ) : ImageStoreClient { - override fun getPresignedObjectUrl(fileName: ImageGetPresignedObjectUrlArgs): String { + val log: Logger = LoggerFactory.getLogger(MinioImageStoreClient::class.java) + + override fun getPresignedObjectUrl(fileName: ImageGetPresignedObjectUrlArgs): String? { GetPresignedObjectUrlArgs.builder() .bucket(fileName.bucket) .`object`(fileName.`object`) .method(Method.valueOf(fileName.method)) .build() .let { args -> - return minIoClient.getPresignedObjectUrl(args) + try { + return minIoClient.getPresignedObjectUrl(args) + } catch (e: Exception) { + log.debug("Failed to get presigned url for object: ${fileName.`object`}") + return null + } } } - override fun removeObject(fileName: ImageRemoveObjectArgs) { + override fun removeObject(fileName: ImageRemoveObjectArgs): Boolean { RemoveObjectArgs.builder() .bucket(fileName.bucket) .`object`(fileName.`object`) .build() .let { args -> - minIoClient.removeObject(args) + try { + minIoClient.removeObject(args) + return true + } catch (e: Exception) { + log.debug("Failed to remove object: ${fileName.`object`}") + return false + } } } - override fun putObject(fileName: ImagePutObjectArgs): ImageWriteResponse { + override fun putObject(fileName: ImagePutObjectArgs): ImageWriteResponse? { PutObjectArgs.builder() .bucket(fileName.bucket) .`object`(fileName.`object`) @@ -39,14 +54,19 @@ class MinioImageStoreClient( .contentType(fileName.contentType) .build() .let { args -> - minIoClient.putObject(args).let { owr -> - return ImageWriteResponse( - owr.bucket(), - owr.region(), - owr.`object`(), - owr.etag(), - owr.versionId() - ) + try { + minIoClient.putObject(args).let { owr -> + return ImageWriteResponse( + owr.bucket(), + owr.region(), + owr.`object`(), + owr.etag(), + owr.versionId() + ) + } + } catch (e: Exception) { + log.debug("Failed to put object: ${fileName.`object`}") + return null } } } From c7222b694232d7235cb27a10adaf79577801315e Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 01:04:02 +0900 Subject: [PATCH 67/81] =?UTF-8?q?refactor:=20null=EC=9D=B4=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=EB=90=98=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EB=B0=9C=EC=83=9D=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image/service/minio/MinioGetPreSignedImageUrlService.kt | 2 +- .../com/walking/image/service/minio/MinioUploadImageService.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt index 3623b482..3b05b017 100644 --- a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt +++ b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt @@ -15,7 +15,7 @@ class MinioGetPreSignedImageUrlService( ) : GetPreSignedImageUrlService { override fun execute(image: String): String { ImageArgsGenerator.preSignedUrl(bucket, image).let { args -> - return imageStoreClient.getPresignedObjectUrl(args) + return imageStoreClient.getPresignedObjectUrl(args) ?: throw Exception("Failed to get pre-signed url") } } } \ No newline at end of file diff --git a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt index b370da7d..fa1a18ee 100644 --- a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt +++ b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt @@ -17,7 +17,7 @@ class MinioUploadImageService( ) : UploadImageService { override fun execute(name: String, file: File): ImageWriteResponse { ImageArgsGenerator.putImage(bucket, name, file).let { args -> - return imageStoreClient.putObject(args) + return imageStoreClient.putObject(args) ?: throw Exception("Failed to upload image") } } } \ No newline at end of file From f15b1e886fd7debf2f794a416fbdeae038441a23 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 01:05:00 +0900 Subject: [PATCH 68/81] =?UTF-8?q?refactor:=20MinioImageStoreClient#removeO?= =?UTF-8?q?bject=20=EB=B0=98=ED=99=98=20=EC=88=98=EC=A0=95=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EA=B5=AC=ED=98=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image/service/minio/MinioRemoveImageService.kt | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt index 9aa12c60..89887722 100644 --- a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt +++ b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt @@ -14,13 +14,8 @@ class MinioRemoveImageService( private val imageStoreClient: MinioImageStoreClient ) : RemoveImageService { override fun execute(image: String): Boolean { - try { - ImageArgsGenerator.remove(bucket, image).let { args -> - imageStoreClient.removeObject(args) - return true - } - } catch (e: Exception) { - return false + ImageArgsGenerator.remove(bucket, image).let { args -> + return imageStoreClient.removeObject(args) } } } \ No newline at end of file From 733990b2c2c0b7228c00175c8ee4da8343df83c6 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 01:21:11 +0900 Subject: [PATCH 69/81] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=95=84?= =?UTF-8?q?=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=A1=B0=ED=9A=8C=EC=97=90=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=ED=95=98=EB=A9=B4=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A5=BC=20=EB=8C=80=EC=B2=B4?= =?UTF-8?q?=ED=95=B4=EC=84=9C=20=EC=A0=9C=EA=B3=B5=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/usecase/GetMemberDetailUseCase.kt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt index 52ab2b06..a849f4e2 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt @@ -1,9 +1,12 @@ package com.walking.member.api.usecase +import com.walking.data.entity.member.MemberEntity import com.walking.image.service.GetPreSignedImageUrlService import com.walking.member.api.dao.MemberDao import com.walking.member.api.usecase.dto.response.GetMemberDetailUseCaseResponse +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -12,6 +15,8 @@ class GetMemberDetailUseCase( private val memberRepository: MemberDao, private val getPreSignedImageUrlService: GetPreSignedImageUrlService ) { + val log: Logger = LoggerFactory.getLogger(GetMemberDetailUseCase::class.java) + @Transactional fun execute(id: Long): GetMemberDetailUseCaseResponse { val member = memberRepository.findById(id) ?: throw IllegalArgumentException("Member not found") @@ -19,7 +24,7 @@ class GetMemberDetailUseCase( val nickName = member.nickName val certificationSubject = member.certificationSubject.name val status = member.status.name - val profile = getPreSignedImageUrlService.execute(member.profile) + val profile = getProfile(member) return GetMemberDetailUseCaseResponse( id, @@ -29,4 +34,13 @@ class GetMemberDetailUseCase( status ) } + + private fun getProfile(member: MemberEntity): String { + return try { + getPreSignedImageUrlService.execute(member.profile) + } catch (e: Exception) { + log.debug("Failed to get profile image: ${e.message}") + "" // todo fix 기본 이미지 + } + } } \ No newline at end of file From d80817d647d3ac9dde65cad0c8368c9338aa2125 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 02:11:41 +0900 Subject: [PATCH 70/81] =?UTF-8?q?feat:=20cache=20starter=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=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 --- member-api/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/member-api/build.gradle b/member-api/build.gradle index b7c2d0cc..eea57694 100644 --- a/member-api/build.gradle +++ b/member-api/build.gradle @@ -23,6 +23,9 @@ dependencies { // spring implementation 'org.springframework.boot:spring-boot-starter-web' + // spring cache + implementation 'org.springframework.boot:spring-boot-starter-cache' + // jackson implementation 'com.fasterxml.jackson.module:jackson-module-kotlin' implementation 'com.fasterxml.jackson.core:jackson-databind' From 540cdac8d1fbec0ca6f4fc8d4c26ba72e5f3c677 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 02:11:58 +0900 Subject: [PATCH 71/81] =?UTF-8?q?feat:=20MemberApiCacheConfig=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/api/config/MemberApiCacheConfig.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/config/MemberApiCacheConfig.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/config/MemberApiCacheConfig.kt b/member-api/src/main/kotlin/com/walking/member/api/config/MemberApiCacheConfig.kt new file mode 100644 index 00000000..4a28da46 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/config/MemberApiCacheConfig.kt @@ -0,0 +1,26 @@ +package com.walking.member.api.config + +import org.springframework.cache.CacheManager +import org.springframework.cache.annotation.EnableCaching +import org.springframework.cache.concurrent.ConcurrentMapCache +import org.springframework.cache.support.SimpleCacheManager +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import java.util.List + +@Configuration +@EnableCaching +class MemberApiCacheConfig { + + @Bean(value = [MemberApiConfig.BEAN_NAME_PREFIX + "CacheManager"]) + fun memberApiCacheManager(): CacheManager { + SimpleCacheManager().apply { + this.setCaches( + List.of( + ConcurrentMapCache("member-profile-url") + ) + ) + return this + } + } +} \ No newline at end of file From 5d44298a0a97cf8b497e0cbc10b670636df4f4e6 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 02:12:51 +0900 Subject: [PATCH 72/81] =?UTF-8?q?feat:=20member=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20id=20=EA=B8=B0=EC=A4=80=20=EC=BA=90=EC=8B=9C=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/member/api/usecase/DeleteMemberUseCase.kt | 2 ++ .../com/walking/member/api/usecase/GetMemberDetailUseCase.kt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt index 394750eb..0d2f2250 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt @@ -4,6 +4,7 @@ import com.walking.data.entity.member.MemberEntity import com.walking.image.service.minio.MinioRemoveImageService import com.walking.member.api.dao.MemberDao import com.walking.member.api.usecase.dto.response.DeleteMemberUseCaseResponse +import org.springframework.cache.annotation.CacheEvict import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -13,6 +14,7 @@ class DeleteMemberUseCase( private val removeImageService: MinioRemoveImageService ) { @Transactional + @CacheEvict(key = "#id", cacheManager = "memberApiCacheManager", cacheNames = ["member-profile-url"]) fun execute(id: Long): DeleteMemberUseCaseResponse { val member = memberRepository.findById(id) ?: throw IllegalArgumentException("Member not found") val deletedMember = withdrawMember(member) diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt index a849f4e2..355a0e3a 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/GetMemberDetailUseCase.kt @@ -7,6 +7,7 @@ import com.walking.member.api.dao.MemberDao import com.walking.member.api.usecase.dto.response.GetMemberDetailUseCaseResponse import org.slf4j.Logger import org.slf4j.LoggerFactory +import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -18,6 +19,7 @@ class GetMemberDetailUseCase( val log: Logger = LoggerFactory.getLogger(GetMemberDetailUseCase::class.java) @Transactional + @Cacheable(key = "#id", cacheManager = "memberApiCacheManager", cacheNames = ["member-profile-url"]) fun execute(id: Long): GetMemberDetailUseCaseResponse { val member = memberRepository.findById(id) ?: throw IllegalArgumentException("Member not found") val id = member.id From 5685c9b5a7811c19e4f69f6a540ae84e08dfcbc8 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 02:13:04 +0900 Subject: [PATCH 73/81] =?UTF-8?q?feat:=20MemberApiCacheConfig=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CacheAbleMemberProfileUpdateDelegator.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/service/CacheAbleMemberProfileUpdateDelegator.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/service/CacheAbleMemberProfileUpdateDelegator.kt b/member-api/src/main/kotlin/com/walking/member/api/service/CacheAbleMemberProfileUpdateDelegator.kt new file mode 100644 index 00000000..c88183af --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/service/CacheAbleMemberProfileUpdateDelegator.kt @@ -0,0 +1,13 @@ +package com.walking.member.api.service + +import com.walking.data.entity.member.MemberEntity +import org.springframework.cache.annotation.CachePut +import org.springframework.stereotype.Service + +@Service +class CacheAbleMemberProfileUpdateDelegator { + @CachePut(key = "#entity.id", cacheManager = "memberApiCacheManager", cacheNames = ["member-profile-url"]) + fun execute(entity: MemberEntity, imageName: String): MemberEntity { + return entity.updateProfile(imageName) + } +} \ No newline at end of file From 894e97ef40416d21139d6f4b1209f5bf47d0a780 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 02:13:33 +0900 Subject: [PATCH 74/81] =?UTF-8?q?refactor:=20CacheAbleMemberProfileUpdateD?= =?UTF-8?q?elegator=EC=9D=B4=20member=20profile=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EA=B5=AC=ED=98=84=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 --- .../walking/member/api/usecase/PatchProfileImageUseCase.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/PatchProfileImageUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/PatchProfileImageUseCase.kt index bee9de60..8d4516c1 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/usecase/PatchProfileImageUseCase.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/PatchProfileImageUseCase.kt @@ -2,6 +2,7 @@ package com.walking.member.api.usecase import com.walking.image.service.UploadImageService import com.walking.member.api.dao.MemberDao +import com.walking.member.api.service.CacheAbleMemberProfileUpdateDelegator import com.walking.member.api.usecase.dto.response.PatchProfileImageUseCaseResponse import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -12,7 +13,8 @@ import kotlin.random.Random @Service class PatchProfileImageUseCase( private val memberDao: MemberDao, - private val uploadImageService: UploadImageService + private val uploadImageService: UploadImageService, + private val memberProfileUpdateDelegator: CacheAbleMemberProfileUpdateDelegator ) { @Transactional fun execute(id: Long, image: File): PatchProfileImageUseCaseResponse { @@ -20,7 +22,7 @@ class PatchProfileImageUseCase( val imageName = generateImageName() uploadImageService.execute(imageName, image).let { - member.updateProfile(imageName).let { member -> + memberProfileUpdateDelegator.execute(member, imageName).let { member -> memberDao.save(member) return PatchProfileImageUseCaseResponse(member.id, member.nickName, imageName) } From 3ea27bd6fb4818f9f08f190b75d18b5eaac6bda1 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 02:21:37 +0900 Subject: [PATCH 75/81] =?UTF-8?q?chore:=20social=20client=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../walking/member/api/client/member/KaKaoMemberClient.kt | 4 ++-- .../walking/member/api/client/member/SocialMemberClient.kt | 6 +++++- .../walking/member/api/client/token/SocialIdTokenClient.kt | 5 +++++ .../walking/member/api/client/token/SocialTokenClient.kt | 4 ++++ .../walking/member/api/client/unlink/SocialUnlinkClient.kt | 4 ++++ 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt index 63d496b0..1b240c5d 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/KaKaoMemberClient.kt @@ -21,13 +21,13 @@ class KaKaoMemberClient( private val restTemplate: RestTemplate, private val properties: KaKaoApiProperties ) : SocialMemberClient { - override fun execute(userId: String): SocialMemberData { + override fun execute(targetId: String): SocialMemberData { val adminKey = properties.adminKey val headers = HttpHeaders() headers.addKakaoHeader(adminKey) headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=utf-8") - val queryParameter = "?target_id_type=user_id&target_id=$userId" + val queryParameter = "?target_id_type=user_id&target_id=$targetId" val response: ResponseEntity = restTemplate.exchange( properties.uriMeInfo + queryParameter, HttpMethod.POST, diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt index 8da0f7d1..e585e7a9 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/member/SocialMemberClient.kt @@ -3,5 +3,9 @@ package com.walking.member.api.client.member import com.walking.member.api.client.member.dto.SocialMemberData fun interface SocialMemberClient { - fun execute(userId: String): SocialMemberData + /** + * Get social member data by userId + * @param targetId social user id + */ + fun execute(targetId: String): SocialMemberData } \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialIdTokenClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialIdTokenClient.kt index 37cae0b7..724f12b4 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialIdTokenClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialIdTokenClient.kt @@ -1,5 +1,10 @@ import com.walking.member.api.client.token.dto.SocialIdToken fun interface SocialIdTokenClient { + + /** + * Get social id token by auth code + * @param code social auth code + */ fun execute(code: String): SocialIdToken } \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialTokenClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialTokenClient.kt index aea01125..52f88d12 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialTokenClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/token/SocialTokenClient.kt @@ -5,5 +5,9 @@ import com.walking.member.api.client.token.dto.SocialToken fun interface SocialTokenClient { + /** + * Get social token by social id token + * @param token social id token + */ fun execute(token: SocialIdToken): SocialToken } \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt index 586a2175..4b5e00dd 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt @@ -4,5 +4,9 @@ import com.walking.member.api.client.unlink.dto.SocialUnlinkData fun interface SocialUnlinkClient { + /** + * Unlink social account by targetId + * @param targetId social user id + */ fun execute(targetId: String): SocialUnlinkData } \ No newline at end of file From af465fe95cc540e07a33f3164398658fcdf1882a Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 02:31:38 +0900 Subject: [PATCH 76/81] =?UTF-8?q?feat:=20SocialUnlinkClientManager?= =?UTF-8?q?=EC=97=90=20=EC=9D=98=ED=95=B4=20=EA=B4=80=EB=A6=AC=EB=8F=84?= =?UTF-8?q?=EA=B8=B0=20=EC=9C=84=ED=95=9C=20supports=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/member/api/client/unlink/KaKaoUnlinkClient.kt | 4 ++++ .../walking/member/api/client/unlink/SocialUnlinkClient.kt | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/KaKaoUnlinkClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/KaKaoUnlinkClient.kt index 8a1ba306..8caf8acd 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/KaKaoUnlinkClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/KaKaoUnlinkClient.kt @@ -49,4 +49,8 @@ class KaKaoUnlinkClient( return response.body!! } + + override fun supports(type: String): Boolean { + return "KAKAO" == type.toUpperCase() + } } \ No newline at end of file diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt index 4b5e00dd..7240c573 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClient.kt @@ -2,11 +2,13 @@ package com.walking.member.api.client.unlink import com.walking.member.api.client.unlink.dto.SocialUnlinkData -fun interface SocialUnlinkClient { +interface SocialUnlinkClient { /** * Unlink social account by targetId * @param targetId social user id */ fun execute(targetId: String): SocialUnlinkData + + fun supports(type: String): Boolean } \ No newline at end of file From 639b79c47f8f9025c6368a37e540caae8eba9ec9 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 02:31:54 +0900 Subject: [PATCH 77/81] =?UTF-8?q?feat:=20SocialUnlinkClientManager=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/unlink/SocialUnlinkClientManager.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClientManager.kt diff --git a/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClientManager.kt b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClientManager.kt new file mode 100644 index 00000000..508ce819 --- /dev/null +++ b/member-api/src/main/kotlin/com/walking/member/api/client/unlink/SocialUnlinkClientManager.kt @@ -0,0 +1,18 @@ +package com.walking.member.api.client.unlink + +import com.walking.member.api.client.unlink.dto.SocialUnlinkData +import org.springframework.stereotype.Component + +@Component +class SocialUnlinkClientManager( + private val socialUnlinkClients: List +) { + fun execute(socialType: String, targetId: String): SocialUnlinkData { + socialUnlinkClients.forEach { client -> + if (client.supports(socialType)) { + return client.execute(targetId) + } + } + throw IllegalArgumentException("Unsupported social type: $socialType") + } +} \ No newline at end of file From b065270d130e9c2ba45bf39eac4c95234506a6eb Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 20 May 2024 02:32:14 +0900 Subject: [PATCH 78/81] =?UTF-8?q?feat:=20SocialUnlinkClientManager?= =?UTF-8?q?=EB=A1=9C=20=EC=86=8C=EC=85=9C=20=EC=97=B0=EA=B2=B0=20=ED=95=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/member/api/usecase/DeleteMemberUseCase.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt b/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt index 0d2f2250..f32cbf53 100644 --- a/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt +++ b/member-api/src/main/kotlin/com/walking/member/api/usecase/DeleteMemberUseCase.kt @@ -2,6 +2,7 @@ package com.walking.member.api.usecase import com.walking.data.entity.member.MemberEntity import com.walking.image.service.minio.MinioRemoveImageService +import com.walking.member.api.client.unlink.SocialUnlinkClientManager import com.walking.member.api.dao.MemberDao import com.walking.member.api.usecase.dto.response.DeleteMemberUseCaseResponse import org.springframework.cache.annotation.CacheEvict @@ -11,7 +12,8 @@ import org.springframework.transaction.annotation.Transactional @Service class DeleteMemberUseCase( private val memberRepository: MemberDao, - private val removeImageService: MinioRemoveImageService + private val removeImageService: MinioRemoveImageService, + private val unlinkClientManager: SocialUnlinkClientManager ) { @Transactional @CacheEvict(key = "#id", cacheManager = "memberApiCacheManager", cacheNames = ["member-profile-url"]) @@ -19,6 +21,10 @@ class DeleteMemberUseCase( val member = memberRepository.findById(id) ?: throw IllegalArgumentException("Member not found") val deletedMember = withdrawMember(member) removeImageService.execute(deletedMember.profile) + unlinkClientManager.execute( + deletedMember.certificationSubject.name, + deletedMember.certificationId + ) return DeleteMemberUseCaseResponse(deletedMember.id, deletedMember.updatedAt) } From 6238abeb313876dbbb71a793b1169ac8f129d108 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Tue, 4 Jun 2024 18:13:31 +0900 Subject: [PATCH 79/81] =?UTF-8?q?feat:=20S3=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 + image-store/build.gradle | 3 + .../com/walking/image/S3ImageStoreClient.kt | 77 +++++++++++++++++++ .../image/config/S3ImageStoreConfig.kt | 57 ++++++++++++++ .../s3/S3GetPreSignedImageUrlService.kt | 21 +++++ .../image/service/s3/S3RemoveImageService.kt | 21 +++++ .../image/service/s3/S3UploadImageService.kt | 23 ++++++ .../resources/application-iamge-store.yml | 11 +-- .../resources/application-image-store-dev.yml | 11 +-- .../application-image-store-prod.yml | 11 +-- 10 files changed, 223 insertions(+), 15 deletions(-) create mode 100644 image-store/src/main/kotlin/com/walking/image/S3ImageStoreClient.kt create mode 100644 image-store/src/main/kotlin/com/walking/image/config/S3ImageStoreConfig.kt create mode 100644 image-store/src/main/kotlin/com/walking/image/service/s3/S3GetPreSignedImageUrlService.kt create mode 100644 image-store/src/main/kotlin/com/walking/image/service/s3/S3RemoveImageService.kt create mode 100644 image-store/src/main/kotlin/com/walking/image/service/s3/S3UploadImageService.kt diff --git a/build.gradle b/build.gradle index 724c10fa..78dd93b1 100644 --- a/build.gradle +++ b/build.gradle @@ -36,6 +36,9 @@ buildscript { // Minio minioVersion = '8.5.5' + // aws s3 + awsS3Version = "1.12.220" + // spring cloud set('springCloudVersion', "2021.0.1") } diff --git a/image-store/build.gradle b/image-store/build.gradle index 76289a8c..5fb8c70c 100644 --- a/image-store/build.gradle +++ b/image-store/build.gradle @@ -18,4 +18,7 @@ dependencies { // minio implementation "io.minio:minio:${minioVersion}" + + // s3 + implementation "com.amazonaws:aws-java-sdk-s3:${awsS3Version}" } diff --git a/image-store/src/main/kotlin/com/walking/image/S3ImageStoreClient.kt b/image-store/src/main/kotlin/com/walking/image/S3ImageStoreClient.kt new file mode 100644 index 00000000..1bad8bb3 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/S3ImageStoreClient.kt @@ -0,0 +1,77 @@ +package com.walking.image + +import com.amazonaws.HttpMethod +import com.amazonaws.services.s3.AmazonS3Client +import com.amazonaws.services.s3.model.DeleteObjectRequest +import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest +import com.amazonaws.services.s3.model.ObjectMetadata +import com.amazonaws.services.s3.model.PutObjectRequest +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +class S3ImageStoreClient( + private val s3client: AmazonS3Client, + private val region: String +) : ImageStoreClient { + + val log: Logger = LoggerFactory.getLogger(S3ImageStoreClient::class.java) + + override fun getPresignedObjectUrl(fileName: ImageGetPresignedObjectUrlArgs): String? { + GeneratePresignedUrlRequest( + fileName.bucket, + fileName.`object`, + HttpMethod.valueOf(fileName.method) + ) + .let { args -> + try { + s3client.generatePresignedUrl(args) + .let { url -> + return url.toString() + } + } catch (e: Exception) { + log.debug("Failed to get presigned url for object: ${fileName.`object`}\n ${e.message}") + return null + } + } + } + + override fun removeObject(fileName: ImageRemoveObjectArgs): Boolean { + DeleteObjectRequest(fileName.bucket, fileName.`object`) + .let { args -> + try { + s3client.deleteObject(args) + return true + } catch (e: Exception) { + log.debug("Failed to remove object: ${fileName.`object`}\n ${e.message}") + return false + } + } + } + + override fun putObject(fileName: ImagePutObjectArgs): ImageWriteResponse? { + PutObjectRequest( + fileName.bucket, + fileName.`object`, + fileName.stream, + ObjectMetadata().apply { + contentType = fileName.contentType + } + ) + .let { args -> + try { + s3client.putObject(args).let { owr -> + return ImageWriteResponse( + fileName.bucket, + region, + fileName.`object`, + owr.eTag ?: "", + owr.versionId ?: "" + ) + } + } catch (e: Exception) { + log.debug("Failed to put object: ${fileName.`object`}\n ${e.message}") + return null + } + } + } +} \ No newline at end of file diff --git a/image-store/src/main/kotlin/com/walking/image/config/S3ImageStoreConfig.kt b/image-store/src/main/kotlin/com/walking/image/config/S3ImageStoreConfig.kt new file mode 100644 index 00000000..043e2f8f --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/config/S3ImageStoreConfig.kt @@ -0,0 +1,57 @@ +package com.walking.image.config + +import com.amazonaws.auth.AWSStaticCredentialsProvider +import com.amazonaws.auth.BasicAWSCredentials +import com.amazonaws.services.s3.AmazonS3Client +import com.walking.image.S3ImageStoreClient +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.ApplicationListener +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Profile +import org.springframework.context.event.ContextRefreshedEvent + +@Profile("!local") +@Configuration +class S3ImageStoreConfig( + @Value("\${s3.url}") val url: String, + @Value("\${s3.access-key}") val accessKey: String, + @Value("\${s3.secret-key}") val secretKey: String, + @Value("\${s3.bucket-name}") val bucket: String, + @Value("\${s3.region}:ap-northeast-2") val region: String +) : ApplicationListener { + + var log: Logger = LoggerFactory.getLogger(S3ImageStoreConfig::class.java) + + private var client: AmazonS3Client? = null + + override fun onApplicationEvent(event: ContextRefreshedEvent) { + client?.let { client -> + if (!client.doesBucketExistV2(bucket)) { + client.createBucket(bucket) + log.info("Create bucket $bucket") + } else { + log.info("Bucket $bucket already exists") + } + } + } + + @Bean + fun s3ImageStoreClient(): S3ImageStoreClient { + AmazonS3Client.builder() + .withRegion(region) + .withCredentials( + AWSStaticCredentialsProvider( + BasicAWSCredentials( + accessKey, + secretKey + ) + ) + ).build().let { client -> + this.client = client as AmazonS3Client + return S3ImageStoreClient(client, region) + } + } +} \ No newline at end of file diff --git a/image-store/src/main/kotlin/com/walking/image/service/s3/S3GetPreSignedImageUrlService.kt b/image-store/src/main/kotlin/com/walking/image/service/s3/S3GetPreSignedImageUrlService.kt new file mode 100644 index 00000000..7d882c07 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/service/s3/S3GetPreSignedImageUrlService.kt @@ -0,0 +1,21 @@ +package com.walking.image.service.s3 + +import com.walking.image.S3ImageStoreClient +import com.walking.image.service.GetPreSignedImageUrlService +import com.walking.image.util.ImageArgsGenerator +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Service + +@Profile("!local") +@Service +class S3GetPreSignedImageUrlService( + @Value("\${s3.bucket-name}") val bucket: String, + private val imageStoreClient: S3ImageStoreClient +) : GetPreSignedImageUrlService { + override fun execute(image: String): String { + ImageArgsGenerator.preSignedUrl(bucket, image).let { args -> + return imageStoreClient.getPresignedObjectUrl(args) ?: throw Exception("Failed to get pre-signed url") + } + } +} \ No newline at end of file diff --git a/image-store/src/main/kotlin/com/walking/image/service/s3/S3RemoveImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/s3/S3RemoveImageService.kt new file mode 100644 index 00000000..45074dca --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/service/s3/S3RemoveImageService.kt @@ -0,0 +1,21 @@ +package com.walking.image.service.s3 + +import com.walking.image.S3ImageStoreClient +import com.walking.image.service.RemoveImageService +import com.walking.image.util.ImageArgsGenerator +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Service + +@Profile("!local") +@Service +class S3RemoveImageService( + @Value("\${s3.bucket-name}") val bucket: String, + private val imageStoreClient: S3ImageStoreClient +) : RemoveImageService { + override fun execute(image: String): Boolean { + ImageArgsGenerator.remove(bucket, image).let { args -> + return imageStoreClient.removeObject(args) + } + } +} \ No newline at end of file diff --git a/image-store/src/main/kotlin/com/walking/image/service/s3/S3UploadImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/s3/S3UploadImageService.kt new file mode 100644 index 00000000..625e35c6 --- /dev/null +++ b/image-store/src/main/kotlin/com/walking/image/service/s3/S3UploadImageService.kt @@ -0,0 +1,23 @@ +package com.walking.image.service.s3 + +import com.walking.image.ImageWriteResponse +import com.walking.image.S3ImageStoreClient +import com.walking.image.service.UploadImageService +import com.walking.image.util.ImageArgsGenerator +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Service +import java.io.File + +@Profile("!local") +@Service +class S3UploadImageService( + @Value("\${s3.bucket-name}") val bucket: String, + private val imageStoreClient: S3ImageStoreClient +) : UploadImageService { + override fun execute(name: String, file: File): ImageWriteResponse { + ImageArgsGenerator.putImage(bucket, name, file).let { args -> + return imageStoreClient.putObject(args) ?: throw Exception("Failed to upload image") + } + } +} \ No newline at end of file diff --git a/image-store/src/main/resources/application-iamge-store.yml b/image-store/src/main/resources/application-iamge-store.yml index 8e3058fa..1b38de17 100644 --- a/image-store/src/main/resources/application-iamge-store.yml +++ b/image-store/src/main/resources/application-iamge-store.yml @@ -1,5 +1,6 @@ -minio: - url: ${MINIO_URL} - access-key: ${MINIO_ACCESS_KEY} - secret-key: ${MINIO_SECRET_KEY} - bucket-name: ${MINIO_BUCKET_NAME} +s3: + url: ${S3_URL} + access-key: ${S3_ACCESS_KEY} + secret-key: ${S3_SECRET_KEY} + bucket-name: ${S3_BUCKET_NAME} + region: ${S3_REGION} diff --git a/image-store/src/main/resources/application-image-store-dev.yml b/image-store/src/main/resources/application-image-store-dev.yml index 8e3058fa..1b38de17 100644 --- a/image-store/src/main/resources/application-image-store-dev.yml +++ b/image-store/src/main/resources/application-image-store-dev.yml @@ -1,5 +1,6 @@ -minio: - url: ${MINIO_URL} - access-key: ${MINIO_ACCESS_KEY} - secret-key: ${MINIO_SECRET_KEY} - bucket-name: ${MINIO_BUCKET_NAME} +s3: + url: ${S3_URL} + access-key: ${S3_ACCESS_KEY} + secret-key: ${S3_SECRET_KEY} + bucket-name: ${S3_BUCKET_NAME} + region: ${S3_REGION} diff --git a/image-store/src/main/resources/application-image-store-prod.yml b/image-store/src/main/resources/application-image-store-prod.yml index 8e3058fa..1b38de17 100644 --- a/image-store/src/main/resources/application-image-store-prod.yml +++ b/image-store/src/main/resources/application-image-store-prod.yml @@ -1,5 +1,6 @@ -minio: - url: ${MINIO_URL} - access-key: ${MINIO_ACCESS_KEY} - secret-key: ${MINIO_SECRET_KEY} - bucket-name: ${MINIO_BUCKET_NAME} +s3: + url: ${S3_URL} + access-key: ${S3_ACCESS_KEY} + secret-key: ${S3_SECRET_KEY} + bucket-name: ${S3_BUCKET_NAME} + region: ${S3_REGION} From 038ffbcdb7f33adaeb7a3990e891dbb0ae1713f5 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Tue, 4 Jun 2024 18:13:56 +0900 Subject: [PATCH 80/81] =?UTF-8?q?refactor:=20Minio=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/walking/image/config/MinioImageStoreClientConfig.kt | 2 +- .../image/service/minio/MinioGetPreSignedImageUrlService.kt | 2 +- .../com/walking/image/service/minio/MinioRemoveImageService.kt | 2 +- .../com/walking/image/service/minio/MinioUploadImageService.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/image-store/src/main/kotlin/com/walking/image/config/MinioImageStoreClientConfig.kt b/image-store/src/main/kotlin/com/walking/image/config/MinioImageStoreClientConfig.kt index 78261c0c..27632da1 100644 --- a/image-store/src/main/kotlin/com/walking/image/config/MinioImageStoreClientConfig.kt +++ b/image-store/src/main/kotlin/com/walking/image/config/MinioImageStoreClientConfig.kt @@ -13,7 +13,7 @@ import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Profile import org.springframework.context.event.ContextRefreshedEvent -@Profile("minio") +@Profile("local") @Configuration class MinioImageStoreClientConfig( @Value("\${minio.url}") val url: String, diff --git a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt index 3b05b017..bee8b854 100644 --- a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt +++ b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioGetPreSignedImageUrlService.kt @@ -7,7 +7,7 @@ import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Profile import org.springframework.stereotype.Service -@Profile("minio") +@Profile("local") @Service class MinioGetPreSignedImageUrlService( @Value("\${minio.bucket-name}") val bucket: String, diff --git a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt index 89887722..14762707 100644 --- a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt +++ b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioRemoveImageService.kt @@ -7,7 +7,7 @@ import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Profile import org.springframework.stereotype.Service -@Profile("minio") +@Profile("local") @Service class MinioRemoveImageService( @Value("\${minio.bucket-name}") val bucket: String, diff --git a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt index fa1a18ee..f1b8fe37 100644 --- a/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt +++ b/image-store/src/main/kotlin/com/walking/image/service/minio/MinioUploadImageService.kt @@ -9,7 +9,7 @@ import org.springframework.context.annotation.Profile import org.springframework.stereotype.Service import java.io.File -@Profile("minio") +@Profile("local") @Service class MinioUploadImageService( @Value("\${minio.bucket-name}") val bucket: String, From 9995d8d604e1d9594ea771defda09de382fe07f4 Mon Sep 17 00:00:00 2001 From: Moon-1C Date: Sat, 1 Jun 2024 15:24:51 +0900 Subject: [PATCH 81/81] =?UTF-8?q?!fix:=20=EC=B6=A9=EB=8F=8C=EC=9D=84=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/dao/member/PathFavoritesRepository.java | 2 +- .../repository/dao/member/TrafficFavoritesRepository.java | 8 -------- .../repository/dao/traffic/TrafficDetailRepository.java | 2 +- .../dao/traffic/TrafficFavoritesRepository.java | 2 +- api/build.gradle | 2 ++ .../domain/traffic/usecase/AddFavoriteTrafficUseCase.java | 2 +- .../traffic/usecase/BrowseFavoriteTrafficsUseCase.java | 2 +- .../traffic/usecase/DeleteFavoriteTrafficUseCase.java | 2 +- .../traffic/usecase/UpdateFavoriteTrafficUseCase.java | 2 +- .../api/service/TrafficCurrentDetailPredictService.java | 2 +- .../api/service/TrafficCyclePredictServiceImpl.java | 4 ++-- .../api/service/path/ExtractPathTrafficInfoService.java | 2 +- .../api/service/path/ReadFavoritesPathService.java | 2 +- .../api/service/path/RouteDetailResponseService.java | 2 +- .../api/service/traffic/ReadTrafficFavoritesService.java | 2 +- .../walking/api/service/traffic/ReadTrafficService.java | 2 +- 16 files changed, 17 insertions(+), 23 deletions(-) delete mode 100644 api-repository/src/main/java/com/walking/api/repository/dao/member/TrafficFavoritesRepository.java diff --git a/api-repository/src/main/java/com/walking/api/repository/dao/member/PathFavoritesRepository.java b/api-repository/src/main/java/com/walking/api/repository/dao/member/PathFavoritesRepository.java index 396606ed..d7bb495c 100644 --- a/api-repository/src/main/java/com/walking/api/repository/dao/member/PathFavoritesRepository.java +++ b/api-repository/src/main/java/com/walking/api/repository/dao/member/PathFavoritesRepository.java @@ -1,6 +1,6 @@ package com.walking.api.repository.dao.member; -import com.walking.data.entity.member.PathFavoritesEntity; +import com.walking.data.entity.path.PathFavoritesEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/api-repository/src/main/java/com/walking/api/repository/dao/member/TrafficFavoritesRepository.java b/api-repository/src/main/java/com/walking/api/repository/dao/member/TrafficFavoritesRepository.java deleted file mode 100644 index 23ed0cbd..00000000 --- a/api-repository/src/main/java/com/walking/api/repository/dao/member/TrafficFavoritesRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.walking.api.repository.dao.member; - -import com.walking.data.entity.member.TrafficFavoritesEntity; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface TrafficFavoritesRepository extends JpaRepository {} diff --git a/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficDetailRepository.java b/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficDetailRepository.java index facf5661..999cbb7c 100644 --- a/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficDetailRepository.java +++ b/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficDetailRepository.java @@ -1,4 +1,4 @@ -package com.walking.api.repository.traffic; +package com.walking.api.repository.dao.traffic; import com.walking.data.entity.traffic.TrafficDetailEntity; import java.util.List; diff --git a/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficFavoritesRepository.java b/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficFavoritesRepository.java index 25a9baec..090952e9 100644 --- a/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficFavoritesRepository.java +++ b/api-repository/src/main/java/com/walking/api/repository/dao/traffic/TrafficFavoritesRepository.java @@ -1,4 +1,4 @@ -package com.walking.api.repository.traffic; +package com.walking.api.repository.dao.traffic; import com.walking.data.entity.member.MemberEntity; import com.walking.data.entity.member.TrafficFavoritesEntity; diff --git a/api/build.gradle b/api/build.gradle index faf7eb3a..e8f9bd29 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -40,6 +40,8 @@ dependencies { implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' implementation group: 'com.google.code.findbugs', name: 'jsr305', version: "${jsr305Version}" + implementation 'org.json:json:20200518' + // security implementation 'org.springframework.boot:spring-boot-starter-security' diff --git a/api/src/main/java/com/walking/api/domain/traffic/usecase/AddFavoriteTrafficUseCase.java b/api/src/main/java/com/walking/api/domain/traffic/usecase/AddFavoriteTrafficUseCase.java index df0024dd..324e314d 100644 --- a/api/src/main/java/com/walking/api/domain/traffic/usecase/AddFavoriteTrafficUseCase.java +++ b/api/src/main/java/com/walking/api/domain/traffic/usecase/AddFavoriteTrafficUseCase.java @@ -1,7 +1,7 @@ package com.walking.api.domain.traffic.usecase; import com.walking.api.domain.traffic.dto.AddFavoriteTrafficUseCaseRequest; -import com.walking.api.repository.traffic.TrafficFavoritesRepository; +import com.walking.api.repository.dao.traffic.TrafficFavoritesRepository; import com.walking.data.entity.member.MemberEntity; import com.walking.data.entity.member.TrafficFavoritesEntity; import com.walking.data.entity.traffic.TrafficEntity; diff --git a/api/src/main/java/com/walking/api/domain/traffic/usecase/BrowseFavoriteTrafficsUseCase.java b/api/src/main/java/com/walking/api/domain/traffic/usecase/BrowseFavoriteTrafficsUseCase.java index f86830f5..38f43d38 100644 --- a/api/src/main/java/com/walking/api/domain/traffic/usecase/BrowseFavoriteTrafficsUseCase.java +++ b/api/src/main/java/com/walking/api/domain/traffic/usecase/BrowseFavoriteTrafficsUseCase.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.walking.api.domain.traffic.dto.BrowseFavoriteTrafficsUseCaseRequest; -import com.walking.api.repository.traffic.TrafficFavoritesRepository; +import com.walking.api.repository.dao.traffic.TrafficFavoritesRepository; import com.walking.api.web.dto.response.BrowseFavoriteTrafficsResponse; import com.walking.api.web.dto.response.detail.FavoriteTrafficDetail; import com.walking.api.web.dto.response.detail.PointDetail; diff --git a/api/src/main/java/com/walking/api/domain/traffic/usecase/DeleteFavoriteTrafficUseCase.java b/api/src/main/java/com/walking/api/domain/traffic/usecase/DeleteFavoriteTrafficUseCase.java index 8caf3dad..171f209f 100644 --- a/api/src/main/java/com/walking/api/domain/traffic/usecase/DeleteFavoriteTrafficUseCase.java +++ b/api/src/main/java/com/walking/api/domain/traffic/usecase/DeleteFavoriteTrafficUseCase.java @@ -1,7 +1,7 @@ package com.walking.api.domain.traffic.usecase; import com.walking.api.domain.traffic.dto.DeleteFavoriteTrafficUseCaseRequest; -import com.walking.api.repository.traffic.TrafficFavoritesRepository; +import com.walking.api.repository.dao.traffic.TrafficFavoritesRepository; import com.walking.data.entity.member.MemberEntity; import com.walking.data.entity.member.TrafficFavoritesEntity; import lombok.RequiredArgsConstructor; diff --git a/api/src/main/java/com/walking/api/domain/traffic/usecase/UpdateFavoriteTrafficUseCase.java b/api/src/main/java/com/walking/api/domain/traffic/usecase/UpdateFavoriteTrafficUseCase.java index ad2e9a98..7189268d 100644 --- a/api/src/main/java/com/walking/api/domain/traffic/usecase/UpdateFavoriteTrafficUseCase.java +++ b/api/src/main/java/com/walking/api/domain/traffic/usecase/UpdateFavoriteTrafficUseCase.java @@ -1,7 +1,7 @@ package com.walking.api.domain.traffic.usecase; import com.walking.api.domain.traffic.dto.UpdateFavoriteTrafficUseCaseRequest; -import com.walking.api.repository.traffic.TrafficFavoritesRepository; +import com.walking.api.repository.dao.traffic.TrafficFavoritesRepository; import com.walking.data.entity.member.TrafficFavoritesEntity; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/api/src/main/java/com/walking/api/service/TrafficCurrentDetailPredictService.java b/api/src/main/java/com/walking/api/service/TrafficCurrentDetailPredictService.java index 0e9bc671..24bbcce8 100644 --- a/api/src/main/java/com/walking/api/service/TrafficCurrentDetailPredictService.java +++ b/api/src/main/java/com/walking/api/service/TrafficCurrentDetailPredictService.java @@ -1,6 +1,6 @@ package com.walking.api.service; -import com.walking.api.repository.traffic.TrafficDetailRepository; +import com.walking.api.repository.dao.traffic.TrafficDetailRepository; import com.walking.api.service.dto.ColorAndTimeLeft; import com.walking.api.service.dto.PredictedData; import com.walking.api.service.dto.request.CurrentDetailRequestDto; diff --git a/api/src/main/java/com/walking/api/service/TrafficCyclePredictServiceImpl.java b/api/src/main/java/com/walking/api/service/TrafficCyclePredictServiceImpl.java index 6941d827..ffbbf3b3 100644 --- a/api/src/main/java/com/walking/api/service/TrafficCyclePredictServiceImpl.java +++ b/api/src/main/java/com/walking/api/service/TrafficCyclePredictServiceImpl.java @@ -1,7 +1,7 @@ package com.walking.api.service; -import com.walking.api.repository.traffic.TrafficDetailRepository; -import com.walking.api.repository.traffic.TrafficRepository; +import com.walking.api.repository.dao.traffic.TrafficDetailRepository; +import com.walking.api.repository.dao.traffic.TrafficRepository; import com.walking.api.service.dto.PredictedData; import com.walking.api.service.dto.request.CyclePredictionRequestDto; import com.walking.api.util.OffsetDateTimeCalculator; diff --git a/api/src/main/java/com/walking/api/service/path/ExtractPathTrafficInfoService.java b/api/src/main/java/com/walking/api/service/path/ExtractPathTrafficInfoService.java index 8b81bfb0..39b8cb9c 100644 --- a/api/src/main/java/com/walking/api/service/path/ExtractPathTrafficInfoService.java +++ b/api/src/main/java/com/walking/api/service/path/ExtractPathTrafficInfoService.java @@ -1,6 +1,6 @@ package com.walking.api.service.path; -import com.walking.api.repository.traffic.TrafficRepository; +import com.walking.api.repository.dao.traffic.TrafficRepository; import com.walking.api.service.dto.PathTrafficData; import com.walking.api.util.JsonParser; import com.walking.data.entity.path.TrafficDirection; diff --git a/api/src/main/java/com/walking/api/service/path/ReadFavoritesPathService.java b/api/src/main/java/com/walking/api/service/path/ReadFavoritesPathService.java index 5f4a9dcf..43ca47c7 100644 --- a/api/src/main/java/com/walking/api/service/path/ReadFavoritesPathService.java +++ b/api/src/main/java/com/walking/api/service/path/ReadFavoritesPathService.java @@ -1,7 +1,7 @@ package com.walking.api.service.path; +import com.walking.api.repository.dao.member.MemberRepository; import com.walking.api.repository.dto.response.PathFavoritesVo; -import com.walking.api.repository.member.MemberRepository; import com.walking.api.repository.path.PathFavoritesRepository; import com.walking.api.service.dto.response.ReadFavoritesPathResponse; import com.walking.api.web.dto.request.OrderFilter; diff --git a/api/src/main/java/com/walking/api/service/path/RouteDetailResponseService.java b/api/src/main/java/com/walking/api/service/path/RouteDetailResponseService.java index 81684ed8..17879227 100644 --- a/api/src/main/java/com/walking/api/service/path/RouteDetailResponseService.java +++ b/api/src/main/java/com/walking/api/service/path/RouteDetailResponseService.java @@ -1,7 +1,7 @@ package com.walking.api.service.path; import com.walking.api.converter.TrafficDetailConverter; -import com.walking.api.repository.traffic.TrafficRepository; +import com.walking.api.repository.dao.traffic.TrafficRepository; import com.walking.api.service.TrafficIntegrationPredictService; import com.walking.api.service.dto.PathPrimaryData; import com.walking.api.service.dto.PathTrafficData; diff --git a/api/src/main/java/com/walking/api/service/traffic/ReadTrafficFavoritesService.java b/api/src/main/java/com/walking/api/service/traffic/ReadTrafficFavoritesService.java index 5ec2b711..4bb1ebea 100644 --- a/api/src/main/java/com/walking/api/service/traffic/ReadTrafficFavoritesService.java +++ b/api/src/main/java/com/walking/api/service/traffic/ReadTrafficFavoritesService.java @@ -1,6 +1,6 @@ package com.walking.api.service.traffic; -import com.walking.api.repository.traffic.TrafficFavoritesRepository; +import com.walking.api.repository.dao.traffic.TrafficFavoritesRepository; import com.walking.data.entity.member.MemberEntity; import com.walking.data.entity.member.TrafficFavoritesEntity; import java.util.List; diff --git a/api/src/main/java/com/walking/api/service/traffic/ReadTrafficService.java b/api/src/main/java/com/walking/api/service/traffic/ReadTrafficService.java index 84fb3df1..f411c06e 100644 --- a/api/src/main/java/com/walking/api/service/traffic/ReadTrafficService.java +++ b/api/src/main/java/com/walking/api/service/traffic/ReadTrafficService.java @@ -1,6 +1,6 @@ package com.walking.api.service.traffic; -import com.walking.api.repository.traffic.TrafficRepository; +import com.walking.api.repository.dao.traffic.TrafficRepository; import com.walking.data.entity.traffic.TrafficEntity; import java.util.List; import lombok.RequiredArgsConstructor;