Skip to content

Commit

Permalink
[FEAT] 게시글, 채팅방, 채팅 예외처리 (#124)
Browse files Browse the repository at this point in the history
* no change

* feat: 장애 유형 및 도움 유형에 따른 필터링 추가

* feat: 게시글 예외처리

* feat: 게시글을 찾고 없을 시 예외로 던지는 함수 작성

* feat: 매칭, 매칭 방 예외 처리

* feat: 채팅 메시지 예외처리

* fix: 오류 메시지 수정

* chore: validation 의존성 추가
  • Loading branch information
injae-348 authored Sep 2, 2024
1 parent 16b4aaa commit 90bd53c
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 35 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.session:spring-session-data-redis'

implementation 'org.springframework.boot:spring-boot-starter-validation'

// p6spy 의존성 추가 - SQL 로그 확인
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package econo.buddybridge.chat.chatmessage.exception;

import econo.buddybridge.common.exception.ErrorCode;
import org.springframework.http.HttpStatus;

public enum ChatMessageErrorCode implements ErrorCode {
LAST_CHAT_MESSAGE_NOT_FOUND("CH01", HttpStatus.NOT_FOUND, "마지막 메시지가 존재하지 않습니다."),
;

private final String code;
private final HttpStatus httpStatus;
private final String message;

ChatMessageErrorCode(String code, HttpStatus httpStatus, String message) {
this.code = code;
this.httpStatus = httpStatus;
this.message = message;
}

@Override
public String getCode() {
return code;
}

@Override
public HttpStatus getHttpStatus() {
return httpStatus;
}

@Override
public String getMessage() {
return message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package econo.buddybridge.chat.chatmessage.exception;

import econo.buddybridge.common.exception.BusinessException;

public class LastChatMessageNotFoundException extends BusinessException {

public static BusinessException EXCEPTION = new LastChatMessageNotFoundException();

public LastChatMessageNotFoundException() { super(ChatMessageErrorCode.LAST_CHAT_MESSAGE_NOT_FOUND); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,36 @@
import econo.buddybridge.chat.chatmessage.dto.ChatMessageReqDto;
import econo.buddybridge.chat.chatmessage.dto.ChatMessageResDto;
import econo.buddybridge.chat.chatmessage.entity.ChatMessage;
import econo.buddybridge.chat.chatmessage.exception.LastChatMessageNotFoundException;
import econo.buddybridge.chat.chatmessage.repository.ChatMessageRepository;
import econo.buddybridge.matching.entity.Matching;
import econo.buddybridge.matching.repository.MatchingRepository;
import econo.buddybridge.matching.exception.MatchingUnauthorizedAccessException;
import econo.buddybridge.matching.service.MatchingService;
import econo.buddybridge.member.entity.Member;
import econo.buddybridge.member.service.MemberService;
import econo.buddybridge.notification.entity.NotificationType;
import econo.buddybridge.notification.service.EmitterService;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class ChatMessageService {

private final MemberService memberService;
private final MatchingRepository matchingRepository;
private final ChatMessageRepository chatMessageRepository;
private final EmitterService emitterService;
private final MatchingService matchingService;

@Transactional // 메시지 저장
public ChatMessageResDto save(Long senderId, ChatMessageReqDto chatMessageReqDto, Long matchingId) {
Member sender = memberService.findMemberByIdOrThrow(senderId);

Matching matching = matchingRepository.findById(matchingId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 매칭입니다."));
Matching matching = matchingService.findMatchingByIdOrThrow(matchingId);

ChatMessage chatMessage = ChatMessage.builder()
.matching(matching)
Expand Down Expand Up @@ -61,23 +63,22 @@ public ChatMessageResDto save(Long senderId, ChatMessageReqDto chatMessageReqDto
}

private Long getReceiverId(Long senderId, Long matchingId) {
Matching matching = matchingRepository.findById(matchingId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 매칭입니다."));
Matching matching = matchingService.findMatchingByIdOrThrow(matchingId);

if (matching.getGiver().getId().equals(senderId)) {
return matching.getTaker().getId();
} else if (matching.getTaker().getId().equals(senderId)) {
return matching.getGiver().getId();
} else {
throw new IllegalArgumentException("매칭에 속하지 않은 사용자입니다.");
throw MatchingUnauthorizedAccessException.EXCEPTION;
}
}

@Transactional // 마지막 메시지 조회
public ChatMessageResDto getLastChatMessage(Long matchingId) {
List<ChatMessage> chatMessageList = chatMessageRepository.findLastMessageByMatchingId(matchingId, PageRequest.of(0, 1));
if (chatMessageList.isEmpty()) {
throw new IllegalArgumentException("마지막 메시지가 존재하지 않습니다.");
throw LastChatMessageNotFoundException.EXCEPTION;
}

ChatMessage chatMessage = chatMessageList.getFirst();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package econo.buddybridge.matching.exception;

import econo.buddybridge.common.exception.ErrorCode;
import org.springframework.http.HttpStatus;

public enum MatchingErrorCode implements ErrorCode {
MATCHING_NOT_FOUND("MA001", HttpStatus.NOT_FOUND, "존재하지 않는 매칭입니다."),
MATCHING_UNAUTHORIZED_ACCESS("MA002", HttpStatus.FORBIDDEN, "사용자가 생성한 매칭방이 아닙니다.")
;

private final String code;
private final HttpStatus httpStatus;
private final String message;

MatchingErrorCode(String code, HttpStatus httpStatus, String message) {
this.code = code;
this.httpStatus = httpStatus;
this.message = message;
}

@Override
public String getCode() {
return code;
}

@Override
public HttpStatus getHttpStatus() {
return httpStatus;
}

@Override
public String getMessage() {
return message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package econo.buddybridge.matching.exception;

import econo.buddybridge.common.exception.BusinessException;

public class MatchingNotFoundException extends BusinessException {

public static BusinessException EXCEPTION = new MatchingNotFoundException();

private MatchingNotFoundException() { super(MatchingErrorCode.MATCHING_NOT_FOUND); }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package econo.buddybridge.matching.exception;

import econo.buddybridge.common.exception.BusinessException;

public class MatchingUnauthorizedAccessException extends BusinessException {

public static BusinessException EXCEPTION = new MatchingUnauthorizedAccessException();

public MatchingUnauthorizedAccessException() { super(MatchingErrorCode.MATCHING_UNAUTHORIZED_ACCESS); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,29 @@
import econo.buddybridge.matching.dto.ReceiverDto;
import econo.buddybridge.matching.entity.Matching;
import econo.buddybridge.matching.entity.MatchingStatus;
import econo.buddybridge.matching.repository.MatchingRepository;
import econo.buddybridge.matching.exception.MatchingUnauthorizedAccessException;
import econo.buddybridge.matching.repository.MatchingRepositoryCustom;
import econo.buddybridge.member.entity.Member;
import econo.buddybridge.member.service.MemberService;
import econo.buddybridge.post.entity.Post;
import java.time.LocalDateTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@RequiredArgsConstructor
public class MatchingRoomService {

private final MemberService memberService;
private final MatchingRepository matchingRepository;
private final ChatMessageRepository chatMessageRepository;
private final MatchingRepositoryCustom matchingRepositoryCustom;
private final MatchingService matchingService;

@Transactional
public MatchingCustomPage getMatchings(Long memberId, Integer size, LocalDateTime cursor, MatchingStatus matchingStatus){
Expand All @@ -41,11 +42,10 @@ public MatchingCustomPage getMatchings(Long memberId, Integer size, LocalDateTim
public ChatMessageCustomPage getMatchingRoomMessages(Long memberId, Long matchingId, Integer size, Long cursor){

// 사용자 확인 // TODO: 예외처리 필요, 사용자가 매칭방에 속해있지 않을 경우 500 발생
Matching matching = matchingRepository.findById(matchingId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 매칭방입니다."));
Matching matching = matchingService.findMatchingByIdOrThrow(matchingId);

if (!matching.getGiver().getId().equals(memberId) && !matching.getTaker().getId().equals(memberId)){
throw new IllegalArgumentException("사용자가 매칭방에 속해있지 않습니다.");
throw MatchingUnauthorizedAccessException.EXCEPTION;
}

Pageable pageable = PageRequest.of(0, size+1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
import econo.buddybridge.matching.dto.MatchingUpdateDto;
import econo.buddybridge.matching.entity.Matching;
import econo.buddybridge.matching.entity.MatchingStatus;
import econo.buddybridge.matching.exception.MatchingNotFoundException;
import econo.buddybridge.matching.repository.MatchingRepository;
import econo.buddybridge.member.entity.Member;
import econo.buddybridge.member.service.MemberService;
import econo.buddybridge.post.entity.Post;
import econo.buddybridge.post.entity.PostType;
import econo.buddybridge.post.repository.PostRepository;
import econo.buddybridge.post.exception.PostUnauthorizedAccessException;
import econo.buddybridge.post.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -22,13 +24,19 @@
public class MatchingService {
private final ChatMessageRepository chatMessageRepository;
private final MatchingRepository matchingRepository;
private final PostRepository postRepository;
private final MemberService memberService;
private final PostService postService;

@Transactional // TODO: 매칭 생성 -> 예외처리 필요 + 댓글에서 사용자 정보 가져오기 고려
// 존재하는 매칭인지 확인
@Transactional(readOnly = true)
public Matching findMatchingByIdOrThrow(Long matchingId) {
return matchingRepository.findById(matchingId)
.orElseThrow(() -> MatchingNotFoundException.EXCEPTION);
}

@Transactional
public Long createMatchingById(MatchingReqDto matchingReqDto, Long memberId) {
Post post = postRepository.findById(matchingReqDto.postId())
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 게시글입니다."));
Post post = postService.findPostByIdOrThrow(matchingReqDto.postId());

Member loginMember = memberService.findMemberByIdOrThrow(memberId);

Expand Down Expand Up @@ -60,8 +68,8 @@ public Long createMatchingById(MatchingReqDto matchingReqDto, Long memberId) {

@Transactional // 매칭 업데이트
public Long updateMatching(Long matchingId, MatchingUpdateDto matchingUpdateDto, Long memberId) {
Matching matching = matchingRepository.findById(matchingId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 매칭입니다."));

Matching matching = findMatchingByIdOrThrow(matchingId);

validatePostAuthor(matching.getPost(), memberId);

Expand All @@ -72,9 +80,7 @@ public Long updateMatching(Long matchingId, MatchingUpdateDto matchingUpdateDto,

@Transactional // 매칭 삭제
public void deleteMatching(Long matchingId, Long memberId) {
Matching matching = matchingRepository.findById(matchingId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 매칭입니다."));

Matching matching = findMatchingByIdOrThrow(matchingId);
validatePostAuthor(matching.getPost(), memberId);

matchingRepository.delete(matching);
Expand All @@ -94,7 +100,7 @@ private Matching matchingReqToMatching(Post post, Member taker, Member giver) {
private void validatePostAuthor(Post post, Long memberId) {
if ((post.getPostType() == PostType.GIVER && !post.getAuthor().getId().equals(memberId)) ||
(post.getPostType() == PostType.TAKER && !post.getAuthor().getId().equals(memberId))) {
throw new IllegalArgumentException("회원님이 작성한 게시글이 아닙니다.");
throw PostUnauthorizedAccessException.EXCEPTION;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package econo.buddybridge.post.exception;

import econo.buddybridge.common.exception.BusinessException;

public class PostDeleteNotAllowedException extends BusinessException {
public static BusinessException EXCEPTION = new PostDeleteNotAllowedException();

private PostDeleteNotAllowedException() {
super(PostErrorCode.POST_DELETE_NOT_ALLOWED);
}
}
39 changes: 39 additions & 0 deletions src/main/java/econo/buddybridge/post/exception/PostErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package econo.buddybridge.post.exception;

import econo.buddybridge.common.exception.ErrorCode;
import org.springframework.http.HttpStatus;

public enum PostErrorCode implements ErrorCode {
// TODO: Implement PostErrorCode
// EX) INVALID_INPUT_VALUE("P001", HttpStatus.BAD_REQUEST, "요청 값이 잘못되었습니다."),
POST_NOT_FOUND("P001", HttpStatus.NOT_FOUND, "존재하지 않는 게시글입니다."),
POST_DELETE_NOT_ALLOWED("P002", HttpStatus.FORBIDDEN, "본인의 게시글만 삭제할 수 있습니다."),
POST_UPDATE_NOT_ALLOWED("P003", HttpStatus.FORBIDDEN, "본인의 게시글만 수정할 수 있습니다."),
POST_UNAUTHORIZED_ACCESS("P004", HttpStatus.BAD_REQUEST, "회원님이 작성한 게시글이 아닙니다."),
;

private final String code;
private final HttpStatus httpStatus;
private final String message;

PostErrorCode(String code, HttpStatus httpStatus, String message) {
this.code = code;
this.httpStatus = httpStatus;
this.message = message;
}

@Override
public String getCode() {
return code;
}

@Override
public HttpStatus getHttpStatus() {
return httpStatus;
}

@Override
public String getMessage() {
return message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package econo.buddybridge.post.exception;

import econo.buddybridge.common.exception.BusinessException;

public class PostNotFoundException extends BusinessException {

public static BusinessException EXCEPTION = new PostNotFoundException();

private PostNotFoundException() {
super(PostErrorCode.POST_NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package econo.buddybridge.post.exception;

import econo.buddybridge.common.exception.BusinessException;

public class PostUnauthorizedAccessException extends BusinessException {

public static BusinessException EXCEPTION = new PostUnauthorizedAccessException();

private PostUnauthorizedAccessException() {super(PostErrorCode.POST_UNAUTHORIZED_ACCESS);}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package econo.buddybridge.post.exception;

import econo.buddybridge.common.exception.BusinessException;

public class PostUpdateNotAllowedException extends BusinessException {

public static BusinessException EXCEPTION = new PostUpdateNotAllowedException();

private PostUpdateNotAllowedException() { super(PostErrorCode.POST_UPDATE_NOT_ALLOWED); }

}
Loading

0 comments on commit 90bd53c

Please sign in to comment.