Skip to content

Commit

Permalink
Merge pull request #44 from Domitory-CheckMate/feature/39-report
Browse files Browse the repository at this point in the history
[feat] 게시물, 채팅 신고
  • Loading branch information
OJOJIN authored Jan 13, 2024
2 parents 0691db0 + 0fee7f9 commit a524d0c
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.gachon.checkmate.domain.report.controller;


import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.gachon.checkmate.domain.report.dto.request.ChatRoomReportRequestDto;
import org.gachon.checkmate.domain.report.dto.request.PostReportRequestDto;
import org.gachon.checkmate.domain.report.service.ReportService;
import org.gachon.checkmate.global.common.SuccessResponse;
import org.gachon.checkmate.global.config.auth.UserId;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RequestMapping("/api/report")
@RestController
public class ReportController {

private final ReportService reportService;

@PostMapping("/post")
public ResponseEntity<SuccessResponse<?>> reportPost(@UserId final Long userId,
@RequestBody @Valid final PostReportRequestDto requestDto) {
reportService.reportPost(userId, requestDto);
return SuccessResponse.created(null);
}

@PostMapping("/chat-room")
public ResponseEntity<SuccessResponse<?>> reportChatRoom(@UserId final Long userId,
@RequestBody @Valid final ChatRoomReportRequestDto requestDto) {
reportService.reportChatRoom(userId, requestDto);
return SuccessResponse.created(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.gachon.checkmate.domain.report.dto.request;

public record ChatRoomReportRequestDto(
String chatRoomId,
String reason
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.gachon.checkmate.domain.report.dto.request;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;

public record PostReportRequestDto (
@NotNull(message = "신고할 게시물의 ID를 입력해주세요.") Long postId,
@NotEmpty(message = "신고할 이유를 입력해주세요") String reason
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.gachon.checkmate.domain.report.entity;

import jakarta.persistence.*;
import lombok.*;
import org.gachon.checkmate.domain.chat.entity.ChatRoom;
import org.gachon.checkmate.domain.member.entity.User;
import org.gachon.checkmate.domain.post.entity.Post;
import org.gachon.checkmate.domain.scrap.entity.Scrap;
import org.gachon.checkmate.global.common.BaseTimeEntity;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder(access = AccessLevel.PRIVATE)
@Getter
@Entity
public class ChatRoomReport extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "chat_room_report_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "chat_room_id")
private ChatRoom chatRoom;
@Column(name = "reason")
private String reason;

public static ChatRoomReport createChatRoomReport(User user, ChatRoom chatRoom, String reason) {
return ChatRoomReport.builder()
.user(user)
.chatRoom(chatRoom)
.reason(reason)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.gachon.checkmate.domain.report.entity;


import jakarta.persistence.*;
import lombok.*;
import org.gachon.checkmate.domain.member.entity.User;
import org.gachon.checkmate.domain.post.entity.Post;
import org.gachon.checkmate.global.common.BaseTimeEntity;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder(access = AccessLevel.PRIVATE)
@Getter
@Entity
public class PostReport extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "post_report_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private Post post;
@Column(name = "reason")
private String reason;

public static PostReport createPostReport(User user, Post post, String reason) {
return PostReport.builder()
.user(user)
.post(post)
.reason(reason)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.gachon.checkmate.domain.report.repository;

import org.gachon.checkmate.domain.report.entity.ChatRoomReport;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ChatRoomReportRepository extends JpaRepository<ChatRoomReport, Long> {

Boolean existsChatRoomReportByUserIdAndChatRoomId(Long userId, String chatRoomId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.gachon.checkmate.domain.report.repository;

import org.gachon.checkmate.domain.report.entity.PostReport;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface PostReportRepository extends JpaRepository<PostReport, Long> {

Boolean existsPostReportByUserIdAndPostId(Long userId, Long postId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.gachon.checkmate.domain.report.service;

import lombok.RequiredArgsConstructor;
import org.gachon.checkmate.domain.chat.entity.ChatRoom;
import org.gachon.checkmate.domain.chat.repository.ChatRoomRepository;
import org.gachon.checkmate.domain.member.entity.User;
import org.gachon.checkmate.domain.member.repository.UserRepository;
import org.gachon.checkmate.domain.post.entity.Post;
import org.gachon.checkmate.domain.post.repository.PostRepository;
import org.gachon.checkmate.domain.report.dto.request.ChatRoomReportRequestDto;
import org.gachon.checkmate.domain.report.dto.request.PostReportRequestDto;
import org.gachon.checkmate.domain.report.entity.ChatRoomReport;
import org.gachon.checkmate.domain.report.entity.PostReport;
import org.gachon.checkmate.domain.report.repository.ChatRoomReportRepository;
import org.gachon.checkmate.domain.report.repository.PostReportRepository;
import org.gachon.checkmate.global.error.exception.ConflictException;
import org.gachon.checkmate.global.error.exception.EntityNotFoundException;
import org.gachon.checkmate.global.error.exception.ForbiddenException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static org.gachon.checkmate.domain.report.entity.ChatRoomReport.*;
import static org.gachon.checkmate.domain.report.entity.PostReport.*;
import static org.gachon.checkmate.global.error.ErrorCode.*;

@RequiredArgsConstructor
@Transactional
@Service
public class ReportService {

private final PostReportRepository postReportRepository;
private final ChatRoomReportRepository chatRoomReportRepository;
private final UserRepository userRepository;
private final PostRepository postRepository;
private final ChatRoomRepository chatRoomRepository;

public void reportPost(Long userId, PostReportRequestDto requestDto) {
User user = getUserOrThrow(userId);
Post post = getPostOrThrow(requestDto.postId());
validateUserAlreadyReportPost(user, post);
PostReport postReport = createPostReport(user, post, requestDto.reason());
postReportRepository.save(postReport);
}

public void reportChatRoom(Long userId, ChatRoomReportRequestDto requestDto) {
User user = getUserOrThrow(userId);
ChatRoom chatRoom = getChatRoomOrThrow(requestDto.chatRoomId());
validateUserChatRoomMember(user, chatRoom);
validateUserAlreadyReportChatRoom(user, chatRoom);
ChatRoomReport chatRoomReport = createChatRoomReport(user, chatRoom, requestDto.reason());
chatRoomReportRepository.save(chatRoomReport);
}

private void validateUserChatRoomMember(User user, ChatRoom chatRoom) {
if(!chatRoom.getFirstMemberId().equals(user.getId()) &&
!chatRoom.getSecondMemberId().equals(user.getId())) {
throw new ForbiddenException(NOT_CHATROOM_USER);
}
}

private void validateUserAlreadyReportChatRoom(User user, ChatRoom chatRoom) {
if(chatRoomReportRepository.existsChatRoomReportByUserIdAndChatRoomId(user.getId(), chatRoom.getId())) {
throw new ConflictException(DUPLICATE_CHATROOM_REPORT);
}
}

private void validateUserAlreadyReportPost(User user, Post post) {
if(postReportRepository.existsPostReportByUserIdAndPostId(user.getId(), post.getId())) {
throw new ConflictException(DUPLICATE_POST_REPORT);
}
}

private User getUserOrThrow(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException(USER_NOT_FOUND));
}

private Post getPostOrThrow(Long postId) {
return postRepository.findById(postId)
.orElseThrow(() -> new EntityNotFoundException(POST_NOT_FOUND));
}

private ChatRoom getChatRoomOrThrow(String chatRoomId) {
return chatRoomRepository.findById(chatRoomId)
.orElseThrow(() -> new EntityNotFoundException(CHATROOM_NOT_FOUND));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public enum ErrorCode {
*/
FORBIDDEN(HttpStatus.FORBIDDEN, "리소스 접근 권한이 없습니다."),
NOT_POST_WRITER(HttpStatus.FORBIDDEN, "게시물을 수정할 권한이 없습니다. 작성자만이 게시물을 수정할 수 있습니다."),
NOT_CHATROOM_USER(HttpStatus.FORBIDDEN, "채팅방에 속한 유저가 아닙니다."),

/**
* 404 Not Found
Expand All @@ -44,6 +45,7 @@ public enum ErrorCode {
CHECK_LIST_NOT_FOUND(HttpStatus.NOT_FOUND, "체크리스트를 찾을 수 없습니다."),
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "해당하는 유저를 찾을 수 없습니다."),
POST_NOT_FOUND(HttpStatus.NOT_FOUND, "해당하는 게시글을 찾을 수 없습니다."),
CHATROOM_NOT_FOUND(HttpStatus.NOT_FOUND, "해당하는 채팅방을 찾을 수 없습니다."),
REFRESH_TOKEN_NOT_FOUND(HttpStatus.NOT_FOUND, "해당하는 리프레시 토큰을 찾을 수 없습니다. 다시 로그인해 주세요."),

/**
Expand All @@ -57,6 +59,8 @@ public enum ErrorCode {
CONFLICT(HttpStatus.CONFLICT, "이미 존재하는 리소스입니다."),
DUPLICATE_EMAIL(HttpStatus.CONFLICT, "이미 가입된 이메일입니다."),
DUPLICATE_CHECK_LIST(HttpStatus.CONFLICT, "체크리스트가 이미 존재합니다."),
DUPLICATE_POST_REPORT(HttpStatus.CONFLICT, "이전에 신고했던 게시물입니다."),
DUPLICATE_CHATROOM_REPORT(HttpStatus.CONFLICT, "이전에 신고했던 채팅방입니다."),

/**
* 500 Internal Server Error
Expand Down

0 comments on commit a524d0c

Please sign in to comment.