Skip to content

Commit

Permalink
#74 feat: ClipBoard 신고 생성 API 구현, Validation(유저 횟수 신고 제한, 클립보드 중복 신고)…
Browse files Browse the repository at this point in the history
… 예외처리
  • Loading branch information
xhaktmchl committed Nov 28, 2022
1 parent edc9031 commit 70bef1a
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 1 deletion.
12 changes: 12 additions & 0 deletions server/src/main/java/com/yogit/server/board/entity/ClipBoard.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
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;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
Expand All @@ -37,11 +39,17 @@ public class ClipBoard extends BaseEntity {

private String content;

@OneToMany(mappedBy = "clipBoard")
private List<ClipBoardReport> 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;
}

/*
Expand All @@ -55,4 +63,8 @@ public void updateClipBoard(PatchClipBoardReq dto){
this.title = dto.getTitle();
this.content = dto.getContent();
}

public void changeReportedCnt(){
this.reportedCnt+=1;
}
}
Original file line number Diff line number Diff line change
@@ -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<ClipBoardReportRes> createClipBoardReport(@RequestBody @Validated CreateClipBoardReportReq dto){
return clipBoradReportService.createClipBoardReport(dto);
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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<ClipBoardReport, Long> {

@Query("select cbr from ClipBoardReport cbr where cbr.reportingUser.id = :reportingUserId and cbr.clipBoard.id = :reportedClipBoardId and cbr.status = 'ACTIVE'")
List<ClipBoardReport> findByReportingUserIdAndReportedClipBoardId(@Param("reportingUserId") Long reportingUserId, @Param("reportedClipBoardId") Long reportedClipBoardId);
}
Original file line number Diff line number Diff line change
@@ -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<ClipBoardReportRes> createClipBoardReport(CreateClipBoardReportReq createClipBoardReportReq);
}
Original file line number Diff line number Diff line change
@@ -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<ClipBoardReportRes> 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);
}
}

0 comments on commit 70bef1a

Please sign in to comment.