소셜 로그인 이메일 미필수 정책 적용
소셜 로그인 시 이메일 동의 없이도 계정 생성이 가능하도록 변경합니다. Member 엔티티의 email 필드를 선택 사항으로 변경하고, 관련 API 응답 및 인증 로직에서 이메일이 없는 경우에 대한 처리를 추가합니다.
This commit is contained in:
@@ -126,7 +126,7 @@ class AdminMemberService(
|
||||
|
||||
GetAdminMemberListResponseItem(
|
||||
id = it.id!!,
|
||||
email = it.email,
|
||||
email = it.email ?: "",
|
||||
nickname = it.nickname,
|
||||
profileUrl = if (it.profileImage != null) {
|
||||
"$cloudFrontHost/${it.profileImage}"
|
||||
@@ -160,6 +160,7 @@ class AdminMemberService(
|
||||
val member = repository.findByIdAndActive(memberId = request.memberId)
|
||||
?: throw SodaException(messageKey = "admin.member.reset_password_invalid")
|
||||
|
||||
member.password = passwordEncoder.encode(member.email.split("@")[0])
|
||||
val email = member.email ?: throw SodaException(message = "이메일이 없는 계정은 비밀번호 재설정이 불가능합니다.")
|
||||
member.password = passwordEncoder.encode(email.split("@")[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||
import org.springframework.security.core.userdetails.User
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
@@ -29,6 +28,12 @@ class ChargeTempController(private val service: ChargeTempService) {
|
||||
@PostMapping("/verify")
|
||||
fun verify(
|
||||
@RequestBody request: VerifyRequest,
|
||||
@AuthenticationPrincipal user: User
|
||||
) = ApiResponse.ok(service.verify(user, request))
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
) = run {
|
||||
if (member == null) {
|
||||
throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
}
|
||||
|
||||
ApiResponse.ok(service.verify(member, request))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,8 @@ import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import org.springframework.security.core.userdetails.User
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
|
||||
@@ -26,7 +24,6 @@ import org.springframework.transaction.annotation.Transactional
|
||||
@Transactional(readOnly = true)
|
||||
class ChargeTempService(
|
||||
private val chargeRepository: ChargeRepository,
|
||||
private val memberRepository: MemberRepository,
|
||||
|
||||
private val objectMapper: ObjectMapper,
|
||||
private val messageSource: SodaMessageSource,
|
||||
@@ -54,11 +51,9 @@ class ChargeTempService(
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun verify(user: User, verifyRequest: VerifyRequest) {
|
||||
fun verify(member: Member, verifyRequest: VerifyRequest) {
|
||||
val charge = chargeRepository.findByIdOrNull(verifyRequest.orderId.toLong())
|
||||
?: throw SodaException(messageKey = "can.charge.invalid_payment_info")
|
||||
val member = memberRepository.findByEmail(user.username)
|
||||
?: throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
|
||||
if (charge.payment!!.paymentGateway == PaymentGateway.PG) {
|
||||
val bootpay = Bootpay(bootpayApplicationId, bootpayPrivateKey)
|
||||
|
||||
@@ -87,7 +87,7 @@ class CreatorAdminMemberService(
|
||||
userId = member.id!!,
|
||||
token = jwt,
|
||||
nickname = member.nickname,
|
||||
email = member.email,
|
||||
email = member.email ?: "",
|
||||
profileImage = if (member.profileImage != null) {
|
||||
"$cloudFrontHost/${member.profileImage}"
|
||||
} else {
|
||||
|
||||
@@ -19,7 +19,7 @@ import javax.persistence.OneToOne
|
||||
|
||||
@Entity
|
||||
data class Member(
|
||||
val email: String,
|
||||
var email: String? = null,
|
||||
var password: String,
|
||||
var nickname: String,
|
||||
var profileImage: String? = null,
|
||||
|
||||
@@ -4,7 +4,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||
import org.springframework.security.core.userdetails.User
|
||||
|
||||
class MemberAdapter(val member: Member) : User(
|
||||
member.email,
|
||||
member.email ?: "member:${member.id}",
|
||||
member.password,
|
||||
listOf(SimpleGrantedAuthority("ROLE_${member.role.name}"))
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
interface MemberRepository : JpaRepository<Member, Long>, MemberQueryRepository {
|
||||
fun findByEmail(email: String): Member?
|
||||
fun findByEmail(email: String?): Member?
|
||||
fun findByNickname(nickname: String): Member?
|
||||
fun findByGoogleId(googleId: String): Member?
|
||||
fun findByKakaoId(kakaoId: Long): Member?
|
||||
@@ -51,7 +51,7 @@ interface MemberQueryRepository {
|
||||
fun getMessageRecipientPushToken(messageId: Long): PushTokenInfo?
|
||||
fun getIndividualRecipientPushTokens(recipients: List<Long>, isAuth: Boolean?): List<PushTokenInfo>
|
||||
fun getChangeNicknamePrice(memberId: Long): GetChangeNicknamePriceResponse
|
||||
fun getMemberByEmail(email: String): Member?
|
||||
fun getMemberByEmail(email: String?): Member?
|
||||
|
||||
fun getChangeNoticeRecipientPushTokens(creatorId: Long): List<PushTokenInfo>
|
||||
fun getPushTokenFromReservationList(roomId: Long): List<PushTokenInfo>
|
||||
@@ -363,7 +363,8 @@ class MemberQueryRepositoryImpl(
|
||||
)
|
||||
}
|
||||
|
||||
override fun getMemberByEmail(email: String): Member? {
|
||||
override fun getMemberByEmail(email: String?): Member? {
|
||||
if (email == null) return null
|
||||
return queryFactory
|
||||
.selectFrom(member)
|
||||
.where(member.email.eq(email))
|
||||
|
||||
@@ -346,7 +346,7 @@ class MemberService(
|
||||
userId = member.id!!,
|
||||
token = jwt,
|
||||
nickname = member.nickname,
|
||||
email = member.email,
|
||||
email = member.email ?: "",
|
||||
profileImage = if (member.profileImage != null) {
|
||||
"$cloudFrontHost/${member.profileImage}"
|
||||
} else {
|
||||
@@ -454,8 +454,16 @@ class MemberService(
|
||||
}
|
||||
|
||||
override fun loadUserByUsername(username: String): UserDetails {
|
||||
val member = repository.findByEmail(email = username)
|
||||
?: throw UsernameNotFoundException(username)
|
||||
val member = if (username.startsWith("member:")) {
|
||||
val id = username.substringAfter("member:").toLongOrNull()
|
||||
if (id != null) {
|
||||
repository.findByIdOrNull(id)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
repository.findByEmail(email = username)
|
||||
} ?: throw UsernameNotFoundException(username)
|
||||
|
||||
return MemberAdapter(member)
|
||||
}
|
||||
@@ -592,7 +600,7 @@ class MemberService(
|
||||
|
||||
@Transactional
|
||||
fun signOut(signOutRequest: SignOutRequest, user: User) {
|
||||
val member = repository.findByEmail(user.username)
|
||||
val member = findMemberByUsername(user.username)
|
||||
?: throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
if (
|
||||
member.provider == MemberProvider.EMAIL &&
|
||||
@@ -620,11 +628,7 @@ class MemberService(
|
||||
|
||||
@Transactional
|
||||
fun updateNickname(profileUpdateRequest: ProfileUpdateRequest, user: User) {
|
||||
if (profileUpdateRequest.email != user.username) {
|
||||
throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
}
|
||||
|
||||
val member = repository.findByEmail(user.username)
|
||||
val member = findMemberByUsername(user.username)
|
||||
?: throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
|
||||
if (profileUpdateRequest.nickname != null) {
|
||||
@@ -652,11 +656,7 @@ class MemberService(
|
||||
|
||||
@Transactional
|
||||
fun profileUpdate(profileUpdateRequest: ProfileUpdateRequest, user: User): ProfileResponse {
|
||||
if (profileUpdateRequest.email != user.username) {
|
||||
throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
}
|
||||
|
||||
val member = repository.findByEmail(user.username)
|
||||
val member = findMemberByUsername(user.username)
|
||||
?: throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
|
||||
if (profileUpdateRequest.modifyPassword != null) {
|
||||
@@ -729,7 +729,7 @@ class MemberService(
|
||||
|
||||
@Transactional
|
||||
fun profileImageUpdate(multipartFile: MultipartFile, user: User): String {
|
||||
val member = repository.findByEmail(user.username)
|
||||
val member = findMemberByUsername(user.username)
|
||||
?: throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
|
||||
val metadata = ObjectMetadata()
|
||||
@@ -932,7 +932,24 @@ class MemberService(
|
||||
return MemberResolveResult(member = member, isNew = true)
|
||||
}
|
||||
|
||||
private fun checkEmail(email: String) {
|
||||
private fun findMemberByUsername(username: String): Member? {
|
||||
return if (username.startsWith("member:")) {
|
||||
val id = username.substringAfter("member:").toLongOrNull()
|
||||
if (id != null) {
|
||||
repository.findByIdOrNull(id)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
repository.findByEmail(email = username)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkEmail(email: String?) {
|
||||
if (email.isNullOrBlank()) {
|
||||
return
|
||||
}
|
||||
|
||||
val member = repository.findByEmail(email)
|
||||
|
||||
if (member != null) {
|
||||
|
||||
@@ -17,7 +17,7 @@ data class ProfileResponse(
|
||||
) {
|
||||
constructor(member: Member, cloudFrontHost: String, container: String) : this(
|
||||
userId = member.id!!,
|
||||
email = member.email,
|
||||
email = member.email ?: "",
|
||||
nickname = member.nickname,
|
||||
gender = member.gender,
|
||||
profileUrl = if (member.profileImage != null) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package kr.co.vividnext.sodalive.member
|
||||
|
||||
data class ProfileUpdateRequest(
|
||||
val email: String,
|
||||
val email: String? = null,
|
||||
val password: String? = null,
|
||||
val modifyPassword: String? = null,
|
||||
val nickname: String? = null,
|
||||
|
||||
@@ -47,7 +47,7 @@ class GoogleAuthService(
|
||||
userId = member.id!!,
|
||||
token = jwt,
|
||||
nickname = member.nickname,
|
||||
email = member.email,
|
||||
email = member.email ?: "",
|
||||
profileImage = if (member.profileImage != null) {
|
||||
"$cloudFrontHost/${member.profileImage}"
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,6 @@ package kr.co.vividnext.sodalive.member.social.google
|
||||
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier
|
||||
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
|
||||
import com.google.api.client.json.gson.GsonFactory
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@@ -27,7 +26,7 @@ class GoogleService(
|
||||
|
||||
if (token != null) {
|
||||
val payload = token.payload
|
||||
val email = payload.email ?: throw SodaException(messageKey = "member.social.email_consent_required")
|
||||
val email = payload.email
|
||||
|
||||
GoogleUserInfo(
|
||||
sub = payload.subject,
|
||||
|
||||
@@ -2,6 +2,6 @@ package kr.co.vividnext.sodalive.member.social.google
|
||||
|
||||
data class GoogleUserInfo(
|
||||
val sub: String,
|
||||
val email: String,
|
||||
val email: String?,
|
||||
val name: String?
|
||||
)
|
||||
|
||||
@@ -47,7 +47,7 @@ class KakaoAuthService(
|
||||
userId = member.id!!,
|
||||
token = jwt,
|
||||
nickname = member.nickname,
|
||||
email = member.email,
|
||||
email = member.email ?: "",
|
||||
profileImage = if (member.profileImage != null) {
|
||||
"$cloudFrontHost/${member.profileImage}"
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package kr.co.vividnext.sodalive.member.social.kakao
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import org.springframework.http.HttpEntity
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.HttpMethod
|
||||
@@ -37,7 +36,6 @@ class KakaoService(
|
||||
val id = jsonNode.get("id").asLong()
|
||||
val kakaoAccount = jsonNode.get("kakao_account")
|
||||
val email = kakaoAccount?.get("email")?.asText()
|
||||
?: throw SodaException(messageKey = "member.social.kakao_login_failed")
|
||||
val properties = jsonNode.get("properties")
|
||||
val nickname = properties?.get("nickname")?.asText()
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@ package kr.co.vividnext.sodalive.member.social.kakao
|
||||
|
||||
data class KakaoUserInfo(
|
||||
val id: Long,
|
||||
val email: String,
|
||||
val email: String?,
|
||||
val nickname: String?
|
||||
)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package kr.co.vividnext.sodalive.menu
|
||||
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||
import org.springframework.security.core.userdetails.User
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
@@ -13,5 +14,13 @@ import org.springframework.web.bind.annotation.RestController
|
||||
class MenuController(private val service: MenuService) {
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyRole('AGENT', 'ADMIN', 'CREATOR')")
|
||||
fun getMenus(@AuthenticationPrincipal user: User) = ApiResponse.ok(service.getMenus(user))
|
||||
fun getMenus(
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
) = run {
|
||||
if (member == null) {
|
||||
throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
}
|
||||
|
||||
ApiResponse.ok(service.getMenus(member))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
package kr.co.vividnext.sodalive.menu
|
||||
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import org.springframework.security.core.userdetails.User
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
class MenuService(
|
||||
private val repository: MenuRepository,
|
||||
private val memberRepository: MemberRepository
|
||||
private val repository: MenuRepository
|
||||
) {
|
||||
fun getMenus(user: User): List<GetMenuResponse> {
|
||||
val member = memberRepository.findByEmail(user.username)
|
||||
?: throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
fun getMenus(member: Member): List<GetMenuResponse> {
|
||||
return repository.getMenu(member.role)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user