diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a534a92..e2307a9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -6,6 +6,7 @@ on: - dev - ci/* - cd/* + - fix/test/* workflow_dispatch: jobs: diff --git a/src/main/java/com/bootcamp/savemypodo/config/jwt/JwtAuthenticationFilter.java b/src/main/java/com/bootcamp/savemypodo/config/jwt/JwtAuthenticationFilter.java index f114430..eb4cbae 100644 --- a/src/main/java/com/bootcamp/savemypodo/config/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/bootcamp/savemypodo/config/jwt/JwtAuthenticationFilter.java @@ -36,11 +36,10 @@ protected void doFilterInternal(HttpServletRequest request, throws ServletException, IOException { String uri = request.getRequestURI(); - log.info("πŸ” [JWT ν•„ν„°] μ‹œμž‘: {}", uri); - if (uri.equals("/") || uri.startsWith("/login") || uri.equals("/api/musicals") || uri.equals("/actuator/prometheus") || uri.equals("/api/user/me")) { + + // μ—¬κΈ° κ²½λ‘œλŠ” Jwt Filter λ¬΄μ‹œ + if (uri.equals("/") || uri.startsWith("/login") || uri.equals("/api/musicals") || uri.equals("/actuator/prometheus")) { filterChain.doFilter(request, response); // κ·Έλƒ₯ 톡과 - /*if (uri.equals("/") || uri.startsWith("/login") || uri.equals("/api/musicals")) { - filterChain.doFilter(request, response);*/ return; } @@ -48,8 +47,6 @@ protected void doFilterInternal(HttpServletRequest request, String refreshToken = cookieUtil.getTokenFromCookie(request, "refreshToken"); log.info("πŸ” [JWT ν•„ν„°] μš”μ²­ URI: {}", uri); - log.info("πŸ”‘ accessToken 쑴재 μ—¬λΆ€: {}", accessToken != null); - log.info("πŸ”‘ refreshToken 쑴재 μ—¬λΆ€: {}", refreshToken != null); try { if (accessToken != null && jwtTokenProvider.validateToken(accessToken)) { diff --git a/src/main/java/com/bootcamp/savemypodo/config/security/SecurityConfig.java b/src/main/java/com/bootcamp/savemypodo/config/security/SecurityConfig.java index b8fe577..0883e02 100644 --- a/src/main/java/com/bootcamp/savemypodo/config/security/SecurityConfig.java +++ b/src/main/java/com/bootcamp/savemypodo/config/security/SecurityConfig.java @@ -9,9 +9,12 @@ import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.List; @@ -25,43 +28,65 @@ public class SecurityConfig { @Value("${frontend.url}") private String frontendUrl; - @Value("${backend.url}") - private String backendUrl; + + private final String[] allowUrls = { + "/", "/favicon.ico", "/actuator/**", "/api/auth/**", "/error", "/oauth/**" + }; + + @Bean + public WebSecurityCustomizer configure() { + return web -> web.ignoring().requestMatchers(allowUrls); + } @Bean - public SecurityFilterChain filterChain(HttpSecurity http, OAuth2SuccessHandler oAuth2SuccessHandler, OAuth2FailureHandler oAuth2FailureHandler, + public SecurityFilterChain filterChain(HttpSecurity http, + OAuth2SuccessHandler oAuth2SuccessHandler, + OAuth2FailureHandler oAuth2FailureHandler, JwtAuthenticationFilter jwtAuthenticationFilter) throws Exception { log.info("[SecurityConfig]: μ§„μž…"); - http - .cors(cors -> cors.configurationSource(request -> { - CorsConfiguration config = new CorsConfiguration(); - config.setAllowedOrigins(List.of(frontendUrl)); // ν”„λ‘ νŠΈ μ£Όμ†Œ - config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); - config.setAllowedHeaders(List.of("*")); - config.setAllowCredentials(true); - return config; - })) + http + .cors(cors -> cors.configurationSource(corsConfigurationSource())) .csrf(csrf -> csrf.disable()) - .authorizeHttpRequests(auth -> auth .requestMatchers("/", "/login", "/api/musicals", "/actuator/prometheus", "/api/user/me").permitAll() .requestMatchers("/api/admin/**").hasRole("ADMIN") .requestMatchers("/api/user/**", "/api/reservations/**", "/api/musicals/**").hasRole("USER") .anyRequest().authenticated() ) - .oauth2Login(oauth2 -> oauth2 - .userInfoEndpoint(userInfo -> userInfo - .userService(customOAuth2UserService) - ) + .userInfoEndpoint(userInfo -> userInfo.userService(customOAuth2UserService)) .successHandler(oAuth2SuccessHandler) .failureHandler(oAuth2FailureHandler) ) .logout(logout -> logout.disable()) - .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } + + /** + * βœ… Cors μ„€μ • 뢄리 - Credentials + Exposed Headers λ“± λͺ…μ‹œ + */ + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOrigins(List.of(frontendUrl)); + configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); + configuration.setAllowedHeaders(List.of( + "Authorization", + "Content-Type", + "X-Requested-With", + "social_access_token" + )); + configuration.setExposedHeaders(List.of( + "Authorization", + "Set-Cookie" + )); + configuration.setAllowCredentials(true); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } } \ No newline at end of file diff --git a/src/main/java/com/bootcamp/savemypodo/config/security/utils/CookieUtil.java b/src/main/java/com/bootcamp/savemypodo/config/security/utils/CookieUtil.java index 0e8d5c2..880c2b2 100644 --- a/src/main/java/com/bootcamp/savemypodo/config/security/utils/CookieUtil.java +++ b/src/main/java/com/bootcamp/savemypodo/config/security/utils/CookieUtil.java @@ -12,7 +12,7 @@ @RequiredArgsConstructor public class CookieUtil { - JwtTokenProvider jwtTokenProvider; + private final JwtTokenProvider jwtTokenProvider; // βœ… 곡톡 μΏ ν‚€ 생성 μœ ν‹Έ public Cookie createCookie(String type, String token) { @@ -30,7 +30,7 @@ public Cookie createCookie(String type, String token) { cookie.setSecure(true); cookie.setPath("/"); cookie.setMaxAge((int) (expirationTime / 1000)); - cookie.setDomain(".savemypodo.shop"); // ν•˜μœ„ λ„λ©”μΈκΉŒμ§€ ν—ˆμš© +// cookie.setDomain(".savemypodo.shop"); // ν•˜μœ„ λ„λ©”μΈκΉŒμ§€ ν—ˆμš© cookie.setAttribute("SameSite", "None"); // CORS ν—ˆμš© return cookie; diff --git a/src/main/java/com/bootcamp/savemypodo/controller/HealthController.java b/src/main/java/com/bootcamp/savemypodo/controller/HealthController.java new file mode 100644 index 0000000..d2bc0b0 --- /dev/null +++ b/src/main/java/com/bootcamp/savemypodo/controller/HealthController.java @@ -0,0 +1,13 @@ +package com.bootcamp.savemypodo.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HealthController { + @GetMapping("/") + public ResponseEntity health() { + return ResponseEntity.ok("OK"); + } +} diff --git a/src/main/java/com/bootcamp/savemypodo/controller/UserController.java b/src/main/java/com/bootcamp/savemypodo/controller/UserController.java index 2cbb0bd..2b1ce66 100644 --- a/src/main/java/com/bootcamp/savemypodo/controller/UserController.java +++ b/src/main/java/com/bootcamp/savemypodo/controller/UserController.java @@ -1,7 +1,6 @@ package com.bootcamp.savemypodo.controller; import com.bootcamp.savemypodo.config.security.utils.CookieUtil; -import com.bootcamp.savemypodo.dto.reservation.MyReservationResponse; import com.bootcamp.savemypodo.dto.user.UserResponse; import com.bootcamp.savemypodo.entity.User; import com.bootcamp.savemypodo.global.exception.ErrorCode; @@ -22,8 +21,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.List; - @Slf4j @RestController @RequestMapping("/api/user") @@ -82,11 +79,4 @@ public ResponseEntity getMyInfo(@AuthenticationPrincipal User user return ResponseEntity.ok(userResponse); } - - @GetMapping("/my-reservations") - public ResponseEntity> getMyReservations(@AuthenticationPrincipal User user) { - List myReservations = reservationService.getMyReservationsByUser(user); - return ResponseEntity.ok(myReservations); - } - } diff --git a/src/main/java/com/bootcamp/savemypodo/service/ReservationService.java b/src/main/java/com/bootcamp/savemypodo/service/ReservationService.java index 8b79c2e..17692bf 100644 --- a/src/main/java/com/bootcamp/savemypodo/service/ReservationService.java +++ b/src/main/java/com/bootcamp/savemypodo/service/ReservationService.java @@ -1,6 +1,5 @@ package com.bootcamp.savemypodo.service; -import com.bootcamp.savemypodo.dto.reservation.MyReservationResponse; import com.bootcamp.savemypodo.entity.Musical; import com.bootcamp.savemypodo.entity.Reservation; import com.bootcamp.savemypodo.entity.Seat; @@ -20,7 +19,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -90,12 +88,6 @@ public void doReservation(User user, Long mid, String seatName) { redisSeatService.cacheSeatsForMusicalIfHot(mid); } - - public List getMyReservationsByUser(User user) { - List reservations = reservationRepository.findAllByUser(user); - return reservations.stream().map(MyReservationResponse::fromEntity).collect(Collectors.toList()); - } - @Transactional public void cancelReservation(Long userId, Long musicalId) { // 1. λ¨Όμ € μ˜ˆμ•½μ΄ μ‹€μ œλ‘œ μ‘΄μž¬ν•˜λŠ”μ§€ 확인 @@ -122,5 +114,4 @@ public void cancelReservation(Long userId, Long musicalId) { redisSeatService.cacheSeatsForMusicalIfHot(musicalId); } - -} +} \ No newline at end of file