diff --git a/backend/src/main/java/codesquard/app/api/chat/ChatLogService.java b/backend/src/main/java/codesquard/app/api/chat/ChatLogService.java index 134b59360..f4103dd18 100644 --- a/backend/src/main/java/codesquard/app/api/chat/ChatLogService.java +++ b/backend/src/main/java/codesquard/app/api/chat/ChatLogService.java @@ -16,6 +16,7 @@ import codesquard.app.api.chat.response.ChatLogMessageResponse; import codesquard.app.api.chat.response.ChatLogSendResponse; import codesquard.app.api.errors.errorcode.ErrorCode; +import codesquard.app.api.errors.exception.ForBiddenException; import codesquard.app.api.errors.exception.NotFoundResourceException; import codesquard.app.domain.chat.ChatLog; import codesquard.app.domain.chat.ChatLogPaginationRepository; @@ -51,6 +52,10 @@ public ChatLogListResponse readMessages(Long chatRoomId, Principal principal, Lo ChatRoom chatRoom = findChatRoomBy(chatRoomId); Item item = findItemBy(chatRoom); + if (!principal.isSeller(chatRoom.getSeller()) && !principal.isBuyer(chatRoom.getBuyer())) { + throw new ForBiddenException(ErrorCode.FORBIDDEN_CHAT_LOG); + } + String chatPartnerName = principal.getChatPartnerName(item, chatRoom); BooleanBuilder whereBuilder = new BooleanBuilder(); whereBuilder.orAllOf( diff --git a/backend/src/main/java/codesquard/app/api/chat/ChatRoomService.java b/backend/src/main/java/codesquard/app/api/chat/ChatRoomService.java index 0d9f5488e..1db9305d1 100644 --- a/backend/src/main/java/codesquard/app/api/chat/ChatRoomService.java +++ b/backend/src/main/java/codesquard/app/api/chat/ChatRoomService.java @@ -144,7 +144,7 @@ public ChatRoomListResponse readAllChatRoomByItem(Long itemId, Principal princip Item item = findItemBy(itemId); BooleanBuilder whereBuilder = new BooleanBuilder(); - whereBuilder.andAnyOf(QChatRoom.chatRoom.item.eq(item)); + whereBuilder.andAnyOf(chatRoomRepository.equalItemId(item.getId())); Slice slice = chatRoomPaginationRepository.searchBySlice(whereBuilder, pageable); diff --git a/backend/src/main/java/codesquard/app/api/errors/errorcode/ErrorCode.java b/backend/src/main/java/codesquard/app/api/errors/errorcode/ErrorCode.java index 5e4773068..a0827745c 100644 --- a/backend/src/main/java/codesquard/app/api/errors/errorcode/ErrorCode.java +++ b/backend/src/main/java/codesquard/app/api/errors/errorcode/ErrorCode.java @@ -61,6 +61,7 @@ public enum ErrorCode { // ChatLog NOT_FOUND_CHAT_LOG(HttpStatus.NOT_FOUND, "채팅이 존재하지 않습니다."), + FORBIDDEN_CHAT_LOG(HttpStatus.FORBIDDEN, "채팅에 대한 권한이 없습니다."), // ChatRoom NOT_FOUND_CHATROOM(HttpStatus.NOT_FOUND, "채팅방을 찾을 수 없습니다."); diff --git a/backend/src/main/java/codesquard/app/domain/chat/ChatRoomRepository.java b/backend/src/main/java/codesquard/app/domain/chat/ChatRoomRepository.java index fc41c458f..05711baa6 100644 --- a/backend/src/main/java/codesquard/app/domain/chat/ChatRoomRepository.java +++ b/backend/src/main/java/codesquard/app/domain/chat/ChatRoomRepository.java @@ -1,13 +1,25 @@ package codesquard.app.domain.chat; +import static codesquard.app.domain.chat.QChatRoom.*; + import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import com.querydsl.core.types.dsl.BooleanExpression; + public interface ChatRoomRepository extends JpaRepository { + default BooleanExpression equalItemId(Long itemId) { + if (itemId == null) { + return null; + } + + return chatRoom.item.id.eq(itemId); + } + int deleteByItemId(Long itemId); @Query("select chatRoom.id from ChatRoom chatRoom where chatRoom.item.id = :itemId and chatRoom.buyer.id = :memberId") diff --git a/backend/src/test/java/codesquard/app/api/chat/ChatLogServiceTest.java b/backend/src/test/java/codesquard/app/api/chat/ChatLogServiceTest.java index 050b50754..c8d2361a6 100644 --- a/backend/src/test/java/codesquard/app/api/chat/ChatLogServiceTest.java +++ b/backend/src/test/java/codesquard/app/api/chat/ChatLogServiceTest.java @@ -28,6 +28,7 @@ import codesquard.app.api.chat.request.ChatLogSendRequest; import codesquard.app.api.chat.response.ChatLogListResponse; import codesquard.app.api.chat.response.ChatLogSendResponse; +import codesquard.app.api.errors.exception.ForBiddenException; import codesquard.app.domain.category.Category; import codesquard.app.domain.category.CategoryRepository; import codesquard.app.domain.chat.ChatLog; @@ -176,4 +177,50 @@ public void readMessage() { ); } + @DisplayName("구매자와 판매자가 아닌 제 3자가 채팅방의 채팅 메시지를 읽을 수 없다.") + @Test + public void readMessageWithOtherMember() { + // given + Member seller = memberRepository.save(createMember("avatarUrlValue1", "23Yong@gmail.com", "23Yong")); + Member buyer = memberRepository.save(createMember("avatarUrlValue2", "bruni@gmail.com", "bruni")); + Member anonymous = memberRepository.save(createMember("avatarUrlValue3", "lee1234@gmail.com", "lee1234")); + + Region region = regionRepository.save(RegionTestSupport.createRegion("서울 종로구 청운동")); + + memberTownRepository.saveAll(List.of( + createMemberTown(seller, region, true), + createMemberTown(buyer, region, true))); + + Category sport = categoryRepository.save(findByName("스포츠/레저")); + Item item = createItem("빈티지 롤러 블레이드", "어린시절 추억의향수를 불러 일으키는 롤러 스케이트입니다.", 200000L, ON_SALE, + "가락동", "thumbnailUrl", seller, sport); + + Item saveItem = itemRepository.save(item); + List images = List.of( + new Image("imageUrlValue1", saveItem, true), + new Image("imageUrlValue2", saveItem, false)); + imageRepository.saveAll(images); + + ChatRoom chatRoom = chatRoomRepository.save(new ChatRoom(buyer, item)); + + chatLogRepository.saveAll(List.of( + ChatLog.createBySender("롤러 블레이드 사고 싶음", chatRoom, Principal.from(buyer)), + ChatLog.createBySender("깍아주세요.", chatRoom, Principal.from(buyer)) + )); + + Long cursor = null; + Pageable pageable = Pageable.ofSize(10); + + // when + Throwable throwable = catchThrowable( + () -> chatLogService.readMessages(chatRoom.getId(), Principal.from(anonymous), cursor, + pageable)); + + // then + assertThat(throwable) + .isInstanceOf(ForBiddenException.class) + .extracting("errorCode.message") + .isEqualTo("채팅에 대한 권한이 없습니다."); + } + }