From 79fdec97281eb585130ad41112278ce5c14b0cc9 Mon Sep 17 00:00:00 2001 From: TueBack Date: Mon, 12 Jan 2026 00:09:33 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=97=AC=ED=96=89=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D/=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EB=B9=84?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=A0=91=EA=B7=BC=20=ED=97=88?= =?UTF-8?q?=EC=9A=A9=20=EB=B0=8F=20=EC=9D=B8=EC=A6=9D=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/request/context/WithUserContext.java | 6 +- .../filter/AuthenticationFilter.java | 58 +++++++------------ .../resolver/UserContextArgumentResolver.java | 18 ++++-- .../in/presentation/rest/TripController.java | 13 +++-- 4 files changed, 45 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/retrip/trip/application/in/request/context/WithUserContext.java b/src/main/java/com/retrip/trip/application/in/request/context/WithUserContext.java index 73b9228..65d9ea7 100644 --- a/src/main/java/com/retrip/trip/application/in/request/context/WithUserContext.java +++ b/src/main/java/com/retrip/trip/application/in/request/context/WithUserContext.java @@ -1,14 +1,14 @@ package com.retrip.trip.application.in.request.context; import io.swagger.v3.oas.annotations.Parameter; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) @Parameter(hidden = true) public @interface WithUserContext { -} + boolean required() default true; +} \ No newline at end of file diff --git a/src/main/java/com/retrip/trip/infra/adapter/in/presentation/filter/AuthenticationFilter.java b/src/main/java/com/retrip/trip/infra/adapter/in/presentation/filter/AuthenticationFilter.java index 97e0cb3..06bede1 100644 --- a/src/main/java/com/retrip/trip/infra/adapter/in/presentation/filter/AuthenticationFilter.java +++ b/src/main/java/com/retrip/trip/infra/adapter/in/presentation/filter/AuthenticationFilter.java @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; @@ -30,55 +31,38 @@ public class AuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - String path = request.getRequestURI(); - String pathLowercase = path.toLowerCase(); - - if (path.equals("/") || - pathLowercase.contains("swagger") || - pathLowercase.contains("api-docs") || - pathLowercase.contains("actuator") || - pathLowercase.contains("robots.txt") || - pathLowercase.contains("status-check") || - pathLowercase.contains("/h2-console")) { - filterChain.doFilter(request, response); - return; - } String token = resolveToken(request); - if (token == null || token.isEmpty()) { - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - return; - } - - try { - Claims claims = getClaims(token); - String subject = claims.getSubject(); - UUID memberId = UUID.fromString(subject); + if (StringUtils.hasText(token)) { + try { + Claims claims = getClaims(token); - UserContext userContext = new UserContext( - memberId, - claims.get("nickname", String.class), - claims.get("email", String.class), - claims.get("name", String.class), - null, - 0 - ); + String subject = claims.getSubject(); + UUID memberId = UUID.fromString(subject); - request.setAttribute("userContext", userContext); + UserContext userContext = new UserContext( + memberId, + claims.get("nickname", String.class), + claims.get("email", String.class), + claims.get("name", String.class), + null, + 0 + ); - filterChain.doFilter(request, response); - - } catch (Exception e) { - log.error("Token validation failed: {}", e.getMessage()); - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + request.setAttribute("userContext", userContext); + } catch (Exception e) { + log.warn("Invalid Token: {}", e.getMessage()); + } } + + filterChain.doFilter(request, response); } private String resolveToken(HttpServletRequest request) { String bearerToken = request.getHeader("Authorization"); - if (bearerToken != null && bearerToken.startsWith("Bearer ")) { + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } return null; diff --git a/src/main/java/com/retrip/trip/infra/adapter/in/presentation/resolver/UserContextArgumentResolver.java b/src/main/java/com/retrip/trip/infra/adapter/in/presentation/resolver/UserContextArgumentResolver.java index b0e2623..6692fda 100644 --- a/src/main/java/com/retrip/trip/infra/adapter/in/presentation/resolver/UserContextArgumentResolver.java +++ b/src/main/java/com/retrip/trip/infra/adapter/in/presentation/resolver/UserContextArgumentResolver.java @@ -15,20 +15,26 @@ public class UserContextArgumentResolver implements HandlerMethodArgumentResolve @Override public boolean supportsParameter(MethodParameter parameter) { - return parameter.hasParameterAnnotation(WithUserContext.class); + return parameter.hasParameterAnnotation(WithUserContext.class) + && parameter.getParameterType().equals(UserContext.class); } @Override - public UserContext resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, - NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + UserContext userContext = (UserContext) webRequest.getAttribute( "userContext", RequestAttributes.SCOPE_REQUEST ); - if (userContext == null) { - throw new IllegalStateException("UserContext not found in request"); + WithUserContext annotation = parameter.getParameterAnnotation(WithUserContext.class); + boolean required = (annotation != null) && annotation.required(); + + if (required && userContext == null) { + throw new IllegalStateException("Login required"); } + return userContext; } -} +} \ No newline at end of file diff --git a/src/main/java/com/retrip/trip/infra/adapter/in/presentation/rest/TripController.java b/src/main/java/com/retrip/trip/infra/adapter/in/presentation/rest/TripController.java index ce9427b..aba7156 100644 --- a/src/main/java/com/retrip/trip/infra/adapter/in/presentation/rest/TripController.java +++ b/src/main/java/com/retrip/trip/infra/adapter/in/presentation/rest/TripController.java @@ -77,15 +77,20 @@ public ApiResponse> getTrips( return ApiResponse.ok(trips); } + @Operation( summary = "여행 상세 조회", - description = "tripId를 이용하여 여행 상세 정보를 조회합니다." + description = "tripId를 이용하여 여행 상세 정보를 조회합니다. (비로그인 가능)" ) @GetMapping("/{tripId}") @Schema(description = "여행 상세 조회") - public ApiResponse getTripDetail(@WithUserContext UserContext userContext, - @PathVariable UUID tripId) { - TripDetailResponse tripDetail = getTripUseCase.getTripDetail(userContext.memberId(), tripId); + public ApiResponse getTripDetail( + @WithUserContext(required = false) UserContext userContext, + @PathVariable UUID tripId) { + + UUID memberId = (userContext != null) ? userContext.memberId() : null; + + TripDetailResponse tripDetail = getTripUseCase.getTripDetail(memberId, tripId); return ApiResponse.ok(tripDetail); } From 8483f74560150cb69bd387d731b893448e4a9848 Mon Sep 17 00:00:00 2001 From: TueBack Date: Mon, 12 Jan 2026 00:38:33 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EC=97=AC=ED=96=89=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=20=EA=B3=B5=EA=B0=9C=20=EC=97=AC=EB=B6=80?= =?UTF-8?q?=20=EB=B0=8F=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../retrip/trip/application/in/TripService.java | 4 +--- .../application/in/request/TripCreateRequest.java | 14 +++++++------- .../in/response/TripDetailResponse.java | 11 +++++------ 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/retrip/trip/application/in/TripService.java b/src/main/java/com/retrip/trip/application/in/TripService.java index 614633c..b338937 100644 --- a/src/main/java/com/retrip/trip/application/in/TripService.java +++ b/src/main/java/com/retrip/trip/application/in/TripService.java @@ -40,7 +40,6 @@ public class TripService @Override public TripCreateResponse createTrip(UUID memberId, TripCreateRequest request) { Trip trip = request.to(memberId); - assignPasswordIfNotOpen(trip, request.password()); Trip savedTrip = tripRepository.save(trip); return TripCreateResponse.of(savedTrip); } @@ -48,7 +47,6 @@ public TripCreateResponse createTrip(UUID memberId, TripCreateRequest request) { @Override public TripCreateResponse createTripWithItineraries(UUID memberId, TripCreateRequest request) { Trip trip = request.toWithItineraries(memberId); - assignPasswordIfNotOpen(trip, request.password()); Trip savedTrip = tripRepository.save(trip); return TripCreateResponse.of(savedTrip); } @@ -161,7 +159,7 @@ private void assignPasswordIfNotOpen(Trip trip, String password) { if (trip.isOpen()) { return; } - String trimPassword = password.trim(); + String trimPassword = (password != null) ? password.trim() : ""; if (!StringUtils.hasText(trimPassword)) { throw new InvalidValueException("비공개 여행은 비밀번호를 반드시 입력해야 합니다."); } diff --git a/src/main/java/com/retrip/trip/application/in/request/TripCreateRequest.java b/src/main/java/com/retrip/trip/application/in/request/TripCreateRequest.java index a705aae..86ffa94 100644 --- a/src/main/java/com/retrip/trip/application/in/request/TripCreateRequest.java +++ b/src/main/java/com/retrip/trip/application/in/request/TripCreateRequest.java @@ -39,11 +39,11 @@ public record TripCreateRequest( @FutureOrPresent LocalDate end, - @Schema(description = "여행 공개 여부") - boolean open, - - @Schema(description = "여행 참여 비밀번호") - String password, +// @Schema(description = "여행 공개 여부") +// boolean open, +// +// @Schema(description = "여행 참여 비밀번호") +// String password, @Schema(description = "여행 최대 참가 인원") int maxParticipants, @@ -63,7 +63,7 @@ public Trip to(UUID memberId) { imageUrl, new TripDescription(description), new TripPeriod(start, end), - open, + true, maxParticipants, hashTags, category, @@ -79,7 +79,7 @@ public Trip toWithItineraries(UUID memberId) { imageUrl, new TripDescription(description), new TripPeriod(start, end), - open, + true, maxParticipants, hashTags, category, diff --git a/src/main/java/com/retrip/trip/application/in/response/TripDetailResponse.java b/src/main/java/com/retrip/trip/application/in/response/TripDetailResponse.java index fce91ab..f0d48b1 100644 --- a/src/main/java/com/retrip/trip/application/in/response/TripDetailResponse.java +++ b/src/main/java/com/retrip/trip/application/in/response/TripDetailResponse.java @@ -98,8 +98,8 @@ public record TripDetailResponse( public static TripDetailResponse of(UUID memberId, Trip trip) { return TripDetailResponse.builder() .id(trip.getId()) - .isLeader(trip.getTripParticipants().isLeader(memberId)) - .isParticipant(trip.getTripParticipants().isParticipant(memberId)) + .isLeader(memberId != null && trip.getTripParticipants().isLeader(memberId)) + .isParticipant(memberId != null && trip.getTripParticipants().isParticipant(memberId)) .title(trip.getTitle().getValue()) .createdAt(trip.getCreatedAt()) .participantCount(trip.getTripParticipants().getCurrentCount()) @@ -158,14 +158,13 @@ public static List toList(List tripPar .toList(); } - //TODO: 해당 참가자 정보 auth API 에서 따로 가져오도록 수정해야함 private static TripParticipantResponse of(TripParticipant participant) { return TripParticipantResponse.builder() .participantId(participant.getId()) .memberId(participant.getMemberId()) - .introduction("안녕하세여") - .nickName("박정수") - .imageUrl("http://~~~") + .introduction(null) + .nickName("여행자-" + participant.getMemberId().toString().substring(0, 8)) + .imageUrl(null) .role(participant.getRole()) .build(); }