Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Tag(name = "채팅방 관련 API")
@RestController
Expand Down Expand Up @@ -47,4 +46,20 @@ public StateResponse leaveChatRoom(@JwtValidation Long userId,
public UserInfoList getUsersInChatRoom(@PathVariable Long chatRoomId) {
return userChatRoomService.getUserInfoList(chatRoomId);
}

@PatchMapping("/{chatRoomId}/image")
@Operation(summary = "채팅방 이미지 변경 API", description = "채팅방 대표 이미지를 변경하는 API 입니다.")
public StateResponse updateChatRoomImage(@JwtValidation Long userId,
@PathVariable Long chatRoomId,
@RequestParam("chatRoomImage") MultipartFile chatRoomImage) throws IOException {
return chatRoomService.updateChatRoomImage(userId, chatRoomId, chatRoomImage);
}

@DeleteMapping("/{chatRoomId}/users/{userId}")
@Operation(summary = "채팅방 유저 강제 퇴장 API", description = "채팅방에 참여한 유저를 강제 퇴장하는 API 입니다.")
public StateResponse kickUserFromChatRoom(@JwtValidation Long loginUserId,
@PathVariable Long chatRoomId,
@PathVariable Long userId) {
return chatRoomService.kickUserFromChatRoom(loginUserId, chatRoomId, userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

Expand All @@ -24,7 +23,9 @@ public ChatRoom toEntity(Board board) {
return ChatRoom.builder()
.board(board)
.participantCount(1)
.lastMessageAt(LocalDateTime.now())
.lastMessageAt(null)
.lastMessageContent(null)
.chatRoomImage(String.valueOf(board.getClub().getId()))
.build();
}

Expand All @@ -50,6 +51,8 @@ public ChatRoomInfo toChatRoomInfo(ChatRoom chatRoom, Board board) {
.boardInfo(boardInfo)
.participantCount(chatRoom.getParticipantCount())
.lastMessageAt(chatRoom.getLastMessageAt())
.lastMessageContent(chatRoom.getLastMessageContent())
.chatRoomImage(chatRoom.getChatRoomImage())
.build();
}
}
24 changes: 13 additions & 11 deletions src/main/java/com/back/catchmate/domain/chat/dto/ChatResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,24 @@ public static class PagedChatMessageInfo {
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class PagedChatRoomInfo {
private List<ChatRoomInfo> chatRoomInfoList;
private Integer totalPages;
private Long totalElements;
private Boolean isFirst;
private Boolean isLast;
public static class ChatRoomInfo {
private Long chatRoomId;
private BoardInfo boardInfo;
private Integer participantCount;
private LocalDateTime lastMessageAt;
private String lastMessageContent;
private String chatRoomImage;
}

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class ChatRoomInfo {
private Long chatRoomId;
private BoardInfo boardInfo;
private Integer participantCount;
private LocalDateTime lastMessageAt;
public static class PagedChatRoomInfo {
private List<ChatRoomInfo> chatRoomInfoList;
private Integer totalPages;
private Long totalElements;
private Boolean isFirst;
private Boolean isLast;
}
}
18 changes: 16 additions & 2 deletions src/main/java/com/back/catchmate/domain/chat/entity/ChatRoom.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ public class ChatRoom extends BaseTimeEntity {
@Column(nullable = false)
private int participantCount;

// 마지막 메시지 시간
@Column(nullable = false)
private LocalDateTime lastMessageAt;

private String lastMessageContent;

private String chatRoomImage;

// 채팅방에 메시지가 있을 때 마지막 메시지 시간 업데이트
public void updateLastMessageTime() {
this.lastMessageAt = LocalDateTime.now();
Expand All @@ -57,4 +59,16 @@ public void incrementParticipantCount() {
public void decrementParticipantCount() {
this.participantCount--;
}

public boolean isOwner(Long userId) {
return this.board.getUser().getId().equals(userId);
}

public void updateChatRoomImage(String chatRoomImage) {
this.chatRoomImage = chatRoomImage;
}

public void updateLastMessageContent(String content) {
this.lastMessageContent = content;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
public interface UserChatRoomRepository extends JpaRepository<UserChatRoom, Long> {
Optional<UserChatRoom> findByUserIdAndChatRoomId(Long userId, Long chatRoomId);

boolean existsByUserIdAndChatRoomId(Long userId, Long chatRoomId);
boolean existsByUserIdAndChatRoomIdAndDeletedAtIsNull(Long userId, Long chatRoomId);

@Query("SELECT ucr FROM UserChatRoom ucr " +
"JOIN FETCH ucr.chatRoom cr " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@
import com.back.catchmate.domain.chat.dto.ChatResponse.PagedChatRoomInfo;
import com.back.catchmate.global.dto.StateResponse;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

public interface ChatRoomService {
StateResponse leaveChatRoom(Long userId, Long chatRoomId);

PagedChatRoomInfo getChatRoomList(Long userId, Pageable pageable);

StateResponse updateChatRoomImage(Long userId, Long chatRoomId, MultipartFile image) throws IOException;

StateResponse kickUserFromChatRoom(Long adminId, Long chatRoomId, Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,23 @@
import com.back.catchmate.global.dto.StateResponse;
import com.back.catchmate.global.error.ErrorCode;
import com.back.catchmate.global.error.exception.BaseException;
import com.back.catchmate.global.s3.S3Service;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

import static com.back.catchmate.domain.chat.dto.ChatRequest.ChatMessageRequest.MessageType;

@Service
@RequiredArgsConstructor
public class ChatRoomServiceImpl implements ChatRoomService {
private final ChatService chatService;
private final S3Service s3Service;
private final UserRepository userRepository;
private final ChatRoomRepository chatRoomRepository;
private final UserChatRoomRepository userChatRoomRepository;
Expand Down Expand Up @@ -63,4 +68,42 @@ public StateResponse leaveChatRoom(Long userId, Long chatRoomId) {

return new StateResponse(true);
}

@Override
@Transactional
public StateResponse updateChatRoomImage(Long userId, Long chatRoomId, MultipartFile image) throws IOException {
ChatRoom chatRoom = chatRoomRepository.findById(chatRoomId)
.orElseThrow(() -> new BaseException(ErrorCode.CHATROOM_NOT_FOUND));

if (!chatRoom.isOwner(userId)) {
throw new BaseException(ErrorCode.IMAGE_UPDATE_UNAUTHORIZED_ACCESS);
}

String imageUrl = s3Service.uploadFile(image);
chatRoom.updateChatRoomImage(imageUrl);
return new StateResponse(true);
}

@Override
@Transactional
public StateResponse kickUserFromChatRoom(Long loginUserId, Long chatRoomId, Long userId) {
ChatRoom chatRoom = chatRoomRepository.findById(chatRoomId)
.orElseThrow(() -> new BaseException(ErrorCode.CHATROOM_NOT_FOUND));

if (!chatRoom.isOwner(loginUserId)) {
throw new BaseException(ErrorCode.KICK_CHATROOM_UNAUTHORIZED_ACCESS);
}

UserChatRoom userChatRoom = userChatRoomRepository.findByUserIdAndChatRoomId(userId, chatRoom.getId())
.orElseThrow(() -> new BaseException(ErrorCode.USER_CHATROOM_NOT_FOUND));

userChatRoom.delete();

User user = userRepository.findById(userId)
.orElseThrow(() -> new BaseException(ErrorCode.USER_NOT_FOUND));

String content = "방장의 결정으로 " + user.getNickName() + " 님이 채팅방에서 나갔습니다.";
chatService.sendEnterLeaveMessage(chatRoomId, content, userId, MessageType.LEAVE);
return new StateResponse(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public void sendChatMessage(Long chatRoomId, ChatMessageRequest request) {
ChatRoom chatRoom = chatRoomRepository.findById(chatRoomId)
.orElseThrow(() -> new BaseException(ErrorCode.CHATROOM_NOT_FOUND));

chatRoom.updateLastMessageContent(request.getContent());
chatRoom.updateLastMessageTime();
}

Expand Down Expand Up @@ -86,7 +87,7 @@ public void sendEnterLeaveMessage(Long chatRoomId, String content, Long senderId
@Override
@Transactional(readOnly = true)
public PagedChatMessageInfo getChatMessageList(Long userId, Long chatRoomId, Pageable pageable) {
if (!userChatRoomRepository.existsByUserIdAndChatRoomId(userId, chatRoomId)) {
if (!userChatRoomRepository.existsByUserIdAndChatRoomIdAndDeletedAtIsNull(userId, chatRoomId)) {
throw new BaseException(ErrorCode.USER_CHATROOM_NOT_FOUND);
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/back/catchmate/global/error/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public enum ErrorCode {

// 파일
FILE_UPLOAD_FAILED(HttpStatus.BAD_REQUEST, "파일 업로드를 실패했습니다."),
IMAGE_UPDATE_UNAUTHORIZED_ACCESS(HttpStatus.UNAUTHORIZED, "채팅방 이미지를 수정할 권한이 없습니다."),
KICK_CHATROOM_UNAUTHORIZED_ACCESS(HttpStatus.UNAUTHORIZED, "채팅방에서 내보낼 권한이 없습니다."),

INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "유효하지 않은 토큰입니다."),
BAD_REQUEST(HttpStatus.BAD_REQUEST, "클라이언트 에러입니다"),
Expand Down