Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

게시글, 댓글, 닉네임 신고 기능 구현 #316

Merged
merged 1 commit into from
Aug 9, 2023
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 @@ -15,10 +15,12 @@
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.apache.commons.lang3.RandomStringUtils;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(of = {"id"})
@ToString
@Getter
@Entity
public class Member extends BaseEntity {
Expand Down Expand Up @@ -91,8 +93,13 @@ public void changeNickname(final String nickname) {
this.nickname = new Nickname(nickname);
}

public void changeNicknameByReport() {
final String reportedNickname = "Pause1" + RandomStringUtils.random(9, true, true);
this.nickname = new Nickname(reportedNickname);
}

public String getNickname() {
return nickname.getValue();
return this.nickname.getValue();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.votogether.domain.member.entity.Member;
import com.votogether.domain.post.entity.comment.Comment;
import com.votogether.domain.post.exception.PostExceptionType;
import com.votogether.domain.report.exception.ReportExceptionType;
import com.votogether.domain.vote.entity.Vote;
import com.votogether.exception.BadRequestException;
import jakarta.persistence.Basic;
Expand Down Expand Up @@ -57,6 +58,9 @@ public class Post extends BaseEntity {
@Column(columnDefinition = "datetime(6)", nullable = false)
private LocalDateTime deadline;

@Column(nullable = false)
private boolean isHidden;

@Basic(fetch = FetchType.LAZY)
@Formula("(select count(v.id) from Vote v where v.post_option_id in "
+ "(select po.id from Post_Option po where po.post_id = id)"
Expand All @@ -70,13 +74,15 @@ public class Post extends BaseEntity {
private Post(
final Member writer,
final PostBody postBody,
final LocalDateTime deadline
final LocalDateTime deadline,
final boolean isHidden
) {
this.writer = writer;
this.postBody = postBody;
this.deadline = deadline;
this.postCategories = new PostCategories();
this.postOptions = new PostOptions();
this.isHidden = isHidden;
}

public void mapCategories(final List<Category> categories) {
Expand Down Expand Up @@ -178,6 +184,22 @@ public boolean isVisibleVoteResult(final Member member) {
return this.postOptions.getSelectedOptionId(member) != 0 || this.writer.equals(member);
}

public void blind() {
this.isHidden = true;
}

public void validateMine(final Member member) {
if (this.writer.equals(member)) {
throw new BadRequestException(ReportExceptionType.REPORT_MY_POST);
}
}

public void validateHidden() {
if (this.isHidden) {
throw new BadRequestException(ReportExceptionType.ALREADY_HIDDEN_POST);
}
}

public void addComment(final Comment comment) {
comments.add(comment);
comment.setPost(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import com.votogether.domain.member.entity.Member;
import com.votogether.domain.post.entity.Post;
import com.votogether.domain.post.exception.CommentExceptionType;
import com.votogether.domain.report.exception.ReportExceptionType;
import com.votogether.exception.BadRequestException;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
Expand Down Expand Up @@ -41,11 +43,20 @@ public class Comment extends BaseEntity {
@Embedded
private Content content;

@Column(nullable = false)
private boolean isHidden;

@Builder
private Comment(final Post post, final Member member, final String content) {
private Comment(
final Post post,
final Member member,
final String content,
final boolean isHidden
) {
this.post = post;
this.member = member;
this.content = new Content(content);
this.isHidden = isHidden;
}

public void validateWriter(final Member member) {
Expand All @@ -60,6 +71,22 @@ public void validateBelong(final Post post) {
}
}

public void blind() {
this.isHidden = true;
}

public void validateMine(final Member reporter) {
if (this.member.equals(reporter)) {
throw new BadRequestException(ReportExceptionType.REPORT_MY_COMMENT);
}
}

public void validateHidden() {
if (this.isHidden) {
throw new BadRequestException(ReportExceptionType.ALREADY_HIDDEN_COMMENT);
}
}

public void updateContent(final String content) {
this.content = new Content(content);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.votogether.domain.member.entity.Member;
import com.votogether.domain.post.entity.Post;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -17,6 +18,8 @@ public interface PostRepository extends JpaRepository<Post, Long>, PostCustomRep

int countByWriter(final Member member);

List<Post> findAllByWriter(final Member member);

@Query("SELECT v.postOption.post FROM Vote v WHERE v.member = :member "
+ "AND v.postOption.post.deadline < CURRENT_TIMESTAMP")
Slice<Post> findClosedPostsVotedByMember(@Param("member") final Member member, final Pageable pageable);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.votogether.domain.report.controller;

import com.votogether.domain.member.entity.Member;
import com.votogether.domain.report.dto.ReportRequest;
import com.votogether.domain.report.service.ReportService;
import com.votogether.global.jwt.Auth;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
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.RestController;

@RequiredArgsConstructor
@RestController
public class ReportController {

private final ReportService reportService;

@Operation(summary = "신고 기능", description = "게시글, 댓글, 닉네임을 신고한다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "신고 성공"),
@ApiResponse(responseCode = "400", description = "올바르지 않은 요청"),
@ApiResponse(responseCode = "404", description = "존재하지 않는 신고 대상")
})
@PostMapping("/report")
public ResponseEntity<Void> report(@Valid @RequestBody final ReportRequest request, @Auth final Member member) {
reportService.report(member, request);
return ResponseEntity.ok().build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.votogether.domain.report.dto;

import com.votogether.domain.report.entity.ReportType;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

@Schema(description = "신고 요청")
public record ReportRequest(
@Schema(description = "신고유형", example = "POST")
ReportType type,
@Schema(description = "신고대상ID", example = "1")
@NotNull(message = "대상 ID값은 빈 값일 수 없습니다.")
Long id,
@Schema(description = "신고 사유", example = "불건전한 닉네임")
@NotBlank(message = "신고 이유는 빈 값이거나 공백으로만 이루어질 수 없습니다.")
String reason
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.votogether.domain.report.entity;

import com.votogether.domain.common.BaseEntity;
import com.votogether.domain.member.entity.Member;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Table(
uniqueConstraints = {@UniqueConstraint(columnNames = {"member_id", "reportType", "targetId"})},
indexes = {@Index(columnList = "reportType, targetId")}
)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class Report extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", nullable = false)
private Member member;

@Enumerated(value = EnumType.STRING)
@Column(length = 10, nullable = false)
private ReportType reportType;

@Column(nullable = false)
private Long targetId;

@Column(nullable = false, length = 50)
private String reason;

@Builder
private Report(
final Member member,
final ReportType reportType,
final Long targetId,
final String reason
) {
this.member = member;
this.reportType = reportType;
this.targetId = targetId;
this.reason = reason;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.votogether.domain.report.entity;

public enum ReportType {

POST,
COMMENT,
NICKNAME,
;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.votogether.domain.report.exception;

import com.votogether.exception.ExceptionType;
import lombok.Getter;

@Getter
public enum ReportExceptionType implements ExceptionType {

REPORT_MY_POST(1200, "자신의 게시글은 신고할 수 없습니다."),
ALREADY_HIDDEN_POST(1201, "이미 블라인드 처리된 글입니다."),
DUPLICATE_POST_REPORT(1202, "하나의 글에 대해서 중복하여 신고할 수 없습니다."),
REPORT_MY_COMMENT(1203, "자신의 댓글은 신고할 수 없습니다."),
ALREADY_HIDDEN_COMMENT(1204, "이미 블라인드 처리된 댓글입니다."),
DUPLICATE_COMMENT_REPORT(1205, "하나의 댓글에 대해서 중복하여 신고할 수 없습니다."),
REPORT_MY_NICKNAME(1206, "자신의 닉네임은 신고할 수 없습니다."),
DUPLICATE_NICKNAME_REPORT(1207, "하나의 닉네임에 대해서 중복하여 신고할 수 없습니다."),
;

private final int code;
private final String message;

ReportExceptionType(final int code, final String message) {
this.code = code;
this.message = message;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.votogether.domain.report.repository;

import com.votogether.domain.member.entity.Member;
import com.votogether.domain.report.entity.Report;
import com.votogether.domain.report.entity.ReportType;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ReportRepository extends JpaRepository<Report, Long> {

int countByReportTypeAndTargetId(final ReportType reportType, final Long targetId);

Optional<Report> findByMemberAndReportTypeAndTargetId(
final Member member,
final ReportType reportType,
final Long targetId
);

}
Loading