diff --git a/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/CheckAuthCodeUseCase.kt b/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/CheckAuthCodeUseCase.kt index 957ce293..af53bf70 100644 --- a/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/CheckAuthCodeUseCase.kt +++ b/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/CheckAuthCodeUseCase.kt @@ -13,7 +13,7 @@ import team.comit.simtong.global.annotation.UseCase * @author Chokyunghyeon * @author kimbeomjin * @date 2022/09/24 - * @version 1.0.0 + * @version 1.2.5 **/ @UseCase class CheckAuthCodeUseCase( @@ -22,9 +22,10 @@ class CheckAuthCodeUseCase( ) { fun execute(email: String, code: String) { - val authCode = queryAuthCodePort.queryAuthCodeByEmail(email) ?: throw AuthExceptions.RequiredNewEmailAuthentication() + val authCode = queryAuthCodePort.queryAuthCodeByEmail(email) + ?: throw AuthExceptions.RequiredNewEmailAuthentication() - if (authCode.code != code) { + if (!authCode.code.match(code)) { throw AuthExceptions.DifferentAuthCode() } @@ -32,5 +33,4 @@ class CheckAuthCodeUseCase( AuthCodeLimit.certified(email) ) } - } \ No newline at end of file diff --git a/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/ReissueTokenUseCase.kt b/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/ReissueTokenUseCase.kt index c66f9c65..096af534 100644 --- a/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/ReissueTokenUseCase.kt +++ b/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/ReissueTokenUseCase.kt @@ -13,7 +13,7 @@ import team.comit.simtong.global.annotation.UseCase * @author Chokyunghyeon * @author kimbeomjin * @date 2022/09/18 - * @version 1.0.0 + * @version 1.2.5 **/ @UseCase class ReissueTokenUseCase( @@ -21,13 +21,13 @@ class ReissueTokenUseCase( private val queryRefreshTokenPort: QueryRefreshTokenPort ) { - fun execute(request: String): TokenResponse { - val token = queryRefreshTokenPort.queryRefreshTokenByToken(request) + fun execute(token: String): TokenResponse { + val refreshToken = queryRefreshTokenPort.queryRefreshTokenByToken(token) ?: throw AuthExceptions.RefreshTokenNotFound() return jwtPort.receiveToken( - userId = token.userId, - authority = token.authority + userId = refreshToken.userId, + authority = refreshToken.authority ) } } \ No newline at end of file diff --git a/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/SendAuthCodeUseCase.kt b/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/SendAuthCodeUseCase.kt index 3373244b..8820da58 100644 --- a/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/SendAuthCodeUseCase.kt +++ b/simtong-application/src/main/kotlin/team/comit/simtong/domain/auth/usecase/SendAuthCodeUseCase.kt @@ -1,6 +1,5 @@ package team.comit.simtong.domain.auth.usecase -import team.comit.simtong.domain.auth.exception.AuthExceptions import team.comit.simtong.domain.auth.model.AuthCode import team.comit.simtong.domain.auth.model.AuthCodeLimit import team.comit.simtong.domain.auth.spi.CommandAuthCodeLimitPort @@ -15,7 +14,7 @@ import team.comit.simtong.global.annotation.UseCase * * @author Chokyunghyeon * @date 2022/09/24 - * @version 1.0.0 + * @version 1.2.5 **/ @UseCase class SendAuthCodeUseCase( @@ -27,17 +26,16 @@ class SendAuthCodeUseCase( fun execute(email: String) { val authCodeLimit = queryAuthCodeLimitPort.queryAuthCodeLimitByEmail(email) - ?: AuthCodeLimit(email) + ?: AuthCodeLimit.issue(email) - if (authCodeLimit.verified) { - throw AuthExceptions.AlreadyCertifiedEmail() - } + commandAuthCodeLimitPort.save( + authCodeLimit.increaseCount() + ) - commandAuthCodeLimitPort.save(authCodeLimit.increaseCount()) + val authCode = commandAuthCodePort.save( + AuthCode.issue(email) + ) - val authCode = commandAuthCodePort.save(AuthCode(email)) - - sendEmailPort.sendAuthCode(authCode.code, email) + sendEmailPort.sendAuthCode(authCode.code.value, email) } - } \ No newline at end of file diff --git a/simtong-application/src/test/kotlin/team/comit/simtong/domain/auth/usecase/CheckAuthCodeUseCaseTests.kt b/simtong-application/src/test/kotlin/team/comit/simtong/domain/auth/usecase/CheckAuthCodeUseCaseTests.kt index 98f30b0b..5d16429f 100644 --- a/simtong-application/src/test/kotlin/team/comit/simtong/domain/auth/usecase/CheckAuthCodeUseCaseTests.kt +++ b/simtong-application/src/test/kotlin/team/comit/simtong/domain/auth/usecase/CheckAuthCodeUseCaseTests.kt @@ -8,6 +8,7 @@ import org.mockito.BDDMockito.given import org.springframework.boot.test.mock.mockito.MockBean import team.comit.simtong.domain.auth.exception.AuthExceptions import team.comit.simtong.domain.auth.model.AuthCode +import team.comit.simtong.domain.auth.model.Code import team.comit.simtong.domain.auth.spi.CommandAuthCodeLimitPort import team.comit.simtong.domain.auth.spi.QueryAuthCodePort import team.comit.simtong.global.annotation.SimtongTest @@ -30,7 +31,7 @@ class CheckAuthCodeUseCaseTests { private val authCodeStub: AuthCode by lazy { AuthCode( key = email, - code = code, + code = Code.of(code), expirationTime = AuthCode.EXPIRED ) } @@ -38,7 +39,7 @@ class CheckAuthCodeUseCaseTests { private val differentAuthCodeStub by lazy { AuthCode( key = email, - code = "654321", + code = Code.of("654321"), expirationTime = AuthCode.EXPIRED ) } diff --git a/simtong-application/src/test/kotlin/team/comit/simtong/domain/auth/usecase/SendAuthCodeUseCaseTests.kt b/simtong-application/src/test/kotlin/team/comit/simtong/domain/auth/usecase/SendAuthCodeUseCaseTests.kt index 084affcb..627a33ee 100644 --- a/simtong-application/src/test/kotlin/team/comit/simtong/domain/auth/usecase/SendAuthCodeUseCaseTests.kt +++ b/simtong-application/src/test/kotlin/team/comit/simtong/domain/auth/usecase/SendAuthCodeUseCaseTests.kt @@ -11,6 +11,7 @@ import org.springframework.boot.test.mock.mockito.MockBean import team.comit.simtong.domain.auth.exception.AuthExceptions import team.comit.simtong.domain.auth.model.AuthCode import team.comit.simtong.domain.auth.model.AuthCodeLimit +import team.comit.simtong.domain.auth.model.Code import team.comit.simtong.domain.auth.spi.CommandAuthCodeLimitPort import team.comit.simtong.domain.auth.spi.CommandAuthCodePort import team.comit.simtong.domain.auth.spi.QueryAuthCodeLimitPort @@ -59,7 +60,7 @@ class SendAuthCodeUseCaseTests { private val authCodeStub by lazy { AuthCode( key = email, - code = code, + code = Code.of(code), expirationTime = AuthCode.EXPIRED ) } diff --git a/simtong-application/src/test/kotlin/team/comit/simtong/domain/user/usecase/ChangeEmailUseCaseTests.kt b/simtong-application/src/test/kotlin/team/comit/simtong/domain/user/usecase/ChangeEmailUseCaseTests.kt index 40b28719..ff807f13 100644 --- a/simtong-application/src/test/kotlin/team/comit/simtong/domain/user/usecase/ChangeEmailUseCaseTests.kt +++ b/simtong-application/src/test/kotlin/team/comit/simtong/domain/user/usecase/ChangeEmailUseCaseTests.kt @@ -51,7 +51,7 @@ class ChangeEmailUseCaseTests { } private val uncertifiedAuthCodeLimit: AuthCodeLimit by lazy { - AuthCodeLimit( + AuthCodeLimit.issue( email = "test@test.com" ) } diff --git a/simtong-application/src/test/kotlin/team/comit/simtong/domain/user/usecase/ResetPasswordUseCaseTests.kt b/simtong-application/src/test/kotlin/team/comit/simtong/domain/user/usecase/ResetPasswordUseCaseTests.kt index 90ccf977..82fd6cc0 100644 --- a/simtong-application/src/test/kotlin/team/comit/simtong/domain/user/usecase/ResetPasswordUseCaseTests.kt +++ b/simtong-application/src/test/kotlin/team/comit/simtong/domain/user/usecase/ResetPasswordUseCaseTests.kt @@ -57,7 +57,7 @@ class ResetPasswordUseCaseTests { } private val uncertifiedAuthCodeLimit: AuthCodeLimit by lazy { - AuthCodeLimit( + AuthCodeLimit.issue( email = email ) } diff --git a/simtong-domain/src/main/kotlin/team/comit/simtong/domain/auth/model/AuthCode.kt b/simtong-domain/src/main/kotlin/team/comit/simtong/domain/auth/model/AuthCode.kt index 35d17e28..9dd5a10d 100644 --- a/simtong-domain/src/main/kotlin/team/comit/simtong/domain/auth/model/AuthCode.kt +++ b/simtong-domain/src/main/kotlin/team/comit/simtong/domain/auth/model/AuthCode.kt @@ -4,34 +4,63 @@ import net.bytebuddy.utility.RandomString import team.comit.simtong.global.DomainProperties.getProperty import team.comit.simtong.global.DomainPropertiesPrefix import team.comit.simtong.global.annotation.Aggregate -import team.comit.simtong.global.annotation.Default /** * - * AuthCodeAggregate Root를 담당하는 AuthCode + * AuthCode Aggregate Root를 담당하는 AuthCode * * @author Chokyunghyeon + * @author kimbeomjin * @date 2022/09/24 - * @version 1.0.0 + * @version 1.2.5 **/ @Aggregate -data class AuthCode @Default constructor( +data class AuthCode( val key: String, - val code: String, + val code: Code, val expirationTime: Int ) { - constructor(email: String) : this( - key = email, - code = RandomString(6).nextString(), - expirationTime = EXPIRED - ) - companion object { @JvmField val EXPIRED = getProperty(DomainPropertiesPrefix.AUTHCODE_EXP).toInt() + + fun of(key: String, code: Code, expirationTime: Int) = AuthCode( + key = key, + code = code, + expirationTime = expirationTime + ) + + fun issue(email: String) = AuthCode( + key = email, + code = Code.defaultValue(), + expirationTime = EXPIRED + ) + } +} + +/** + * + * AuthCode Aggregate 중 인증코드를 담당하는 Code + * + * @author kimbeomjin + * @date 2023/01/09 + * @version 1.2.5 + **/ +@JvmInline +value class Code private constructor( + val value: String +) { + + fun match(code: String): Boolean { + return this.value == code } + companion object { + fun of(value: String) = Code(value) + + fun defaultValue() = Code(RandomString(6).nextString()) + } } \ No newline at end of file diff --git a/simtong-domain/src/main/kotlin/team/comit/simtong/domain/auth/model/AuthCodeLimit.kt b/simtong-domain/src/main/kotlin/team/comit/simtong/domain/auth/model/AuthCodeLimit.kt index 8f50c4e3..4a6a172c 100644 --- a/simtong-domain/src/main/kotlin/team/comit/simtong/domain/auth/model/AuthCodeLimit.kt +++ b/simtong-domain/src/main/kotlin/team/comit/simtong/domain/auth/model/AuthCodeLimit.kt @@ -4,7 +4,6 @@ import team.comit.simtong.domain.auth.exception.AuthExceptions import team.comit.simtong.global.DomainProperties.getProperty import team.comit.simtong.global.DomainPropertiesPrefix import team.comit.simtong.global.annotation.Aggregate -import team.comit.simtong.global.annotation.Default /** * @@ -13,10 +12,10 @@ import team.comit.simtong.global.annotation.Default * @author Chokyunghyeon * @author kimbeomjin * @date 2022/09/11 - * @version 1.0.0 + * @version 1.2.5 **/ @Aggregate -data class AuthCodeLimit @Default constructor( +data class AuthCodeLimit( val key: String, val expirationTime: Int, @@ -25,14 +24,6 @@ data class AuthCodeLimit @Default constructor( val verified: Boolean ) { - - constructor(email: String) : this( - key = email, - expirationTime = EXPIRED, - attemptCount = 0, - verified = false - ) - companion object { @JvmField val MAX_ATTEMPT_COUNT: Short = getProperty(DomainPropertiesPrefix.AUTHCODELIMIT_MAX_ATTEMPT_COUNT).toShort() @@ -43,6 +34,13 @@ data class AuthCodeLimit @Default constructor( @JvmField val VERIFIED_EXPIRED: Int = getProperty(DomainPropertiesPrefix.AUTHCODELIMIT_VERIFIED_EXP).toInt() + fun issue(email: String) = AuthCodeLimit( + key = email, + expirationTime = EXPIRED, + attemptCount = 0, + verified = false + ) + fun certified(email: String) = AuthCodeLimit( key = email, expirationTime = VERIFIED_EXPIRED, @@ -52,9 +50,8 @@ data class AuthCodeLimit @Default constructor( } fun increaseCount(): AuthCodeLimit { - if (attemptCount >= MAX_ATTEMPT_COUNT) { - throw AuthExceptions.ExceededSendAuthCodeRequest() - } + checkNotYetVerified() + checkNotExceededAttemptCount() return AuthCodeLimit( key = key, @@ -64,4 +61,15 @@ data class AuthCodeLimit @Default constructor( ) } + private fun checkNotYetVerified() { + if (verified) { + throw AuthExceptions.AlreadyCertifiedEmail() + } + } + + private fun checkNotExceededAttemptCount() { + if (attemptCount >= MAX_ATTEMPT_COUNT) { + throw AuthExceptions.ExceededSendAuthCodeRequest() + } + } } \ No newline at end of file diff --git a/simtong-infrastructure/src/main/kotlin/team/comit/simtong/persistence/auth/mapper/AuthCodeMapper.kt b/simtong-infrastructure/src/main/kotlin/team/comit/simtong/persistence/auth/mapper/AuthCodeMapper.kt index 48ceae6d..dbdc8e8f 100644 --- a/simtong-infrastructure/src/main/kotlin/team/comit/simtong/persistence/auth/mapper/AuthCodeMapper.kt +++ b/simtong-infrastructure/src/main/kotlin/team/comit/simtong/persistence/auth/mapper/AuthCodeMapper.kt @@ -1,7 +1,8 @@ package team.comit.simtong.persistence.auth.mapper -import org.mapstruct.Mapper +import org.springframework.stereotype.Component import team.comit.simtong.domain.auth.model.AuthCode +import team.comit.simtong.domain.auth.model.Code import team.comit.simtong.persistence.GenericMapper import team.comit.simtong.persistence.auth.entity.AuthCodeEntity @@ -10,9 +11,36 @@ import team.comit.simtong.persistence.auth.entity.AuthCodeEntity * AuthCodeEntity와 DomainAuthCode를 변환하는 AuthCodeMapper * * @author Chokyunghyeon + * @author kimbeomjin * @date 2022/09/25 - * @version 1.0.0 + * @version 1.2.5 **/ -@Mapper -abstract class AuthCodeMapper : GenericMapper { +@Component +class AuthCodeMapper : GenericMapper { + + override fun toEntity(model: AuthCode): AuthCodeEntity { + return AuthCodeEntity( + key = model.key, + code = model.code.value, + expirationTime = model.expirationTime + ) + } + + override fun toDomain(entity: AuthCodeEntity?): AuthCode? { + return entity?.let { + AuthCode.of( + key = it.key, + code = Code.of(it.code), + expirationTime = it.expirationTime + ) + } + } + + override fun toDomainNotNull(entity: AuthCodeEntity): AuthCode { + return AuthCode.of( + key = entity.key, + code = Code.of(entity.code), + expirationTime = entity.expirationTime + ) + } } \ No newline at end of file