diff --git a/src/main/kotlin/roomescape/auth/web/support/AuthAnnotations.kt b/src/main/kotlin/roomescape/auth/web/support/AuthAnnotations.kt index f06e0bc2..5cc61d1e 100644 --- a/src/main/kotlin/roomescape/auth/web/support/AuthAnnotations.kt +++ b/src/main/kotlin/roomescape/auth/web/support/AuthAnnotations.kt @@ -31,3 +31,7 @@ annotation class Authenticated @Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) annotation class Public + +@Target(AnnotationTarget.VALUE_PARAMETER) +@Retention(AnnotationRetention.RUNTIME) +annotation class CurrentUser diff --git a/src/main/kotlin/roomescape/auth/web/support/resolver/CurrentUserContextResolver.kt b/src/main/kotlin/roomescape/auth/web/support/resolver/CurrentUserContextResolver.kt new file mode 100644 index 00000000..662537db --- /dev/null +++ b/src/main/kotlin/roomescape/auth/web/support/resolver/CurrentUserContextResolver.kt @@ -0,0 +1,54 @@ +package roomescape.auth.web.support.resolver + +import io.github.oshai.kotlinlogging.KLogger +import io.github.oshai.kotlinlogging.KotlinLogging +import jakarta.servlet.http.HttpServletRequest +import org.springframework.core.MethodParameter +import org.springframework.stereotype.Component +import org.springframework.web.bind.support.WebDataBinderFactory +import org.springframework.web.context.request.NativeWebRequest +import org.springframework.web.method.support.HandlerMethodArgumentResolver +import org.springframework.web.method.support.ModelAndViewContainer +import roomescape.auth.business.AuthServiceV2 +import roomescape.auth.business.CLAIM_TYPE_KEY +import roomescape.auth.exception.AuthErrorCode +import roomescape.auth.exception.AuthException +import roomescape.auth.infrastructure.jwt.JwtUtils +import roomescape.auth.web.support.CurrentUser +import roomescape.auth.web.support.accessToken +import roomescape.common.dto.PrincipalType + +private val log: KLogger = KotlinLogging.logger {} + +@Component +class CurrentUserContextResolver( + private val jwtUtils: JwtUtils, + private val authService: AuthServiceV2 +) : HandlerMethodArgumentResolver { + + override fun supportsParameter(parameter: MethodParameter): Boolean { + return parameter.hasParameterAnnotation(CurrentUser::class.java) + } + + override fun resolveArgument( + parameter: MethodParameter, + mavContainer: ModelAndViewContainer?, + webRequest: NativeWebRequest, + binderFactory: WebDataBinderFactory? + ): Any? { + val request: HttpServletRequest = webRequest.nativeRequest as HttpServletRequest + val token: String? = request.accessToken() + + try { + val id: String = jwtUtils.extractSubject(token) + val type: PrincipalType = PrincipalType.valueOf(jwtUtils.extractClaim(token, CLAIM_TYPE_KEY)) + + return authService.findContextById(id.toLong(), type) + } catch (e: Exception) { + log.info { "[MemberIdResolver] 회원 조회 실패. message=${e.message}" } + val errorCode = AuthErrorCode.MEMBER_NOT_FOUND + throw AuthException(errorCode, e.message ?: errorCode.message) + } + } +} +