From 88a81532b2c4f11f51d992b1280558ce7fa2240d Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:20:48 +0900 Subject: [PATCH 01/10] chore: feign dependency added and config yaml file modified for feign client --- build.gradle.kts | 15 ++++++++++++--- src/main/resources/application.yaml | 11 ++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a23ee62..504c883 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { val kotlinVersion = "1.5.20" - id("org.springframework.boot") version "2.5.2" + id("org.springframework.boot") version "2.5.3" id("io.spring.dependency-management") version "1.0.11.RELEASE" kotlin("jvm") version kotlinVersion kotlin("plugin.spring") version kotlinVersion @@ -37,9 +37,14 @@ repositories { mavenCentral() } +extra["springCloudVersion"] = "2020.0.3" + dependencies { annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") + implementation("org.springframework.cloud:spring-cloud-starter-openfeign") + implementation("io.github.openfeign:feign-okhttp") + implementation("io.github.openfeign:feign-jackson:9.3.1") implementation("org.springframework.boot:spring-boot-starter-webflux") implementation("io.projectreactor.kotlin:reactor-kotlin-extensions") @@ -65,8 +70,6 @@ dependencies { testAnnotationProcessor ("com.querydsl:querydsl-apt:$querydslVersion:jpa") runtimeOnly("mysql:mysql-connector-java") -// runtimeOnly("org.mariadb.jdbc:mariadb-java-client") -// implementation("com.zaxxer:HikariCP:5.0.0") compileOnly("org.projectlombok:lombok") annotationProcessor("org.projectlombok:lombok") @@ -86,6 +89,12 @@ dependencies { runtimeOnly(group= "io.jsonwebtoken", name= "jjwt-jackson", version= "0.11.2") } +dependencyManagement { + imports { + mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}") + } +} + val generatedSourcesDir = file("${buildDir}/generated/querydsl") configurations { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 83d824e..fba5072 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -4,4 +4,13 @@ spring: springdoc: swagger-ui: - path: /doc \ No newline at end of file + path: /doc + +feign: + compression: + request: + enabled: true + response: + enabled: true + okhttp: + enabled: true \ No newline at end of file From bc30cb9c07f48dcc6b05d800092822e46b2dc0b1 Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:28:30 +0900 Subject: [PATCH 02/10] =?UTF-8?q?chore:=20=EC=93=B8=EB=95=8C=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F?= =?UTF-8?q?=20=EB=B6=88=20=ED=95=84=EC=9A=94=ED=95=9C=20=EB=B8=8C=EB=9D=BC?= =?UTF-8?q?=EC=BC=93=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attendanceapimono/application/dto/user/UserTemp.kt | 4 ---- .../example/attendanceapimono/domain/user/UserRepository.kt | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 src/main/kotlin/com/example/attendanceapimono/application/dto/user/UserTemp.kt diff --git a/src/main/kotlin/com/example/attendanceapimono/application/dto/user/UserTemp.kt b/src/main/kotlin/com/example/attendanceapimono/application/dto/user/UserTemp.kt deleted file mode 100644 index 3839e55..0000000 --- a/src/main/kotlin/com/example/attendanceapimono/application/dto/user/UserTemp.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.example.attendanceapimono.application.dto.user - -class UserTemp { -} \ No newline at end of file diff --git a/src/main/kotlin/com/example/attendanceapimono/domain/user/UserRepository.kt b/src/main/kotlin/com/example/attendanceapimono/domain/user/UserRepository.kt index 417ff96..b4a6b0f 100644 --- a/src/main/kotlin/com/example/attendanceapimono/domain/user/UserRepository.kt +++ b/src/main/kotlin/com/example/attendanceapimono/domain/user/UserRepository.kt @@ -5,5 +5,4 @@ import org.springframework.stereotype.Repository import java.util.* @Repository -interface UserRepository : JpaRepository { -} \ No newline at end of file +interface UserRepository : JpaRepository \ No newline at end of file From 55b65acfc982056280874183fd68149b6be56654 Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:29:54 +0900 Subject: [PATCH 03/10] feat(feign-setup): feign client enabled, feign config defined --- .../AttendanceApiMonoApplication.kt | 4 ++ .../infra/config/FeignDefaultConfig.kt | 55 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/main/kotlin/com/example/attendanceapimono/adapter/infra/config/FeignDefaultConfig.kt diff --git a/src/main/kotlin/com/example/attendanceapimono/AttendanceApiMonoApplication.kt b/src/main/kotlin/com/example/attendanceapimono/AttendanceApiMonoApplication.kt index c6a48b1..dd7178c 100644 --- a/src/main/kotlin/com/example/attendanceapimono/AttendanceApiMonoApplication.kt +++ b/src/main/kotlin/com/example/attendanceapimono/AttendanceApiMonoApplication.kt @@ -1,8 +1,12 @@ package com.example.attendanceapimono import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer import org.springframework.boot.runApplication +import org.springframework.cloud.openfeign.EnableFeignClients +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder +@EnableFeignClients @SpringBootApplication class AttendanceApiMonoApplication diff --git a/src/main/kotlin/com/example/attendanceapimono/adapter/infra/config/FeignDefaultConfig.kt b/src/main/kotlin/com/example/attendanceapimono/adapter/infra/config/FeignDefaultConfig.kt new file mode 100644 index 0000000..3333991 --- /dev/null +++ b/src/main/kotlin/com/example/attendanceapimono/adapter/infra/config/FeignDefaultConfig.kt @@ -0,0 +1,55 @@ +package com.example.attendanceapimono.adapter.infra.config + +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import feign.* +import feign.codec.Decoder +import feign.codec.Encoder +import feign.codec.ErrorDecoder +import feign.jackson.JacksonDecoder +import feign.jackson.JacksonEncoder +import org.springframework.cloud.openfeign.FeignFormatterRegistrar +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.format.FormatterRegistry +import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar +import org.springframework.http.HttpStatus +import java.util.* + + +@Configuration +class FeignDefaultConfig { + + @Bean + fun decoder(): Decoder { + return JacksonDecoder(jacksonObjectMapper()) + } + + @Bean + fun encoder(): Encoder { + return JacksonEncoder(jacksonObjectMapper()) + } + + @Bean + fun feignLoggerLevel(): Logger.Level { + return Logger.Level.FULL + } + + @Bean + fun retryer() = Retryer.Default() + + @Bean + fun localDateFeignFormatterRegister(): FeignFormatterRegistrar? { + return FeignFormatterRegistrar { registry: FormatterRegistry -> + val registrar = DateTimeFormatterRegistrar() + registrar.setUseIsoFormat(true) + registrar.registerFormatters(registry) + } + } + +// @Bean +// fun decoder(): ErrorDecoder { todo implements +// return ErrorDecoder { methodKey, response -> +// +// } +// } +} \ No newline at end of file From b0e92b9f4b5f86a883fccc1299af7eb5ef44118d Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:31:57 +0900 Subject: [PATCH 04/10] feat(domain/social-provider): social provider repository, adapter, social info interface defined --- .../attendanceapimono/domain/user/SocialAdapter.kt | 5 +++++ .../example/attendanceapimono/domain/user/SocialInfo.kt | 8 ++++++++ .../domain/user/SocialProviderRepository.kt | 7 +++++++ 3 files changed, 20 insertions(+) create mode 100644 src/main/kotlin/com/example/attendanceapimono/domain/user/SocialAdapter.kt create mode 100644 src/main/kotlin/com/example/attendanceapimono/domain/user/SocialInfo.kt create mode 100644 src/main/kotlin/com/example/attendanceapimono/domain/user/SocialProviderRepository.kt diff --git a/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialAdapter.kt b/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialAdapter.kt new file mode 100644 index 0000000..6a3b88e --- /dev/null +++ b/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialAdapter.kt @@ -0,0 +1,5 @@ +package com.example.attendanceapimono.domain.user + +interface SocialAdapter { + fun findByToken(token: String): SocialInfo +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialInfo.kt b/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialInfo.kt new file mode 100644 index 0000000..e5ae60a --- /dev/null +++ b/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialInfo.kt @@ -0,0 +1,8 @@ +package com.example.attendanceapimono.domain.user + +interface SocialInfo { + val id: String + val type: SocialType + val email: String + val thumb: String? +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialProviderRepository.kt b/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialProviderRepository.kt new file mode 100644 index 0000000..b6c3488 --- /dev/null +++ b/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialProviderRepository.kt @@ -0,0 +1,7 @@ +package com.example.attendanceapimono.domain.user + +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface SocialProviderRepository : JpaRepository \ No newline at end of file From ec4f338004de2ae66ab1ffa91cb70de658876a54 Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:34:48 +0900 Subject: [PATCH 05/10] feat(infra/feign-social-provider): implements social adapter(google) / info data class / define feign client interface, google get token info api --- .../adapter/infra/feign/GoogleAuthClient.kt | 11 ++++++ .../infra/feign/GoogleSocialAdapterImpl.kt | 35 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/main/kotlin/com/example/attendanceapimono/adapter/infra/feign/GoogleAuthClient.kt create mode 100644 src/main/kotlin/com/example/attendanceapimono/adapter/infra/feign/GoogleSocialAdapterImpl.kt diff --git a/src/main/kotlin/com/example/attendanceapimono/adapter/infra/feign/GoogleAuthClient.kt b/src/main/kotlin/com/example/attendanceapimono/adapter/infra/feign/GoogleAuthClient.kt new file mode 100644 index 0000000..35a4e9d --- /dev/null +++ b/src/main/kotlin/com/example/attendanceapimono/adapter/infra/feign/GoogleAuthClient.kt @@ -0,0 +1,11 @@ +package com.example.attendanceapimono.adapter.infra.feign + +import org.springframework.cloud.openfeign.FeignClient +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestParam + +@FeignClient(value = "googleAuth", url = "https://www.googleapis.com") +interface GoogleAuthClient { + @GetMapping("/oauth2/v3/tokeninfo") + fun getByToken(@RequestParam("id_token") idToken: String): GoogleSocialInfo +} diff --git a/src/main/kotlin/com/example/attendanceapimono/adapter/infra/feign/GoogleSocialAdapterImpl.kt b/src/main/kotlin/com/example/attendanceapimono/adapter/infra/feign/GoogleSocialAdapterImpl.kt new file mode 100644 index 0000000..67fd65f --- /dev/null +++ b/src/main/kotlin/com/example/attendanceapimono/adapter/infra/feign/GoogleSocialAdapterImpl.kt @@ -0,0 +1,35 @@ +package com.example.attendanceapimono.adapter.infra.feign + +import com.example.attendanceapimono.domain.user.SocialAdapter +import com.example.attendanceapimono.domain.user.SocialInfo +import com.example.attendanceapimono.domain.user.SocialType +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import feign.QueryMap +import feign.RequestLine +import kotlinx.coroutines.flow.Flow +import org.springframework.cloud.openfeign.FeignClient +import org.springframework.http.ResponseEntity +import org.springframework.stereotype.Component +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestHeader +import javax.inject.Qualifier + + +@JsonIgnoreProperties(ignoreUnknown = true) +data class GoogleSocialInfo( + val sub: String, + override val email: String, + val picture: String, +) : SocialInfo { + override val id: String get() = this.sub + override val type: SocialType get() = SocialType.GOOGLE + override val thumb: String get() = this.picture +} + +@Component("googleAdapter") +class GoogleSocialAdapterImpl(private val auth: GoogleAuthClient) : SocialAdapter { + override fun findByToken(token: String): SocialInfo { + return auth.getByToken(token) + } +} \ No newline at end of file From a4d2cf8b45ca336deeca24bf37d88bebd6152a25 Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:36:13 +0900 Subject: [PATCH 06/10] feat(app/exceptions): validation exception webflux mono handler extension function added --- .../exception/BadRequestBodyException.kt | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/example/attendanceapimono/application/exception/BadRequestBodyException.kt b/src/main/kotlin/com/example/attendanceapimono/application/exception/BadRequestBodyException.kt index d794995..8d8b8e1 100644 --- a/src/main/kotlin/com/example/attendanceapimono/application/exception/BadRequestBodyException.kt +++ b/src/main/kotlin/com/example/attendanceapimono/application/exception/BadRequestBodyException.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import org.springframework.web.bind.support.WebExchangeBindException import org.springframework.web.server.ServerWebInputException +import reactor.core.publisher.Mono import java.lang.RuntimeException class BadRequestBodyException : RuntimeException { @@ -15,11 +16,17 @@ class BadRequestBodyException : RuntimeException { } fun Flow.handleValidationCatch(): Flow { - return catch { - when (it) { - is WebExchangeBindException->throw BadRequestBodyException(it) - is ServerWebInputException->throw BadRequestBodyException(it) - else->throw it - } + return catch { handle(it) } +} + +fun Mono.handleValidationCatch(): Mono { + return doOnError(::handle) +} + +private fun handle(it: Throwable) { + when (it) { + is WebExchangeBindException->throw BadRequestBodyException(it) + is ServerWebInputException->throw BadRequestBodyException(it) + else->throw it } } \ No newline at end of file From e7bce737f714922c926466f9f469bf5f87c54ce0 Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:36:43 +0900 Subject: [PATCH 07/10] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=9E=84=ED=8F=AC=ED=8A=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/present/HelloWorldController.kt | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/main/kotlin/com/example/attendanceapimono/adapter/present/HelloWorldController.kt b/src/main/kotlin/com/example/attendanceapimono/adapter/present/HelloWorldController.kt index 2d55768..469850b 100644 --- a/src/main/kotlin/com/example/attendanceapimono/adapter/present/HelloWorldController.kt +++ b/src/main/kotlin/com/example/attendanceapimono/adapter/present/HelloWorldController.kt @@ -1,26 +1,12 @@ package com.example.attendanceapimono.adapter.present import com.example.attendanceapimono.adapter.present.api.HelloWorldAPI -import com.example.attendanceapimono.application.exception.KotlinTestException -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.media.Content -import io.swagger.v3.oas.annotations.media.ExampleObject -import io.swagger.v3.oas.annotations.media.Schema -import io.swagger.v3.oas.annotations.responses.ApiResponse -import io.swagger.v3.oas.annotations.tags.Tag -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.reactive.asFlow import org.springframework.http.MediaType import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RestController -import reactor.core.publisher.Mono -import reactor.kotlin.core.publisher.toMono @RestController class HelloWorldController : HelloWorldAPI { - - override suspend fun helloWorld() = ResponseEntity.ok() .contentType(MediaType.APPLICATION_JSON) .body("\"hello ddd attendance api mono world\"") From 0099349141bb00c182a3d9ac961fc83abf79f98b Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:37:52 +0900 Subject: [PATCH 08/10] feat(google-signup): bind controller --- .../adapter/present/UserController.kt | 26 +++++++ .../adapter/present/api/UserAPI.kt | 35 ++++++++++ .../application/dto/user/CreateUser.kt | 68 +++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 src/main/kotlin/com/example/attendanceapimono/adapter/present/UserController.kt create mode 100644 src/main/kotlin/com/example/attendanceapimono/application/dto/user/CreateUser.kt diff --git a/src/main/kotlin/com/example/attendanceapimono/adapter/present/UserController.kt b/src/main/kotlin/com/example/attendanceapimono/adapter/present/UserController.kt new file mode 100644 index 0000000..7e95d3a --- /dev/null +++ b/src/main/kotlin/com/example/attendanceapimono/adapter/present/UserController.kt @@ -0,0 +1,26 @@ +package com.example.attendanceapimono.adapter.present + +import com.example.attendanceapimono.adapter.present.api.UserAPI +import com.example.attendanceapimono.application.UserService +import com.example.attendanceapimono.application.dto.user.CreateUser +import com.example.attendanceapimono.application.exception.handleValidationCatch +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.single +import kotlinx.coroutines.reactor.awaitSingle +import org.springframework.web.bind.annotation.RestController +import reactor.core.publisher.Mono + +@RestController +class UserController(private val userService: UserService) : UserAPI { + override suspend fun createUser(body: Mono) { + body.handleValidationCatch() + .map(userService::createUser) + .awaitSingle() + } +} + +/* + [{"error_description": "Invalid Value"}] +* */ \ No newline at end of file diff --git a/src/main/kotlin/com/example/attendanceapimono/adapter/present/api/UserAPI.kt b/src/main/kotlin/com/example/attendanceapimono/adapter/present/api/UserAPI.kt index 80a72dd..a95012f 100644 --- a/src/main/kotlin/com/example/attendanceapimono/adapter/present/api/UserAPI.kt +++ b/src/main/kotlin/com/example/attendanceapimono/adapter/present/api/UserAPI.kt @@ -1,4 +1,39 @@ package com.example.attendanceapimono.adapter.present.api +import com.example.attendanceapimono.application.dto.user.CreateUser +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.media.Content +import io.swagger.v3.oas.annotations.media.ExampleObject +import io.swagger.v3.oas.annotations.media.Schema +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.ResponseStatus +import reactor.core.publisher.Mono +import javax.validation.Valid +import io.swagger.v3.oas.annotations.parameters.RequestBody as DocRequestBody + +@Tag(name = "유저 관련 API") interface UserAPI { + + @Operation( + summary = "유저 생성", + requestBody = DocRequestBody(content = [ + Content( + mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = Schema(implementation = CreateUser::class), + ) + ]) + ) + @ApiResponse( + responseCode = "201", + description = "일반 참가자 생성", + content = [Content(examples = [ExampleObject("")])], + ) + @ResponseStatus(HttpStatus.CREATED) + @PostMapping("/user") + suspend fun createUser(@Valid @RequestBody body: Mono) } \ No newline at end of file diff --git a/src/main/kotlin/com/example/attendanceapimono/application/dto/user/CreateUser.kt b/src/main/kotlin/com/example/attendanceapimono/application/dto/user/CreateUser.kt new file mode 100644 index 0000000..138cd2c --- /dev/null +++ b/src/main/kotlin/com/example/attendanceapimono/application/dto/user/CreateUser.kt @@ -0,0 +1,68 @@ +package com.example.attendanceapimono.application.dto.user + +import com.example.attendanceapimono.domain.user.* +import io.swagger.v3.oas.annotations.media.Schema +import lombok.extern.slf4j.Slf4j +import org.hibernate.validator.constraints.Length +import java.time.LocalDateTime +import java.util.* +import javax.persistence.Column +import javax.persistence.EnumType +import javax.persistence.Enumerated +import javax.validation.constraints.Email +import javax.validation.constraints.NotEmpty + +@Schema( + title = "회원가입", + description = "", + example = CreateUser.Example, +) +data class CreateUser( + @Schema(description = "소셜 토큰") + @field:NotEmpty + val token: String, + + @Schema(description = "소설 타입") + val type: SocialType, + + @Schema(description = "이메일 주소") + @field:Email + val email: String, + + @Schema(description = "이름(성)") + @field:Length(min = 1, max = 20) + val lastName: String, + + @Schema(description = "이름") + @field:Length(min = 1, max = 20) + val firstName: String, + + @Schema(description = "직군 포지션") + val position: UserPosition, +) { + fun entity() = User( + id = UUID.randomUUID(), + state = UserState.NORMAL, + role = UserRole.MEMBER, + position = this.position, + generationID = 6, // TODO 별도의 제네레이션 테이블로 처리 하는게 좋을 듯함 + firstName = this.firstName, + lastName = this.lastName, + email = this.email, + createdAt = LocalDateTime.now(), + updatedAt = LocalDateTime.now(), + ) + + companion object { + const val Example = """ + { + "token": "social_token", + "type": "GOOGLE", + "email": "dddstudy1@gmail.com", + "lastName": "이", + "firstName": "재성", + "position": "BACKEND" + } + """ + } +} \ No newline at end of file From 09db9dc0521fe11e03422c4a33cdf7bad48fde4a Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:39:46 +0900 Subject: [PATCH 09/10] feat(user-service): create user with google --- .../application/UserService.kt | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/example/attendanceapimono/application/UserService.kt b/src/main/kotlin/com/example/attendanceapimono/application/UserService.kt index 60a991a..a2681d5 100644 --- a/src/main/kotlin/com/example/attendanceapimono/application/UserService.kt +++ b/src/main/kotlin/com/example/attendanceapimono/application/UserService.kt @@ -1,8 +1,46 @@ package com.example.attendanceapimono.application -import com.example.attendanceapimono.domain.user.UserRepository +import com.example.attendanceapimono.application.dto.user.CreateUser +import com.example.attendanceapimono.domain.user.* +import kotlinx.coroutines.* +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + @Service -class UserService(private val userRepository: UserRepository) { +class UserService( + private val userRepository: UserRepository, + private val socialProviderRepository: SocialProviderRepository, + @Qualifier("googleAdapter") + private val googleAdapter: SocialAdapter +) { + + @Transactional + fun createUser(dto: CreateUser): Unit = runBlocking { + val user = dto.entity() + listOf( + async { userRepository.save(user) }, + async { + val socialInfo = when (dto.type) { + SocialType.GOOGLE->googleAdapter.findByToken(dto.token) + SocialType.APPLE->TODO("not implemented, throw exception") + } + val socialID = SocialProviderID(socialInfo.id, socialInfo.type) + socialProviderRepository + .findByIdOrNull( + socialID + )?.run { + TODO("conflict, exists social provider, throw exception") + } + socialProviderRepository.save( + SocialProvider( + socialID, + user + ) + ) + } + ).awaitAll() + } } \ No newline at end of file From 91c662c26564488a498d8573c64d516ebde560f3 Mon Sep 17 00:00:00 2001 From: Lee Jaeseong Date: Thu, 29 Jul 2021 00:51:18 +0900 Subject: [PATCH 10/10] fix(social-provider): idclass -> embeddedId, because if use idClass will add to some two more columns. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 문법 몰라으ㅏㅇ그에그덱ㄷ게ㅡㄴㅇㅁ라 영어 잘하고싶습니다 영어 과외 해주실분 구해요 영어 스터디 구해요 연락주십셔 --- .../domain/user/SocialProvider.kt | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialProvider.kt b/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialProvider.kt index be4446f..ed846a0 100644 --- a/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialProvider.kt +++ b/src/main/kotlin/com/example/attendanceapimono/domain/user/SocialProvider.kt @@ -4,22 +4,14 @@ import java.io.Serializable import javax.persistence.* enum class SocialType { - GOOGLE + GOOGLE, APPLE } @Entity @Table(name = "social_providers") -@IdClass(SocialProviderID::class) class SocialProvider( - - @Id - @Column(length = 30, nullable = false) - val id: String, - - @Id - @Enumerated(EnumType.STRING) - @Column(length = 10, nullable = false) - val type: SocialType, + @EmbeddedId + val id: SocialProviderID, @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) // user.id @@ -27,7 +19,12 @@ class SocialProvider( ) -data class SocialProviderID( +@Embeddable +class SocialProviderID( + @Column(name = "id", length = 30, nullable = false) val id: String, + + @Enumerated(EnumType.STRING) + @Column(name = "type", length = 10, nullable = false) val type: SocialType, -) : Serializable +) : Serializable \ No newline at end of file