Skip to content

Commit

Permalink
MERGE :: develop -> main
Browse files Browse the repository at this point in the history
  • Loading branch information
Daybreak312 committed Jul 25, 2024
2 parents 396248a + f3ea237 commit db46c26
Show file tree
Hide file tree
Showing 35 changed files with 709 additions and 192 deletions.
132 changes: 132 additions & 0 deletions .d2/ModulesArchitecture.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/DependencyNames.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ object DependencyNames {
const val REDIS = "$STARTER-data-redis"

// test
const val SPRING_TEST = "$STARTER-test:${PluginVersions.SPRING_BOOT_VERSION}"
const val SPRING_TEST = "$STARTER-test"
const val JUNIT_JUPITER = "org.junit.jupiter:junit-jupiter"
const val JUNIT_JUPITER_API = "org.junit.jupiter:junit-jupiter-api"
const val JUNIT_JUPITER_ENGINE = "org.junit.jupiter:junit-jupiter-engine"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ object TableNames {

const val ACCESS_TOKEN_TABLE = "${TABLE_PREFIX}access"
const val REFRESH_TOKEN_TABLE = "${TABLE_PREFIX}refresh"
const val REVOKED_MAEUMGAGYM_TOKEN_TABLE = "${TABLE_PREFIX}revoked_mgt"
const val USABLE_MAEUMGAGYM_TOKEN_TABLE = "${TABLE_PREFIX}usable_mgt"

const val REDIS_STEP_TABLE = "${TABLE_PREFIX}step"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.info.maeumgagym.core.auth.service

import com.info.maeumgagym.common.annotation.responsibility.UseCase
import com.info.maeumgagym.common.exception.BusinessLogicException
import com.info.maeumgagym.core.auth.port.`in`.GoogleLoginUseCase
import com.info.maeumgagym.core.auth.port.`in`.GoogleRecoveryUseCase
import com.info.maeumgagym.core.auth.port.`in`.GoogleSignupUseCase
import com.info.maeumgagym.core.auth.port.out.GenerateJwtPort
import com.info.maeumgagym.core.auth.port.out.GetGoogleInfoPort
import com.info.maeumgagym.core.auth.port.out.RevokeGoogleTokenPort
import com.info.maeumgagym.common.exception.BusinessLogicException
import com.info.maeumgagym.core.user.model.Role
import com.info.maeumgagym.core.user.model.User
import com.info.maeumgagym.core.user.port.out.ExistUserPort
Expand All @@ -20,7 +19,6 @@ internal class GoogleOAuthService(
private val saveUserPort: SaveUserPort,
private val existUserPort: ExistUserPort,
private val generateJwtPort: GenerateJwtPort,
private val revokeGoogleTokenPort: RevokeGoogleTokenPort,
private val recoveryUserPort: RecoveryUserPort
) : GoogleLoginUseCase, GoogleSignupUseCase, GoogleRecoveryUseCase {

Expand All @@ -31,9 +29,6 @@ internal class GoogleOAuthService(
// 존재하지 않는 유저라면 NotFound 예외처리
if (!existUserPort.existsByOAuthId(profile.sub)) throw BusinessLogicException.USER_NOT_FOUND

// google access_token 만료 시키기
revokeGoogleTokenPort.revoke(accessToken)

// subject로 토큰 발급 및 반환
return generateJwtPort.generateTokens(profile.sub)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.info.maeumgagym.core.auth.service

import com.info.maeumgagym.common.annotation.responsibility.UseCase
import com.info.maeumgagym.common.exception.BusinessLogicException
import com.info.maeumgagym.core.auth.port.`in`.KakaoLoginUseCase
import com.info.maeumgagym.core.auth.port.`in`.KakaoRecoveryUseCase
import com.info.maeumgagym.core.auth.port.`in`.KakaoSignupUseCase
import com.info.maeumgagym.core.auth.port.out.*
import com.info.maeumgagym.common.exception.BusinessLogicException
import com.info.maeumgagym.core.auth.port.out.GenerateJwtPort
import com.info.maeumgagym.core.auth.port.out.GetKakaoProfilePort
import com.info.maeumgagym.core.auth.port.out.GetKakaoTokenPort
import com.info.maeumgagym.core.auth.port.out.KakaoGenerateTokenUseCase
import com.info.maeumgagym.core.user.model.Role
import com.info.maeumgagym.core.user.model.User
import com.info.maeumgagym.core.user.port.out.ExistUserPort
Expand All @@ -19,8 +22,7 @@ internal class KakaoOAuthService(
private val existUserPort: ExistUserPort,
private val saveUserPort: SaveUserPort,
private val recoveryUserPort: RecoveryUserPort,
private val getKakaoTokenPort: GetKakaoTokenPort,
private val revokeKakaoTokenPort: RevokeKakaoTokenPort
private val getKakaoTokenPort: GetKakaoTokenPort
) : KakaoLoginUseCase, KakaoSignupUseCase, KakaoRecoveryUseCase, KakaoGenerateTokenUseCase {

override fun login(accessToken: String): Pair<String, String> {
Expand All @@ -30,8 +32,6 @@ internal class KakaoOAuthService(
// 존재하지 않는 유저라면 NotFound 예외처리
if (!existUserPort.existsByOAuthId(userInfo.id)) throw BusinessLogicException.USER_NOT_FOUND

revokeKakaoTokenPort.revoke(accessToken)

// subject로 토큰 발급 및 반환
return generateJwtPort.generateTokens(userInfo.id)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.info.maeumgagym.core.pose.dto.response

data class PoseRecommendationListResponse(
val poses: Map<String, PoseListResponse>
val response: List<CategoryMarkedPoseListResponse>
)

data class CategoryMarkedPoseListResponse(
val category: String,
val poses: PoseListResponse
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.info.maeumgagym.core.pose.service

import com.info.maeumgagym.common.annotation.responsibility.ReadOnlyUseCase
import com.info.maeumgagym.core.pose.dto.response.CategoryMarkedPoseListResponse
import com.info.maeumgagym.core.pose.dto.response.PoseListResponse
import com.info.maeumgagym.core.pose.dto.response.PoseRecommendationListResponse
import com.info.maeumgagym.core.pose.model.Pose
Expand Down Expand Up @@ -37,8 +38,15 @@ class ReadPosesRecommendationService(

return PoseRecommendationListResponse(
recommendationPoses.map {
Pair(it.key, PoseListResponse(it.value.map { pose -> pose.toInfoResponse() }))
}.toMap()
CategoryMarkedPoseListResponse(
it.key,
PoseListResponse(
it.value.map {
it.toInfoResponse()
}
)
)
}
)
}
}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private class UserController(
nickname: String?
): UserProfileResponse = readUserProfileFromNicknameUseCase.profileFromNickname(nickname!!)

@Operation(summary = "현재 로그인한 유저 프로필 보기 API")
@Operation(summary = "현재 로그인한 유저 프로필 조회 API")
@RequireAuthentication
@GetMapping
fun getCurrentUserProfile(): UserProfileResponse = readCurrentUserProfileUseCase.readCurrentUserProfile()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.info.maeumgagym.security.access.checker
import com.info.maeumgagym.common.exception.AuthenticationException
import org.springframework.security.authentication.AnonymousAuthenticationToken
import org.springframework.security.core.context.SecurityContextHolder
import kotlin.reflect.KClass

/**
* [AnnotationBasedUserAuthenticationChecker]의 구현체에서 사용되는 일부 중복 코드에 대해 추출된 함수 집합의 추상화
Expand All @@ -13,15 +12,8 @@ import kotlin.reflect.KClass
* @author Daybreak312
* @since 20-04-2024
*/
abstract class AbstractAnnotationBasedUserAuthenticationChecker : AnnotationBasedUserAuthenticationChecker {

protected fun <A : Annotation> Any.getAnnotationOrNull(annotation: KClass<A>): A? {
this::class.annotations.forEach {
if (it.annotationClass == annotation) return it as A
}

return null
}
abstract class AbstractAnnotationBasedUserAuthenticationChecker :
AnnotationBasedUserAuthenticationChecker {

protected fun checkInvalidAuthentication() {
if (SecurityContextHolder.getContext().authentication == null ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@ class RequireRoleChecker(

checkInvalidAuthentication()

readCurrentUserPort.readCurrentUser().roles.forEach {
if (it == annotation.role) return
if (!readCurrentUserPort.readCurrentUser().roles.contains(annotation.role)) {
throw AuthenticationException.ROLE_REQUIRED
}

throw AuthenticationException.ROLE_REQUIRED
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ interface AuthenticationManager {
* 이후에 [getAuthentication]을 실행할 때 [UserModelAuthentication.user]가 채워짐
*/
fun setUserNotLoadedAuthentication(username: String)

/**
* 등록된 [UserModelAuthentication] 제거
*/
fun clear()
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ class AuthenticationManagerImpl(
userModelAuthenticationFactory.createEmptyAuthentication(username)
}

override fun clear() {
SecurityContextHolder.clearContext()
}

private fun isInvalidAuthentication(authentication: Authentication?): Boolean =
authentication == null || authentication !is UserModelAuthentication
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ class UserModelAuthenticationFactoryImpl(
UserModelAuthentication(
userSubject = username,
user = readUserPort.readByOAuthId(username)
?: throw CriticalException("Cannot Find User By username : $username")
?: throw CriticalException(
"Cannot Find User By username : $username, user was deleted but token did not revoked."
)
)

override fun createEmptyAuthentication(username: String): UserModelAuthentication =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,8 @@ interface MaeumgagymTokenDecoder {
/**
* 미리 설정된 암호화 키를 이용해 토큰 복호화
*
* @param token 암호화된 상태의 인증용 토큰. 토큰 형태에 따라 그에 해당하는 접두사 필요.
* @param token 암호화된 상태의 인증용 토큰. 마음가짐 토큰 접두사 필요.
* @return 토큰의 정보를 담은 VO
*/
fun decode(token: String): MaeumgagymToken

/**
* 입력된 임의의 암호화 키를 이용해 복호화
*
* @param token 암호화된 상태의 인증용 토큰. 토큰 형태에 따라 그에 해당하는 접두사 필요.
* @param key 암호화 키
*
* @return 토큰의 정보를 담은 VO
*/
fun decode(token: String, key: String): MaeumgagymToken
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import com.info.maeumgagym.security.mgtoken.vo.MaeumgagymTokenPair
*
* 반환되는 [MaeumgagymTokenPair]의 각 토큰은 동일한 [tokenId][com.info.maeumgagym.security.mgtoken.vo.MaeumgagymToken.tokenId]를 가지며, 미리 설정된 [prefix][com.info.maeumgagym.security.mgtoken.env.MaeumgagymTokenProperties.prefix]가 부착됨
*
* [MaeumgagymTokenProperties][com.info.maeumgagym.security.mgtoken.env.MaeumgagymTokenProperties]의 만료 기간 관련 설정들은 초 단위로 반영됨
*
* @see MaeumgagymTokenDecoder
* @see MaeumgagymTokenValidator
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import com.info.maeumgagym.security.mgtoken.vo.MaeumgagymToken
/**
* [MaeumgagymToken]을 무효화.
*
* 토큰의 검증 과정은 거치지 않고, 단순히 [tokenId][MaeumgagymToken.tokenId]를 무효화된 토큰들을 담아두는 [Redis][com.info.maeumgagym.security.mgtoken.revoked.RevokedMGTokenRepository]를 통해 저장
* 토큰의 검증 과정은 거치지 않고, 단순히 [tokenId][MaeumgagymToken.tokenId]를 무효화된 토큰들을 담아두는 [Redis][com.info.maeumgagym.security.mgtoken.revoked.UsableMGTokenRepository]를 통해 저장
*
* [RevokedMGTokenContext][com.info.maeumgagym.security.mgtoken.revoked.RevokedMGTokenContext]를 통해 [Redis][com.info.maeumgagym.security.mgtoken.revoked.RevokedMGTokenRepository]에 접근
* [RevokedMGTokenContext][com.info.maeumgagym.security.mgtoken.revoked.UsableMGTokenContext]를 통해 [Redis][com.info.maeumgagym.security.mgtoken.revoked.UsableMGTokenRepository]에 접근
*
* @see com.info.maeumgagym.security.mgtoken.revoked.RevokedMGTokenContext
* @see com.info.maeumgagym.security.mgtoken.revoked.UsableMGTokenContext
*
* @see MaeumgagymTokenEncoder
* @see MaeumgagymTokenDecoder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ interface MaeumgagymTokenValidator {
* - [tokenId][MaeumgagymToken.tokenId]의 무효화되지 않았는가
* - 토큰의 [유효 시간 길이][MaeumgagymToken.expireAt]가 [의도한 바][MaeumgagymTokenEncoder.encode]와 같은가
* - [토큰 유효 기간][MaeumgagymToken.expireAt]을 지나지 않았는가
* - 토큰 발급 대상과 현재 사용자가 일차하는가: [IP 주소][MaeumgagymToken.ip] 비교
* - [username][MaeumgagymToken.username]이 존재하는가
* - 토큰 발급 대상과 현재 사용자가 일차하는가: [IP 주소][MaeumgagymToken.ip] 비교 (사용자 네트워크 환경에 따라 잦은 주소 변화가 발생할 수 있어 해당 과정은 제거됨.)
*
* @param maeumgagymToken 복호화된 인증용 토큰의 VO
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,11 @@ internal class MaeumgagymTokenDecoderImpl(
) : MaeumgagymTokenDecoder {

override fun decode(token: String): MaeumgagymToken {
return decode(token, maeumgagymTokenProperties.secretKey)
}

override fun decode(token: String, key: String): MaeumgagymToken {
val prefixResolved = resolveTokenPrefix(token)

val decrypted =
try {
decrypt.decrypt(prefixResolved, key)
decrypt.decrypt(prefixResolved, maeumgagymTokenProperties.secretKey)
} catch (e: Exception) {
throw AuthenticationException.INVALID_TOKEN
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.info.maeumgagym.infrastructure.request.context.CurrentRequestContext
import com.info.maeumgagym.security.cryption.Encrypt
import com.info.maeumgagym.security.mgtoken.MaeumgagymTokenEncoder
import com.info.maeumgagym.security.mgtoken.env.MaeumgagymTokenProperties
import com.info.maeumgagym.security.mgtoken.revoked.UsableMGTokenContext
import com.info.maeumgagym.security.mgtoken.vo.MaeumgagymToken
import com.info.maeumgagym.security.mgtoken.vo.MaeumgagymTokenPair
import com.info.maeumgagym.security.mgtoken.vo.MaeumgagymTokenType
Expand All @@ -21,6 +22,7 @@ import java.util.*
@Component
internal class MaeumgagymTokenEncoderImpl(
private val encrypt: Encrypt,
private val usableMGTokenContext: UsableMGTokenContext,
private val currentRequestContext: CurrentRequestContext,
private val maeumgagymTokenProperties: MaeumgagymTokenProperties,
private val objectMapper: ObjectMapper
Expand All @@ -47,6 +49,8 @@ internal class MaeumgagymTokenEncoderImpl(
tokenId = tokenId
)

usableMGTokenContext.saveToken(token)

return appendTokenPrefix(
encryptToken(token)
)
Expand All @@ -65,6 +69,8 @@ internal class MaeumgagymTokenEncoderImpl(
tokenId = tokenId
)

usableMGTokenContext.saveToken(token)

return appendTokenPrefix(
encryptToken(token)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.info.maeumgagym.security.mgtoken.impl

import com.info.maeumgagym.security.mgtoken.MaeumgagymTokenRevoker
import com.info.maeumgagym.security.mgtoken.revoked.RevokedMGTokenContext
import com.info.maeumgagym.security.mgtoken.revoked.UsableMGTokenContext
import com.info.maeumgagym.security.mgtoken.vo.MaeumgagymToken
import org.springframework.stereotype.Component

@Component
class MaeumgagymTokenRevokerImpl(
private val revokedMGTokenContext: RevokedMGTokenContext
private val usableMGTokenContext: UsableMGTokenContext
) : MaeumgagymTokenRevoker {

override fun revoke(token: MaeumgagymToken) {
revokedMGTokenContext.revoke(token)
usableMGTokenContext.revoke(token)
}
}
Loading

0 comments on commit db46c26

Please sign in to comment.