Skip to content

Commit

Permalink
Merge pull request #75 from KUIT-Space/feat/#71/userSpacevalidationIn…
Browse files Browse the repository at this point in the history
…terceptor

userSpace 검증 인터셉터 개발
  • Loading branch information
drbug2000 authored Aug 12, 2024
2 parents 6710738 + 559f968 commit fbd098d
Show file tree
Hide file tree
Showing 19 changed files with 254 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package space.space_spring.argument_resolver.jwtLogin;
package space.space_spring.argumentResolver.jwtLogin;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package space.space_spring.argument_resolver.jwtLogin;
package space.space_spring.argumentResolver.jwtLogin;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package space.space_spring.argumentResolver.userSpace;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckUserSpace {
boolean required() default true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package space.space_spring.argumentResolver.userSpace;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserSpaceAuth {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package space.space_spring.argumentResolver.userSpace;

import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
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 space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import space.space_spring.dao.UserSpaceDao;

@Component
@RequiredArgsConstructor
public class UserSpaceAuthHandlerArgumentResolver implements HandlerMethodArgumentResolver {

private final UserSpaceDao userSpaceDao;
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 일단 parameter의 return value type 을 검사하지는 X
return parameter.hasParameterAnnotation(UserSpaceAuth.class);
}

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
return
userSpaceDao.findUserSpaceAuthById((Long)request.getAttribute("userSpaceId"));

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package space.space_spring.argumentResolver.userSpace;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserSpaceId {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package space.space_spring.argumentResolver.userSpace;

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 space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;

@Component
public class UserSpaceIdHandlerArgumentResolver implements HandlerMethodArgumentResolver {

@Override
public boolean supportsParameter(MethodParameter parameter) {
// 일단 parameter의 return value type 을 검사하지는 X
return parameter.hasParameterAnnotation(UserSpaceId.class);
}

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
return request.getAttribute("userSpaceId");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package space.space_spring.config;

import lombok.Getter;

@Getter
public enum UserSpaceValidationInterceptorURL {
//SPACE("/space/**"),
TEST("/space/{spaceId}/test/**"),
;

private final String urlPattern;

UserSpaceValidationInterceptorURL(String urlPattern) {
this.urlPattern = urlPattern;
}
}
20 changes: 19 additions & 1 deletion src/main/java/space/space_spring/config/WebConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuthHandlerArgumentResolver;
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuthHandlerArgumentResolver;
import space.space_spring.argumentResolver.userSpace.UserSpaceAuth;
import space.space_spring.argumentResolver.userSpace.UserSpaceAuthHandlerArgumentResolver;
import space.space_spring.argumentResolver.userSpace.UserSpaceIdHandlerArgumentResolver;
import space.space_spring.interceptor.UserSpaceValidationInterceptor;
import space.space_spring.interceptor.jwtLogin.JwtLoginAuthInterceptor;

import java.util.List;
Expand All @@ -19,6 +23,9 @@ public class WebConfig implements WebMvcConfigurer {
private final JwtLoginAuthInterceptor jwtLoginAuthInterceptor;

private final JwtLoginAuthHandlerArgumentResolver jwtLoginAuthHandlerArgumentResolver;
private final UserSpaceIdHandlerArgumentResolver userSpaceIdHandlerArgumentResolver;
private final UserSpaceAuthHandlerArgumentResolver userSpaceAuthHandlerArgumentResolver;
private final UserSpaceValidationInterceptor userSpaceValidationInterceptor;

private static final String DEVELOP_FRONT_ADDRESS = "http://localhost:5173";

Expand All @@ -31,11 +38,22 @@ public void addInterceptors(InterceptorRegistry registry) {
for (InterceptorURL interceptorURL : InterceptorURL.values()) {
registration.addPathPatterns(interceptorURL.getUrlPattern());
}

InterceptorRegistration userSpaceRegistration =
registry.addInterceptor(userSpaceValidationInterceptor)
.order(2);
for(UserSpaceValidationInterceptorURL url:UserSpaceValidationInterceptorURL.values()) {
userSpaceRegistration.addPathPatterns(url.getUrlPattern());
}


}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(jwtLoginAuthHandlerArgumentResolver);
argumentResolvers.add(userSpaceIdHandlerArgumentResolver);
argumentResolvers.add(userSpaceAuthHandlerArgumentResolver);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth;
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import space.space_spring.dto.chat.request.CreateChatRoomRequest;
import space.space_spring.dto.chat.request.JoinChatRoomRequest;
import space.space_spring.dto.chat.response.ChatSuccessResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth;
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import space.space_spring.dto.pay.dto.PayReceiveInfoDto;
import space.space_spring.dto.pay.dto.PayRequestInfoDto;
import space.space_spring.dto.pay.dto.PayTargetInfoDto;
import space.space_spring.dto.pay.dto.TotalPayInfoDto;
import space.space_spring.dto.pay.request.PostPayCompleteRequest;
import space.space_spring.dto.pay.request.PostPayCreateRequest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import org.springframework.web.multipart.MultipartFile;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth;
import space.space_spring.dto.post.request.CreatePostRequest;
import space.space_spring.dto.post.response.ReadPostsResponse;

import space.space_spring.entity.UserSpace;
import space.space_spring.exception.PostException;
import space.space_spring.exception.SpaceException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth;
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import space.space_spring.dto.space.GetSpaceJoinDto;
import space.space_spring.dto.space.PostSpaceJoinDto;
import space.space_spring.dto.space.response.GetUserInfoBySpaceResponse;
Expand Down
34 changes: 33 additions & 1 deletion src/main/java/space/space_spring/controller/TestController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth;
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;

import space.space_spring.argumentResolver.userSpace.CheckUserSpace;
import space.space_spring.argumentResolver.userSpace.UserSpaceAuth;
import space.space_spring.argumentResolver.userSpace.UserSpaceId;
import space.space_spring.response.BaseResponse;

@RestController
Expand All @@ -22,4 +26,32 @@ public BaseResponse<String> jwtLoginTest(@JwtLoginAuth Long userId) {
return new BaseResponse<>("jwt login test 성공");
}

@GetMapping("/space/{spaceId}/test")
public BaseResponse<String> LoginTest(
@JwtLoginAuth Long userId,
@UserSpaceId Long userSpaceId,
@UserSpaceAuth String userSpaceAuth) {
log.info("userId = {}", userId);
return new BaseResponse<>("{ userId : "+ userId.toString()
+""
+"userSpaceId : "+userSpaceId
+""
+"userSpaceAuth : "+userSpaceAuth

+ "}"
);
}

@GetMapping("/space/{spaceId}/test/pass")
@CheckUserSpace(required = false)
public BaseResponse<String> LoginPassAnnotaionTest(
@JwtLoginAuth Long userId,
@PathVariable Long spaceId
){
return new BaseResponse<>("{ userId : "+ userId.toString()
+"");
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth;
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import space.space_spring.dto.user.request.PostUserLoginRequest;
import space.space_spring.dto.user.request.PostUserSignupRequest;
import space.space_spring.dto.user.response.GetSpaceInfoForUserResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth;
import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth;
import space.space_spring.dao.UserSpaceDao;
import space.space_spring.dao.VoiceRoomRepository;
import space.space_spring.dto.VoiceRoom.*;
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/space/space_spring/dao/UserSpaceDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.TypedQuery;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import space.space_spring.dto.user.dto.SpaceChoiceInfo;
import space.space_spring.dto.user.dto.SpaceChoiceViewDto;
import space.space_spring.dto.userSpace.UserInfoInSpace;
Expand Down Expand Up @@ -116,4 +117,13 @@ public int calculateSpaceMemberNum(Space space) {

return query.getSingleResult().intValue();
}


@Transactional(readOnly = true)
public String findUserSpaceAuthById(Long userSpaceId) {
String jpql = "SELECT us.userSpaceAuth FROM UserSpace us WHERE us.userSpaceId = :userSpaceId";
return em.createQuery(jpql, String.class)
.setParameter("userSpaceId", userSpaceId)
.getSingleResult();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package space.space_spring.interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import space.space_spring.argumentResolver.userSpace.CheckUserSpace;
import space.space_spring.dao.SpaceDao;
import space.space_spring.dao.UserDao;
import space.space_spring.dao.UserSpaceDao;
import space.space_spring.entity.Space;
import space.space_spring.entity.User;
import space.space_spring.entity.UserSpace;
import space.space_spring.exception.CustomException;
import space.space_spring.exception.UserSpaceException;

import java.util.Map;
import java.util.Optional;

import static space.space_spring.response.status.BaseExceptionResponseStatus.*;

@Component
@RequiredArgsConstructor
public class UserSpaceValidationInterceptor implements HandlerInterceptor {

private final UserSpaceDao userSpaceDao;
private final UserDao userDao;
private final SpaceDao spaceDao;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception{

// @CheckUserSpace(require=false)인 경우 검증하지 않음
HandlerMethod handlerMethod = (HandlerMethod) handler;
CheckUserSpace methodAnnotation= handlerMethod.getMethodAnnotation(CheckUserSpace.class);
if(methodAnnotation!=null && !methodAnnotation.required()){
System.out.print("[DeBug]Interceptor pass By Annotation");
return true;
}
Long userId = (Long) request.getAttribute("userId");

// URL에서 spaceId 추출
Map pathVariables = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
Long spaceId = Long.parseLong((String) pathVariables.get("spaceId"));

request.setAttribute("userSpaceId",getUserSpace(spaceId,userId));
System.out.print("userSpaceID:"+getUserSpace(spaceId,userId));
return true;

}

private Long getUserSpace(long spaceId,long userId){
// userSpaceDao에서 검증
User userByUserId = userDao.findUserByUserId(userId);
if(userByUserId==null){
throw new CustomException(CANNOT_FIND_USER_ID);
}
Space spaceBySpaceId = spaceDao.findSpaceBySpaceId(spaceId);
if(spaceBySpaceId==null){
throw new CustomException(SPACE_NOT_FOUND);
}
Optional<UserSpace> userSpace = userSpaceDao.findUserSpaceByUserAndSpace(userByUserId, spaceBySpaceId);
Optional.ofNullable(userSpace
.orElseThrow(() -> new UserSpaceException(USER_IS_NOT_IN_SPACE)));
return userSpace.get().getUserSpaceId();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public enum BaseExceptionResponseStatus implements ResponseStatus {
MALFORMED_TOKEN(4004, HttpStatus.UNAUTHORIZED, "토큰이 올바르게 구성되지 않았습니다."),
EXPIRED_TOKEN(4005, HttpStatus.UNAUTHORIZED, "만료된 토큰입니다."),
TOKEN_MISMATCH(4006, HttpStatus.UNAUTHORIZED, "로그인 정보가 토큰 정보와 일치하지 않습니다."),
CANNOT_FIND_USER_ID(4007, HttpStatus.UNAUTHORIZED,"토큰의 userId정보를 찾을 수 없습니다."),

/**
* 5000: User 오류
Expand All @@ -53,9 +54,11 @@ public enum BaseExceptionResponseStatus implements ResponseStatus {
* 6000: Space 오류
*/
INVALID_SPACE_CREATE(6000, HttpStatus.BAD_REQUEST, "스페이스 생성 요청에서 잘못된 값이 존재합니다."),

SPACE_NOT_FOUND(6001, HttpStatus.BAD_REQUEST, "존재하지 않는 스페이스입니다."),
INVALID_USER_SPACE_PROFILE(6002, HttpStatus.BAD_REQUEST, "스페이스 별 유저 프로필 정보 수정 요청에서 잘못된 값이 존재합니다."),
INVALID_SPACE_JOIN_REQUEST(6003, HttpStatus.BAD_REQUEST, "스페이스 가입 요청에서 잘못된 값이 존재합니다."),

nff(6004, HttpStatus.BAD_REQUEST, "비밀번호가 일치하지 않습니다."),
gnf(6005, HttpStatus.BAD_REQUEST, "잘못된 회원 status 값입니다."),
fb(6006, HttpStatus.BAD_REQUEST, "존재하지 않는 이메일입니다."),
Expand Down

0 comments on commit fbd098d

Please sign in to comment.