diff --git a/.github/workflows/TestCi.yml b/.github/workflows/TestCi.yml index d878e17c..e3bec159 100644 --- a/.github/workflows/TestCi.yml +++ b/.github/workflows/TestCi.yml @@ -10,6 +10,10 @@ env: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest diff --git a/be/src/main/java/yeonba/be/chatting/controller/ChatController.java b/be/src/main/java/yeonba/be/chatting/controller/ChatController.java index 4d4ffeec..d60d2ea7 100644 --- a/be/src/main/java/yeonba/be/chatting/controller/ChatController.java +++ b/be/src/main/java/yeonba/be/chatting/controller/ChatController.java @@ -5,16 +5,12 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; -import java.util.Set; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.listener.ChannelTopic; -import org.springframework.data.redis.listener.RedisMessageListenerContainer; -import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; import org.springframework.http.ResponseEntity; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -37,8 +33,6 @@ public class ChatController { @MessageMapping("/chat") public void chat(ChatPublishRequest request) { - log.info("chatting test log {}", request.getContent()); - chatService.publish(request); } @@ -103,4 +97,19 @@ public ResponseEntity> acceptRequestedChat( .ok() .body(new CustomResponse<>()); } + + @Operation(summary = "채팅방 나가기", description = "채팅방을 나갈 수 있습니다.") + @ApiResponse(responseCode = "200", description = "채팅방 나가기 정상 처리") + @DeleteMapping("/chat-rooms/{roomId}") + public ResponseEntity> leaveChatRoom( + @RequestAttribute("userId") long userId, + @Parameter(description = "채팅방 ID", example = "1") + @PathVariable long roomId) { + + chatService.leaveChatRoom(userId, roomId); + + return ResponseEntity + .ok() + .body(new CustomResponse<>()); + } } diff --git a/be/src/main/java/yeonba/be/chatting/entity/ChatMessage.java b/be/src/main/java/yeonba/be/chatting/entity/ChatMessage.java index 3f4a2e7a..6fdb9a75 100644 --- a/be/src/main/java/yeonba/be/chatting/entity/ChatMessage.java +++ b/be/src/main/java/yeonba/be/chatting/entity/ChatMessage.java @@ -62,4 +62,8 @@ public ChatMessage(ChatRoom chatRoom, User sender, User receiver, String content this.sentAt = sentAt; this.read = false; } + + public void readMessage() { + this.read = true; + } } diff --git a/be/src/main/java/yeonba/be/chatting/entity/ChatRoom.java b/be/src/main/java/yeonba/be/chatting/entity/ChatRoom.java index 0d5754e1..9acdbd34 100644 --- a/be/src/main/java/yeonba/be/chatting/entity/ChatRoom.java +++ b/be/src/main/java/yeonba/be/chatting/entity/ChatRoom.java @@ -18,6 +18,8 @@ import lombok.NoArgsConstructor; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import yeonba.be.exception.ChatException; +import yeonba.be.exception.GeneralException; import yeonba.be.user.entity.User; @Table(name = "chat_rooms") @@ -61,4 +63,11 @@ public void activeRoom() { this.active = true; } + + public void validateRoom(User user) { + + if (!this.sender.equals(user) && !this.receiver.equals(user)) { + throw new GeneralException(ChatException.NOT_YOUR_CHAT_ROOM); + } + } } diff --git a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageCommand.java b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageCommand.java index f9137e37..0a878df0 100644 --- a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageCommand.java +++ b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageCommand.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import yeonba.be.chatting.entity.ChatMessage; +import yeonba.be.chatting.entity.ChatRoom; @Component @RequiredArgsConstructor @@ -14,4 +15,9 @@ public ChatMessage save(ChatMessage message) { return chatMessageRepository.save(message); } + + public void deleteAllByChatRoom(ChatRoom chatRoom) { + + chatMessageRepository.deleteAllByChatRoom(chatRoom); + } } diff --git a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageRepository.java b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageRepository.java index 4bcc60a3..f53e41d8 100644 --- a/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageRepository.java +++ b/be/src/main/java/yeonba/be/chatting/repository/chatmessage/ChatMessageRepository.java @@ -14,4 +14,6 @@ public interface ChatMessageRepository extends JpaRepository int countByChatRoomIdAndReadIsFalse(long chatRoomId); List findAllByChatRoomOrderBySentAtDesc(ChatRoom chatRoom); + + void deleteAllByChatRoom(ChatRoom chatRoom); } diff --git a/be/src/main/java/yeonba/be/chatting/repository/chatroom/ChatRoomCommand.java b/be/src/main/java/yeonba/be/chatting/repository/chatroom/ChatRoomCommand.java index 9089594a..d53fc068 100644 --- a/be/src/main/java/yeonba/be/chatting/repository/chatroom/ChatRoomCommand.java +++ b/be/src/main/java/yeonba/be/chatting/repository/chatroom/ChatRoomCommand.java @@ -14,4 +14,9 @@ public ChatRoom createChatRoom(ChatRoom chatRoom) { return chatRoomRepository.save(chatRoom); } + + public void delete(ChatRoom chatRoom) { + + chatRoomRepository.delete(chatRoom); + } } diff --git a/be/src/main/java/yeonba/be/chatting/service/ChatService.java b/be/src/main/java/yeonba/be/chatting/service/ChatService.java index 028798f8..9003926c 100644 --- a/be/src/main/java/yeonba/be/chatting/service/ChatService.java +++ b/be/src/main/java/yeonba/be/chatting/service/ChatService.java @@ -72,16 +72,19 @@ public List getChatMessages(long userId, long roomId) { ChatRoom chatRoom = chatRoomQuery.findById(roomId); - if (!user.equals(chatRoom.getSender()) && !user.equals(chatRoom.getReceiver())) { - throw new GeneralException(ChatException.NOT_YOUR_CHAT_ROOM); - } + chatRoom.validateRoom(user); List chatMessages = chatMessageQuery.findAllByChatRoom(chatRoom); return chatMessages.stream() - .map(chatMessage -> new ChatMessageResponse(chatMessage.getSender().getId(), - chatMessage.getSender().getNickname(), - chatMessage.getContent(), chatMessage.getSentAt())) + .map(chatMessage -> { + if (!chatMessage.isRead() && chatMessage.getReceiver().equals(user)) { + chatMessage.readMessage(); + } + return new ChatMessageResponse(chatMessage.getSender().getId(), + chatMessage.getSender().getNickname(), chatMessage.getContent(), + chatMessage.getSentAt()); + }) .toList(); } @@ -181,4 +184,16 @@ public void acceptRequestedChat(long userId, long notificationId) { eventPublisher.publishEvent(notificationSendEvent); } + + @Transactional + public void leaveChatRoom(long userId, long roomId) { + + User user = userQuery.findById(userId); + ChatRoom chatRoom = chatRoomQuery.findById(roomId); + + chatRoom.validateRoom(user); + + chatRoomCommand.delete(chatRoom); + chatMessageCommand.deleteAllByChatRoom(chatRoom); + } } diff --git a/be/src/main/java/yeonba/be/user/dto/request/UserQueryRequest.java b/be/src/main/java/yeonba/be/user/dto/request/UserQueryRequest.java index 0be6bd3d..1aa306b1 100644 --- a/be/src/main/java/yeonba/be/user/dto/request/UserQueryRequest.java +++ b/be/src/main/java/yeonba/be/user/dto/request/UserQueryRequest.java @@ -18,7 +18,7 @@ public class UserQueryRequest { 조회 기준 - 즐겨찾는 이성 : FAVORITES - 나에게 관심 있는 이성(나에게 화살을 보낸 이성) : ARROW_SENDERS - - 나에게 화살을 보낸 이성 : ARROW_RECEIVERS""", + - 내가 화살을 보낸 이성 : ARROW_RECEIVERS""", example = "FAVORITES", in = ParameterIn.QUERY) @NotBlank(message = "조회 기준은 반드시 입력되어야 합니다.")