diff --git a/src/main/java/net/teumteum/alert/app/AlertHandler.java b/src/main/java/net/teumteum/alert/app/AlertHandler.java index 86e6bc6..56b6400 100644 --- a/src/main/java/net/teumteum/alert/app/AlertHandler.java +++ b/src/main/java/net/teumteum/alert/app/AlertHandler.java @@ -45,7 +45,7 @@ public void handleBeforeMeetingAlerts(BeforeMeetingAlerted alerted) { @Async(ALERT_EXECUTOR) @EventListener(EndMeetingAlerted.class) - public void handleEndMeetingAlerts(EndMeetingAlerted alerted) { + public void handleStartMeetingAlerts(EndMeetingAlerted alerted) { userAlertService.findAllByUserId(alerted.userIds()) .stream() .map(userAlert -> Pair.of(userAlert.getToken(), @@ -64,7 +64,7 @@ private String toCommaString(List ids) { for (int i = 0; i < ids.size() - 1; i++) { stringBuilder.append(ids.get(i)).append(","); } - stringBuilder.append(ids.get(ids.size() - 1)); + stringBuilder.append(ids.getLast()); return stringBuilder.toString(); } diff --git a/src/main/java/net/teumteum/core/security/filter/JwtAuthenticationFilter.java b/src/main/java/net/teumteum/core/security/filter/JwtAuthenticationFilter.java index 20ef8e3..36e960d 100644 --- a/src/main/java/net/teumteum/core/security/filter/JwtAuthenticationFilter.java +++ b/src/main/java/net/teumteum/core/security/filter/JwtAuthenticationFilter.java @@ -72,7 +72,7 @@ private void saveUserAuthentication(User user) { private String resolveTokenFromRequest(HttpServletRequest request) { String token = request.getHeader(jwtProperty.getAccess().getHeader()); - if (token.toLowerCase().startsWith(jwtProperty.getBearer().toLowerCase())) { + if (StringUtils.hasText(token) && token.toLowerCase().startsWith(jwtProperty.getBearer().toLowerCase())) { return token.substring(7); } return null; diff --git a/src/main/java/net/teumteum/user/controller/UserController.java b/src/main/java/net/teumteum/user/controller/UserController.java index 6523683..feb37d9 100644 --- a/src/main/java/net/teumteum/user/controller/UserController.java +++ b/src/main/java/net/teumteum/user/controller/UserController.java @@ -116,10 +116,10 @@ public void registerReview( userService.registerReview(meetingId, getCurrentUserId(), request); } - @GetMapping("/reviews") + @GetMapping("/{userId}/reviews") @ResponseStatus(HttpStatus.OK) - public List getUserReviews() { - return userService.getUserReviews(getCurrentUserId()); + public UserReviewsResponse getUserReviews(@PathVariable("userId") Long userId) { + return userService.getUserReviews(userId); } @ResponseStatus(HttpStatus.BAD_REQUEST) diff --git a/src/main/java/net/teumteum/user/domain/UserRepository.java b/src/main/java/net/teumteum/user/domain/UserRepository.java index d0380f2..b611a17 100644 --- a/src/main/java/net/teumteum/user/domain/UserRepository.java +++ b/src/main/java/net/teumteum/user/domain/UserRepository.java @@ -3,7 +3,7 @@ import java.util.List; import java.util.Optional; import net.teumteum.core.security.Authenticated; -import net.teumteum.user.domain.response.UserReviewsResponse; +import net.teumteum.user.domain.response.UserReviewResponse; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -15,7 +15,8 @@ public interface UserRepository extends JpaRepository { Optional findByAuthenticatedAndOAuthId(@Param("authenticated") Authenticated authenticated, @Param("oAuthId") String oAuthId); - @Query("select new net.teumteum.user.domain.response.UserReviewsResponse(r,count(r)) " - + "from users u join u.reviews r where u.id = :userId group by r") - List countUserReviewsByUserId(@Param("userId") Long userId); + @Query("select new net.teumteum.user.domain.response.UserReviewResponse(r, count(r)) " + + "from users u join u.reviews r where u = :user group by r") + List countUserReviewsByUser(@Param("user") User user); + } diff --git a/src/main/java/net/teumteum/user/domain/response/UserReviewResponse.java b/src/main/java/net/teumteum/user/domain/response/UserReviewResponse.java new file mode 100644 index 0000000..8ec04a8 --- /dev/null +++ b/src/main/java/net/teumteum/user/domain/response/UserReviewResponse.java @@ -0,0 +1,10 @@ +package net.teumteum.user.domain.response; + +import net.teumteum.user.domain.Review; + +public record UserReviewResponse( + Review review, + long count +) { + +} diff --git a/src/main/java/net/teumteum/user/domain/response/UserReviewsResponse.java b/src/main/java/net/teumteum/user/domain/response/UserReviewsResponse.java index 7454f52..bf53ed6 100644 --- a/src/main/java/net/teumteum/user/domain/response/UserReviewsResponse.java +++ b/src/main/java/net/teumteum/user/domain/response/UserReviewsResponse.java @@ -1,10 +1,12 @@ package net.teumteum.user.domain.response; -import net.teumteum.user.domain.Review; +import java.util.List; public record UserReviewsResponse( - Review review, - long count + List reviews ) { + public static UserReviewsResponse of(List reviews) { + return new UserReviewsResponse(reviews); + } } diff --git a/src/main/java/net/teumteum/user/service/UserService.java b/src/main/java/net/teumteum/user/service/UserService.java index 8429d05..723d628 100644 --- a/src/main/java/net/teumteum/user/service/UserService.java +++ b/src/main/java/net/teumteum/user/service/UserService.java @@ -116,8 +116,10 @@ public void registerReview(Long meetingId, Long currentUserId, ReviewRegisterReq }); } - public List getUserReviews(Long userId) { - return userRepository.countUserReviewsByUserId(userId); + public UserReviewsResponse getUserReviews(Long userId) { + var user = getUser(userId); + + return UserReviewsResponse.of(userRepository.countUserReviewsByUser(user)); } public FriendsResponse findFriendsByUserId(Long userId) { diff --git a/src/test/java/net/teumteum/integration/Api.java b/src/test/java/net/teumteum/integration/Api.java index a65e350..0002b52 100644 --- a/src/test/java/net/teumteum/integration/Api.java +++ b/src/test/java/net/teumteum/integration/Api.java @@ -196,10 +196,10 @@ ResponseSpec deleteMeeting(String accessToken, Long meetingId) { .exchange(); } - ResponseSpec getUserReviews(String accessToken) { + ResponseSpec getUserReviews(Long userId, String accessToken) { return webTestClient .get() - .uri("/users/reviews") + .uri("/users/" + userId + "/reviews") .header(HttpHeaders.AUTHORIZATION, accessToken) .exchange(); } diff --git a/src/test/java/net/teumteum/integration/UserIntegrationTest.java b/src/test/java/net/teumteum/integration/UserIntegrationTest.java index 916bb80..bb42461 100644 --- a/src/test/java/net/teumteum/integration/UserIntegrationTest.java +++ b/src/test/java/net/teumteum/integration/UserIntegrationTest.java @@ -346,10 +346,12 @@ void Get_user_reviews() { // given var existUser = repository.saveAndGetUser(); + var userId = existUser.getId(); + securityContextSetting.set(existUser.getId()); // when - var expected = api.getUserReviews(VALID_TOKEN); + var expected = api.getUserReviews(userId, VALID_TOKEN); // then Assertions.assertThat(expected.expectStatus().isOk() diff --git a/src/test/java/net/teumteum/unit/user/controller/UserControllerTest.java b/src/test/java/net/teumteum/unit/user/controller/UserControllerTest.java index f425e05..77afd49 100644 --- a/src/test/java/net/teumteum/unit/user/controller/UserControllerTest.java +++ b/src/test/java/net/teumteum/unit/user/controller/UserControllerTest.java @@ -37,6 +37,7 @@ import net.teumteum.user.domain.request.UserRegisterRequest; import net.teumteum.user.domain.request.UserWithdrawRequest; import net.teumteum.user.domain.response.UserRegisterResponse; +import net.teumteum.user.domain.response.UserReviewResponse; import net.teumteum.user.domain.response.UserReviewsResponse; import net.teumteum.user.service.UserService; import org.junit.jupiter.api.BeforeEach; @@ -238,27 +239,25 @@ void Register_reviews_with_400_bad_request() throws Exception { class Get_user_reviews_api_unit { @Test - @DisplayName("로그인한 회원 id 에 해당하는 회원 리뷰와 200 OK을 반환한다.") + @DisplayName("user id 에 해당하는 회원 리뷰와 200 OK을 반환한다.") void Get_user_reviews_with_200_ok() throws Exception { // given var userId = 1L; - given(securityService.getCurrentUserId()).willReturn(userId); - given(userService.getUserReviews(anyLong())) - .willReturn(List.of(new UserReviewsResponse(별로에요, 2L), - new UserReviewsResponse(최고에요, 3L))); + .willReturn(UserReviewsResponse.of(List.of(new UserReviewResponse(별로에요, 2L), + new UserReviewResponse(최고에요, 3L)))); // when & then - mockMvc.perform(get("/users/reviews") + mockMvc.perform(get("/users/{userId}/reviews", 1) .with(csrf()) .header(AUTHORIZATION, VALID_ACCESS_TOKEN)) .andDo(print()) .andExpect(status().isOk()) - .andExpect(jsonPath("$", notNullValue())) - .andExpect(jsonPath("$", hasSize(2))) - .andExpect(jsonPath("$[0].count", is(2))) - .andExpect(jsonPath("$[0].review").value("별로에요")); + .andExpect(jsonPath("$.reviews", notNullValue())) + .andExpect(jsonPath("$.reviews", hasSize(2))) + .andExpect(jsonPath("$.reviews[0].count", is(2))) + .andExpect(jsonPath("$.reviews[0].review").value("별로에요")); } } diff --git a/src/test/java/net/teumteum/unit/user/service/UserServiceTest.java b/src/test/java/net/teumteum/unit/user/service/UserServiceTest.java index f682353..66b1668 100644 --- a/src/test/java/net/teumteum/unit/user/service/UserServiceTest.java +++ b/src/test/java/net/teumteum/unit/user/service/UserServiceTest.java @@ -30,7 +30,7 @@ import net.teumteum.user.domain.request.UserRegisterRequest; import net.teumteum.user.domain.request.UserWithdrawRequest; import net.teumteum.user.domain.response.UserRegisterResponse; -import net.teumteum.user.domain.response.UserReviewsResponse; +import net.teumteum.user.domain.response.UserReviewResponse; import net.teumteum.user.service.UserService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -251,23 +251,24 @@ class Get_user_reviews_api_unit { void Return_user_reviews_with_200_ok() { // given var userId = 1L; + var existUser = UserFixture.getIdUser(); - var response = List.of(new UserReviewsResponse(최고에요, 2L) - , new UserReviewsResponse(별로에요, 3L)); + var response = List.of(new UserReviewResponse(최고에요, 2L) + , new UserReviewResponse(별로에요, 3L)); - given(userRepository.countUserReviewsByUserId(anyLong())).willReturn(response); + given(userRepository.findById(anyLong())).willReturn(Optional.of(existUser)); + given(userRepository.countUserReviewsByUser(any(User.class))).willReturn(response); // when var result = userService.getUserReviews(userId); // then - assertThat(result).hasSize(2); - assertThat(result.get(0).review()).isEqualTo(최고에요); - assertThat(result.get(0).count()).isEqualTo(2L); - assertThat(result.get(1).review()).isEqualTo(별로에요); - assertThat(result.get(1).count()).isEqualTo(3L); + assertThat(result.reviews()).hasSize(2); + assertThat(result.reviews().get(0).review()).isEqualTo(최고에요); + assertThat(result.reviews().get(0).count()).isEqualTo(2L); + assertThat(result.reviews().get(1).review()).isEqualTo(별로에요); - verify(userRepository, times(1)).countUserReviewsByUserId(anyLong()); + verify(userRepository, times(1)).countUserReviewsByUser(any(User.class)); } } } diff --git a/src/test/java/net/teumteum/user/domain/UserRepositoryTest.java b/src/test/java/net/teumteum/user/domain/UserRepositoryTest.java index 59d607b..a046f11 100644 --- a/src/test/java/net/teumteum/user/domain/UserRepositoryTest.java +++ b/src/test/java/net/teumteum/user/domain/UserRepositoryTest.java @@ -7,7 +7,7 @@ import jakarta.persistence.EntityManager; import java.util.Optional; import net.teumteum.core.config.AppConfig; -import net.teumteum.user.domain.response.UserReviewsResponse; +import net.teumteum.user.domain.response.UserReviewResponse; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -85,13 +85,14 @@ void Count_user_reviews_by_user_id() { entityManager.clear(); // when - var result = userRepository.countUserReviewsByUserId(id); + var result = userRepository.countUserReviewsByUser(existUser); // then Assertions.assertThat(result) .isNotEmpty() .hasSize(3) - .extracting(UserReviewsResponse::review, UserReviewsResponse::count) + .extracting(UserReviewResponse::review, + UserReviewResponse::count) .contains( Assertions.tuple(최고에요, 3L), Assertions.tuple(별로에요, 1L),