Skip to content

[FEAT] 대화 상대 차단/해제 api 구현#141

Merged
e2guana merged 6 commits intodevfrom
feat/140-block-unblock
Dec 11, 2025
Merged

[FEAT] 대화 상대 차단/해제 api 구현#141
e2guana merged 6 commits intodevfrom
feat/140-block-unblock

Conversation

@e2guana
Copy link
Copy Markdown
Contributor

@e2guana e2guana commented Dec 11, 2025

🎋 이슈 및 작업중인 브랜치

#140

🔑 주요 내용

-채팅방에서 대화 상대를 차단 및 차단 해제
-차단한 상대가 차단 되었음을 인지하지 못함(카카오톡과 유사하게 차단한 상대가 메세지를 보낼 수는 있지만 내가 수신하지는 않음)
-상대 차단시 상대방이 등록한 경매 아이템이 검색되지 않도록 하였음
-차단 해제시 다시 정상적으로 검색이 되도록 하였음
-커뮤니티가 목적인 서비스가 아니기 때문에 따로 차단 유저 목록 조회는 하지 않고 채팅방에서만 이루어지도록 하였음

-ItemRepository에 @param("me") Long me 추가 -> 비로그인의 경우 null

Check List

  • Reviewers 등록을 하였나요?
  • Assignees 등록을 하였나요?
  • 라벨(Label) 등록을 하였나요?
  • PR 머지하기 전 반드시 CI가 정상적으로 작동하는지 확인해주세요!

Summary by CodeRabbit

  • New Features

    • Users can block and unblock chat partners via new chat controls.
    • Messages involving blocked users are marked as ignored.
    • Search results respect blocking: items from blocked sellers are excluded.
  • Chores

    • Updated database schema management configuration (JPA/Hibernate ddl-auto).

✏️ Tip: You can customize this high-level summary in your review settings.

@e2guana e2guana self-assigned this Dec 11, 2025
@e2guana e2guana added the ✨FEAT 기능 구현 관련 label Dec 11, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 11, 2025

Walkthrough

Adds chat blocking: new block/unblock endpoints and DTO, block-list persistence and service logic, MessageService checks block status to optionally ignore messages, and search/item queries gain user-aware filtering to exclude sellers blocked by the querying user.

Changes

Cohort / File(s) Summary
Chat Controller
src/main/java/com/salemale/domain/chat/controller/ChatController.java
Added POST /{chatId}/block and POST /{chatId}/unblock endpoints delegating to ChatService and returning BlockResponse wrapped in ApiResponse.
Block DTO
src/main/java/com/salemale/domain/chat/dto/BlockResponse.java
New DTO with blockedUserId: Long and blocked: boolean (Lombok annotations).
Message DTO
src/main/java/com/salemale/domain/chat/dto/MessageDtos.java
Added boolean ignored field to MessageResponse.
Chat Service
src/main/java/com/salemale/domain/chat/service/ChatService.java
Injected BlockListRepository; added blockPartner(me, chatId) and unblockPartner(me, chatId) transactional methods to manage block entries and return BlockResponse.
Message Service
src/main/java/com/salemale/domain/chat/service/MessageService.java
Injected BlockListRepository; updated send flow to determine receiver early and return an ignored response when either party has blocked the other.
Block List Repository
src/main/java/com/salemale/domain/user/repository/BlockListRepository.java
New Spring Data JPA interface with existsByBlocker_IdAndBlocked_Id, deleteByBlocker_IdAndBlocked_Id, and @Query findBlockedUserIds.
Item Repository
src/main/java/com/salemale/domain/item/repository/ItemRepository.java
Added me/userId parameter across multiple queries and updated JPQL/native queries to exclude items whose seller is blocked by me.
Keyword Search Service
src/main/java/com/salemale/domain/search/service/KeywordItemSearchServiceImpl.java
Private helpers and repository calls updated to accept and propagate userId (or null) so completed/nationwide/nearby searches are user-aware.
Nearby Search Service
src/main/java/com/salemale/domain/search/service/NearbyItemSearchServiceImpl.java
Updated itemRepository.findNearbyItems(...) call to include userId parameter before Pageable.
Config
src/main/resources/application.yml
Changed spring.jpa.hibernate.ddl-auto from validate to update.

Sequence Diagram(s)

sequenceDiagram
    participant Client as User/Client
    participant Controller as ChatController
    participant ChatSvc as ChatService
    participant BlockRepo as BlockListRepository
    participant MsgSvc as MessageService

    Note over Client,Controller: Block/Unblock request
    Client->>Controller: POST /{chatId}/block (header: user-id)
    Controller->>ChatSvc: blockPartner(me, chatId)
    ChatSvc->>BlockRepo: existsByBlocker_IdAndBlocked_Id(me, partner)
    alt already blocked
        BlockRepo-->>ChatSvc: true
        ChatSvc-->>Controller: BlockResponse(partner, blocked=true)
    else not blocked
        ChatSvc->>BlockRepo: save(BlockList(blocker=me, blocked=partner))
        BlockRepo-->>ChatSvc: saved entity
        ChatSvc-->>Controller: BlockResponse(partner, blocked=true)
    end
    Controller-->>Client: ApiResponse.onSuccess(BlockResponse)

    Note over Client,MsgSvc: Message send with block checks
    Client->>MsgSvc: send(messageDto)
    MsgSvc->>BlockRepo: existsByBlocker_IdAndBlocked_Id(sender, receiver)
    alt sender blocked receiver OR receiver blocked sender
        BlockRepo-->>MsgSvc: true
        MsgSvc-->>Client: MessageResponse(ignored=true)
    else not blocked
        BlockRepo-->>MsgSvc: false
        MsgSvc->>MsgSvc: persist message, update chat lastMessage, emit event
        MsgSvc-->>Client: MessageResponse(ignored=false)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Review attention:
    • Consistency and parameter order in all modified ItemRepository queries using me/userId.
    • Null/anonymous handling where userId is passed as null in search service call sites.
    • Concurrency and transaction behavior in blockPartner/unblockPartner (existence check + save/delete).
    • MessageService early-return path for ignored messages and downstream consumers of ignored.

Possibly related PRs

Suggested reviewers

  • nomorefifa
  • beans3142

Poem

🐰 I hopped through code to add a little fence,

Block and unblock with one small sense;
Messages may skip where fences grow,
Searches hide shops that I don't know.
A tidy hop — the marketplace can rest, from me, the DevRabbit, blessed.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.18% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: implementing block/unblock APIs for chat partners, which aligns with the primary changes across ChatController, ChatService, MessageService, and related components.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/140-block-unblock

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/main/java/com/salemale/domain/chat/controller/ChatController.java (1)

4-133: Block/unblock endpoint paths likely missing /chats prefix

All existing chat APIs in this controller use /chats/... (e.g., /chats/{chatId}/exit, /chats/{chatId}/enter), but the new ones are:

@PostMapping("/{chatId}/block")
@PostMapping("/{chatId}/unblock")

This exposes them at the root (/{chatId}/block) and is inconsistent with the rest of the chat API surface. It will also be hard for clients to discover.

You almost certainly want:

@PostMapping("/chats/{chatId}/block")
@PostMapping("/chats/{chatId}/unblock")

Also, for the unblock API, the @Operation summary is still "대화 상대 차단"; consider updating it to something like "대화 상대 차단 해제" for clarity.

[suggest_minor_refactor]

src/main/java/com/salemale/domain/search/service/KeywordItemSearchServiceImpl.java (2)

210-240: Incorrect total count and potential IndexOutOfBoundsException in pagination.

Two issues:

  1. Wrong total count: combined.size() (Line 238) only counts items from the current page fetch (up to 2×pageSize), not the actual total across all pages. This breaks pagination metadata.

  2. Missing bounds check: Line 233 can throw IndexOutOfBoundsException when start >= combined.size() (e.g., requesting page 10 when only 5 items exist).

-    private Page<Item> searchCompletedItems(String keyword, java.util.List<Category> categories, Integer minPrice, Integer maxPrice, org.springframework.data.domain.Pageable pageable, Long userId) {
+    private Page<Item> searchCompletedItems(String keyword, java.util.List<Category> categories, Integer minPrice, Integer maxPrice, org.springframework.data.domain.Pageable pageable, Long userId) {
         // SUCCESS와 FAIL 둘 다 조회 (COMPLETED는 POPULAR 조건 적용 안 함)
         LocalDateTime now = LocalDateTime.now();
         LocalDateTime threeDaysAgo = now.minusDays(3);
         Page<Item> successPage = keyword != null
                 ? itemRepository.searchItemsByKeywordWithFilters(ItemStatus.SUCCESS, keyword, categories, minPrice, maxPrice, false, threeDaysAgo, now, userId, pageable)
                 : itemRepository.searchItemsByFiltersOnly(ItemStatus.SUCCESS, categories, minPrice, maxPrice, false, threeDaysAgo, now, userId, pageable);
         
         Page<Item> failPage = keyword != null
                 ? itemRepository.searchItemsByKeywordWithFilters(ItemStatus.FAIL, keyword, categories, minPrice, maxPrice, false, threeDaysAgo, now, userId, pageable)
                 : itemRepository.searchItemsByFiltersOnly(ItemStatus.FAIL, categories, minPrice, maxPrice, false, threeDaysAgo, now, userId, pageable);
         
         // 두 결과를 합치기
         java.util.List<Item> combined = new java.util.ArrayList<>();
         combined.addAll(successPage.getContent());
         combined.addAll(failPage.getContent());
         
         // 정렬 적용
         combined.sort(java.util.Comparator.comparing(Item::getCreatedAt).reversed());
         
         // 페이징 적용
         int start = (int) pageable.getOffset();
         int end = Math.min(start + pageable.getPageSize(), combined.size());
-        java.util.List<Item> pagedContent = combined.subList(start, end);
+        java.util.List<Item> pagedContent = start < combined.size() 
+                ? combined.subList(start, end) 
+                : java.util.Collections.emptyList();
         
+        long totalElements = successPage.getTotalElements() + failPage.getTotalElements();
         return new org.springframework.data.domain.PageImpl<>(
                 pagedContent,
                 pageable,
-                combined.size()
+                totalElements
         );
     }

Note: This in-memory pagination approach is fundamentally flawed for large datasets—consider using a single query with IN (SUCCESS, FAIL) condition instead.


245-283: Same pagination issues as searchCompletedItems.

This method has the same two problems: incorrect totalElements calculation and inconsistent handling is partially addressed at Line 276 but the total count is still wrong.

Apply the same fix: use successPage.getTotalElements() + failPage.getTotalElements() for the total count.

🧹 Nitpick comments (3)
src/main/resources/application.yml (1)

20-21: Hibernate ddl-auto: update can be dangerous outside local/dev

Changing from validate to update lets Hibernate auto-modify the schema at runtime. That’s convenient for local development but risky in staging/prod (unexpected DDL, drift from Flyway scripts, harder rollbacks).

If the goal is just to support new entities (e.g., BlockList) locally, I’d strongly suggest moving this to a application-local.yml profile (or similar) and keeping validate for shared environments.

src/main/java/com/salemale/domain/user/repository/BlockListRepository.java (1)

10-21: Repository API looks appropriate for the use‑cases

The existsBy…, deleteBy…, and findBlockedUserIds methods match the service patterns and keep call sites simple. The JPQL for findBlockedUserIds is clear and focused on just IDs.

As a future improvement, you might want a DB-level unique constraint on (blocker_id, blocked_id) to guarantee no duplicates, but functionally this repository looks good.

src/main/java/com/salemale/domain/chat/dto/MessageDtos.java (1)

33-43: Document ignored field semantics for clients

Adding ignored makes sense for block-handling, but its meaning isn’t obvious from the DTO comment block.

Consider briefly documenting it, e.g., “ignored: true면 서버에서 차단 등으로 인해 실제로 저장·전달되지 않은 메시지” so API consumers know how to interpret it and how it differs from a normal send failure (exception/4xx).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6546e4 and e3009f4.

📒 Files selected for processing (10)
  • src/main/java/com/salemale/domain/chat/controller/ChatController.java (2 hunks)
  • src/main/java/com/salemale/domain/chat/dto/BlockResponse.java (1 hunks)
  • src/main/java/com/salemale/domain/chat/dto/MessageDtos.java (1 hunks)
  • src/main/java/com/salemale/domain/chat/service/ChatService.java (4 hunks)
  • src/main/java/com/salemale/domain/chat/service/MessageService.java (3 hunks)
  • src/main/java/com/salemale/domain/item/repository/ItemRepository.java (12 hunks)
  • src/main/java/com/salemale/domain/search/service/KeywordItemSearchServiceImpl.java (9 hunks)
  • src/main/java/com/salemale/domain/search/service/NearbyItemSearchServiceImpl.java (1 hunks)
  • src/main/java/com/salemale/domain/user/repository/BlockListRepository.java (1 hunks)
  • src/main/resources/application.yml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/com/salemale/domain/search/service/KeywordItemSearchServiceImpl.java (1)
src/main/java/com/salemale/domain/item/converter/ItemConverter.java (1)
  • ItemConverter (21-258)
🔇 Additional comments (8)
src/main/java/com/salemale/domain/search/service/NearbyItemSearchServiceImpl.java (1)

39-40: Propagation of userId into nearby search looks correct

Passing userId into itemRepository.findNearbyItems(...) here is consistent with the new block-aware search behavior, and findNearbyItemsForUser guarantees a non-null user.

Just ensure the repository method handles this parameter consistently with other search paths (e.g., keyword search) so block filtering behavior is uniform.

src/main/java/com/salemale/domain/chat/service/ChatService.java (1)

44-49: New repository dependencies are wired correctly

Adding UserRepository and BlockListRepository into ChatService is consistent with the new block/unblock workflow and keeps block logic centralized here rather than in the controller.

No issues with the wiring from a service-design perspective.

src/main/java/com/salemale/domain/item/repository/ItemRepository.java (3)

120-126: LGTM: JPQL blocking filter is correctly structured.

The subquery correctly uses entity names and property paths in JPQL syntax.


150-156: LGTM: JPQL blocking filter syntax is correct.


193-199: LGTM: JPQL blocking filter syntax is correct.

src/main/java/com/salemale/domain/search/service/KeywordItemSearchServiceImpl.java (3)

61-62: LGTM: Correctly passing null for unauthenticated users.

The blocking filter is skipped when me is null, which is the expected behavior for anonymous searches.

Also applies to: 74-74, 81-81


115-116: LGTM: Correctly propagating userId for authenticated users.

The user ID is correctly passed to repository methods to filter out blocked sellers' items.

Also applies to: 139-139, 145-145, 152-152, 155-155


322-322: LGTM: Passing null for generic search is correct.

This method doesn't have user context, so passing null correctly disables the blocking filter.

Comment on lines +8 to +16
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BlockResponse {

private Long blockedUserId; // 내가 차단하거나 해제한 상대의 ID
private boolean blocked; // true = 차단됨, false = 차단 해제됨
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Clarify blocked semantics to match service behavior

The comment says true = 차단됨, false = 차단 해제됨, i.e., current block state. But ChatService.blockPartner currently returns blocked=false when the user is already blocked (no-op). That makes the DTO ambiguous: is it “현재 차단 여부” or “이번 호출로 상태가 바뀌었는지”?

Either:

  • Define it strictly as “현재 차단 상태” and always return blocked=true from the block API (even if 이미 차단됨), or
  • Rename the field or add another flag (e.g., alreadyBlocked) so the meaning is explicit.

Right now the DTO contract and implementation don’t line up cleanly.

🤖 Prompt for AI Agents
In src/main/java/com/salemale/domain/chat/dto/BlockResponse.java around lines
8-16 the boolean field `blocked` is ambiguous relative to
ChatService.blockPartner (service returns false on no-op when user was already
blocked); update the DTO and service so the contract is explicit: either (A)
make `blocked` represent the current block state (true if the target is
currently blocked) and ensure ChatService.blockPartner always sets
`blocked=true` after a block attempt (even if it was already blocked), or (B)
keep `blocked` as “result of this call” and add a second field like
`alreadyBlocked` (or rename `blocked` to `isBlockedNow` and add
`alreadyBlocked`) and populate both in ChatService.blockPartner accordingly;
implement the chosen change consistently in the DTO, service return values, and
any callers/tests that consume this response.

Comment on lines +290 to +348
//대화상대 차단
@Transactional
public BlockResponse blockPartner(Long me, Long chatId) {

Chat chat = chatRepository.findById(chatId)
.orElseThrow(() -> new EntityNotFoundException("채팅방이 존재하지 않습니다."));

Long partnerId = chat.getSeller().getId().equals(me)
? chat.getBuyer().getId()
: chat.getSeller().getId();

// 이미 차단된 경우 → blocked=false 로 반환 (프론트가 "이미 차단됨" UI 처리 가능)
if (blockListRepository.existsByBlocker_IdAndBlocked_Id(me, partnerId)) {
return BlockResponse.builder()
.blockedUserId(partnerId)
.blocked(false)
.build();
}

User meUser = userRepository.findById(me).orElseThrow();
User partner = userRepository.findById(partnerId).orElseThrow();

blockListRepository.save(BlockList.builder()
.blocker(meUser)
.blocked(partner)
.build());

return BlockResponse.builder()
.blockedUserId(partnerId)
.blocked(true)
.build();
}

//대화상대 차단 해제
@Transactional
public BlockResponse unblockPartner(Long me, Long chatId) {

Chat chat = chatRepository.findById(chatId)
.orElseThrow(() -> new EntityNotFoundException("채팅방이 존재하지 않습니다."));

Long partnerId = chat.getSeller().getId().equals(me)
? chat.getBuyer().getId()
: chat.getSeller().getId();

// 이미 차단 안 된 상태 → blocked=false로 그대로 반환
if (!blockListRepository.existsByBlocker_IdAndBlocked_Id(me, partnerId)) {
return BlockResponse.builder()
.blockedUserId(partnerId)
.blocked(false)
.build();
}

blockListRepository.deleteByBlocker_IdAndBlocked_Id(me, partnerId);

return BlockResponse.builder()
.blockedUserId(partnerId)
.blocked(false)
.build();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Enforce chat participation and fix blockPartner response semantics

Two important issues in blockPartner/unblockPartner:

  1. Missing participant validation (authorization bug)
    Unlike enter, exitChat, and markAllReadInChat, these methods do not verify that me is actually the seller or buyer in the chat. For a user not in the chat:

    Long partnerId = chat.getSeller().getId().equals(me)
            ? chat.getBuyer().getId()
            : chat.getSeller().getId();

    will fall into the else branch and treat the seller as the “partner”, allowing any authenticated user who knows a chatId to create or delete block relations with that seller.

    You should add the same participation guard used elsewhere:

    if (!chat.getSeller().getId().equals(me) && !chat.getBuyer().getId().equals(me)) {
        throw new IllegalStateException("대화 참여자가 아닙니다.");
    }

    and then compute partnerId only after that check.

  2. Inconsistent blocked flag in blockPartner when already blocked
    When the block already exists, you return:

    if (blockListRepository.existsByBlocker_IdAndBlocked_Id(me, partnerId)) {
        return BlockResponse.builder()
                .blockedUserId(partnerId)
                .blocked(false)
                .build();
    }

    But the DTO’s comment says true = 차단됨, false = 차단 해제됨. After this call, the user is still blocked, so blocked should be true if that field represents current state. If you want idempotent behavior, the simplest is to always return blocked=true from the block API, regardless of whether it was newly created or already existed.

    Combined, these two issues affect both security (who can block) and client-visible behavior, so they should be addressed before release.

🤖 Prompt for AI Agents
In src/main/java/com/salemale/domain/chat/service/ChatService.java around lines
290-348, add the same participation guard used elsewhere to both blockPartner
and unblockPartner by checking that me is either chat.getSeller().getId() or
chat.getBuyer().getId() and throw IllegalStateException("대화 참여자가 아닙니다.") if not,
then compute partnerId; also fix blockPartner's response semantics so that when
a block already exists you return blocked=true (reflecting the current blocked
state) instead of blocked=false, making the API idempotent and secure.

Comment on lines +65 to +85
// 새 메시지 알림: 상대방에게만 전송
Long sellerId = chat.getSeller().getId();
Long buyerId = chat.getBuyer().getId();
Long senderId = me;

// 내가 판매자면 수신자는 구매자, 내가 구매자면 수신자는 판매자
Long receiverId = senderId.equals(sellerId) ? buyerId : sellerId;

// 내가 상대를 차단한 경우 → 메시지 저장 X
if (blockListRepository.existsByBlocker_IdAndBlocked_Id(me, receiverId)) {
return MessageResponse.builder()
.ignored(true) // 무시하기
.build();
}

// 상대가 나를 차단한 경우 → 메시지 저장 X
if (blockListRepository.existsByBlocker_IdAndBlocked_Id(receiverId, me)) {
return MessageResponse.builder()
.ignored(true) // 무시하기
.build();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Blocked-send handling is consistent, but ignored responses may be under-specified

The early-return checks against BlockListRepository correctly prevent message persistence and side effects when either side has blocked the other, which matches the described KakaoTalk-like behavior.

However, the ignored response currently only sets ignored=true and leaves other fields (chatId, senderId, etc.) null:

return MessageResponse.builder()
        .ignored(true)
        .build();

If clients assume those fields are always present (e.g., for optimistic UI or WS payloads), this could be fragile. Consider either:

  • Including at least chatId and senderId in the ignored payload, or
  • Clearly documenting that an ignored send only guarantees ignored=true and other fields may be null.

Functionally the block logic is fine; this is mostly about making the API contract explicit and robust for consumers.

🤖 Prompt for AI Agents
In src/main/java/com/salemale/domain/chat/service/MessageService.java around
lines 65 to 85, the early-return ignored responses only set ignored=true leaving
other fields null which can break clients expecting minimal context; change the
builder to include at least chatId and senderId (e.g.,
.chatId(chat.getId()).senderId(me).ignored(true).build()) so the ignored payload
provides minimal context for clients while keeping persistence and side effects
suppressed.

Copy link
Copy Markdown
Member

@beans3142 beans3142 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오우 너무 좋았습니다. 차단은 어떻게 가능할까 생각해봤었는데 me랑 chat-id를 넘겨서 되네요 이게

@beans3142
Copy link
Copy Markdown
Member

토끼 피드백만 확인하시고, DB에 column 추가된것 없다면 application.yml 은 validate로 부탁드리겠습니다!

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3009f4 and c78c0bc.

📒 Files selected for processing (1)
  • src/main/java/com/salemale/domain/chat/controller/ChatController.java (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (1)
src/main/java/com/salemale/domain/chat/controller/ChatController.java (1)

4-4: LGTM!

The import for BlockResponse is correctly added to support the new block/unblock endpoints.

Comment on lines +107 to +119
/**
대화 상대 차단 API
-채팅방에서 대화 상대 차단
*/
@Operation(summary = "대화 상대 차단", description = "상대방을 차단하고 상대방이 경매 등록한 물품이 보이지 않게 됨.")
@PostMapping("/{chatId}/block")
public ResponseEntity<ApiResponse<BlockResponse>> blockPartner(
@RequestHeader("user-id") Long me,
@PathVariable Long chatId
) {
BlockResponse res = chatService.blockPartner(me, chatId);
return ResponseEntity.ok(ApiResponse.onSuccess(res));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix the URL path to include /chats prefix.

The @PostMapping path is missing the /chats prefix. All other chat-related endpoints in this controller use /chats/{chatId}/* pattern (see lines 67, 82, 98). The current path /{chatId}/block will not route correctly.

Apply this diff to fix the path:

-    @PostMapping("/{chatId}/block")
+    @PostMapping("/chats/{chatId}/block")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
대화 상대 차단 API
-채팅방에서 대화 상대 차단
*/
@Operation(summary = "대화 상대 차단", description = "상대방을 차단하고 상대방이 경매 등록한 물품이 보이지 않게 됨.")
@PostMapping("/{chatId}/block")
public ResponseEntity<ApiResponse<BlockResponse>> blockPartner(
@RequestHeader("user-id") Long me,
@PathVariable Long chatId
) {
BlockResponse res = chatService.blockPartner(me, chatId);
return ResponseEntity.ok(ApiResponse.onSuccess(res));
}
/**
대화 상대 차단 API
-채팅방에서 대화 상대 차단
*/
@Operation(summary = "대화 상대 차단", description = "상대방을 차단하고 상대방이 경매 등록한 물품이 보이지 않게 됨.")
@PostMapping("/chats/{chatId}/block")
public ResponseEntity<ApiResponse<BlockResponse>> blockPartner(
@RequestHeader("user-id") Long me,
@PathVariable Long chatId
) {
BlockResponse res = chatService.blockPartner(me, chatId);
return ResponseEntity.ok(ApiResponse.onSuccess(res));
}
🤖 Prompt for AI Agents
In src/main/java/com/salemale/domain/chat/controller/ChatController.java around
lines 107 to 119, the @PostMapping path uses "/{chatId}/block" which lacks the
"/chats" prefix used by other endpoints; update the mapping to
"/chats/{chatId}/block" so the route matches the controller's chat endpoint
pattern and requests are routed correctly.

Comment on lines +121 to +133
/**
대화 상대 차단 해제 API
-채팅방에서 대화 상대 차단 해제
*/
@Operation(summary = "대화 상대 차단 해제", description = "상대방을 차단 해제.")
@PostMapping("/{chatId}/unblock")
public ResponseEntity<ApiResponse<BlockResponse>> unblockPartner(
@RequestHeader("user-id") Long me,
@PathVariable Long chatId
) {
BlockResponse res = chatService.unblockPartner(me, chatId);
return ResponseEntity.ok(ApiResponse.onSuccess(res));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix the URL path to include /chats prefix.

The @PostMapping path is missing the /chats prefix. All other chat-related endpoints in this controller use /chats/{chatId}/* pattern. The current path /{chatId}/unblock will not route correctly.

Apply this diff to fix the path:

-    @PostMapping("/{chatId}/unblock")
+    @PostMapping("/chats/{chatId}/unblock")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
대화 상대 차단 해제 API
-채팅방에서 대화 상대 차단 해제
*/
@Operation(summary = "대화 상대 차단 해제", description = "상대방을 차단 해제.")
@PostMapping("/{chatId}/unblock")
public ResponseEntity<ApiResponse<BlockResponse>> unblockPartner(
@RequestHeader("user-id") Long me,
@PathVariable Long chatId
) {
BlockResponse res = chatService.unblockPartner(me, chatId);
return ResponseEntity.ok(ApiResponse.onSuccess(res));
}
/**
대화 상대 차단 해제 API
-채팅방에서 대화 상대 차단 해제
*/
@Operation(summary = "대화 상대 차단 해제", description = "상대방을 차단 해제.")
@PostMapping("/chats/{chatId}/unblock")
public ResponseEntity<ApiResponse<BlockResponse>> unblockPartner(
@RequestHeader("user-id") Long me,
@PathVariable Long chatId
) {
BlockResponse res = chatService.unblockPartner(me, chatId);
return ResponseEntity.ok(ApiResponse.onSuccess(res));
}
🤖 Prompt for AI Agents
src/main/java/com/salemale/domain/chat/controller/ChatController.java lines
121-133: The mapping for the unblock endpoint is missing the required "/chats"
prefix so it won't match the controller's other chat routes; update the
@PostMapping annotation to include the "/chats" prefix (i.e., change the mapping
to use the same "/chats/{chatId}/unblock" pattern as other endpoints) and ensure
any route documentation or tests referencing the old path are adjusted
accordingly.

@e2guana e2guana merged commit 8343f4e into dev Dec 11, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨FEAT 기능 구현 관련

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants