Skip to content
Open
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
71 changes: 71 additions & 0 deletions src/main/java/com/picnee/travel/api/ReportController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.picnee.travel.api;

import com.picnee.travel.api.in.ReportApi;
import com.picnee.travel.domain.report.dto.req.CreateReportReq;
import com.picnee.travel.domain.report.dto.res.FindReportRes;
import com.picnee.travel.domain.report.service.ReportService;
import com.picnee.travel.domain.user.dto.req.AuthenticatedUserReq;
import com.picnee.travel.global.security.annotation.AuthenticatedUser;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;

import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.OK;

@Slf4j
@RestController
@RequestMapping("/reports")
@RequiredArgsConstructor
public class ReportController implements ReportApi {

private final ReportService reportService;

@PostMapping
public ResponseEntity<String> createReport(@Valid @RequestBody CreateReportReq dto,
@AuthenticatedUser AuthenticatedUserReq auth) {

return ResponseEntity.status(CREATED).body(reportService.create(dto, auth).getId().toString());
}

@DeleteMapping("/{reportId}")
public ResponseEntity<String> deleteReport(@PathVariable("reportId") UUID reportId,
@AuthenticatedUser AuthenticatedUserReq auth) {
reportService.delete(reportId, auth);
return ResponseEntity.status(OK).build();
}

@GetMapping("/{reportId}")
public ResponseEntity<FindReportRes> findReport(@PathVariable("reportId") UUID reportId,
@AuthenticatedUser AuthenticatedUserReq auth) {
FindReportRes findReportRes = reportService.find(reportId, auth);
return ResponseEntity.status(OK).body(findReportRes);
}

@GetMapping
public ResponseEntity<Page<FindReportRes>> findReports(@RequestParam(name = "targetId", required = false) String targetId,
@RequestParam(name = "reportTargetType", required = false) String reportTargetType,
@RequestParam(name = "reportType", required = false) String reportType,
@RequestParam(name = "is_visible", required = false) String isVisible,
@RequestParam(name = "sort", required = false) String sort,
@RequestParam(name = "page", defaultValue = "0") int page,
@AuthenticatedUser AuthenticatedUserReq auth) {
Page<FindReportRes> reports = reportService.findReports(auth, targetId, reportTargetType, reportType, isVisible, sort, page);
return ResponseEntity.status(OK).body(reports);
}

@PatchMapping("/{reportId}")
public ResponseEntity<String> processReport(@PathVariable("reportId") UUID reportId,
@AuthenticatedUser AuthenticatedUserReq auth) {
reportService.processReport(reportId, auth);
return ResponseEntity.status(OK).build();
}



}
31 changes: 31 additions & 0 deletions src/main/java/com/picnee/travel/api/in/ReportApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.picnee.travel.api.in;

import com.picnee.travel.domain.report.dto.req.CreateReportReq;
import com.picnee.travel.domain.report.dto.res.FindReportRes;
import com.picnee.travel.domain.user.dto.req.AuthenticatedUserReq;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;

import java.util.UUID;

@Tag(name = "reports", description = "report API")
public interface ReportApi {
@Operation(summary = "신고", description = "신고를 진행한다")
ResponseEntity<String> createReport(CreateReportReq dto, AuthenticatedUserReq auth);

@Operation(summary = "신고 삭제(어드민)", description = "신고된 것을 삭제한다")
public ResponseEntity<String> deleteReport(UUID reportId, AuthenticatedUserReq auth);

@Operation(summary = "신고 단건 조회(어드민)", description = "신고한 내역 단건 조회")
public ResponseEntity<FindReportRes> findReport(UUID reportId, AuthenticatedUserReq auth);

@Operation(summary = "신고 다중 건 조회(어드민)", description = "신고한 내역 리스트 조회")
public ResponseEntity<Page<FindReportRes>> findReports(String targetId, String reportTargetType, String reportType, String isVisible, String sort, int page, AuthenticatedUserReq auth);

@Operation(summary = "신고 제재(어드민)", description = "신고 제재처리")
public ResponseEntity<String> processReport(UUID reportTargetId, AuthenticatedUserReq auth);


}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public static Post toEntity(CreatePostReq dto, Board board, User user) {
.title(dto.getTitle())
.content(dto.getContent())
.viewed(0L)
.reportSanctionCount(0)
.user(user)
.board(board)
.build();
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/picnee/travel/domain/post/entity/Post.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public class Post extends SoftDeleteBaseEntity {
private String content;
@Column(name = "viewed")
private Long viewed;
@Column(name = "report_sanction_count")
private Integer reportSanctionCount;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "user_id")
private User user;
Expand Down Expand Up @@ -75,4 +77,18 @@ public void softDelete() {
public void incrementViewCount() {
this.viewed++;
}

/**
* 신고 횟수 누적
*/
public void reportSanctionCountPlus(){
this.reportSanctionCount++;
}

/**
* 게시글 제재 가능여부 확인
*/
public boolean isRequiringSanctions() {
return this.reportSanctionCount >= 5;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public Page<FindPostRes> findPosts(String boardCategory, String region, String s
* 내가 작성한 게시글 조회
*/
public Page<FindPostRes> getMyPosts(AuthenticatedUserReq auth, int page) {
if(!isUserAuthenticated(auth)) {
if (!isUserAuthenticated(auth)) {
throw new NotAuthException(NOT_AUTH_EXCEPTION);
}

Expand Down Expand Up @@ -161,4 +161,21 @@ public Post findById(UUID postId) {
return postRepository.findById(postId)
.orElseThrow(() -> new NotFoundPostException(NOT_FOUND_POST_EXCEPTION));
}

/**
* 신고된 댓글 제재
*/
@Transactional
public User sanction(UUID reportTargetId) {
Post post = postRepository.findById(reportTargetId)
.orElseThrow(() -> new NotFoundPostException(NOT_FOUND_POST_EXCEPTION));

post.reportSanctionCountPlus();
if(post.isRequiringSanctions()){
post.softDelete();
boardService.delete(post);
}

return post.getUser();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public static PostComment toEntity(CreatePostCommentReq dto, User user, Post pos
.user(user)
.content(dto.content)
.likes(0L)
.reportSanctionCount(0)
.post(post)
.build();
}
Expand All @@ -36,6 +37,7 @@ public static PostComment toEntityCoComment(Post post, PostComment postComment,
.user(user)
.content(dto.content)
.likes(0L)
.reportSanctionCount(0)
.commentParent(postComment)
.post(post)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public class PostComment extends SoftDeleteBaseEntity {
private String content;
@Column(name = "likes")
private Long likes;
@Column(name = "report_sanction_count")
private Integer reportSanctionCount;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "post_comment_parent_id")
private PostComment commentParent;
Expand Down Expand Up @@ -75,4 +77,25 @@ public void addLike() {
public void deleteLike() {
this.likes--;
}

/**
* 댓글 삭제
*/
public void softDelete() {
super.delete();
}

/**
* 신고 횟수 누적
*/
public void reportSanctionCountPlus(){
this.reportSanctionCount++;
}

/**
* 댓글 제재 가능여부 확인
*/
public boolean isRequiringSanctions() {
return this.reportSanctionCount >= 5;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -184,4 +184,19 @@ public PostComment findById(UUID commentId) {
return postCommentRepository.findById(commentId)
.orElseThrow(() -> new NotFoundCommentException(NOT_FOUND_COMMENT_EXCEPTION));
}

/**
* 신고된 댓글 제재
*/
@Transactional
public User sanction(UUID reportTargetId) {
PostComment postComment = findById(reportTargetId);

postComment.reportSanctionCountPlus();
if(postComment.isRequiringSanctions()){
postComment.softDelete();
}

return postComment.getUser();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.picnee.travel.domain.report.dto.req;

import com.picnee.travel.domain.report.entity.Report;
import com.picnee.travel.domain.report.entity.ReportTargetType;
import com.picnee.travel.domain.report.entity.ReportType;
import com.picnee.travel.domain.user.entity.User;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.UUID;

import static lombok.AccessLevel.PROTECTED;

@Getter
@Builder
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor
public class CreateReportReq {

@NotNull(message = "targetId는 필수입니다.")
private UUID targetId;

@NotNull(message = "신고 대상은 타입은 필수입니다.(ex : REVIEW)")
private ReportTargetType reportTargetType;

@NotNull(message = "신고 유형은 필수입니다.(ex : ADVERTISEMENT)")
private ReportType reportType;

public Report toEntity(CreateReportReq dto, User user) {
return Report.builder()
.targetId(dto.getTargetId())
.reportTargetType(dto.getReportTargetType())
.reportType(dto.getReportType())
.isVisible(false)
.user(user)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.picnee.travel.domain.report.dto.res;

import com.picnee.travel.domain.report.entity.Report;
import com.picnee.travel.domain.report.entity.ReportTargetType;
import com.picnee.travel.domain.report.entity.ReportType;
import com.picnee.travel.domain.user.entity.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;

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

import static lombok.AccessLevel.PROTECTED;

@Getter
@Builder
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor
public class FindReportRes {

private UUID reportId;
private UUID targetId;
private ReportTargetType reportTargetType;
private ReportType reportType;
private Boolean isVisible;
private LocalDateTime createAt;
private UUID userId;

public static FindReportRes from(Report report){
return FindReportRes.builder()
.reportId(report.getId())
.targetId(report.getTargetId())
.reportTargetType(report.getReportTargetType())
.reportType(report.getReportType())
.isVisible(report.getIsVisible())
.createAt(report.getCreatedAt())
.userId(report.getUser().getId())
.build();
}

public static Page<FindReportRes> paging(Page<Report> reports) {
List<FindReportRes> reportResList = reports.stream()
.map(FindReportRes::from)
.toList();

return new PageImpl<>(reportResList, reports.getPageable(), reports.getTotalElements());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public class Report extends BaseEntity {
@JdbcTypeCode(SqlTypes.VARCHAR)
@Column(name = "report_id", columnDefinition = "VARCHAR(36)")
private UUID id;
@UuidGenerator(style = RANDOM)
@JdbcTypeCode(SqlTypes.VARCHAR)
@Column(name = "target_id", columnDefinition = "VARCHAR(36)")
private UUID targetId;
Expand All @@ -48,4 +47,8 @@ public class Report extends BaseEntity {
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "user_id")
private User user;

public void softDelete() {
this.isVisible = true;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.picnee.travel.domain.report.entity;

public enum ReportType {
ADVERTISEMENT,
SWEAR
ADVERTISEMENT, // 스팸
SWEAR // 욕설
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.picnee.travel.domain.report.exception;

import com.picnee.travel.global.exception.BusinessException;
import com.picnee.travel.global.exception.ErrorCode;

public class NotFoundReportException extends BusinessException {
public NotFoundReportException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.picnee.travel.domain.report.repository;

import com.picnee.travel.domain.report.entity.Report;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.UUID;

@Repository
public interface ReportRepository extends JpaRepository<Report, UUID>, ReportRepositoryCustom {
}
Loading