From eea9eef99135ea6bc49151e6b62656304ef0ab08 Mon Sep 17 00:00:00 2001 From: Donghyeon Lee Date: Fri, 20 Sep 2024 09:53:15 +0900 Subject: [PATCH] Feat: Member API Dto validate (#47) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: member api req validation * fix: 위경도 유효성검사 추가 --- .../presentation/api/AddressController.kt | 3 +- .../presentation/api/MemberInfoController.kt | 3 +- .../presentation/api/MemberLoginController.kt | 3 +- .../member/presentation/dto/AddressRequest.kt | 25 +++++++++--- .../member/presentation/dto/LoginRequest.kt | 7 ++-- .../member/presentation/dto/MemberRequest.kt | 38 +++++++++++++++---- 6 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/AddressController.kt b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/AddressController.kt index f6eb1ac..ba36dc0 100644 --- a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/AddressController.kt +++ b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/AddressController.kt @@ -1,5 +1,6 @@ package org.inner.circle.o2oserver.member.presentation.api +import jakarta.validation.Valid import org.inner.circle.o2oserver.commons.response.BaseResponse import org.inner.circle.o2oserver.member.application.MemberInfoFacade import org.inner.circle.o2oserver.member.presentation.dto.AddressIdResponse @@ -50,7 +51,7 @@ class AddressController( @PostMapping override fun createAddress( - @RequestBody createRequest: AddressRequest.CreateAddress, + @RequestBody @Valid createRequest: AddressRequest.CreateAddress, @AuthenticationPrincipal userDetails: UserDetails, ): BaseResponse { val memberId = userDetails.username diff --git a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/MemberInfoController.kt b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/MemberInfoController.kt index f918206..09f811e 100644 --- a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/MemberInfoController.kt +++ b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/MemberInfoController.kt @@ -1,5 +1,6 @@ package org.inner.circle.o2oserver.member.presentation.api +import jakarta.validation.Valid import org.inner.circle.o2oserver.commons.response.BaseResponse import org.inner.circle.o2oserver.member.application.MemberInfoFacade import org.inner.circle.o2oserver.member.presentation.dto.MemberIdResponse @@ -40,7 +41,7 @@ class MemberInfoController( @PostMapping override fun createMemberInfo( - @RequestBody createRequest: MemberRequest.MemberInfo, + @RequestBody @Valid createRequest: MemberRequest.MemberInfo, @AuthenticationPrincipal userDetails: UserDetails, ): BaseResponse { val memberId = userDetails.username diff --git a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/MemberLoginController.kt b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/MemberLoginController.kt index b58b175..e84c88c 100644 --- a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/MemberLoginController.kt +++ b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/api/MemberLoginController.kt @@ -1,5 +1,6 @@ package org.inner.circle.o2oserver.member.presentation.api +import jakarta.validation.Valid import org.inner.circle.o2oserver.member.application.LoginFacade import org.inner.circle.o2oserver.member.presentation.dto.LoginRequest import org.inner.circle.o2oserver.member.presentation.dto.LoginResponse @@ -22,7 +23,7 @@ class MemberLoginController( @PostMapping override fun loginMember( - @RequestBody loginRequest: LoginRequest.Login, + @RequestBody @Valid loginRequest: LoginRequest.Login, ): ResponseEntity { log.info("login 요청") val member = LoginRequest.Login.toMember(loginRequest) diff --git a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/AddressRequest.kt b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/AddressRequest.kt index b0d644d..4bc91a9 100644 --- a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/AddressRequest.kt +++ b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/AddressRequest.kt @@ -1,14 +1,29 @@ package org.inner.circle.o2oserver.member.presentation.dto +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Pattern import org.inner.circle.o2oserver.member.domain.Address class AddressRequest { data class CreateAddress( - val address: String, - val addressDetail: String, - val latitude: Double, - val longitude: Double, - val zipCode: String, + @field:NotBlank(message = "Address cannot be blank") val address: String, + @field:NotBlank(message = "Address detail cannot be blank") val addressDetail: String, + @field:DecimalMin( + value = "33.0", + inclusive = true, + message = "Latitude must be at least 33.0", + ) @field:DecimalMax(value = "39.0", inclusive = true, message = "Latitude must be at most 39.0") val latitude: Double, + @field:DecimalMin( + value = "124.0", + inclusive = true, + message = "Longitude must be at least 124.0", + ) @field:DecimalMax(value = "132.0", inclusive = true, message = "Longitude must be at most 132.0") val longitude: Double, + @field:NotBlank(message = "Zip code cannot be blank") @field:Pattern( + regexp = "\\d{5}(?:-\\d{4})?", + message = "ZipCode must be a valid format (e.g., 12345 or 12345-6789)", + ) val zipCode: String, ) { companion object { fun toAddress(createAddress: CreateAddress, memberId: String): Address { diff --git a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/LoginRequest.kt b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/LoginRequest.kt index b91b5ff..d7610c8 100644 --- a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/LoginRequest.kt +++ b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/LoginRequest.kt @@ -1,12 +1,13 @@ package org.inner.circle.o2oserver.member.presentation.dto +import jakarta.validation.constraints.NotBlank import org.inner.circle.o2oserver.member.domain.Member class LoginRequest { data class Login( - val snsType: String, - val subId: String, - val name: String, + @field:NotBlank(message = "SNS type cannot be blank") val snsType: String, + @field:NotBlank(message = "Sub ID cannot be blank") val subId: String, + @field:NotBlank(message = "Name cannot be blank") val name: String, ) { companion object { fun toMember(login: Login): Member { diff --git a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/MemberRequest.kt b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/MemberRequest.kt index 14e8db1..a31174f 100644 --- a/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/MemberRequest.kt +++ b/src/main/kotlin/org/inner/circle/o2oserver/member/presentation/dto/MemberRequest.kt @@ -1,10 +1,23 @@ package org.inner.circle.o2oserver.member.presentation.dto +import jakarta.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern import org.inner.circle.o2oserver.member.domain.Address import org.inner.circle.o2oserver.member.domain.MemberDetail class MemberRequest { - data class MemberInfo(val nickName: String, val contact: String, val address: AddressRequest) { + data class MemberInfo( + @field:NotBlank(message = "NickName cannot be blank") val nickName: String, + @field:NotBlank(message = "Contact cannot be blank") @field:Pattern( + regexp = "\\d{2,3}-?\\d{3,4}-?\\d{4}", + message = "Contact must be a valid format (e.g., 01012345678, 010-123-4567, 011-2345-6789)", + ) val contact: String, + @field:NotNull(message = "Address cannot be null") @field:Valid val address: AddressRequest, + ) { companion object { fun toMemberDetail(memberInfo: MemberInfo, memberId: String): MemberDetail { return MemberDetail( @@ -20,7 +33,7 @@ class MemberRequest { address = memberInfo.address.address, addressDetail = memberInfo.address.addressDetail, latitude = memberInfo.address.latitude, - longitude = memberInfo.address.longitude, + longitude = memberInfo.address.longitude!!, zipCode = memberInfo.address.zipCode, isDefault = true, // 기본 주소로 설정 ) @@ -28,11 +41,22 @@ class MemberRequest { } data class AddressRequest( - val address: String, - val addressDetail: String, - val latitude: Double, - val longitude: Double, - val zipCode: String, + @field:NotBlank(message = "Address cannot be blank") val address: String, + @field:NotBlank(message = "Address detail cannot be blank") val addressDetail: String, + @field:DecimalMin( + value = "33.0", + inclusive = true, + message = "Latitude must be at least 33.0", + ) @field:DecimalMax(value = "39.0", inclusive = true, message = "Latitude must be at most 39.0") val latitude: Double, + @field:DecimalMin( + value = "124.0", + inclusive = true, + message = "Longitude must be at least 124.0", + ) @field:DecimalMax(value = "132.0", inclusive = true, message = "Longitude must be at most 132.0") val longitude: Double, + @field:NotBlank(message = "Zip code cannot be blank") @field:Pattern( + regexp = "\\d{5}(?:-\\d{4})?", + message = "ZipCode must be a valid format (e.g., 12345 or 12345-6789)", + ) val zipCode: String, ) } }