From 1b236554a57eda0dd6326224d46a34fde9bf7011 Mon Sep 17 00:00:00 2001 From: cussle Date: Fri, 15 Nov 2024 02:14:25 +0900 Subject: [PATCH 1/4] feat: Add chat room creation and deletion logic when adding/removing cards in group --- .../devcard/card/service/GroupService.java | 49 +++++++++++++------ .../devcard/chat/dto/CreateRoomRequest.java | 7 ++- .../chat/repository/ChatRoomRepository.java | 4 ++ .../devcard/chat/service/ChatRoomService.java | 21 +++++++- .../devcard/devcard/chat/util/Constants.java | 1 + 5 files changed, 63 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/devcard/devcard/card/service/GroupService.java b/src/main/java/com/devcard/devcard/card/service/GroupService.java index 23574f1..1054034 100644 --- a/src/main/java/com/devcard/devcard/card/service/GroupService.java +++ b/src/main/java/com/devcard/devcard/card/service/GroupService.java @@ -6,23 +6,31 @@ import com.devcard.devcard.card.entity.Group; import com.devcard.devcard.card.repository.CardRepository; import com.devcard.devcard.card.repository.GroupRepository; +import com.devcard.devcard.chat.dto.CreateRoomRequest; +import com.devcard.devcard.chat.service.ChatRoomService; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.server.ResponseStatusException; -import java.util.List; -import java.util.stream.Collectors; - @Service public class GroupService { private final GroupRepository groupRepository; private final CardRepository cardRepository; + private final ChatRoomService chatRoomService; - public GroupService(GroupRepository groupRepository, CardRepository cardRepository) { + public GroupService( + GroupRepository groupRepository, + CardRepository cardRepository, + ChatRoomService chatRoomService + ) { this.groupRepository = groupRepository; this.cardRepository = cardRepository; + this.chatRoomService = chatRoomService; } @Transactional @@ -37,22 +45,29 @@ public List getGroupsByMember(Member member) { List groups = groupRepository.findByMember(member); return groups.stream() - .map(group -> new GroupResponseDto(group.getId(), group.getName(), group.getCount())) - .collect(Collectors.toList()); + .map(group -> new GroupResponseDto(group.getId(), group.getName(), group.getCount())) + .collect(Collectors.toList()); } @Transactional public void addCardToGroup(Long groupId, Long cardId, Member member) { Group group = groupRepository.findByIdAndMember(groupId, member) - .orElseThrow(() -> new IllegalArgumentException("해당 그룹이 존재하지 않거나 접근 권한이 없습니다.")); + .orElseThrow(() -> new IllegalArgumentException("해당 그룹이 존재하지 않거나 접근 권한이 없습니다.")); Card card = cardRepository.findById(cardId) - .orElseThrow(() -> new IllegalArgumentException("해당 ID의 명함이 존재하지 않습니다.")); + .orElseThrow(() -> new IllegalArgumentException("해당 ID의 명함이 존재하지 않습니다.")); if (group.getCards().contains(card)) { throw new IllegalArgumentException("이미 해당 그룹에 추가되어 있는 명함입니다."); } + // 채팅방 생성 + CreateRoomRequest createRoomRequest = new CreateRoomRequest(Arrays.asList( + member.getId(), + card.getMember().getId() + )); + chatRoomService.createChatRoom(createRoomRequest); + group.addCard(card); groupRepository.save(group); } @@ -60,10 +75,16 @@ public void addCardToGroup(Long groupId, Long cardId, Member member) { @Transactional public void deleteCardFromGroup(Long groupId, Long cardId, Member member) { Group group = groupRepository.findByIdAndMember(groupId, member) - .orElseThrow(() -> new IllegalArgumentException("해당 그룹이 존재하지 않거나 접근 권한이 없습니다.")); + .orElseThrow(() -> new IllegalArgumentException("해당 그룹이 존재하지 않거나 접근 권한이 없습니다.")); Card card = cardRepository.findById(cardId) - .orElseThrow(() -> new IllegalArgumentException("해당 ID의 명함이 존재하지 않습니다.")); + .orElseThrow(() -> new IllegalArgumentException("해당 ID의 명함이 존재하지 않습니다.")); + + // 채팅방 제거 + chatRoomService.deleteChatRoomByParticipants(Arrays.asList( + member.getId(), + card.getMember().getId() + )); group.removeCard(card); // 그룹에서 명함을 제거 groupRepository.save(group); // 변경사항 저장 @@ -72,9 +93,9 @@ public void deleteCardFromGroup(Long groupId, Long cardId, Member member) { @Transactional public void updateGroupName(Long groupId, String newName, Member member) { Group group = groupRepository.findByIdAndMember(groupId, member) - .orElseThrow(() -> new ResponseStatusException( - HttpStatus.BAD_REQUEST, "해당 그룹이 존재하지 않거나 접근 권한이 없습니다." - )); + .orElseThrow(() -> new ResponseStatusException( + HttpStatus.BAD_REQUEST, "해당 그룹이 존재하지 않거나 접근 권한이 없습니다." + )); group.setName(newName); groupRepository.save(group); @@ -83,7 +104,7 @@ public void updateGroupName(Long groupId, String newName, Member member) { @Transactional public void deleteGroup(Long groupId, Member member) { Group group = groupRepository.findByIdAndMember(groupId, member) - .orElseThrow(() -> new IllegalArgumentException("해당 그룹이 존재하지 않거나 접근 권한이 없습니다.")); + .orElseThrow(() -> new IllegalArgumentException("해당 그룹이 존재하지 않거나 접근 권한이 없습니다.")); groupRepository.delete(group); // 그룹 삭제 } diff --git a/src/main/java/com/devcard/devcard/chat/dto/CreateRoomRequest.java b/src/main/java/com/devcard/devcard/chat/dto/CreateRoomRequest.java index 26d6705..67b6a49 100644 --- a/src/main/java/com/devcard/devcard/chat/dto/CreateRoomRequest.java +++ b/src/main/java/com/devcard/devcard/chat/dto/CreateRoomRequest.java @@ -6,11 +6,10 @@ public class CreateRoomRequest { private List participantsId; - public List getParticipantsId() { - return participantsId; + public CreateRoomRequest(List list) { } - public void setParticipantsId(List participantsId) { - this.participantsId = participantsId; + public List getParticipantsId() { + return participantsId; } } diff --git a/src/main/java/com/devcard/devcard/chat/repository/ChatRoomRepository.java b/src/main/java/com/devcard/devcard/chat/repository/ChatRoomRepository.java index 31672af..d945a2c 100644 --- a/src/main/java/com/devcard/devcard/chat/repository/ChatRoomRepository.java +++ b/src/main/java/com/devcard/devcard/chat/repository/ChatRoomRepository.java @@ -1,7 +1,9 @@ package com.devcard.devcard.chat.repository; import com.devcard.devcard.chat.model.ChatRoom; +import java.util.Collection; import java.util.List; +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; @@ -10,4 +12,6 @@ public interface ChatRoomRepository extends JpaRepository { @Query("SELECT cr FROM ChatRoom cr JOIN cr.participants p WHERE p.id = :userId") List findByParticipantId(@Param("userId") String userId); + + Optional findByParticipantsIdIn(Collection> participantsId); } diff --git a/src/main/java/com/devcard/devcard/chat/service/ChatRoomService.java b/src/main/java/com/devcard/devcard/chat/service/ChatRoomService.java index acaa062..c4f9c76 100644 --- a/src/main/java/com/devcard/devcard/chat/service/ChatRoomService.java +++ b/src/main/java/com/devcard/devcard/chat/service/ChatRoomService.java @@ -1,6 +1,7 @@ package com.devcard.devcard.chat.service; import static com.devcard.devcard.chat.util.Constants.CHAT_ROOM_NOT_FOUND; +import static com.devcard.devcard.chat.util.Constants.CHAT_ROOM_NOT_FOUND_BY_PARTICIPANTS; import com.devcard.devcard.auth.entity.Member; import com.devcard.devcard.chat.dto.ChatMessageResponse; @@ -15,6 +16,7 @@ import com.devcard.devcard.chat.repository.ChatRoomRepository; import com.devcard.devcard.chat.repository.ChatUserRepository; import java.time.LocalDateTime; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import org.springframework.stereotype.Service; @@ -122,7 +124,7 @@ public ChatRoomResponse getChatRoomById(String chatId) { } /** - * 채팅방 삭제 + * chatId를 이용해 채팅방 삭제 * @param chatId 채팅방 ID */ public void deleteChatRoom(String chatId) { @@ -139,6 +141,23 @@ public void deleteChatRoom(String chatId) { chatRoomRepository.deleteById(chatRoomId); } + /** + * 참여자 ID를 이용해 채팅방 삭제 + * @param participantsId 채팅방에 참여하는 모든 유저의 ID List + */ + public void deleteChatRoomByParticipants(List participantsId) { + // 참여자 ID 목록으로 채팅방 조회 + ChatRoom chatRoom = chatRoomRepository.findByParticipantsIdIn(Collections.singleton(participantsId)) + .orElseThrow(() -> new ChatRoomNotFoundException( + CHAT_ROOM_NOT_FOUND_BY_PARTICIPANTS + participantsId.toString())); + + // 관련된 메시지 삭제 + chatRepository.deleteByChatRoomId(chatRoom.getId()); + + // 채팅방 삭제 + chatRoomRepository.delete(chatRoom); + } + /** * 특정 채팅방이 존재하는지 확인 * @param chatId 채팅방 ID diff --git a/src/main/java/com/devcard/devcard/chat/util/Constants.java b/src/main/java/com/devcard/devcard/chat/util/Constants.java index c78cdaf..5ce5a15 100644 --- a/src/main/java/com/devcard/devcard/chat/util/Constants.java +++ b/src/main/java/com/devcard/devcard/chat/util/Constants.java @@ -4,6 +4,7 @@ public class Constants { // 채팅방 상수 public static final String CHAT_ROOM_NOT_FOUND = "채팅방을 다음의 id로 찾을 수 없습니다. id: "; + public static final String CHAT_ROOM_NOT_FOUND_BY_PARTICIPANTS = "해당 참여자 ID 목록으로 채팅방을 찾을 수 없습니다. 참여자 ID 목록: "; public static final String USER_NOT_IN_CHAT_ROOM = "사용자가 해당 채팅방의 참여자가 아닙니다."; public static final String EMPTY_MESSAGE = "메시지가 비어 있습니다."; From b3a4dee199c53d288a6f97ac9e1f5600e178216f Mon Sep 17 00:00:00 2001 From: cussle Date: Fri, 15 Nov 2024 02:18:59 +0900 Subject: [PATCH 2/4] fix: Correct participant ID handling in chat room deletion logic --- .../com/devcard/devcard/chat/repository/ChatRoomRepository.java | 2 +- .../java/com/devcard/devcard/chat/service/ChatRoomService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/devcard/devcard/chat/repository/ChatRoomRepository.java b/src/main/java/com/devcard/devcard/chat/repository/ChatRoomRepository.java index d945a2c..78ea99b 100644 --- a/src/main/java/com/devcard/devcard/chat/repository/ChatRoomRepository.java +++ b/src/main/java/com/devcard/devcard/chat/repository/ChatRoomRepository.java @@ -13,5 +13,5 @@ public interface ChatRoomRepository extends JpaRepository { @Query("SELECT cr FROM ChatRoom cr JOIN cr.participants p WHERE p.id = :userId") List findByParticipantId(@Param("userId") String userId); - Optional findByParticipantsIdIn(Collection> participantsId); + Optional findByParticipants_IdIn(Collection participantsId); } diff --git a/src/main/java/com/devcard/devcard/chat/service/ChatRoomService.java b/src/main/java/com/devcard/devcard/chat/service/ChatRoomService.java index c4f9c76..ea58167 100644 --- a/src/main/java/com/devcard/devcard/chat/service/ChatRoomService.java +++ b/src/main/java/com/devcard/devcard/chat/service/ChatRoomService.java @@ -147,7 +147,7 @@ public void deleteChatRoom(String chatId) { */ public void deleteChatRoomByParticipants(List participantsId) { // 참여자 ID 목록으로 채팅방 조회 - ChatRoom chatRoom = chatRoomRepository.findByParticipantsIdIn(Collections.singleton(participantsId)) + ChatRoom chatRoom = chatRoomRepository.findByParticipants_IdIn(participantsId) .orElseThrow(() -> new ChatRoomNotFoundException( CHAT_ROOM_NOT_FOUND_BY_PARTICIPANTS + participantsId.toString())); From 6cc7c5fe268c57a47f82ca6e4af9030287632f76 Mon Sep 17 00:00:00 2001 From: cussle Date: Fri, 15 Nov 2024 02:22:14 +0900 Subject: [PATCH 3/4] chore: Update all localhost references to production deployment URL --- .../devcard/devcard/chat/service/ChatService.java | 2 +- src/main/resources/application.properties | 4 ++-- src/main/resources/static/js/card/card-share.js | 8 ++++---- src/main/resources/static/js/chat.js | 2 +- .../devcard/chat/service/ChatServiceTest.java | 12 ++++++------ 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/devcard/devcard/chat/service/ChatService.java b/src/main/java/com/devcard/devcard/chat/service/ChatService.java index 1f012fe..6f2c58b 100644 --- a/src/main/java/com/devcard/devcard/chat/service/ChatService.java +++ b/src/main/java/com/devcard/devcard/chat/service/ChatService.java @@ -212,7 +212,7 @@ public Long extractUserIdFromSession(WebSocketSession session) { * @return 해당 파라미터 값 (존재하지 않으면 null 반환) */ private Long extractParamFromUri(String uri, String paramName) { - // e.g. `ws://localhost:8080/ws?chatId=1&userId=1` 입력의 경우, + // e.g. `ws://3.34.144.148:8080/ws?chatId=1&userId=1` 입력의 경우, try { // "?"로 나누어 쿼리 파라미터 부분만 가져옴 (e.g. `chatId=1&userId=1`) String[] parts = uri.split("\\?"); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1968c83..7b1d23d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -18,7 +18,7 @@ spring.jpa.show-sql=true #spring.datasource.url=jdbc:h2:mem:test;MODE=MYSQL;DB_CLOSE_DELAY=-1 #spring.datasource.username=sa #spring.datasource.password= -spring.datasource.url=jdbc:mysql://localhost:3306/devcard_db?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&characterEncoding=UTF-8 +spring.datasource.url=jdbc:mysql://3.34.144.148:3306/devcard_db?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&characterEncoding=UTF-8 spring.datasource.username=${DB_USERNAME} spring.datasource.password=${DB_PASSWORD} spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver @@ -37,7 +37,7 @@ logging.level.org.springframework.security=DEBUG # QR Code Service -qr.domain.uri=http://localhost:8080/ +qr.domain.uri=http://3.34.144.148:8080/ qr.code.directory=src/main/resources/static/qrcodes/ # Kakao Service diff --git a/src/main/resources/static/js/card/card-share.js b/src/main/resources/static/js/card/card-share.js index e5ac237..6f0758c 100644 --- a/src/main/resources/static/js/card/card-share.js +++ b/src/main/resources/static/js/card/card-share.js @@ -8,16 +8,16 @@ document.getElementById('kakao-share-btn').addEventListener('click', function () description: '회사: [[${card.company}]], 직책: [[${card.position}]]', imageUrl: 'https://developers.kakao.com/assets/img/about/logos/kakaolink/kakaolink_btn_medium.png', link: { - mobileWebUrl: 'http://localhost:8080/cards/' + cardId + '/view', - webUrl: 'http://localhost:8080/cards/' + cardId + '/view' + mobileWebUrl: 'http://3.34.144.148:8080/cards/' + cardId + '/view', + webUrl: 'http://3.34.144.148:8080/cards/' + cardId + '/view' } }, buttons: [ { title: '명함 보기', link: { - mobileWebUrl: 'http://localhost:8080/cards/' + cardId + '/view', - webUrl: 'http://localhost:8080/cards/' + cardId + '/view' + mobileWebUrl: 'http://3.34.144.148:8080/cards/' + cardId + '/view', + webUrl: 'http://3.34.144.148:8080/cards/' + cardId + '/view' } } ], diff --git a/src/main/resources/static/js/chat.js b/src/main/resources/static/js/chat.js index 697f1ce..ccaa441 100644 --- a/src/main/resources/static/js/chat.js +++ b/src/main/resources/static/js/chat.js @@ -148,7 +148,7 @@ $(document).ready(function () { fetchChatRoom(chatId); // 임시로 로컬 서버 설정 - const socket = new WebSocket(`ws://localhost:8080/ws?chatId=${chatId}&userId=${memberId}`); + const socket = new WebSocket(`ws://3.34.144.148:8080/ws?chatId=${chatId}&userId=${memberId}`); // 웹소켓 연결 socket.addEventListener("open", () => { diff --git a/src/test/java/com/devcard/devcard/chat/service/ChatServiceTest.java b/src/test/java/com/devcard/devcard/chat/service/ChatServiceTest.java index b23d1c5..489a95d 100644 --- a/src/test/java/com/devcard/devcard/chat/service/ChatServiceTest.java +++ b/src/test/java/com/devcard/devcard/chat/service/ChatServiceTest.java @@ -370,7 +370,7 @@ void testExtractMessage_EmptyJsonObject() { @DisplayName("유효한 chatId 추출 성공") void testExtractChatIdFromSession_ValidChatId() { // 유효한 URI 설정 - when(session.getUri()).thenReturn(URI.create("ws://localhost:8080/ws?chatId=1&userId=1")); + when(session.getUri()).thenReturn(URI.create("ws://3.34.144.148:8080/ws?chatId=1&userId=1")); // chatId가 1로 반환되는지 확인 Long chatId = chatService.extractChatIdFromSession(session); @@ -381,7 +381,7 @@ void testExtractChatIdFromSession_ValidChatId() { @DisplayName("쿼리 파라미터 없음 - chatId") void testExtractChatIdFromSession_NoChatId() { // chatId가 없는 URI 설정 - when(session.getUri()).thenReturn(URI.create("ws://localhost:8080/ws")); + when(session.getUri()).thenReturn(URI.create("ws://3.34.144.148:8080/ws")); // chatId가 없으므로 IllegalArgumentException 발생 Exception exception = assertThrows( @@ -395,7 +395,7 @@ void testExtractChatIdFromSession_NoChatId() { @DisplayName("chatId 숫자 형식 오류") void testExtractChatIdFromSession_InvalidChatIdFormat() { // chatId가 잘못된 형식인 URI 설정 - when(session.getUri()).thenReturn(URI.create("ws://localhost:8080/ws?chatId=abc&userId=1")); + when(session.getUri()).thenReturn(URI.create("ws://3.34.144.148:8080/ws?chatId=abc&userId=1")); // chatId가 숫자 형식이 아니므로 IllegalArgumentException 발생 Exception exception = assertThrows( @@ -409,7 +409,7 @@ void testExtractChatIdFromSession_InvalidChatIdFormat() { @DisplayName("유효한 userId 추출 성공") void testExtractUserIdFromSession_ValidUserId() { // 유효한 URI 설정 - when(session.getUri()).thenReturn(URI.create("ws://localhost:8080/ws?chatId=1&userId=1")); + when(session.getUri()).thenReturn(URI.create("ws://3.34.144.148:8080/ws?chatId=1&userId=1")); // userId가 1로 반환되는지 확인 Long userId = chatService.extractUserIdFromSession(session); @@ -420,7 +420,7 @@ void testExtractUserIdFromSession_ValidUserId() { @DisplayName("쿼리 파라미터 없음 - userId") void testExtractUserIdFromSession_NoUserId() { // userId가 없는 URI 설정 - when(session.getUri()).thenReturn(URI.create("ws://localhost:8080/ws")); + when(session.getUri()).thenReturn(URI.create("ws://3.34.144.148:8080/ws")); // userId가 없으므로 IllegalArgumentException 발생 Exception exception = assertThrows( @@ -434,7 +434,7 @@ void testExtractUserIdFromSession_NoUserId() { @DisplayName("userId 숫자 형식 오류") void testExtractUserIdFromSession_InvalidUserIdFormat() { // userId가 잘못된 형식인 URI 설정 - when(session.getUri()).thenReturn(URI.create("ws://localhost:8080/ws?chatId=1&userId=abc")); + when(session.getUri()).thenReturn(URI.create("ws://3.34.144.148:8080/ws?chatId=1&userId=abc")); // userId가 숫자 형식이 아니므로 IllegalArgumentException 발생 Exception exception = assertThrows( From 6d8e60dab51e8bc1c73e0593335b6239a82e16fb Mon Sep 17 00:00:00 2001 From: cussle Date: Fri, 15 Nov 2024 02:28:16 +0900 Subject: [PATCH 4/4] build: Restrict deployment workflow only on merges to main repository --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a65112a..ecb4372 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,7 @@ on: # push: # branches: [ "weekly/11"] pull_request: - branches: [ "Master" ] +# branches: [ "Master" ] types: [closed] # AWS 관련 값 변수로 설정 @@ -18,6 +18,7 @@ env: jobs: deploy: runs-on: ubuntu-latest + if: github.repository == 'kakao-tech-campus-2nd-step3/Team28_BE' && github.event.pull_request.merged == true permissions: contents: read packages: write