From dba5be1cf24b6195ad7359a1ce0a9e440feeb53b Mon Sep 17 00:00:00 2001 From: chaerlo127 Date: Fri, 28 Jul 2023 00:11:56 +0900 Subject: [PATCH 1/4] =?UTF-8?q?#15=20feat:=20valid=20dependencies=20?= =?UTF-8?q?=EB=B0=8F=20valid=20ExceptionHandler=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 3 +++ .../psr/psr/global/exception/ExceptionHandler.kt | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 81ca14d..25435de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -50,6 +50,9 @@ dependencies { //log implementation ("io.github.microutils:kotlin-logging:3.0.5") + + // valid + implementation("org.springframework.boot:spring-boot-starter-validation") } allOpen { diff --git a/src/main/kotlin/com/psr/psr/global/exception/ExceptionHandler.kt b/src/main/kotlin/com/psr/psr/global/exception/ExceptionHandler.kt index 3be41fa..cc1a796 100644 --- a/src/main/kotlin/com/psr/psr/global/exception/ExceptionHandler.kt +++ b/src/main/kotlin/com/psr/psr/global/exception/ExceptionHandler.kt @@ -1,9 +1,14 @@ package com.psr.psr.global.exception -import com.psr.psr.global.dto.BaseResponse +import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity +import org.springframework.validation.FieldError +import org.springframework.web.bind.MethodArgumentNotValidException import org.springframework.web.bind.annotation.ExceptionHandler +import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestControllerAdvice +import java.util.* + @RestControllerAdvice class ExceptionHandler { @@ -12,4 +17,12 @@ class ExceptionHandler { return ResponseEntity.status(e.baseResponseCode.status) .body(BaseRes(e.baseResponseCode.status.value(), e.baseResponseCode.message)) } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MethodArgumentNotValidException::class) + protected fun handleMethodArgumentNotValidException(e:MethodArgumentNotValidException): ResponseEntity{ + val fieldError = Objects.requireNonNull(e.fieldError) + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(BaseRes(HttpStatus.BAD_REQUEST.value(), String.format("%s", fieldError?.defaultMessage))) + } } \ No newline at end of file From e1172d78f11463fcf534a09df64cc9a8eefef82a Mon Sep 17 00:00:00 2001 From: chaerlo127 Date: Fri, 28 Jul 2023 00:12:09 +0900 Subject: [PATCH 2/4] =?UTF-8?q?#15=20feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=EC=97=90=20valid=20annotation=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../psr/psr/user/controller/UserController.kt | 4 +-- .../kotlin/com/psr/psr/user/dto/SignUpReq.kt | 27 ++++++++++++++++--- .../com/psr/psr/user/service/UserService.kt | 6 ++--- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com/psr/psr/user/controller/UserController.kt b/src/main/kotlin/com/psr/psr/user/controller/UserController.kt index 220a1be..9f15244 100644 --- a/src/main/kotlin/com/psr/psr/user/controller/UserController.kt +++ b/src/main/kotlin/com/psr/psr/user/controller/UserController.kt @@ -1,10 +1,10 @@ package com.psr.psr.user.controller import com.psr.psr.global.dto.BaseResponse -import com.psr.psr.global.exception.BaseResponseCode import com.psr.psr.global.jwt.dto.TokenRes import com.psr.psr.user.dto.SignUpReq import com.psr.psr.user.service.UserService +import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.* @RestController @@ -17,7 +17,7 @@ class UserController( */ @PostMapping("/signup") @ResponseBody - fun signUp (@RequestBody signUpReq: SignUpReq) : BaseResponse{ + fun signUp (@RequestBody @Validated signUpReq: SignUpReq) : BaseResponse{ return BaseResponse(userService.signUp(signUpReq)) } } \ No newline at end of file diff --git a/src/main/kotlin/com/psr/psr/user/dto/SignUpReq.kt b/src/main/kotlin/com/psr/psr/user/dto/SignUpReq.kt index bcdd8be..5c2818a 100644 --- a/src/main/kotlin/com/psr/psr/user/dto/SignUpReq.kt +++ b/src/main/kotlin/com/psr/psr/user/dto/SignUpReq.kt @@ -1,21 +1,40 @@ package com.psr.psr.user.dto import com.psr.psr.user.entity.* -import java.util.stream.Collector +import jakarta.annotation.Nullable +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotEmpty +import jakarta.validation.constraints.Pattern +import org.jetbrains.annotations.NotNull import java.util.stream.Collectors - - data class SignUpReq ( + @field:NotBlank + @field:Email(message = "올바르지 않은 이메일 형식입니다.") val email: String, + @field:NotBlank + @field:Pattern( + regexp = "^.*(?=^.{8,15}\$)(?=.*\\d)(?=.*[a-zA-Z])(?=.*[!@#\$%^&+=]).*\$", + message = "비밀번호를 숫자, 문자, 특수문자 포함 8~15자리 이내로 입력해주세요" + ) var password: String, + @field:NotBlank val type: String, + @field:Pattern( + regexp = "^01([0|1|6|7|8|9])-?([0-9]{3,4})-?([0-9]{4})\$", + message = "올바르지 않은 휴대폰 형식입니다." + ) val phone: String, - val imgKey: String, + @field:Nullable + val imgKey: String? = null, + @field:NotBlank val nickname: String, val marketing: Boolean, + @field:NotNull val notification: Boolean, + @field:NotEmpty val interestList: List ) { fun toEntity(): User { diff --git a/src/main/kotlin/com/psr/psr/user/service/UserService.kt b/src/main/kotlin/com/psr/psr/user/service/UserService.kt index 503fd9d..304dd8d 100644 --- a/src/main/kotlin/com/psr/psr/user/service/UserService.kt +++ b/src/main/kotlin/com/psr/psr/user/service/UserService.kt @@ -36,11 +36,11 @@ class UserService( @Transactional fun signUp(signUpReq: SignUpReq): TokenRes { // 이메일의 형식이 맞는지 확인 - if(!isValidRegularExpression(signUpReq.email, EMAIL_VALIDATION)) throw BaseException(BaseResponseCode.INVALID_EMAIL) +// if(!isValidRegularExpression(signUpReq.email, EMAIL_VALIDATION)) throw BaseException(BaseResponseCode.INVALID_EMAIL) // 비밀번호의 형식이 맞는지 확인 - if(!isValidRegularExpression(signUpReq.password, PASSWORD_VALIDATION)) throw BaseException(BaseResponseCode.INVALID_PASSWORD) +// if(!isValidRegularExpression(signUpReq.password, PASSWORD_VALIDATION)) throw BaseException(BaseResponseCode.INVALID_PASSWORD) // 휴대폰 번호의 형식이 맞는지 확인 - if(!isValidRegularExpression(signUpReq.phone, PHONE_VALIDATION)) throw BaseException(BaseResponseCode.INVALID_PHONE) +// if(!isValidRegularExpression(signUpReq.phone, PHONE_VALIDATION)) throw BaseException(BaseResponseCode.INVALID_PHONE) // Category가 알맞은 이름을 갖고 있는지, 값이 중복되어있는지 확인 val categoryCheck = signUpReq.interestList.stream().map { i -> i.checkInterestCategory() }.collect(Collectors.toList()).groupingBy { it }.eachCount().any { it.value > 1 } if(categoryCheck) throw BaseException(BaseResponseCode.INVALID_USER_INTEREST_COUNT) From 5ef11d275664fa8d324a98815eb4b315363361ba Mon Sep 17 00:00:00 2001 From: chaerlo127 Date: Fri, 28 Jul 2023 00:14:05 +0900 Subject: [PATCH 3/4] =?UTF-8?q?#15=20chore:=20vaild=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=B4=20?= =?UTF-8?q?=ED=95=84=EC=9A=94=20=EC=97=86=EB=8A=94=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/psr/psr/global/Constant.kt | 13 ++----------- .../psr/psr/global/exception/BaseResponseCode.kt | 3 --- .../kotlin/com/psr/psr/user/service/UserService.kt | 7 ------- 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/main/kotlin/com/psr/psr/global/Constant.kt b/src/main/kotlin/com/psr/psr/global/Constant.kt index 5c6b585..a7bb788 100644 --- a/src/main/kotlin/com/psr/psr/global/Constant.kt +++ b/src/main/kotlin/com/psr/psr/global/Constant.kt @@ -1,20 +1,11 @@ package com.psr.psr.global class Constant { - class JWT{ - companion object JWT{ + class JWT { + companion object JWT { const val AUTHORIZATION_HEADER = "Authorization" const val BEARER_PREFIX: String = "Bearer " } } - class User{ - companion object User{ - // 비밀번호 (숫자, 문자, 특수문자 포함 8~15자리 이내) - const val PASSWORD_VALIDATION = "^.*(?=^.{8,15}\$)(?=.*\\d)(?=.*[a-zA-Z])(?=.*[!@#\$%^&+=]).*\$" - const val EMAIL_VALIDATION = "^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}\$" - const val PHONE_VALIDATION = "^01([0|1|6|7|8|9])-?([0-9]{3,4})-?([0-9]{4})\$" - } - } - } \ No newline at end of file diff --git a/src/main/kotlin/com/psr/psr/global/exception/BaseResponseCode.kt b/src/main/kotlin/com/psr/psr/global/exception/BaseResponseCode.kt index e13b99a..6f74a53 100644 --- a/src/main/kotlin/com/psr/psr/global/exception/BaseResponseCode.kt +++ b/src/main/kotlin/com/psr/psr/global/exception/BaseResponseCode.kt @@ -13,9 +13,6 @@ enum class BaseResponseCode(status: HttpStatus, message: String) { EXPIRED_TOKEN(HttpStatus.FORBIDDEN, "만료된 토큰 값입니다."), // user - INVALID_EMAIL(HttpStatus.BAD_REQUEST, "올바르지 않은 이메일 형식입니다."), - INVALID_PASSWORD(HttpStatus.BAD_REQUEST, "올바르지 않은 비밀번호 형식입니다."), - INVALID_PHONE(HttpStatus.BAD_REQUEST, "올바르지 않은 휴대폰 형식입니다."), EXISTS_PHONE(HttpStatus.BAD_REQUEST, "이미 가입되어 있는 휴대폰 번호입니다."), EXISTS_EMAIL(HttpStatus.BAD_REQUEST, "이미 가입되어 있는 이메일입니다."), EXISTS_NICKNAME(HttpStatus.BAD_REQUEST, "이미 가입되어 있는 닉네임입니다."), diff --git a/src/main/kotlin/com/psr/psr/user/service/UserService.kt b/src/main/kotlin/com/psr/psr/user/service/UserService.kt index 304dd8d..deabdf1 100644 --- a/src/main/kotlin/com/psr/psr/user/service/UserService.kt +++ b/src/main/kotlin/com/psr/psr/user/service/UserService.kt @@ -35,13 +35,6 @@ class UserService( // 회원가입 @Transactional fun signUp(signUpReq: SignUpReq): TokenRes { - // 이메일의 형식이 맞는지 확인 -// if(!isValidRegularExpression(signUpReq.email, EMAIL_VALIDATION)) throw BaseException(BaseResponseCode.INVALID_EMAIL) - // 비밀번호의 형식이 맞는지 확인 -// if(!isValidRegularExpression(signUpReq.password, PASSWORD_VALIDATION)) throw BaseException(BaseResponseCode.INVALID_PASSWORD) - // 휴대폰 번호의 형식이 맞는지 확인 -// if(!isValidRegularExpression(signUpReq.phone, PHONE_VALIDATION)) throw BaseException(BaseResponseCode.INVALID_PHONE) - // Category가 알맞은 이름을 갖고 있는지, 값이 중복되어있는지 확인 val categoryCheck = signUpReq.interestList.stream().map { i -> i.checkInterestCategory() }.collect(Collectors.toList()).groupingBy { it }.eachCount().any { it.value > 1 } if(categoryCheck) throw BaseException(BaseResponseCode.INVALID_USER_INTEREST_COUNT) // category 의 사이즈 확인 From 3c9708e501cd6454d7bc5df20b9ee738f9f3be82 Mon Sep 17 00:00:00 2001 From: chaerlo127 Date: Fri, 28 Jul 2023 00:20:52 +0900 Subject: [PATCH 4/4] =?UTF-8?q?#15=20fix:=20constant=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20import=20?= =?UTF-8?q?=EC=A7=80=EC=9B=8C=EC=A7=80=EC=A7=80=20=EC=95=8A=EC=9D=80=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/psr/psr/user/service/UserService.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/kotlin/com/psr/psr/user/service/UserService.kt b/src/main/kotlin/com/psr/psr/user/service/UserService.kt index deabdf1..00bf390 100644 --- a/src/main/kotlin/com/psr/psr/user/service/UserService.kt +++ b/src/main/kotlin/com/psr/psr/user/service/UserService.kt @@ -1,17 +1,11 @@ package com.psr.psr.user.service -import com.fasterxml.jackson.databind.ser.Serializers.Base -import com.psr.psr.global.Constant.User.User.EMAIL_VALIDATION -import com.psr.psr.global.Constant.User.User.PASSWORD_VALIDATION -import com.psr.psr.global.Constant.User.User.PHONE_VALIDATION import com.psr.psr.global.exception.BaseException import com.psr.psr.global.exception.BaseResponseCode import com.psr.psr.global.jwt.dto.TokenRes import com.psr.psr.global.jwt.utils.JwtUtils import com.psr.psr.user.dto.SignUpReq -import com.psr.psr.user.entity.Category import com.psr.psr.user.entity.User -import com.psr.psr.user.entity.UserInterest import com.psr.psr.user.repository.UserInterestRepository import com.psr.psr.user.repository.UserRepository import org.springframework.security.authentication.UsernamePasswordAuthenticationToken