Skip to content

Commit

Permalink
merge: 유저 게시글 신고하기 및 신고함 조회 기능
Browse files Browse the repository at this point in the history
  • Loading branch information
amaran-th authored Aug 16, 2023
2 parents 241eca6 + f5f54bc commit 2ee5685
Show file tree
Hide file tree
Showing 23 changed files with 941 additions and 3 deletions.
27 changes: 27 additions & 0 deletions backend/emm-sale/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -495,3 +495,30 @@ include::{snippets}/find-tags/http-response.adoc[]

.HTTP response 설명
include::{snippets}/find-tags/response-fields.adoc[]

== Report

=== `POST` : 특정 사용자의 게시물 신고

.HTTP request
include::{snippets}/add-report/http-request.adoc[]

.HTTP request 설명
include::{snippets}/add-report/request-fields.adoc[]

.HTTP response
include::{snippets}/add-report/http-response.adoc[]

.HTTP response 설명
include::{snippets}/add-report/response-fields.adoc[]

=== `GET` : 신고 목록 전체 조회

.HTTP request
include::{snippets}/find-reports/http-request.adoc[]

.HTTP response
include::{snippets}/find-reports/http-response.adoc[]

.HTTP response 설명
include::{snippets}/find-reports/response-fields.adoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ public Long getParentIdOrSelfId() {
return parent.id;
}

public boolean isNotOwner(final Long memberId) {
return member.isNotMe(memberId);
}

@Override
public boolean equals(final Object o) {
if (this == o) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ public boolean isSameMember(final Member member) {
return this.member.isMe(member);
}

public boolean isNotOwner(final Long memberId) {
return member.isNotMe(memberId);
}

public void updateContent(final String content) {
this.content = content;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,18 @@ private void validateDescriptionLength(final String description) {
}
}

public boolean isMe(final Member member) {
return isMe(member.getId());
}

public boolean isMe(final Long id) {
return this.id.equals((id));
}

public boolean isNotMe(final Member member) {
return isNotMe(member.getId());
}

public boolean isMe(final Member member) {
return this.id.equals(member.id);
}

public boolean isNotMe(final Long id) {
return !this.id.equals(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public boolean isNotOwner(final Long memberId) {
return !receiverId.equals(memberId);
}

public boolean isNotSender(final Long memberId) {
return !senderId.equals(memberId);
}

public void modifyStatus(final RequestNotificationStatus status) {
this.status = status;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.emmsale.report.api;

import com.emmsale.member.domain.Member;
import com.emmsale.report.application.ReportCommandService;
import com.emmsale.report.application.ReportQueryService;
import com.emmsale.report.application.dto.ReportCreateRequest;
import com.emmsale.report.application.dto.ReportCreateResponse;
import com.emmsale.report.application.dto.ReportFindResponse;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class ReportApi {

private final ReportCommandService reportCommandService;
private final ReportQueryService reportQueryService;

@PostMapping("/reports")
@ResponseStatus(HttpStatus.CREATED)
public ReportCreateResponse create(@RequestBody final ReportCreateRequest reportRequest,
final Member member) {
return reportCommandService.create(reportRequest, member);
}

@GetMapping("/reports")
public List<ReportFindResponse> findReports() {
return reportQueryService.findReports();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package com.emmsale.report.application;

import com.emmsale.block.domain.Block;
import com.emmsale.block.domain.BlockRepository;
import com.emmsale.comment.domain.Comment;
import com.emmsale.comment.domain.CommentRepository;
import com.emmsale.event.domain.RecruitmentPost;
import com.emmsale.event.domain.repository.RecruitmentPostRepository;
import com.emmsale.member.domain.Member;
import com.emmsale.member.domain.MemberRepository;
import com.emmsale.notification.domain.RequestNotification;
import com.emmsale.notification.domain.RequestNotificationRepository;
import com.emmsale.report.application.dto.ReportCreateRequest;
import com.emmsale.report.application.dto.ReportCreateResponse;
import com.emmsale.report.domain.Report;
import com.emmsale.report.domain.ReportType;
import com.emmsale.report.domain.repository.ReportRepository;
import com.emmsale.report.exception.ReportException;
import com.emmsale.report.exception.ReportExceptionType;
import javax.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@Transactional
@RequiredArgsConstructor
public class ReportCommandService {

private final ReportRepository reportRepository;
private final MemberRepository memberRepository;
private final CommentRepository commentRepository;
private final RecruitmentPostRepository recruitmentPostRepository;
private final RequestNotificationRepository requestNotificationRepository;
private final BlockRepository blockRepository;

public ReportCreateResponse create(final ReportCreateRequest reportRequest, final Member member) {
validateReportRequest(reportRequest, member);
final Report report = reportRequest.toReport();
blockReportedMember(reportRequest);
return ReportCreateResponse.from(reportRepository.save(report));
}


private void validateReportRequest(final ReportCreateRequest reportRequest, final Member member) {
validateReporterMismatch(reportRequest, member);
validateReportMySelf(reportRequest, member);
validateNotFoundReportedMember(reportRequest);
validateAlreadyExistReport(reportRequest);
validateContent(reportRequest);
}

private void validateReporterMismatch(final ReportCreateRequest reportRequest,
final Member member) {
if (member.isNotMe(reportRequest.getReporterId())) {
throw new ReportException(ReportExceptionType.REPORTER_MISMATCH);
}
}

private void validateReportMySelf(final ReportCreateRequest reportRequest, final Member member) {
if (member.isMe(reportRequest.getReportedId())) {
throw new ReportException(ReportExceptionType.FORBIDDEN_REPORT_MYSELF);
}
}

private void validateNotFoundReportedMember(final ReportCreateRequest reportRequest) {
if (!memberRepository.existsById(reportRequest.getReportedId())) {
throw new ReportException(ReportExceptionType.NOT_FOUND_MEMBER);
}
}

private void validateAlreadyExistReport(final ReportCreateRequest reportRequest) {
if (reportRepository.existsReportByReporterIdAndReportedId(
reportRequest.getReporterId(), reportRequest.getReportedId())) {
throw new ReportException(ReportExceptionType.ALREADY_EXIST_REPORT);
}
}

private void validateContent(final ReportCreateRequest reportRequest) {
if (reportRequest.getType() == ReportType.COMMENT) {
validateComment(reportRequest);
}
if (reportRequest.getType() == ReportType.RECRUITMENT_POST) {
validateRecruitmentPost(reportRequest);
}
if (reportRequest.getType() == ReportType.REQUEST_NOTIFICATION) {
validateRequestNotification(reportRequest);
}
}

private void validateComment(final ReportCreateRequest reportRequest) {
Comment comment = commentRepository.findById(reportRequest.getContentId())
.orElseThrow(() -> new ReportException(ReportExceptionType.NOT_FOUND_CONTENT));
if (comment.isNotOwner(reportRequest.getReportedId())) {
throw new ReportException(ReportExceptionType.REPORTED_MISMATCH_WRITER);
}
}

private void validateRecruitmentPost(final ReportCreateRequest reportRequest) {
RecruitmentPost recruitmentPost = recruitmentPostRepository.findById(
reportRequest.getContentId())
.orElseThrow(() -> new ReportException(ReportExceptionType.NOT_FOUND_CONTENT));
if (recruitmentPost.isNotOwner(reportRequest.getReportedId())) {
throw new ReportException(ReportExceptionType.REPORTED_MISMATCH_WRITER);
}
}

private void validateRequestNotification(final ReportCreateRequest reportCreateRequest) {
RequestNotification requestNotification = requestNotificationRepository.findById(
reportCreateRequest.getContentId())
.orElseThrow(() -> new ReportException(ReportExceptionType.NOT_FOUND_CONTENT));
if (requestNotification.isNotSender(reportCreateRequest.getReportedId())) {
throw new ReportException(ReportExceptionType.REPORTED_MISMATCH_WRITER);
}
}

private void blockReportedMember(final ReportCreateRequest reportCreateRequest) {
final Long reporterId = reportCreateRequest.getReporterId();
final Long reportedId = reportCreateRequest.getReportedId();
if (!blockRepository.existsByRequestMemberIdAndBlockMemberId(reporterId, reportedId)) {
final Block block = new Block(reporterId, reportedId);
blockRepository.save(block);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.emmsale.report.application;

import com.emmsale.report.application.dto.ReportFindResponse;
import com.emmsale.report.domain.repository.ReportRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ReportQueryService {

private final ReportRepository reportRepository;

public List<ReportFindResponse> findReports() {
return ReportFindResponse.from(reportRepository.findAll());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.emmsale.report.application.dto;

import com.emmsale.report.domain.Report;
import com.emmsale.report.domain.ReportType;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Getter
public class ReportCreateRequest {

private final Long reporterId;
private final Long reportedId;
private final ReportType type;
private final Long contentId;

public Report toReport() {
return new Report(reporterId, reportedId, type, contentId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.emmsale.report.application.dto;

import com.emmsale.report.domain.Report;
import com.emmsale.report.domain.ReportType;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Getter
public class ReportCreateResponse {

private final Long id;
private final Long reporterId;
private final Long reportedId;
private final ReportType type;
private final Long contentId;
@JsonFormat(pattern = "yyyy:MM:dd:HH:mm:ss")
private final LocalDateTime createdAt;

public static ReportCreateResponse from(final Report report) {
return new ReportCreateResponse(report.getId(), report.getReporterId(),
report.getReportedId(), report.getType(), report.getContentId(),
report.getCreatedAt());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.emmsale.report.application.dto;

import com.emmsale.report.domain.Report;
import com.emmsale.report.domain.ReportType;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Getter
public class ReportFindResponse {

private final Long id;
private final Long reporterId;
private final Long reportedId;
private final ReportType type;
private final Long contentId;
@JsonFormat(pattern = "yyyy:MM:dd:HH:mm:ss")
private final LocalDateTime createdAt;

public static List<ReportFindResponse> from(final List<Report> reports) {
return reports.stream()
.map(ReportFindResponse::from)
.collect(Collectors.toList());
}

private static ReportFindResponse from(final Report report) {
return new ReportFindResponse(report.getId(), report.getReporterId(),
report.getReportedId(), report.getType(), report.getContentId(),
report.getCreatedAt());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.emmsale.report.domain;

import com.emmsale.base.BaseEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Report extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private Long reporterId;
@Column(nullable = false)
private Long reportedId;
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private ReportType type;
@Column(nullable = false)
private Long contentId;

public Report(final Long reporterId, final Long reportedId, final ReportType type,
final Long contentId) {
this.reporterId = reporterId;
this.reportedId = reportedId;
this.type = type;
this.contentId = contentId;
}
}
Loading

0 comments on commit 2ee5685

Please sign in to comment.