From 9b5a3f938b6e62a68024361f64879040f5971fcf Mon Sep 17 00:00:00 2001 From: JaeSeo Yang <96044622+psychology50@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:30:05 +0900 Subject: [PATCH 1/7] feat: chat-member-ban-command --- .../chat/dto/ChatMemberBanCommand.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/dto/ChatMemberBanCommand.java diff --git a/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/dto/ChatMemberBanCommand.java b/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/dto/ChatMemberBanCommand.java new file mode 100644 index 000000000..156de3008 --- /dev/null +++ b/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/dto/ChatMemberBanCommand.java @@ -0,0 +1,19 @@ +package kr.co.pennyway.domain.context.chat.dto; + +public record ChatMemberBanCommand( + Long adminId, + Long targetMemberId +) { + public ChatMemberBanCommand { + if (adminId == null) { + throw new IllegalArgumentException("adminId must not be null"); + } + if (targetMemberId == null) { + throw new IllegalArgumentException("targetMemberId must not be null"); + } + } + + public static ChatMemberBanCommand of(Long adminId, Long targetMemberId) { + return new ChatMemberBanCommand(adminId, targetMemberId); + } +} From 5163bfb3f81d9e9e2f04311c390edcd8febed513 Mon Sep 17 00:00:00 2001 From: JaeSeo Yang <96044622+psychology50@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:25:47 +0900 Subject: [PATCH 2/7] rename: modify admin-id to user-id cause it isn't identicated already --- .../context/chat/dto/ChatMemberBanCommand.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/dto/ChatMemberBanCommand.java b/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/dto/ChatMemberBanCommand.java index 156de3008..0af4a4c51 100644 --- a/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/dto/ChatMemberBanCommand.java +++ b/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/dto/ChatMemberBanCommand.java @@ -1,19 +1,23 @@ package kr.co.pennyway.domain.context.chat.dto; public record ChatMemberBanCommand( - Long adminId, - Long targetMemberId + Long userId, + Long targetMemberId, + Long chatRoomId ) { public ChatMemberBanCommand { - if (adminId == null) { - throw new IllegalArgumentException("adminId must not be null"); + if (userId == null) { + throw new IllegalArgumentException("userId must not be null"); } if (targetMemberId == null) { throw new IllegalArgumentException("targetMemberId must not be null"); } + if (chatRoomId == null) { + throw new IllegalArgumentException("chatRoomId must not be null"); + } } - public static ChatMemberBanCommand of(Long adminId, Long targetMemberId) { - return new ChatMemberBanCommand(adminId, targetMemberId); + public static ChatMemberBanCommand of(Long adminId, Long targetMemberId, Long chatRoomId) { + return new ChatMemberBanCommand(adminId, targetMemberId, chatRoomId); } } From 8ef7e099548f55a13c178ed51be60fd9bce47442 Mon Sep 17 00:00:00 2001 From: JaeSeo Yang <96044622+psychology50@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:26:32 +0900 Subject: [PATCH 3/7] feat: add not-admin errorcode --- .../domain/domains/member/exception/ChatMemberErrorCode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/pennyway-domain/domain-rdb/src/main/java/kr/co/pennyway/domain/domains/member/exception/ChatMemberErrorCode.java b/pennyway-domain/domain-rdb/src/main/java/kr/co/pennyway/domain/domains/member/exception/ChatMemberErrorCode.java index 35deb4ce3..d26a7956c 100644 --- a/pennyway-domain/domain-rdb/src/main/java/kr/co/pennyway/domain/domains/member/exception/ChatMemberErrorCode.java +++ b/pennyway-domain/domain-rdb/src/main/java/kr/co/pennyway/domain/domains/member/exception/ChatMemberErrorCode.java @@ -10,6 +10,7 @@ public enum ChatMemberErrorCode implements BaseErrorCode { /* 403 FORBIDDEN */ BANNED(StatusCode.FORBIDDEN, ReasonCode.ACCESS_TO_THE_REQUESTED_RESOURCE_IS_FORBIDDEN, "차단된 회원입니다."), + NOT_ADMIN(StatusCode.FORBIDDEN, ReasonCode.ACCESS_TO_RESOURCE_NOT_ALLOWED_FOR_USER_ROLE, "관리자가 아닙니다."), /* 404 NOT FOUND */ NOT_FOUND(StatusCode.NOT_FOUND, ReasonCode.REQUESTED_RESOURCE_NOT_FOUND, "회원을 찾을 수 없습니다."), From 1069bf6a99569ded4312652bf787c4000f57d541 Mon Sep 17 00:00:00 2001 From: JaeSeo Yang <96044622+psychology50@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:26:45 +0900 Subject: [PATCH 4/7] feat: impl chat-member-ban-service --- .../chat/service/ChatMemberBanService.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/service/ChatMemberBanService.java diff --git a/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/service/ChatMemberBanService.java b/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/service/ChatMemberBanService.java new file mode 100644 index 000000000..a4d6cf8ef --- /dev/null +++ b/pennyway-domain/domain-service/src/main/java/kr/co/pennyway/domain/context/chat/service/ChatMemberBanService.java @@ -0,0 +1,36 @@ +package kr.co.pennyway.domain.context.chat.service; + +import kr.co.pennyway.common.annotation.DomainService; +import kr.co.pennyway.domain.context.chat.dto.ChatMemberBanCommand; +import kr.co.pennyway.domain.domains.member.domain.ChatMember; +import kr.co.pennyway.domain.domains.member.exception.ChatMemberErrorCode; +import kr.co.pennyway.domain.domains.member.exception.ChatMemberErrorException; +import kr.co.pennyway.domain.domains.member.service.ChatMemberRdbService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@DomainService +@RequiredArgsConstructor +public class ChatMemberBanService { + + private final ChatMemberRdbService chatMemberRdbService; + + @Transactional + public void execute(ChatMemberBanCommand command) { + ChatMember admin = chatMemberRdbService.readChatMember(command.userId(), command.chatRoomId()) + .orElseThrow(() -> new ChatMemberErrorException(ChatMemberErrorCode.NOT_FOUND)); + + if (!admin.isAdmin()) { + throw new ChatMemberErrorException(ChatMemberErrorCode.NOT_ADMIN); + } + + ChatMember targetMember = chatMemberRdbService.readChatMemberByChatMemberId(command.targetMemberId()) + .orElseThrow(() -> new ChatMemberErrorException(ChatMemberErrorCode.NOT_FOUND)); + + targetMember.ban(); + + chatMemberRdbService.update(targetMember); + } +} From 6d3c9527c6b7c5e16f6653b9c44e971d0a5dfb1c Mon Sep 17 00:00:00 2001 From: JaeSeo Yang <96044622+psychology50@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:27:54 +0900 Subject: [PATCH 5/7] feat: add ban-chat-member usecase --- .../pennyway/api/apis/chat/usecase/ChatMemberUseCase.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/usecase/ChatMemberUseCase.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/usecase/ChatMemberUseCase.java index 7878aaed5..631bfd0c0 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/usecase/ChatMemberUseCase.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/usecase/ChatMemberUseCase.java @@ -7,6 +7,8 @@ import kr.co.pennyway.api.apis.chat.service.ChatMemberJoinService; import kr.co.pennyway.api.apis.chat.service.ChatMemberSearchService; import kr.co.pennyway.common.annotation.UseCase; +import kr.co.pennyway.domain.context.chat.dto.ChatMemberBanCommand; +import kr.co.pennyway.domain.context.chat.service.ChatMemberBanService; import kr.co.pennyway.domain.context.chat.service.ChatRoomLeaveService; import kr.co.pennyway.domain.domains.chatroom.domain.ChatRoom; import kr.co.pennyway.domain.domains.member.dto.ChatMemberResult; @@ -24,6 +26,7 @@ public class ChatMemberUseCase { private final ChatMemberJoinService chatMemberJoinService; private final ChatMemberSearchService chatMemberSearchService; private final ChatRoomLeaveService chatRoomLeaveService; + private final ChatMemberBanService chatMemberBanService; public ChatRoomRes.Detail joinChatRoom(Long userId, Long chatRoomId, Integer password) { Triple chatRoom = chatMemberJoinService.execute(userId, chatRoomId, password); @@ -40,4 +43,8 @@ public List readChatMembers(Long chatRoomId, Set Date: Sat, 11 Jan 2025 19:29:21 +0900 Subject: [PATCH 6/7] feat: ban-chat-member controller --- .../api/apis/chat/controller/ChatMemberController.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/controller/ChatMemberController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/controller/ChatMemberController.java index 9f975634a..b7388380e 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/controller/ChatMemberController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/controller/ChatMemberController.java @@ -61,4 +61,12 @@ public ResponseEntity leaveChatRoom(@PathVariable("chatRoomId") Long chatRoom return ResponseEntity.ok(SuccessResponse.noContent()); } + + @DeleteMapping("/{chatMemberId}/ban") + @PreAuthorize("isAuthenticated() and @chatRoomManager.hasPermission(principal.userId, #chatRoomId)") + public ResponseEntity banChatMember(@PathVariable("chatRoomId") Long chatRoomId, @PathVariable("chatMemberId") Long chatMemberId, @AuthenticationPrincipal SecurityUserDetails user) { + chatMemberUseCase.banChatMember(user.getUserId(), chatMemberId, chatRoomId); + + return ResponseEntity.ok(SuccessResponse.noContent()); + } } From f164ee131f6bacc6ac7976a6d4a4c3b1bddc776c Mon Sep 17 00:00:00 2001 From: JaeSeo Yang <96044622+psychology50@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:31:32 +0900 Subject: [PATCH 7/7] docs: chat member ban api swagger --- .../co/pennyway/api/apis/chat/api/ChatMemberApi.java | 12 ++++++++++++ .../apis/chat/controller/ChatMemberController.java | 1 + 2 files changed, 13 insertions(+) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/api/ChatMemberApi.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/api/ChatMemberApi.java index ce466b655..b4b056b7a 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/api/ChatMemberApi.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/api/ChatMemberApi.java @@ -73,4 +73,16 @@ ResponseEntity joinChatRoom( ) @ApiResponse(responseCode = "200", description = "채팅방 멤버 탈퇴 성공") ResponseEntity leaveChatRoom(@PathVariable("chatRoomId") Long chatRoomId, @PathVariable("chatMemberId") Long chatMemberId); + + @Operation(summary = "채팅방 멤버 추방", method = "DELETE", description = "채팅방 멤버를 추방한다. 채팅방장만이 채팅방 멤버를 추방할 수 있다.") + @Parameters({ + @Parameter(name = "chatRoomId", description = "채팅방 ID", required = true, in = ParameterIn.PATH), + @Parameter(name = "chatMemberId", description = "추방할 채팅방 멤버 ID (user id가 아님)", required = true, in = ParameterIn.PATH) + }) + @ApiResponseExplanations(errors = { + @ApiExceptionExplanation(value = ChatMemberErrorCode.class, constant = "NOT_FOUND", summary = "채팅방 멤버를 찾을 수 없음", description = "채팅방 멤버를 찾을 수 없어 채팅방 멤버 추방에 실패했습니다."), + @ApiExceptionExplanation(value = ChatMemberErrorCode.class, constant = "NOT_ADMIN", summary = "권한 없음", description = "권한이 없어 채팅방 멤버 추방에 실패했습니다.") + }) + @ApiResponse(responseCode = "200", description = "채팅방 멤버 추방 성공") + ResponseEntity banChatMember(@PathVariable("chatRoomId") Long chatRoomId, @PathVariable("chatMemberId") Long chatMemberId, @AuthenticationPrincipal SecurityUserDetails user); } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/controller/ChatMemberController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/controller/ChatMemberController.java index b7388380e..467d01c92 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/controller/ChatMemberController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/chat/controller/ChatMemberController.java @@ -62,6 +62,7 @@ public ResponseEntity leaveChatRoom(@PathVariable("chatRoomId") Long chatRoom return ResponseEntity.ok(SuccessResponse.noContent()); } + @Override @DeleteMapping("/{chatMemberId}/ban") @PreAuthorize("isAuthenticated() and @chatRoomManager.hasPermission(principal.userId, #chatRoomId)") public ResponseEntity banChatMember(@PathVariable("chatRoomId") Long chatRoomId, @PathVariable("chatMemberId") Long chatMemberId, @AuthenticationPrincipal SecurityUserDetails user) {