From 70bef1ad0860b10a94ce4644ca7728a4e77ab753 Mon Sep 17 00:00:00 2001 From: xhaktmchl Date: Mon, 28 Nov 2022 19:20:13 +0900 Subject: [PATCH] =?UTF-8?q?#74=20feat:=20ClipBoard=20=EC=8B=A0=EA=B3=A0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20API=20=EA=B5=AC=ED=98=84,=20Validation(?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=ED=9A=9F=EC=88=98=20=EC=8B=A0=EA=B3=A0=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C,=20=ED=81=B4=EB=A6=BD=EB=B3=B4=EB=93=9C=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=8B=A0=EA=B3=A0)=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yogit/server/board/entity/ClipBoard.java | 12 ++++ .../controller/ClipBoardReportController.java | 43 ++++++++++++++ .../dto/req/CreateClipBoardReportReq.java | 32 ++++++++++ .../report/dto/res/ClipBoardReportRes.java | 31 ++++++++++ .../server/report/entity/ClipBoardReport.java | 30 ++++++++++ .../AlreadyReportClipBoardException.java | 9 +++ .../report/exception/ReportExceptionList.java | 4 +- .../repository/ClipBoardReportRepository.java | 17 ++++++ .../service/ClipBoradReportService.java | 10 ++++ .../service/ClipBoradReportServiceImpl.java | 59 +++++++++++++++++++ 10 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 server/src/main/java/com/yogit/server/report/controller/ClipBoardReportController.java create mode 100644 server/src/main/java/com/yogit/server/report/dto/req/CreateClipBoardReportReq.java create mode 100644 server/src/main/java/com/yogit/server/report/dto/res/ClipBoardReportRes.java create mode 100644 server/src/main/java/com/yogit/server/report/entity/ClipBoardReport.java create mode 100644 server/src/main/java/com/yogit/server/report/exception/AlreadyReportClipBoardException.java create mode 100644 server/src/main/java/com/yogit/server/report/repository/ClipBoardReportRepository.java create mode 100644 server/src/main/java/com/yogit/server/report/service/ClipBoradReportService.java create mode 100644 server/src/main/java/com/yogit/server/report/service/ClipBoradReportServiceImpl.java diff --git a/server/src/main/java/com/yogit/server/board/entity/ClipBoard.java b/server/src/main/java/com/yogit/server/board/entity/ClipBoard.java index ef12b91..86ea8a8 100644 --- a/server/src/main/java/com/yogit/server/board/entity/ClipBoard.java +++ b/server/src/main/java/com/yogit/server/board/entity/ClipBoard.java @@ -4,6 +4,7 @@ import com.yogit.server.board.dto.request.clipboard.PatchClipBoardReq; import com.yogit.server.config.domain.BaseEntity; import com.yogit.server.config.domain.BaseStatus; +import com.yogit.server.report.entity.ClipBoardReport; import com.yogit.server.user.entity.User; import lombok.AccessLevel; import lombok.Builder; @@ -11,6 +12,7 @@ import lombok.NoArgsConstructor; import javax.persistence.*; +import java.util.ArrayList; import java.util.List; @Entity @@ -37,11 +39,17 @@ public class ClipBoard extends BaseEntity { private String content; + @OneToMany(mappedBy = "clipBoard") + private List clipBoardReports = new ArrayList<>(); + + private Integer reportedCnt; + public ClipBoard(CreateClipBoardReq dto, User user, Board board) { this.user = user; this.board = board; this.title = dto.getTitle(); this.content = dto.getContent(); + this.reportedCnt = 0; } /* @@ -55,4 +63,8 @@ public void updateClipBoard(PatchClipBoardReq dto){ this.title = dto.getTitle(); this.content = dto.getContent(); } + + public void changeReportedCnt(){ + this.reportedCnt+=1; + } } diff --git a/server/src/main/java/com/yogit/server/report/controller/ClipBoardReportController.java b/server/src/main/java/com/yogit/server/report/controller/ClipBoardReportController.java new file mode 100644 index 0000000..607e102 --- /dev/null +++ b/server/src/main/java/com/yogit/server/report/controller/ClipBoardReportController.java @@ -0,0 +1,43 @@ +package com.yogit.server.report.controller; + +import com.yogit.server.global.dto.ApplicationResponse; +import com.yogit.server.report.dto.req.CreateClipBoardReportReq; +import com.yogit.server.report.dto.res.ClipBoardReportRes; +import com.yogit.server.report.service.ClipBoradReportService; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +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; + +@Slf4j +@RestController +@RequiredArgsConstructor // private final DI의존주입 +@RequestMapping("/clipboardreports") +public class ClipBoardReportController { + + private final ClipBoradReportService clipBoradReportService; + + /** + * 클립 보드 신고 생성 + * @author 토마스 + */ + @ApiOperation(value = "클립 보드 신고 생성", notes = "클립 보드 신고 생성 요청.") + @ApiResponses({ + @ApiResponse(code= 201, message = "요청에 성공하였습니다."), + @ApiResponse(code= 404, message = "존재하지 않는 유저입니다."), + @ApiResponse(code= 404, message = "존재하지 않는 클립 보드입니다."), + @ApiResponse(code= 404, message = "이미 신고한 유저입니다."), + @ApiResponse(code= 404, message = "이미 신고한 클립 보드입니다."), + @ApiResponse(code = 4000 , message = "서버 오류입니다.") + }) + @PostMapping + public ApplicationResponse createClipBoardReport(@RequestBody @Validated CreateClipBoardReportReq dto){ + return clipBoradReportService.createClipBoardReport(dto); + } +} diff --git a/server/src/main/java/com/yogit/server/report/dto/req/CreateClipBoardReportReq.java b/server/src/main/java/com/yogit/server/report/dto/req/CreateClipBoardReportReq.java new file mode 100644 index 0000000..f8de147 --- /dev/null +++ b/server/src/main/java/com/yogit/server/report/dto/req/CreateClipBoardReportReq.java @@ -0,0 +1,32 @@ +package com.yogit.server.report.dto.req; + +import com.yogit.server.report.enums.ReportType; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiParam; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class CreateClipBoardReportReq { + + @ApiModelProperty(example = "음란물이 있습니다.") + @ApiParam(value = "신고 세부 내용", required = false) + private String content; + + @ApiModelProperty(example = "1") + @ApiParam(value = "신고하는 유저 ID", required = true) + private Long reportingUserId; + + @ApiModelProperty(example = "2") + @ApiParam(value = "신고당하는 유저 ID", required = true) + private Long reportedUserId; + + @ApiModelProperty(example = "PORNOGRAPHY") + @ApiParam(value = "신고 이유 타입", required = true) + private ReportType reportType; + + @ApiModelProperty(example = "1") + @ApiParam(value = "신고당하는 클립보드 ID", required = true) + private Long reportedClipBoardId; +} diff --git a/server/src/main/java/com/yogit/server/report/dto/res/ClipBoardReportRes.java b/server/src/main/java/com/yogit/server/report/dto/res/ClipBoardReportRes.java new file mode 100644 index 0000000..55991c6 --- /dev/null +++ b/server/src/main/java/com/yogit/server/report/dto/res/ClipBoardReportRes.java @@ -0,0 +1,31 @@ +package com.yogit.server.report.dto.res; + +import com.yogit.server.report.entity.ClipBoardReport; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiParam; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class ClipBoardReportRes { + + @ApiModelProperty(example = "1") + @ApiParam(value = "신고 ID") + private Long clipBoardReportId; + + /* + 연관관계 편의 메서드 + */ + @Builder + public ClipBoardReportRes(Long clipBoardReportId) { + this.clipBoardReportId = clipBoardReportId; + } + + public static ClipBoardReportRes toDto(ClipBoardReport clipBoardReport){ + return ClipBoardReportRes.builder() + .clipBoardReportId(clipBoardReport.getId()) + .build(); + } +} diff --git a/server/src/main/java/com/yogit/server/report/entity/ClipBoardReport.java b/server/src/main/java/com/yogit/server/report/entity/ClipBoardReport.java new file mode 100644 index 0000000..f60b871 --- /dev/null +++ b/server/src/main/java/com/yogit/server/report/entity/ClipBoardReport.java @@ -0,0 +1,30 @@ +package com.yogit.server.report.entity; + +import com.yogit.server.board.entity.Board; +import com.yogit.server.board.entity.ClipBoard; +import com.yogit.server.report.enums.ReportStatus; +import com.yogit.server.report.enums.ReportType; +import com.yogit.server.user.entity.User; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@DiscriminatorValue("clip_board_report") +@Getter +public class ClipBoardReport extends Report{ + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "clip_board_id") + private ClipBoard clipBoard; + + @Builder + public ClipBoardReport(String content, User reportingUser, User reportedUser, ReportType reportType, ReportStatus reportStatus, ClipBoard clipBoard) { + super(content, reportingUser, reportedUser, reportType, reportStatus); + this.clipBoard = clipBoard; + } +} diff --git a/server/src/main/java/com/yogit/server/report/exception/AlreadyReportClipBoardException.java b/server/src/main/java/com/yogit/server/report/exception/AlreadyReportClipBoardException.java new file mode 100644 index 0000000..b57ed85 --- /dev/null +++ b/server/src/main/java/com/yogit/server/report/exception/AlreadyReportClipBoardException.java @@ -0,0 +1,9 @@ +package com.yogit.server.report.exception; + +import static com.yogit.server.report.exception.ReportExceptionList.*; + +public class AlreadyReportClipBoardException extends ReportException{ + public AlreadyReportClipBoardException(){ + super(ALREADY_REPORT_CLIPBOARD.getCODE(), ALREADY_REPORT_CLIPBOARD.getHTTPSTATUS(), ALREADY_REPORT_CLIPBOARD.getMESSAGE()); + } +} diff --git a/server/src/main/java/com/yogit/server/report/exception/ReportExceptionList.java b/server/src/main/java/com/yogit/server/report/exception/ReportExceptionList.java index 47cd56a..d08a94c 100644 --- a/server/src/main/java/com/yogit/server/report/exception/ReportExceptionList.java +++ b/server/src/main/java/com/yogit/server/report/exception/ReportExceptionList.java @@ -12,7 +12,9 @@ public enum ReportExceptionList { MAX_REPORTING_CNT("R001",BAD_REQUEST, "신고 횟수를 초과했습니다."), ALREADY_REPORT_USER("R0002", BAD_REQUEST, "이미 신고한 유저입니다."), - ALREADY_REPORT_BOARD("R0003", BAD_REQUEST, "이미 신고한 보드입니다."); + ALREADY_REPORT_BOARD("R0003", BAD_REQUEST, "이미 신고한 보드입니다."), + ALREADY_REPORT_CLIPBOARD("R0004", BAD_REQUEST, "이미 신고한 클립 보드입니다."); + private final String CODE; private final HttpStatus HTTPSTATUS; diff --git a/server/src/main/java/com/yogit/server/report/repository/ClipBoardReportRepository.java b/server/src/main/java/com/yogit/server/report/repository/ClipBoardReportRepository.java new file mode 100644 index 0000000..4ac192c --- /dev/null +++ b/server/src/main/java/com/yogit/server/report/repository/ClipBoardReportRepository.java @@ -0,0 +1,17 @@ +package com.yogit.server.report.repository; + +import com.yogit.server.report.entity.BoardReport; +import com.yogit.server.report.entity.ClipBoardReport; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ClipBoardReportRepository extends JpaRepository { + + @Query("select cbr from ClipBoardReport cbr where cbr.reportingUser.id = :reportingUserId and cbr.clipBoard.id = :reportedClipBoardId and cbr.status = 'ACTIVE'") + List findByReportingUserIdAndReportedClipBoardId(@Param("reportingUserId") Long reportingUserId, @Param("reportedClipBoardId") Long reportedClipBoardId); +} diff --git a/server/src/main/java/com/yogit/server/report/service/ClipBoradReportService.java b/server/src/main/java/com/yogit/server/report/service/ClipBoradReportService.java new file mode 100644 index 0000000..a6b077e --- /dev/null +++ b/server/src/main/java/com/yogit/server/report/service/ClipBoradReportService.java @@ -0,0 +1,10 @@ +package com.yogit.server.report.service; + +import com.yogit.server.global.dto.ApplicationResponse; +import com.yogit.server.report.dto.req.CreateClipBoardReportReq; +import com.yogit.server.report.dto.res.ClipBoardReportRes; + +public interface ClipBoradReportService { + + ApplicationResponse createClipBoardReport(CreateClipBoardReportReq createClipBoardReportReq); +} diff --git a/server/src/main/java/com/yogit/server/report/service/ClipBoradReportServiceImpl.java b/server/src/main/java/com/yogit/server/report/service/ClipBoradReportServiceImpl.java new file mode 100644 index 0000000..a07c104 --- /dev/null +++ b/server/src/main/java/com/yogit/server/report/service/ClipBoradReportServiceImpl.java @@ -0,0 +1,59 @@ +package com.yogit.server.report.service; + +import com.yogit.server.board.entity.ClipBoard; +import com.yogit.server.board.exception.clipboard.NotFoundClipBoardException; +import com.yogit.server.board.repository.ClipBoardRepository; +import com.yogit.server.global.dto.ApplicationResponse; +import com.yogit.server.report.dto.req.CreateClipBoardReportReq; +import com.yogit.server.report.dto.res.ClipBoardReportRes; +import com.yogit.server.report.entity.ClipBoardReport; +import com.yogit.server.report.enums.ReportStatus; +import com.yogit.server.report.exception.AlreadyReportClipBoardException; +import com.yogit.server.report.exception.MaxReportingCntException; +import com.yogit.server.report.repository.ClipBoardReportRepository; +import com.yogit.server.user.entity.User; +import com.yogit.server.user.exception.NotFoundUserException; +import com.yogit.server.user.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class ClipBoradReportServiceImpl implements ClipBoradReportService{ + + private final ClipBoardReportRepository clipBoardReportRepository; + private final UserRepository userRepository; + private final ClipBoardRepository clipBoardRepository; + + + @Override + @Transactional(readOnly = false) + public ApplicationResponse createClipBoardReport(CreateClipBoardReportReq dto) { + + User reportingUser = userRepository.findById(dto.getReportingUserId()) + .orElseThrow(() -> new NotFoundUserException()); + User reportedUser = userRepository.findById(dto.getReportedUserId()) + .orElseThrow(() -> new NotFoundUserException()); + ClipBoard reportedClipBoard = clipBoardRepository.findClipBoardById(dto.getReportedClipBoardId()) + .orElseThrow(() -> new NotFoundClipBoardException()); + + //validation: 신고하는 유저의 신고 한 횟수 검증, 일주일에 신고 5번 이하 허용 + if(reportingUser.getReportingCnt() > 5){ + throw new MaxReportingCntException(); + } + //validation: 신고 받는 클립 보드가 이미 신고 받은 보드인지 검증 + if(!clipBoardReportRepository.findByReportingUserIdAndReportedClipBoardId(dto.getReportingUserId(), dto.getReportedClipBoardId()).isEmpty()){ + throw new AlreadyReportClipBoardException(); + } + + ClipBoardReport clipBoardReport = new ClipBoardReport(dto.getContent(), reportingUser, reportedUser, dto.getReportType(), ReportStatus.ONGOIN, reportedClipBoard); + clipBoardReportRepository.save(clipBoardReport); + + reportedClipBoard.changeReportedCnt();//클립 보드 신고 당한 횟수 +1 증가 + + ClipBoardReportRes res = ClipBoardReportRes.toDto(clipBoardReport); + return ApplicationResponse.create("클립 보드 신고가 생성됐습니다.",res); + } +}