Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 이메일 찾기 + 비밀번호 변경을 위한 인증 화면 #104

Merged
merged 3 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class WebSecurityConfig(
c.requestMatchers("/users/reissue").permitAll()
c.requestMatchers("/users/password-reset").permitAll()
c.requestMatchers("/users/phone/*").permitAll()
c.requestMatchers("/users/email/search").permitAll()
c.requestMatchers("/users/password").permitAll()
c.anyRequest().authenticated()
}
.apply(JwtSecurityConfig(jwtUtils, redisTemplate))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ enum class BaseResponseCode(status: HttpStatus, message: String) {
NOT_FOUND_USER(HttpStatus.NOT_FOUND, "사용자를 찾을 수 없습니다."),
INVALID_PHONE(HttpStatus.BAD_REQUEST, "사용자의 휴대폰 번호와 일치하지 않습니다."),
NOT_FOUND_EID(HttpStatus.NOT_FOUND, "사업자를 찾을 수 없습니다."),
NOT_EMPTY_EID(HttpStatus.BAD_REQUEST, "사업자 정보를 입력해주세요. "),
NOT_EMPTY_EID(HttpStatus.BAD_REQUEST, "사업자 정보를 입력해주세요."),
NOT_EMPTY_NAME(HttpStatus.BAD_REQUEST, "사용자 실명을 입력해주세요."),
NOT_EMPTY_EMAIL(HttpStatus.BAD_REQUEST, "사용자 이메일을 입력해주세요."),
INVALID_EID(HttpStatus.BAD_REQUEST, "정상 사업자가 아닙니다. (휴업자 or 폐업자)"),
DUPLICATE_PASSWORD(HttpStatus.BAD_REQUEST, "사용자의 비밀번호와 변경하려는 비밀번호가 동일합니다."),
PHONE_ERROR(HttpStatus.BAD_REQUEST, "naver SMS API 관련 에러입니다."),
Expand Down
28 changes: 26 additions & 2 deletions src/main/kotlin/com/psr/psr/user/controller/UserController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ package com.psr.psr.user.controller
import com.psr.psr.global.Constant.UserStatus.UserStatus.INACTIVE_STATUS
import com.psr.psr.global.Constant.UserStatus.UserStatus.LOGOUT
import com.psr.psr.global.dto.BaseResponse
import com.psr.psr.global.exception.BaseException
import com.psr.psr.global.exception.BaseResponseCode
import com.psr.psr.global.jwt.UserAccount
import com.psr.psr.global.jwt.dto.TokenDto
import com.psr.psr.user.dto.*
import com.psr.psr.user.dto.request.*
import com.psr.psr.user.dto.response.EmailRes
import com.psr.psr.user.dto.response.MyPageInfoRes
import com.psr.psr.user.dto.response.ProfileRes
import com.psr.psr.user.dto.request.*
import com.psr.psr.user.service.UserService
import jakarta.servlet.http.HttpServletRequest
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.util.StringUtils
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*

Expand Down Expand Up @@ -163,7 +166,28 @@ class UserController(
@PostMapping("/phone/validation")
@ResponseBody
fun checkValidSmsKey(@RequestBody @Validated validPhoneReq: ValidPhoneReq) : BaseResponse<Any>{
userService.checkValidSmsKey(validPhoneReq)
userService.checkValidSmsKey(validPhoneReq.phone, validPhoneReq.smsKey!!)
return BaseResponse(BaseResponseCode.SUCCESS)
}

/**
* 아이디 + 인증번호 조회
*/
@PostMapping("/email/search")
@ResponseBody
fun findEmailSearch(@RequestBody @Validated findIdPwReq: FindIdPwReq): BaseResponse<EmailRes>{
if(!StringUtils.hasText(findIdPwReq.name)) throw BaseException(BaseResponseCode.NOT_EMPTY_NAME)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

하나의 같은 클래스 사용해서 null 인 경우일 수도 있고, null 이 되면 안되는 경우도 있어서
이렇게 예외처리 진행햇슴니당

return BaseResponse(userService.findEmailSearch(findIdPwReq))
}

/**
* 비밀번호 변경 + 인증번호 조회
*/
@PostMapping("/password")
@ResponseBody
fun findPWSearch(@RequestBody @Validated findIdPwReq: FindIdPwReq): BaseResponse<Any>{
if(!StringUtils.hasText(findIdPwReq.email)) throw BaseException(BaseResponseCode.NOT_EMPTY_EMAIL)
userService.findPWSearch(findIdPwReq)
return BaseResponse(BaseResponseCode.SUCCESS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.psr.psr.user.dto.phoneReq.SMSReq
import com.psr.psr.user.dto.request.SignUpReq
import com.psr.psr.user.dto.request.UserEidReq
import com.psr.psr.user.dto.request.ValidPhoneReq
import com.psr.psr.user.dto.response.EmailRes
import com.psr.psr.user.entity.*
import org.apache.commons.lang3.RandomStringUtils
import org.springframework.stereotype.Component
Expand All @@ -33,6 +34,7 @@ class UserAssembler {
provider = Provider.LOCAL,
marketing = signUpReq.marketing,
notification = signUpReq.notification,
name = signUpReq.name,
nickname = signUpReq.nickname)
}

Expand Down Expand Up @@ -89,11 +91,14 @@ class UserAssembler {
)
}

fun toEmailResDto(user: User): EmailRes {
return EmailRes(email = user.email)
}

/**
* Utils
*/
fun createSmsKey() : String{
return RandomStringUtils.random(5, false, true);
}

}
19 changes: 19 additions & 0 deletions src/main/kotlin/com/psr/psr/user/dto/request/FindIdPwReq.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.psr.psr.user.dto.request

import jakarta.validation.constraints.Email
import jakarta.validation.constraints.NotNull
import jakarta.validation.constraints.Pattern


data class FindIdPwReq (
@field:Pattern(
regexp = "^01([0|1|6|7|8|9])-?([0-9]{3,4})-?([0-9]{4})\$",
message = "올바르지 않은 휴대폰 형식입니다."
)
@NotNull
val phone: String,
val smsKey: String,
val name: String ?= null,
@field:Email(message = "올바르지 않은 이메일 형식입니다.")
val email: String ?= null
)
2 changes: 2 additions & 0 deletions src/main/kotlin/com/psr/psr/user/dto/request/SignUpReq.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ data class SignUpReq (
message = "한글, 영어, 숫자만 입력해주세요. (10글자)"
)
val nickname: String,
@field:NotNull
val name: String,
Comment on lines +36 to +37
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

실명 컬럼이 없어서 추가했슴니당

val marketing: Boolean,
@field:NotNull
val notification: Boolean,
Expand Down
6 changes: 6 additions & 0 deletions src/main/kotlin/com/psr/psr/user/dto/response/EmailRes.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.psr.psr.user.dto.response


data class EmailRes(
val email: String,
)
4 changes: 4 additions & 0 deletions src/main/kotlin/com/psr/psr/user/entity/User.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class User(
@Column(length = 30)
var nickname:String,

@NotNull
@Column(length = 30)
var name:String,

@NotNull
@Column(length = 15)
var phone:String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ interface UserRepository: JpaRepository<User, Long> {
fun existsByPhone(phone: String): Boolean
fun existsByEmail(nickname: String): Boolean
fun findByEmail(email:String): Optional<User>
fun findByNameAndPhoneAndStatus(name: String, phone: String, status: String) : User?
fun findByEmailAndPhoneAndStatus(name: String, phone: String, status: String) : User?
}
26 changes: 23 additions & 3 deletions src/main/kotlin/com/psr/psr/user/service/UserService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ import com.psr.psr.global.Constant.UserPhone.UserPhone.TIMESTAMP_HEADER
import com.psr.psr.global.Constant.UserPhone.UserPhone.UTF_8
import com.psr.psr.global.Constant.UserStatus.UserStatus.ACTIVE_STATUS
import com.psr.psr.global.exception.BaseException
import com.psr.psr.global.exception.BaseResponseCode
import com.psr.psr.global.exception.BaseResponseCode.*
import com.psr.psr.global.jwt.dto.TokenDto
import com.psr.psr.global.jwt.utils.JwtUtils
import com.psr.psr.user.dto.*
import com.psr.psr.user.dto.assembler.UserAssembler
import com.psr.psr.user.dto.eidReq.BusinessListRes
import com.psr.psr.user.dto.request.*
import com.psr.psr.user.dto.response.EmailRes
import com.psr.psr.user.dto.response.MyPageInfoRes
import com.psr.psr.user.dto.response.ProfileRes
import com.psr.psr.user.entity.Category
Expand Down Expand Up @@ -288,10 +290,25 @@ class UserService(
}

// 휴대폰 인증번호 조회
fun checkValidSmsKey(validPhoneReq: ValidPhoneReq) {
val smsKey = jwtUtils.getSmsKey(validPhoneReq.phone)
fun checkValidSmsKey(phone: String, smsKey: String) {
val sms = jwtUtils.getSmsKey(phone)
// 인증코드가 같지 않은 경우 예외처리 발생
if(smsKey != validPhoneReq.smsKey) throw BaseException(INVALID_SMS_KEY)
if(sms != smsKey) throw BaseException(INVALID_SMS_KEY)
}

// 이메일 찾기를 위한 인증
fun findEmailSearch(findIdPwReq: FindIdPwReq): EmailRes {
// 인증번호 확인
checkValidSmsKey(findIdPwReq.phone, findIdPwReq.smsKey)
val user: User = userRepository.findByNameAndPhoneAndStatus(findIdPwReq.name!!, findIdPwReq.phone, ACTIVE_STATUS) ?: throw BaseException(NOT_FOUND_USER)
return userAssembler.toEmailResDto(user)
}

// 비밀번호 변경을 위한 인증
fun findPWSearch(findIdPwReq: FindIdPwReq) {
// 인증번호 확인
checkValidSmsKey(findIdPwReq.phone, findIdPwReq.smsKey)
userRepository.findByEmailAndPhoneAndStatus(findIdPwReq.email!!, findIdPwReq.phone, ACTIVE_STATUS) ?: throw BaseException(NOT_FOUND_USER)
}

// signature
Expand All @@ -314,4 +331,7 @@ class UserService(
return Base64.encodeBase64String(rawHmac)
}




}
Loading