From ec67f89eb4b0ed6182a838aeec6a452d24609c9e Mon Sep 17 00:00:00 2001 From: bjkim Date: Tue, 5 Aug 2025 17:06:20 +0900 Subject: [PATCH] =?UTF-8?q?[ADD]=20CORS=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../autoflow/common/LoggingInterceptor.java | 48 +++++++++++++++++++ .../autoflow/common/WebConfiguration.java | 29 +++++++++++ .../autoflow/controllers/AuthController.java | 24 +++++++++- 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/main/java/kr/re/etri/autoflow/common/LoggingInterceptor.java create mode 100644 src/main/java/kr/re/etri/autoflow/common/WebConfiguration.java diff --git a/src/main/java/kr/re/etri/autoflow/common/LoggingInterceptor.java b/src/main/java/kr/re/etri/autoflow/common/LoggingInterceptor.java new file mode 100644 index 0000000..2d5873c --- /dev/null +++ b/src/main/java/kr/re/etri/autoflow/common/LoggingInterceptor.java @@ -0,0 +1,48 @@ +package kr.re.etri.autoflow.common; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +@Slf4j +public class LoggingInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, + @NonNull Object handler) { + String userId = request.getHeader("userId"); + String path = request.getRequestURI(); + String method = request.getMethod(); + + //정적인 리소스 로깅 안하게 처리 + if (!(handler instanceof HandlerMethod)) { + log.debug(">>> Static resource or non-handler request. API: {}, method: {}, userId: {}", path, method, userId); + return true; + } + + String handlerName = ((HandlerMethod) handler).getBeanType().getSimpleName(); + log.info(">>> {} invoked. API: {}, method: {}, userId: {}", handlerName, path, method, userId); + return true; + } + + + @Override + public void postHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, + @NonNull Object handler, @Nullable ModelAndView modelAndView) { + log.info("API Response: {}, userId: {}, status: {}", request.getRequestURI(), + request.getHeader("userId"), response.getStatus()); + } + + @Override + public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, + @NonNull Object handler, @Nullable Exception ex) { + if (ex != null) { + log.error("Error during request: {}", ex.getMessage()); + } + } +} diff --git a/src/main/java/kr/re/etri/autoflow/common/WebConfiguration.java b/src/main/java/kr/re/etri/autoflow/common/WebConfiguration.java new file mode 100644 index 0000000..05efb1a --- /dev/null +++ b/src/main/java/kr/re/etri/autoflow/common/WebConfiguration.java @@ -0,0 +1,29 @@ +package kr.re.etri.autoflow.common; + +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfiguration implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowedMethods(HttpMethod.GET.name(), + HttpMethod.HEAD.name(), + HttpMethod.POST.name(), + HttpMethod.PUT.name(), + HttpMethod.DELETE.name()) + .maxAge(3600); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new LoggingInterceptor()) + .addPathPatterns("/**"); // Intercepts all requests + } +} diff --git a/src/main/java/kr/re/etri/autoflow/controllers/AuthController.java b/src/main/java/kr/re/etri/autoflow/controllers/AuthController.java index b8b41d3..2ee0ca5 100644 --- a/src/main/java/kr/re/etri/autoflow/controllers/AuthController.java +++ b/src/main/java/kr/re/etri/autoflow/controllers/AuthController.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import io.swagger.v3.oas.annotations.Parameter; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; @@ -193,6 +194,28 @@ public class AuthController { return ResponseEntity.badRequest().body(new MessageResponse(false,"Refresh Token is empty!")); } + @Operation(summary = "사용자 조회", description = "사용자 ID로 등록된 사용자 정보를 조회합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "사용자 조회 성공"), + @ApiResponse(responseCode = "404", description = "해당 ID의 사용자를 찾을 수 없음") + }) + @GetMapping("/users/{id}") + public ResponseEntity getUserById( + @Parameter(description = "사용자 ID", example = "1") @PathVariable Long id) { + + return userRepository.findById(id) + .map(user -> new UserInfoResponse( + user.getId(), + user.getUsername(), + user.getEmail(), + user.getRoles().stream() + .map(role -> role.getName().name()) + .toList() + )) + .map(ResponseEntity::ok) + .orElse(ResponseEntity.notFound().build()); + } + @Operation(summary = "전체 사용자 조회", description = "등록된 모든 사용자 목록을 조회합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "사용자 목록 조회 성공") @@ -212,5 +235,4 @@ public class AuthController { return ResponseEntity.ok(users); } - }