Merge pull request 'test' (#74) from test into main

Reviewed-on: #74
This commit is contained in:
klaus 2023-11-09 11:18:20 +00:00
commit b848d6b4e0
4 changed files with 120 additions and 43 deletions

View File

@ -19,6 +19,15 @@ class AuthController(private val service: AuthService) {
) = run { ) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.") if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.verify(member, request)) val authenticateData = service.certificate(request, memberId = member.id!!)
if (service.isBlockAuth(authenticateData)) {
service.signOut(member.id!!)
throw SodaException("운영정책을 위반하여 이용을 제한합니다.")
} else {
service.authenticate(authenticateData, member.id!!)
}
ApiResponse.ok(null, null)
} }
} }

View File

@ -3,72 +3,94 @@ package kr.co.vividnext.sodalive.member.auth
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import kr.co.bootpay.Bootpay import kr.co.bootpay.Bootpay
import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.MemberRepository
import kr.co.vividnext.sodalive.member.MemberService
import kr.co.vividnext.sodalive.member.SignOut
import kr.co.vividnext.sodalive.member.SignOutRepository
import org.springframework.beans.factory.annotation.Value import org.springframework.beans.factory.annotation.Value
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional import org.springframework.transaction.annotation.Transactional
import java.time.LocalDate
@Service @Service
@Transactional(readOnly = true)
class AuthService( class AuthService(
private val repository: AuthRepository, private val repository: AuthRepository,
private val objectMapper: ObjectMapper, private val objectMapper: ObjectMapper,
private val blockAuthRepository: BlockAuthRepository,
private val memberService: MemberService,
private val memberRepository: MemberRepository,
private val signOutRepository: SignOutRepository,
@Value("\${bootpay.application-id}") @Value("\${bootpay.application-id}")
private val bootpayApplicationId: String, private val bootpayApplicationId: String,
@Value("\${bootpay.private-key}") @Value("\${bootpay.private-key}")
private val bootpayPrivateKey: String private val bootpayPrivateKey: String
) { ) {
@Transactional fun certificate(request: AuthVerifyRequest, memberId: Long): AuthVerifyCertificate {
fun verify(member: Member, request: AuthVerifyRequest) {
val bootpay = Bootpay(bootpayApplicationId, bootpayPrivateKey) val bootpay = Bootpay(bootpayApplicationId, bootpayPrivateKey)
val authId = repository.getAuthIdByMemberId(memberId = member.id!!) val authId = repository.getAuthIdByMemberId(memberId = memberId)
if (authId != null) throw SodaException("이미 인증된 계정입니다.") if (authId != null) throw SodaException("이미 인증된 계정입니다.")
try { val certificateResult: AuthCertificateResult = try {
val token = bootpay.accessToken val token = bootpay.accessToken
if (token["error_code"] != null) throw SodaException("인증정보에 오류가 있습니다.\n다시 시도해 주세요.") if (token["error_code"] != null) throw SodaException("인증정보에 오류가 있습니다.\n다시 시도해 주세요.")
val res = bootpay.certificate(request.receiptId) val res = bootpay.certificate(request.receiptId)
val certificateResult = objectMapper.convertValue(res, AuthCertificateResult::class.java) objectMapper.convertValue(res, AuthCertificateResult::class.java)
if (
certificateResult.status == 12 &&
certificateResult.statusLocale == "본인인증완료" &&
certificateResult.receiptId == request.receiptId
) {
val certificate = certificateResult.authenticateData
val nowYear = LocalDate.now().year
val certificateYear = certificate.birth.substring(0, 4).toInt()
if (nowYear - certificateYear >= 19) {
val memberIds = repository.getActiveMemberIdsByDi(di = certificate.di)
if (memberIds.size >= 3) {
throw SodaException(
"이미 본인인증한 계정 ${memberIds.size}개 이용중입니다.\n" +
"소다라이브의 본인인증은 최대 3개의 계정만 이용할 수 있습니다."
)
}
val auth = Auth(
name = certificate.name,
birth = certificate.birth,
uniqueCi = certificate.unique,
di = certificate.di,
gender = certificate.gender
)
auth.member = member
repository.save(auth)
} else {
throw SodaException("19세 미만 인증 오류")
}
} else {
throw SodaException("인증정보에 오류가 있습니다.\n다시 시도해 주세요.")
}
} catch (e: Exception) { } catch (e: Exception) {
throw SodaException(e.message ?: "인증정보에 오류가 있습니다.\n다시 시도해 주세요.") throw SodaException(e.message ?: "인증정보에 오류가 있습니다.\n다시 시도해 주세요.")
} }
if (
certificateResult.status == 12 &&
certificateResult.statusLocale == "본인인증완료" &&
certificateResult.receiptId == request.receiptId
) {
return certificateResult.authenticateData
} else {
throw SodaException("인증정보에 오류가 있습니다.\n다시 시도해 주세요.")
}
}
fun isBlockAuth(certificate: AuthVerifyCertificate): Boolean {
val blockAuthId = blockAuthRepository.findByUniqueCiAndDi(certificate.unique, certificate.di)
return blockAuthId != null && blockAuthId > 0
}
@Transactional
fun signOut(memberId: Long) {
val member = memberRepository.findByIdOrNull(memberId) ?: throw SodaException("로그인 정보를 확인해주세요.")
member.isActive = false
val signOut = SignOut(reason = "운영정책을 위반하여 이용을 제한합니다.")
signOut.member = member
signOutRepository.save(signOut)
memberService.logoutAll(memberId = memberId)
}
@Transactional
fun authenticate(certificate: AuthVerifyCertificate, memberId: Long) {
val memberIds = repository.getActiveMemberIdsByDi(di = certificate.di)
if (memberIds.size >= 3) {
throw SodaException(
"이미 본인인증한 계정 ${memberIds.size}개 이용중입니다.\n" +
"소다라이브의 본인인증은 최대 3개의 계정만 이용할 수 있습니다."
)
}
val member = memberRepository.findByIdOrNull(memberId) ?: throw SodaException("로그인 정보를 확인해주세요.")
val auth = Auth(
name = certificate.name,
birth = certificate.birth,
uniqueCi = certificate.unique,
di = certificate.di,
gender = certificate.gender
)
auth.member = member
repository.save(auth)
} }
} }

View File

@ -0,0 +1,19 @@
package kr.co.vividnext.sodalive.member.auth
import kr.co.vividnext.sodalive.common.BaseEntity
import javax.persistence.Column
import javax.persistence.Entity
@Entity
data class BlockAuth(
@Column(nullable = false)
val name: String,
@Column(nullable = false)
val birth: String,
@Column(columnDefinition = "TEXT", nullable = false)
val uniqueCi: String,
@Column(columnDefinition = "TEXT", nullable = false)
val di: String,
@Column(nullable = false)
val gender: Int
) : BaseEntity()

View File

@ -0,0 +1,27 @@
package kr.co.vividnext.sodalive.member.auth
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.member.auth.QBlockAuth.blockAuth
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
@Repository
interface BlockAuthRepository : JpaRepository<BlockAuth, Long>, BlockAuthQueryRepository
interface BlockAuthQueryRepository {
fun findByUniqueCiAndDi(uniqueCi: String, di: String): Long?
}
@Repository
class BlockAuthQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : BlockAuthQueryRepository {
override fun findByUniqueCiAndDi(uniqueCi: String, di: String): Long? {
return queryFactory
.select(blockAuth.id)
.from(blockAuth)
.where(
blockAuth.uniqueCi.eq(uniqueCi)
.and(blockAuth.di.eq(di))
)
.fetchFirst()
}
}