From e2dff2a875c410475a5384bd034b9821b4045d41 Mon Sep 17 00:00:00 2001 From: seungheonlee Date: Thu, 21 Aug 2025 15:30:18 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20PrivateChatRoomMember=20?= =?UTF-8?q?=EB=8B=A8=EC=9D=BC=20=EC=A1=B0=ED=9A=8C=20Optional=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/mos/backend/common/config/SecurityConfig.java | 1 + .../com/mos/backend/common/infrastructure/EntityFacade.java | 4 +++- .../infrastructure/PrivateChatRoomMemberJpaRepository.java | 2 +- .../infrastructure/PrivateChatRoomMemberRepository.java | 2 +- .../infrastructure/PrivateChatRoomMemberRepositoryImpl.java | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/mos/backend/common/config/SecurityConfig.java b/src/main/java/com/mos/backend/common/config/SecurityConfig.java index 4372b141..b17279ff 100644 --- a/src/main/java/com/mos/backend/common/config/SecurityConfig.java +++ b/src/main/java/com/mos/backend/common/config/SecurityConfig.java @@ -71,6 +71,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers(HttpMethod.GET, "/study-schedules", "/studies/*/schedules").permitAll() .requestMatchers(HttpMethod.GET, "/users/tokens").permitAll() .requestMatchers(HttpMethod.GET, "/likes").permitAll() + .requestMatchers(HttpMethod.GET, "/tokens").permitAll() .anyRequest().authenticated() ) diff --git a/src/main/java/com/mos/backend/common/infrastructure/EntityFacade.java b/src/main/java/com/mos/backend/common/infrastructure/EntityFacade.java index 46b90984..3806deaf 100644 --- a/src/main/java/com/mos/backend/common/infrastructure/EntityFacade.java +++ b/src/main/java/com/mos/backend/common/infrastructure/EntityFacade.java @@ -8,6 +8,7 @@ import com.mos.backend.notifications.entity.exception.NotificationLogErrorCode; import com.mos.backend.notifications.infrastructure.notificationlog.NotificationLogRepository; import com.mos.backend.privatechatroommember.entity.PrivateChatRoomMember; +import com.mos.backend.privatechatroommember.entity.PrivateChatRoomMemberErrorCode; import com.mos.backend.privatechatroommember.infrastructure.PrivateChatRoomMemberRepository; import com.mos.backend.privatechatrooms.entity.PrivateChatRoom; import com.mos.backend.privatechatrooms.entity.PrivateChatRoomErrorCode; @@ -152,6 +153,7 @@ public UserStudySetting getUserStudySetting(Long userId, Long studyId) { } public PrivateChatRoomMember getPrivateChatRoomMember(Long userId, Long privateChatRoomId) { - return privateChatRoomMemberRepository.findByUserIdAndPrivateChatRoomId(userId, privateChatRoomId); + return privateChatRoomMemberRepository.findByUserIdAndPrivateChatRoomId(userId, privateChatRoomId) + .orElseThrow(() -> new MosException(PrivateChatRoomMemberErrorCode.NOT_FOUND)); } } diff --git a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberJpaRepository.java b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberJpaRepository.java index b6d3745a..79ac57a2 100644 --- a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberJpaRepository.java +++ b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberJpaRepository.java @@ -13,7 +13,7 @@ public interface PrivateChatRoomMemberJpaRepository extends JpaRepository findByUserAndPrivateChatRoom(User user, PrivateChatRoom privateChatRoom); - PrivateChatRoomMember findByUserIdAndPrivateChatRoomId(Long userId, Long privateChatRoomId); + Optional findByUserIdAndPrivateChatRoomId(Long userId, Long privateChatRoomId); List findByPrivateChatRoom(PrivateChatRoom privateChatRoom); } diff --git a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepository.java b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepository.java index e53d510c..70fea33e 100644 --- a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepository.java +++ b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepository.java @@ -14,7 +14,7 @@ public interface PrivateChatRoomMemberRepository { Optional findByUserAndPrivateChatRoom(User user, PrivateChatRoom privateChatRoom); - PrivateChatRoomMember findByUserIdAndPrivateChatRoomId(Long userId, Long privateChatRoomId); + Optional findByUserIdAndPrivateChatRoomId(Long userId, Long privateChatRoomId); List findByPrivateChatRoom(PrivateChatRoom privateChatRoom); } diff --git a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepositoryImpl.java b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepositoryImpl.java index 0dd6ec76..f0c85091 100644 --- a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepositoryImpl.java +++ b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepositoryImpl.java @@ -30,7 +30,7 @@ public Optional findByUserAndPrivateChatRoom(User user, P } @Override - public PrivateChatRoomMember findByUserIdAndPrivateChatRoomId(Long userId, Long privateChatRoomId) { + public Optional findByUserIdAndPrivateChatRoomId(Long userId, Long privateChatRoomId) { return privateChatRoomMemberJpaRepository.findByUserIdAndPrivateChatRoomId(userId, privateChatRoomId); } From c5f8c56642cd6f06c7f12d835d9a7d4d6265eaad Mon Sep 17 00:00:00 2001 From: seungheonlee Date: Thu, 21 Aug 2025 16:59:29 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EA=B0=9C=EC=9D=B8=20=EC=B1=84?= =?UTF-8?q?=ED=8C=85=EB=B0=A9=20=EB=82=98=EA=B0=80=EA=B8=B0=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PrivateChatRoomMemberService.java | 8 ++++++++ .../entity/PrivateChatRoomMember.java | 18 ++++++++++++++++-- .../PrivateChatRoomMemberRepository.java | 2 ++ .../PrivateChatRoomMemberRepositoryImpl.java | 5 +++++ .../PrivateChatRoomMemberController.java | 19 +++++++++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/mos/backend/privatechatroommember/presentation/PrivateChatRoomMemberController.java diff --git a/src/main/java/com/mos/backend/privatechatroommember/application/PrivateChatRoomMemberService.java b/src/main/java/com/mos/backend/privatechatroommember/application/PrivateChatRoomMemberService.java index a1451f3a..6710b717 100644 --- a/src/main/java/com/mos/backend/privatechatroommember/application/PrivateChatRoomMemberService.java +++ b/src/main/java/com/mos/backend/privatechatroommember/application/PrivateChatRoomMemberService.java @@ -44,4 +44,12 @@ public void updateLastEntryAt(Long userId, Long privateChatRoomId) { public List findByPrivateChatRoom(PrivateChatRoom privateChatRoom) { return privateChatRoomMemberRepository.findByPrivateChatRoom(privateChatRoom); } + + @Transactional + public void leavePrivateChatRoom(Long userId, Long privateChatRoomId) { + PrivateChatRoomMember privateChatRoomMember = privateChatRoomMemberRepository.findByUserIdAndPrivateChatRoomId(userId, privateChatRoomId) + .orElseThrow(() -> new MosException(PrivateChatRoomMemberErrorCode.NOT_FOUND)); + + privateChatRoomMemberRepository.delete(privateChatRoomMember); + } } diff --git a/src/main/java/com/mos/backend/privatechatroommember/entity/PrivateChatRoomMember.java b/src/main/java/com/mos/backend/privatechatroommember/entity/PrivateChatRoomMember.java index b7ed8347..78d5e6e5 100644 --- a/src/main/java/com/mos/backend/privatechatroommember/entity/PrivateChatRoomMember.java +++ b/src/main/java/com/mos/backend/privatechatroommember/entity/PrivateChatRoomMember.java @@ -3,16 +3,27 @@ import com.mos.backend.common.entity.BaseAuditableEntity; import com.mos.backend.privatechatrooms.entity.PrivateChatRoom; import com.mos.backend.users.entity.User; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.SQLDelete; import java.time.LocalDateTime; @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +@SQLDelete(sql = "UPDATE private_chat_room_members SET deleted_at = NOW() WHERE private_chat_room_member_id = ?") @Table(name = "private_chat_room_members") public class PrivateChatRoomMember extends BaseAuditableEntity { @@ -31,6 +42,9 @@ public class PrivateChatRoomMember extends BaseAuditableEntity { private LocalDateTime lastEntryAt = LocalDateTime.now(); + @ColumnDefault("NULL") + private LocalDateTime deletedAt; + public static PrivateChatRoomMember of(PrivateChatRoom privateChatRoom, User user) { PrivateChatRoomMember privateChatRoomMember = new PrivateChatRoomMember(); privateChatRoomMember.privateChatRoom = privateChatRoom; @@ -42,4 +56,4 @@ public static PrivateChatRoomMember of(PrivateChatRoom privateChatRoom, User use public void updateLastEntryAt() { this.lastEntryAt = LocalDateTime.now(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepository.java b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepository.java index 70fea33e..78b2ce0c 100644 --- a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepository.java +++ b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepository.java @@ -17,4 +17,6 @@ public interface PrivateChatRoomMemberRepository { Optional findByUserIdAndPrivateChatRoomId(Long userId, Long privateChatRoomId); List findByPrivateChatRoom(PrivateChatRoom privateChatRoom); + + void delete(PrivateChatRoomMember privateChatRoomMember); } diff --git a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepositoryImpl.java b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepositoryImpl.java index f0c85091..2fd32cf1 100644 --- a/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepositoryImpl.java +++ b/src/main/java/com/mos/backend/privatechatroommember/infrastructure/PrivateChatRoomMemberRepositoryImpl.java @@ -38,4 +38,9 @@ public Optional findByUserIdAndPrivateChatRoomId(Long use public List findByPrivateChatRoom(PrivateChatRoom privateChatRoom) { return privateChatRoomMemberJpaRepository.findByPrivateChatRoom(privateChatRoom); } + + @Override + public void delete(PrivateChatRoomMember privateChatRoomMember) { + privateChatRoomMemberJpaRepository.delete(privateChatRoomMember); + } } diff --git a/src/main/java/com/mos/backend/privatechatroommember/presentation/PrivateChatRoomMemberController.java b/src/main/java/com/mos/backend/privatechatroommember/presentation/PrivateChatRoomMemberController.java new file mode 100644 index 00000000..0b8d6d8c --- /dev/null +++ b/src/main/java/com/mos/backend/privatechatroommember/presentation/PrivateChatRoomMemberController.java @@ -0,0 +1,19 @@ +package com.mos.backend.privatechatroommember.presentation; + +import com.mos.backend.privatechatroommember.application.PrivateChatRoomMemberService; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RestController +public class PrivateChatRoomMemberController { + private final PrivateChatRoomMemberService privateChatRoomMemberService; + + @DeleteMapping("/private-chat-rooms/{privateChatRoomId}/members") + public void leavePrivateChatRoom(@AuthenticationPrincipal Long userId, @PathVariable Long privateChatRoomId) { + privateChatRoomMemberService.leavePrivateChatRoom(userId, privateChatRoomId); + } +} From 9fee34c9a1291e25215753036e6538b9e0df2408 Mon Sep 17 00:00:00 2001 From: seungheonlee Date: Thu, 21 Aug 2025 17:05:05 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EC=B1=84=ED=8C=85=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=A1=B0=ED=9A=8C=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 삭제된 채팅방의 메시지 조회 시, 삭제 이후의 메시지만 조회되도록 수정 --- .../application/PrivateChatMessageService.java | 3 ++- .../PrivateChatMessageQueryDslRepository.java | 15 ++++++++++++--- .../PrivateChatMessageRepository.java | 2 +- .../PrivateChatMessageRepositoryImpl.java | 4 ++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/mos/backend/privatechatmessages/application/PrivateChatMessageService.java b/src/main/java/com/mos/backend/privatechatmessages/application/PrivateChatMessageService.java index 25f3f2d8..38d89c34 100644 --- a/src/main/java/com/mos/backend/privatechatmessages/application/PrivateChatMessageService.java +++ b/src/main/java/com/mos/backend/privatechatmessages/application/PrivateChatMessageService.java @@ -66,9 +66,10 @@ private PrivateChatMessage savePrivateChatMessage(User user, PrivateChatRoom pri @Transactional(readOnly = true) public InfinityScrollRes getPrivateChatMessages(Long userId, Long privateChatRoomId, Long lastPrivateChatMessageId, int size) { PrivateChatRoom privateChatRoom = entityFacade.getPrivateChatRoom(privateChatRoomId); + PrivateChatRoomMember privateChatRoomMember = entityFacade.getPrivateChatRoomMember(userId, privateChatRoomId); List privateChatMessages = privateChatMessageRepository.findAllByChatRoomIdForInfiniteScroll( - privateChatRoom.getId(), lastPrivateChatMessageId, size + privateChatRoom.getId(), lastPrivateChatMessageId, size, privateChatRoomMember.getDeletedAt() ); boolean hasNext = InfinityScrollUtil.hasNext(privateChatMessages, size); diff --git a/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageQueryDslRepository.java b/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageQueryDslRepository.java index 02c140f0..85aa15da 100644 --- a/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageQueryDslRepository.java +++ b/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageQueryDslRepository.java @@ -1,13 +1,14 @@ package com.mos.backend.privatechatmessages.infrastructure; import com.mos.backend.privatechatmessages.entity.PrivateChatMessage; -import com.querydsl.core.types.Predicate; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; import java.util.List; +import java.util.Objects; import static com.mos.backend.privatechatmessages.entity.QPrivateChatMessage.privateChatMessage; @@ -16,18 +17,26 @@ public class PrivateChatMessageQueryDslRepository { private final JPAQueryFactory queryFactory; - public List findByChatRoomIdForInfiniteScroll(Long privateChatRoomId, Long lastPrivateChatMessageId, int size) { + public List findByChatRoomIdForInfiniteScroll(Long privateChatRoomId, + Long lastPrivateChatMessageId, + int size, + LocalDateTime deletedAt) { return queryFactory .selectFrom(privateChatMessage) .where( eqPrivateChatRoomId(privateChatRoomId), - ltPrivateChatMessageId(lastPrivateChatMessageId) + ltPrivateChatMessageId(lastPrivateChatMessageId), + gtPrivateChatMessageCreatedAt(deletedAt) ) .orderBy(privateChatMessage.id.desc()) .limit(size + 1) .fetch(); } + private static BooleanExpression gtPrivateChatMessageCreatedAt(LocalDateTime deletedAt) { + return Objects.isNull(deletedAt) ? null : privateChatMessage.createdAt.gt(deletedAt); + } + private static BooleanExpression eqPrivateChatRoomId(Long privateChatRoomId) { return privateChatMessage.privateChatRoom.id.eq(privateChatRoomId); } diff --git a/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageRepository.java b/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageRepository.java index 09a2df28..94ae7737 100644 --- a/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageRepository.java +++ b/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageRepository.java @@ -12,7 +12,7 @@ public interface PrivateChatMessageRepository { Optional findFirstByPrivateChatRoomOrderByCreatedAtDesc(PrivateChatRoom privateChatRoom); - List findAllByChatRoomIdForInfiniteScroll(Long privateChatRoomId, Long lastPrivateChatMessageId, int size); + List findAllByChatRoomIdForInfiniteScroll(Long privateChatRoomId, Long lastPrivateChatMessageId, int size, LocalDateTime deletedAt); int countByPrivateChatRoomIdAndCreatedAtAfter(Long privateChatRoomId, LocalDateTime lastEntryAt); } diff --git a/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageRepositoryImpl.java b/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageRepositoryImpl.java index 14f6d335..648411d8 100644 --- a/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageRepositoryImpl.java +++ b/src/main/java/com/mos/backend/privatechatmessages/infrastructure/PrivateChatMessageRepositoryImpl.java @@ -26,8 +26,8 @@ public Optional findFirstByPrivateChatRoomOrderByCreatedAtDe } @Override - public List findAllByChatRoomIdForInfiniteScroll(Long privateChatRoomId, Long lastPrivateChatMessageId, int size) { - return privateChatMessageQueryDslRepository.findByChatRoomIdForInfiniteScroll(privateChatRoomId, lastPrivateChatMessageId, size); + public List findAllByChatRoomIdForInfiniteScroll(Long privateChatRoomId, Long lastPrivateChatMessageId, int size, LocalDateTime deletedAt) { + return privateChatMessageQueryDslRepository.findByChatRoomIdForInfiniteScroll(privateChatRoomId, lastPrivateChatMessageId, size, deletedAt); } @Override