diff --git a/src/main/java/com/example/solidconnection/security/aspect/RoleAuthorizationAspect.java b/src/main/java/com/example/solidconnection/security/aspect/RoleAuthorizationAspect.java index 900251514..55d640ed2 100644 --- a/src/main/java/com/example/solidconnection/security/aspect/RoleAuthorizationAspect.java +++ b/src/main/java/com/example/solidconnection/security/aspect/RoleAuthorizationAspect.java @@ -1,16 +1,21 @@ package com.example.solidconnection.security.aspect; import static com.example.solidconnection.common.exception.ErrorCode.ACCESS_DENIED; +import static com.example.solidconnection.common.exception.ErrorCode.USER_NOT_FOUND; import com.example.solidconnection.common.exception.CustomException; +import com.example.solidconnection.common.resolver.AuthorizedUser; import com.example.solidconnection.security.annotation.RequireRoleAccess; import com.example.solidconnection.siteuser.domain.Role; import com.example.solidconnection.siteuser.domain.SiteUser; +import com.example.solidconnection.siteuser.repository.SiteUserRepository; +import java.lang.reflect.Parameter; import java.util.Arrays; import lombok.RequiredArgsConstructor; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; @Aspect @@ -18,24 +23,49 @@ @RequiredArgsConstructor public class RoleAuthorizationAspect { - // todo: 추후 siteUserId로 파라미터 변경 시 수정 필요 + private final SiteUserRepository siteUserRepository; + + // todo: 추후 개선 필요 @Around("@annotation(requireRoleAccess)") public Object checkRoleAccess(ProceedingJoinPoint joinPoint, RequireRoleAccess requireRoleAccess) throws Throwable { - SiteUser siteUser = null; - for (Object arg : joinPoint.getArgs()) { - if (arg instanceof SiteUser) { - siteUser = (SiteUser) arg; - break; - } - } - if (siteUser == null) { + + Long siteUserId = extractAuthorizedUserId(joinPoint); + + if (siteUserId == null) { throw new CustomException(ACCESS_DENIED); } - Role[] allowedRoles = requireRoleAccess.roles(); + + SiteUser siteUser = siteUserRepository.findById(siteUserId) + .orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + + validateUserRole(siteUser, requireRoleAccess.roles()); + + return joinPoint.proceed(); + } + + private Long extractAuthorizedUserId(ProceedingJoinPoint joinPoint) { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Parameter[] parameters = signature.getMethod().getParameters(); + Object[] args = joinPoint.getArgs(); + + for (int i = 0; i < parameters.length; i++) { + if (parameters[i].isAnnotationPresent(AuthorizedUser.class)) { + Object arg = args[i]; + if (arg instanceof Long) { + return (Long) arg; + } else if (parameters[i].getType() == long.class) { + return (Long) arg; + } + } + } + return null; + } + + private void validateUserRole(SiteUser siteUser, Role[] allowedRoles) { boolean hasAccess = Arrays.asList(allowedRoles).contains(siteUser.getRole()); + if (!hasAccess) { throw new CustomException(ACCESS_DENIED); } - return joinPoint.proceed(); } } diff --git a/src/test/java/com/example/solidconnection/security/aspect/RoleAuthorizationAspectTest.java b/src/test/java/com/example/solidconnection/security/aspect/RoleAuthorizationAspectTest.java index 62be411ee..e68c61782 100644 --- a/src/test/java/com/example/solidconnection/security/aspect/RoleAuthorizationAspectTest.java +++ b/src/test/java/com/example/solidconnection/security/aspect/RoleAuthorizationAspectTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.example.solidconnection.common.exception.CustomException; +import com.example.solidconnection.common.resolver.AuthorizedUser; import com.example.solidconnection.security.annotation.RequireRoleAccess; import com.example.solidconnection.siteuser.domain.Role; import com.example.solidconnection.siteuser.domain.SiteUser; @@ -35,9 +36,9 @@ class RoleAuthorizationAspectTest { // when & then assertAll( - () -> assertThatCode(() -> testService.adminOnlyMethod(admin)) + () -> assertThatCode(() -> testService.adminOnlyMethod(admin.getId())) .doesNotThrowAnyException(), - () -> assertThatCode(() -> testService.mentorOrAdminMethod(mentor)) + () -> assertThatCode(() -> testService.mentorOrAdminMethod(mentor.getId())) .doesNotThrowAnyException() ); } @@ -48,7 +49,7 @@ class RoleAuthorizationAspectTest { SiteUser user = siteUserFixture.사용자(); // when & then - assertThatCode(() -> testService.mentorOrAdminMethod(user)) + assertThatCode(() -> testService.mentorOrAdminMethod(user.getId())) .isInstanceOf(CustomException.class) .hasMessage(ACCESS_DENIED.getMessage()); } @@ -62,11 +63,11 @@ class RoleAuthorizationAspectTest { // when & then assertAll( - () -> assertThatCode(() -> testService.publicMethod(admin)) + () -> assertThatCode(() -> testService.publicMethod(admin.getId())) .doesNotThrowAnyException(), - () -> assertThatCode(() -> testService.publicMethod(mentor)) + () -> assertThatCode(() -> testService.publicMethod(mentor.getId())) .doesNotThrowAnyException(), - () -> assertThatCode(() -> testService.publicMethod(user)) + () -> assertThatCode(() -> testService.publicMethod(user.getId())) .doesNotThrowAnyException() ); } @@ -84,16 +85,16 @@ public TestService testService() { static class TestService { @RequireRoleAccess(roles = {Role.ADMIN}) - public boolean adminOnlyMethod(SiteUser siteUser) { + public boolean adminOnlyMethod(@AuthorizedUser long siteUserId) { return true; } @RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR}) - public boolean mentorOrAdminMethod(SiteUser siteUser) { + public boolean mentorOrAdminMethod(@AuthorizedUser long siteUserId) { return true; } - public boolean publicMethod(SiteUser siteUser) { + public boolean publicMethod(@AuthorizedUser long siteUserId) { return true; } }