diff --git a/src/main/java/balancetalk/module/authmail/dto/EmailRequest.java b/src/main/java/balancetalk/module/authmail/dto/EmailRequest.java index 31b45753f..b5ab7ed5b 100644 --- a/src/main/java/balancetalk/module/authmail/dto/EmailRequest.java +++ b/src/main/java/balancetalk/module/authmail/dto/EmailRequest.java @@ -10,7 +10,6 @@ @Data @AllArgsConstructor -@NoArgsConstructor public class EmailRequest { @NotNull diff --git a/src/main/java/balancetalk/module/authmail/dto/EmailVerification.java b/src/main/java/balancetalk/module/authmail/dto/EmailVerification.java index 81e673a66..a7aa52822 100644 --- a/src/main/java/balancetalk/module/authmail/dto/EmailVerification.java +++ b/src/main/java/balancetalk/module/authmail/dto/EmailVerification.java @@ -10,7 +10,6 @@ @Data @AllArgsConstructor -@NoArgsConstructor public class EmailVerification { @NotNull diff --git a/src/main/java/balancetalk/module/comment/application/CommentService.java b/src/main/java/balancetalk/module/comment/application/CommentService.java index b286a9411..df3d59980 100644 --- a/src/main/java/balancetalk/module/comment/application/CommentService.java +++ b/src/main/java/balancetalk/module/comment/application/CommentService.java @@ -15,6 +15,9 @@ import balancetalk.module.post.domain.BalanceOption; import balancetalk.module.post.domain.Post; import balancetalk.module.post.domain.PostRepository; +import balancetalk.module.report.domain.Report; +import balancetalk.module.report.domain.ReportRepository; +import balancetalk.module.report.dto.ReportRequest; import balancetalk.module.member.dto.MyPageResponse; import balancetalk.module.vote.domain.Vote; import balancetalk.module.vote.domain.VoteRepository; @@ -46,6 +49,7 @@ public class CommentService { private final PostRepository postRepository; private final CommentLikeRepository commentLikeRepository; private final VoteRepository voteRepository; + private final ReportRepository reportRepository; @Value("${comments.max-depth}") private int maxDepth; @@ -255,7 +259,25 @@ public List findBestComments(Long postId, String token) { .toList()); } } - return responses; } + + public void reportComment(Long postId, Long commentId, ReportRequest reportRequest) { + Comment comment = validateCommentId(commentId); + Member member = getCurrentMember(memberRepository); +// if (comment.getMember().equals(member)) { +// throw new BalanceTalkException(FORBIDDEN_OWN_REPORT); +// } + + if (!comment.getPost().getId().equals(postId)) { + throw new BalanceTalkException(NOT_FOUND_COMMENT_AT_THAT_POST); + } + Report report = Report.builder() + .content(reportRequest.getDescription()) + .reporter(member) + .comment(comment) + .category(reportRequest.getCategory()) + .build(); + reportRepository.save(report); + } } diff --git a/src/main/java/balancetalk/module/comment/domain/Comment.java b/src/main/java/balancetalk/module/comment/domain/Comment.java index 4b3f1eb2a..eb6798696 100644 --- a/src/main/java/balancetalk/module/comment/domain/Comment.java +++ b/src/main/java/balancetalk/module/comment/domain/Comment.java @@ -46,10 +46,10 @@ public class Comment extends BaseTimeEntity { @JoinColumn(name = "parent_id") private Comment parent; - @OneToMany(mappedBy = "comment") + @OneToMany(mappedBy = "comment", cascade = CascadeType.ALL) private List likes = new ArrayList<>(); - @OneToMany(mappedBy = "comment") + @OneToMany(mappedBy = "comment", cascade = CascadeType.ALL) private List reports = new ArrayList<>(); public void updateContent(String content) { diff --git a/src/main/java/balancetalk/module/comment/dto/CommentResponse.java b/src/main/java/balancetalk/module/comment/dto/CommentResponse.java index 401aec48a..77e9f5d36 100644 --- a/src/main/java/balancetalk/module/comment/dto/CommentResponse.java +++ b/src/main/java/balancetalk/module/comment/dto/CommentResponse.java @@ -1,5 +1,6 @@ package balancetalk.module.comment.dto; +import balancetalk.module.ViewStatus; import balancetalk.module.comment.domain.Comment; import balancetalk.module.file.domain.File; import balancetalk.module.member.domain.Member; @@ -30,9 +31,15 @@ public class CommentResponse { @Schema(description = "해당 댓글에 맞는 선택지 id", example = "23") private Long selectedOptionId; +// @Schema(description = "댓글 블라인드 여부", example = "NORMAL") +// private ViewStatus viewStatus; + @Schema(description = "댓글 추천 수", example = "24") private int likesCount; +// @Schema(description = "댓글 신고 수", example = "3") +// private long reportedCount; + @Schema(description = "추천 여부", example = "true") private boolean myLike; @@ -52,7 +59,9 @@ public static CommentResponse fromEntity(Comment comment, Long balanceOptionId, .memberName(comment.getMember().getNickname()) .postId(comment.getPost().getId()) .selectedOptionId(balanceOptionId) + //.viewStatus(comment.getViewStatus()) .likesCount(comment.getLikes().size()) + //.reportedCount(comment.reportedCount()) .myLike(myLike) .createdAt(comment.getCreatedAt()) .lastModifiedAt(comment.getLastModifiedAt()) diff --git a/src/main/java/balancetalk/module/comment/presentation/CommentController.java b/src/main/java/balancetalk/module/comment/presentation/CommentController.java index 0ea64bf05..0db727e11 100644 --- a/src/main/java/balancetalk/module/comment/presentation/CommentController.java +++ b/src/main/java/balancetalk/module/comment/presentation/CommentController.java @@ -4,6 +4,7 @@ import balancetalk.module.comment.dto.CommentRequest; import balancetalk.module.comment.dto.CommentResponse; import balancetalk.module.comment.dto.ReplyCreateRequest; +import balancetalk.module.report.dto.ReportRequest; import balancetalk.module.comment.dto.ReplyResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -93,4 +94,12 @@ public String likeComment(@PathVariable Long postId, @PathVariable Long commentI public void cancelLikeComment(@PathVariable Long commentId) { commentService.cancelLikeComment(commentId); } + + @ResponseStatus(HttpStatus.OK) + @PostMapping("/{commentId}/report") + @Operation(summary = "댓글 신고", description = "comment-id에 해당하는 댓글을 신고 처리한다.") + public String reportComment(@PathVariable Long postId, @PathVariable Long commentId, @RequestBody ReportRequest reportRequest) { + commentService.reportComment(postId, commentId, reportRequest); + return "신고가 성공적으로 접수되었습니다."; + } } diff --git a/src/main/java/balancetalk/module/file/dto/FileResponse.java b/src/main/java/balancetalk/module/file/dto/FileResponse.java index 5a7faed55..f97763199 100644 --- a/src/main/java/balancetalk/module/file/dto/FileResponse.java +++ b/src/main/java/balancetalk/module/file/dto/FileResponse.java @@ -7,7 +7,6 @@ @Data @Builder -@NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class FileResponse { @Schema(description = "파일 id", example = "1") diff --git a/src/main/java/balancetalk/module/member/application/MemberService.java b/src/main/java/balancetalk/module/member/application/MemberService.java index 81bf89974..4c6ed7e25 100644 --- a/src/main/java/balancetalk/module/member/application/MemberService.java +++ b/src/main/java/balancetalk/module/member/application/MemberService.java @@ -4,11 +4,13 @@ import balancetalk.global.exception.ErrorCode; import balancetalk.global.jwt.JwtTokenProvider; import balancetalk.global.redis.application.RedisService; +import balancetalk.module.comment.domain.Comment; import balancetalk.module.file.domain.File; import balancetalk.module.file.domain.FileRepository; import balancetalk.module.member.domain.Member; import balancetalk.module.member.domain.MemberRepository; import balancetalk.module.member.dto.*; +import balancetalk.module.post.domain.Post; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -124,6 +126,12 @@ public void delete(final LoginRequest loginRequest, HttpServletRequest request) if (!passwordEncoder.matches(loginRequest.getPassword(), member.getPassword())) { throw new BalanceTalkException(ErrorCode.MISMATCHED_EMAIL_OR_PASSWORD); } + List posts = member.getPosts(); + if (posts != null) { + for (Post post : posts) { + post.removeMember(); + } + } memberRepository.deleteByEmail(member.getEmail()); } diff --git a/src/main/java/balancetalk/module/member/dto/JoinRequest.java b/src/main/java/balancetalk/module/member/dto/JoinRequest.java index d9d02abdf..ace7a9c3e 100644 --- a/src/main/java/balancetalk/module/member/dto/JoinRequest.java +++ b/src/main/java/balancetalk/module/member/dto/JoinRequest.java @@ -12,7 +12,6 @@ @Data @Builder -@NoArgsConstructor @AllArgsConstructor public class JoinRequest { diff --git a/src/main/java/balancetalk/module/member/dto/LoginRequest.java b/src/main/java/balancetalk/module/member/dto/LoginRequest.java index fdcd07fb4..c1d5f8521 100644 --- a/src/main/java/balancetalk/module/member/dto/LoginRequest.java +++ b/src/main/java/balancetalk/module/member/dto/LoginRequest.java @@ -9,7 +9,6 @@ @Data @Builder -@NoArgsConstructor @AllArgsConstructor public class LoginRequest { diff --git a/src/main/java/balancetalk/module/member/dto/MemberResponse.java b/src/main/java/balancetalk/module/member/dto/MemberResponse.java index 9cf243e25..4ee1080ef 100644 --- a/src/main/java/balancetalk/module/member/dto/MemberResponse.java +++ b/src/main/java/balancetalk/module/member/dto/MemberResponse.java @@ -11,7 +11,6 @@ import java.util.Optional; @Data @Builder -@NoArgsConstructor @AllArgsConstructor public class MemberResponse { diff --git a/src/main/java/balancetalk/module/post/application/PostService.java b/src/main/java/balancetalk/module/post/application/PostService.java index 8fadd74f2..b1756e446 100644 --- a/src/main/java/balancetalk/module/post/application/PostService.java +++ b/src/main/java/balancetalk/module/post/application/PostService.java @@ -13,6 +13,12 @@ import balancetalk.module.member.domain.Role; import balancetalk.module.member.dto.MyPageResponse; import balancetalk.module.post.domain.*; +import balancetalk.module.post.dto.BalanceOptionRequest; +import balancetalk.module.post.dto.PostRequest; +import balancetalk.module.post.dto.PostResponse; +import balancetalk.module.report.domain.Report; +import balancetalk.module.report.domain.ReportRepository; +import balancetalk.module.report.dto.ReportRequest; import balancetalk.module.post.dto.*; import balancetalk.module.vote.domain.VoteRepository; import java.util.stream.Collectors; @@ -31,7 +37,6 @@ @Transactional public class PostService { private static final int BEST_POSTS_SIZE = 5; - private final PostRepository postRepository; private final MemberRepository memberRepository; private final PostLikeRepository postLikeRepository; @@ -39,6 +44,7 @@ public class PostService { private final VoteRepository voteRepository; private final BookmarkRepository bookmarkRepository; private final RedisService redisService; + private final ReportRepository reportRepository; public PostResponse save(final PostRequest request) { Member writer = getCurrentMember(memberRepository); @@ -226,4 +232,20 @@ public List findPostsByTag(String token, String tagName) { member.hasVoted(post))) .collect(Collectors.toList()); } + + public void reportPost(Long postId, ReportRequest reportRequest) { + Post post = postRepository.findById(postId) + .orElseThrow(() -> new BalanceTalkException(NOT_FOUND_POST)); + Member member = getCurrentMember(memberRepository); +// if (post.getMember().equals(member)) { +// throw new BalanceTalkException(FORBIDDEN_OWN_REPORT); +// } + Report report = Report.builder() + .content(reportRequest.getDescription()) + .reporter(member) + .post(post) + .category(reportRequest.getCategory()) + .build(); + reportRepository.save(report); + } } diff --git a/src/main/java/balancetalk/module/post/domain/BalanceOption.java b/src/main/java/balancetalk/module/post/domain/BalanceOption.java index f2ba07823..0676da667 100644 --- a/src/main/java/balancetalk/module/post/domain/BalanceOption.java +++ b/src/main/java/balancetalk/module/post/domain/BalanceOption.java @@ -40,7 +40,7 @@ public class BalanceOption { @JoinColumn(name = "post_id") private Post post; - @OneToMany(mappedBy = "balanceOption") + @OneToMany(mappedBy = "balanceOption", cascade = CascadeType.ALL) private List votes = new ArrayList<>(); public int voteCount() { diff --git a/src/main/java/balancetalk/module/post/domain/Post.java b/src/main/java/balancetalk/module/post/domain/Post.java index 41b446733..fddd1065f 100644 --- a/src/main/java/balancetalk/module/post/domain/Post.java +++ b/src/main/java/balancetalk/module/post/domain/Post.java @@ -59,22 +59,22 @@ public class Post extends BaseTimeEntity { @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List options = new ArrayList<>(); - @OneToMany(mappedBy = "post") + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List likes = new ArrayList<>(); @Formula("(select count(*) from post_like where post_like.post_id = post_id)") private long likesCount; - @OneToMany(mappedBy = "post") + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List comments = new ArrayList<>(); @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List postTags = new ArrayList<>(); - @OneToMany(mappedBy = "post") + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List bookmarks = new ArrayList<>(); - @OneToMany(mappedBy = "post") + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL) private List reports = new ArrayList<>(); public boolean isCasual() { @@ -101,6 +101,10 @@ public void init() { this.viewStatus = ViewStatus.NORMAL; } + public void removeMember() { + this.member = null; + } + public boolean notContainsBalanceOption(BalanceOption option) { return !options.contains(option); } diff --git a/src/main/java/balancetalk/module/post/dto/BalanceOptionRequest.java b/src/main/java/balancetalk/module/post/dto/BalanceOptionRequest.java index ecac4163f..2287a3738 100644 --- a/src/main/java/balancetalk/module/post/dto/BalanceOptionRequest.java +++ b/src/main/java/balancetalk/module/post/dto/BalanceOptionRequest.java @@ -2,7 +2,6 @@ import balancetalk.module.file.domain.File; import balancetalk.module.post.domain.BalanceOption; -import balancetalk.module.post.domain.BalanceOption.BalanceOptionBuilder; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; @@ -14,9 +13,10 @@ import java.util.List; import java.util.Optional; +import static balancetalk.module.post.domain.BalanceOption.*; + @Data @Builder -@NoArgsConstructor @AllArgsConstructor public class BalanceOptionRequest { diff --git a/src/main/java/balancetalk/module/post/dto/BalanceOptionResponse.java b/src/main/java/balancetalk/module/post/dto/BalanceOptionResponse.java index 5fc5d70d9..cadd9eb1c 100644 --- a/src/main/java/balancetalk/module/post/dto/BalanceOptionResponse.java +++ b/src/main/java/balancetalk/module/post/dto/BalanceOptionResponse.java @@ -2,7 +2,6 @@ import balancetalk.module.file.domain.File; import balancetalk.module.post.domain.BalanceOption; -import balancetalk.module.post.domain.BalanceOption.BalanceOptionBuilder; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; @@ -10,9 +9,10 @@ import lombok.NoArgsConstructor; import org.springframework.lang.Nullable; +import static balancetalk.module.post.domain.BalanceOption.*; + @Data @Builder -@NoArgsConstructor @AllArgsConstructor public class BalanceOptionResponse { diff --git a/src/main/java/balancetalk/module/post/dto/PostRequest.java b/src/main/java/balancetalk/module/post/dto/PostRequest.java index 6e69e2ab7..97ae45de2 100644 --- a/src/main/java/balancetalk/module/post/dto/PostRequest.java +++ b/src/main/java/balancetalk/module/post/dto/PostRequest.java @@ -12,7 +12,6 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; -import lombok.NoArgsConstructor; import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -21,7 +20,6 @@ @Data @Builder -@NoArgsConstructor @AllArgsConstructor public class PostRequest { diff --git a/src/main/java/balancetalk/module/post/dto/PostResponse.java b/src/main/java/balancetalk/module/post/dto/PostResponse.java index 391916c12..5e76503f9 100644 --- a/src/main/java/balancetalk/module/post/dto/PostResponse.java +++ b/src/main/java/balancetalk/module/post/dto/PostResponse.java @@ -1,5 +1,6 @@ package balancetalk.module.post.dto; +import balancetalk.module.ViewStatus; import balancetalk.module.file.domain.File; import balancetalk.module.member.domain.Member; import balancetalk.module.post.domain.BalanceOption; @@ -26,15 +27,21 @@ public class PostResponse { private String title; @JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss") - @Schema(description = "투료 종료 기한", example = "2024-12-25T15:30:00") + @Schema(description = "투료 종료 기한", example = "2024/12/25 15:30:00") private LocalDateTime deadline; @Schema(description = "게시글 조회수", example = "126") private long views; +// @Schema(description = "게시글 블라인드 여부", example = "NORMAL") +// private ViewStatus viewStatus; + @Schema(description = "게시글 추천수", example = "15") private long likesCount; +// @Schema(description = "신고 횟수" , example = "3") +// private long reportedCount; + @Schema(description = "추천 여부", example = "true") private boolean myLike; @@ -61,7 +68,7 @@ public class PostResponse { private long commentsCount; @JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss") - @Schema(description = "게시글 작성일", example = "2023-12-25T15:30:00") + @Schema(description = "게시글 작성일", example = "2024/03/30 11:12:37") private LocalDateTime createdAt; @Schema(description = "게시글 작성자", example = "작성자 닉네임") @@ -77,8 +84,10 @@ public static PostResponse fromEntity(Post post, Member member, boolean myLike, .title(post.getTitle()) .deadline(post.getDeadline()) .views(post.getViews()) +// .viewStatus(post.getViewStatus()) .likesCount(post.likesCount()) .myLike(myLike) +// .reportedCount(post.reportedCount()) .myBookmark(myBookmark) .myVote(myVote) .selectedOptionId(getSelectedOptionId(post, member)) diff --git a/src/main/java/balancetalk/module/post/dto/PostTagDto.java b/src/main/java/balancetalk/module/post/dto/PostTagDto.java index 8623c97ff..2e19439ff 100644 --- a/src/main/java/balancetalk/module/post/dto/PostTagDto.java +++ b/src/main/java/balancetalk/module/post/dto/PostTagDto.java @@ -7,7 +7,6 @@ @Data @Builder -@NoArgsConstructor @AllArgsConstructor public class PostTagDto { diff --git a/src/main/java/balancetalk/module/post/presentation/PostController.java b/src/main/java/balancetalk/module/post/presentation/PostController.java index 8556e37d4..5ba72bf47 100644 --- a/src/main/java/balancetalk/module/post/presentation/PostController.java +++ b/src/main/java/balancetalk/module/post/presentation/PostController.java @@ -3,6 +3,7 @@ import balancetalk.module.post.application.PostService; import balancetalk.module.post.dto.PostRequest; import balancetalk.module.post.dto.PostResponse; +import balancetalk.module.report.dto.ReportRequest; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; @@ -92,4 +93,12 @@ public String cancelLikePost(@PathVariable Long postId) { postService.cancelLikePost(postId); return "요청이 정상적으로 처리되었습니다."; } + + @ResponseStatus(HttpStatus.OK) + @PostMapping("/{postId}/report") + @Operation(summary = "게시글 신고", description = "post-id에 해당하는 게시글을 신고 처리한다.") + public String reportPost(@PathVariable Long postId, @RequestBody ReportRequest request) { + postService.reportPost(postId, request); + return "신고가 성공적으로 접수되었습니다."; + } } diff --git a/src/main/java/balancetalk/module/report/domain/Report.java b/src/main/java/balancetalk/module/report/domain/Report.java index 4ce186bb1..3627e9e12 100644 --- a/src/main/java/balancetalk/module/report/domain/Report.java +++ b/src/main/java/balancetalk/module/report/domain/Report.java @@ -15,11 +15,13 @@ import jakarta.persistence.ManyToOne; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; +import lombok.*; @Entity +@Builder +@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) public class Report extends BaseTimeEntity { @Id diff --git a/src/main/java/balancetalk/module/report/domain/ReportRepository.java b/src/main/java/balancetalk/module/report/domain/ReportRepository.java new file mode 100644 index 000000000..cd63599ee --- /dev/null +++ b/src/main/java/balancetalk/module/report/domain/ReportRepository.java @@ -0,0 +1,6 @@ +package balancetalk.module.report.domain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReportRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/balancetalk/module/report/dto/ReportRequest.java b/src/main/java/balancetalk/module/report/dto/ReportRequest.java new file mode 100644 index 000000000..bf0ab0d52 --- /dev/null +++ b/src/main/java/balancetalk/module/report/dto/ReportRequest.java @@ -0,0 +1,20 @@ +package balancetalk.module.report.dto; + +import balancetalk.module.report.domain.ReportCategory; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +@AllArgsConstructor +public class ReportRequest { + + @Schema(description = "신고 이유", example = "정치 게시글 / 분란성 댓글") + private ReportCategory category; + + @Schema(description = "신고 설명", example = "게시글 / 댓글 신고한 이유") + private String description; + +} diff --git a/src/main/java/balancetalk/module/report/presentation/ReportController.java b/src/main/java/balancetalk/module/report/presentation/ReportController.java new file mode 100644 index 000000000..961c3d5cc --- /dev/null +++ b/src/main/java/balancetalk/module/report/presentation/ReportController.java @@ -0,0 +1,12 @@ +package balancetalk.module.report.presentation; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/admin") +public class ReportController { + +} diff --git a/src/main/resources/config b/src/main/resources/config index ed4cab658..dfd0c39dd 160000 --- a/src/main/resources/config +++ b/src/main/resources/config @@ -1 +1 @@ -Subproject commit ed4cab6581e749d25bb6fbc8cc031260ee61a469 +Subproject commit dfd0c39dd335becea21435284ab8ff0bc18905c3