[#20] 도메인별 예외 분리 #21

Merged
pricelees merged 37 commits from refactor/#20 into main 2025-07-24 02:48:53 +00:00
3 changed files with 33 additions and 75 deletions
Showing only changes of commit c6a5927b72 - Show all commits

View File

@ -2,89 +2,51 @@ package roomescape.auth.web.support
import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse import jakarta.servlet.http.HttpServletResponse
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import org.springframework.web.method.HandlerMethod import org.springframework.web.method.HandlerMethod
import org.springframework.web.servlet.HandlerInterceptor import org.springframework.web.servlet.HandlerInterceptor
import roomescape.auth.exception.AuthErrorCode
import roomescape.auth.exception.AuthException
import roomescape.auth.infrastructure.jwt.JwtHandler import roomescape.auth.infrastructure.jwt.JwtHandler
import roomescape.common.exception.ErrorType
import roomescape.common.exception.RoomescapeException
import roomescape.member.business.MemberService import roomescape.member.business.MemberService
import roomescape.member.infrastructure.persistence.MemberEntity import roomescape.member.infrastructure.persistence.MemberEntity
private fun Any.isIrrelevantWith(annotationType: Class<out Annotation>): Boolean {
if (this !is HandlerMethod) {
return true
}
return !this.hasMethodAnnotation(annotationType)
}
@Component @Component
class LoginInterceptor( class AuthInterceptor(
private val memberService: MemberService, private val memberService: MemberService,
private val jwtHandler: JwtHandler private val jwtHandler: JwtHandler
) : HandlerInterceptor { ) : HandlerInterceptor {
override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
@Throws(Exception::class) if (handler !is HandlerMethod) {
override fun preHandle(
request: HttpServletRequest,
response: HttpServletResponse,
handler: Any
): Boolean {
if (handler.isIrrelevantWith(LoginRequired::class.java)) {
return true return true
} }
val loginRequired = handler.getMethodAnnotation(LoginRequired::class.java)
val admin = handler.getMethodAnnotation(Admin::class.java)
if (loginRequired == null && admin == null) {
return true
}
val member: MemberEntity = findMember(request, response)
if (admin != null && !member.isAdmin()) {
response.sendRedirect("/login")
throw AuthException(AuthErrorCode.ACCESS_DENIED)
}
return true
}
private fun findMember(request: HttpServletRequest, response: HttpServletResponse): MemberEntity {
try { try {
val token: String? = request.accessTokenCookie().value val token: String? = request.accessTokenCookie().value
val memberId: Long = jwtHandler.getMemberIdFromToken(token) val memberId: Long = jwtHandler.getMemberIdFromToken(token)
return memberService.existsById(memberId) return memberService.findById(memberId)
} catch (_: RoomescapeException) { } catch (e: Exception) {
response.sendRedirect("/login") response.sendRedirect("/login")
throw RoomescapeException(ErrorType.LOGIN_REQUIRED, HttpStatus.FORBIDDEN) throw e
}
}
}
@Component
class AdminInterceptor(
private val memberService: MemberService,
private val jwtHandler: JwtHandler
) : HandlerInterceptor {
@Throws(Exception::class)
override fun preHandle(
request: HttpServletRequest,
response: HttpServletResponse,
handler: Any
): Boolean {
if (handler.isIrrelevantWith(Admin::class.java)) {
return true
}
val member: MemberEntity?
try {
val token: String? = request.accessTokenCookie().value
val memberId: Long = jwtHandler.getMemberIdFromToken(token)
member = memberService.findById(memberId)
} catch (_: RoomescapeException) {
response.sendRedirect("/login")
throw RoomescapeException(ErrorType.LOGIN_REQUIRED, HttpStatus.FORBIDDEN)
}
with(member) {
if (this.isAdmin()) {
return true
}
response.sendRedirect("/login")
throw RoomescapeException(
ErrorType.PERMISSION_DOES_NOT_EXIST,
String.format("[memberId: %d, Role: %s]", this.id, this.role),
HttpStatus.FORBIDDEN
)
} }
} }
} }

View File

@ -18,7 +18,6 @@ class MemberIdResolver(
return parameter.hasParameterAnnotation(MemberId::class.java) return parameter.hasParameterAnnotation(MemberId::class.java)
} }
@Throws(Exception::class)
override fun resolveArgument( override fun resolveArgument(
parameter: MethodParameter, parameter: MethodParameter,
mavContainer: ModelAndViewContainer?, mavContainer: ModelAndViewContainer?,

View File

@ -4,15 +4,13 @@ import org.springframework.context.annotation.Configuration
import org.springframework.web.method.support.HandlerMethodArgumentResolver import org.springframework.web.method.support.HandlerMethodArgumentResolver
import org.springframework.web.servlet.config.annotation.InterceptorRegistry import org.springframework.web.servlet.config.annotation.InterceptorRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import roomescape.auth.web.support.AdminInterceptor import roomescape.auth.web.support.AuthInterceptor
import roomescape.auth.web.support.LoginInterceptor
import roomescape.auth.web.support.MemberIdResolver import roomescape.auth.web.support.MemberIdResolver
@Configuration @Configuration
class WebMvcConfig( class WebMvcConfig(
private val memberIdResolver: MemberIdResolver, private val memberIdResolver: MemberIdResolver,
private val adminInterceptor: AdminInterceptor, private val authInterceptor: AuthInterceptor
private val loginInterceptor: LoginInterceptor
) : WebMvcConfigurer { ) : WebMvcConfigurer {
override fun addArgumentResolvers(resolvers: MutableList<HandlerMethodArgumentResolver>) { override fun addArgumentResolvers(resolvers: MutableList<HandlerMethodArgumentResolver>) {
@ -20,7 +18,6 @@ class WebMvcConfig(
} }
override fun addInterceptors(registry: InterceptorRegistry) { override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(adminInterceptor) registry.addInterceptor(authInterceptor)
registry.addInterceptor(loginInterceptor)
} }
} }