Skip to content

Commit cbf7d8c

Browse files
authored
Merge pull request #310 from DevKor-github/develop
#307~#309 반영해 배포
2 parents d8e7aab + 876aa90 commit cbf7d8c

31 files changed

Lines changed: 1810 additions & 4 deletions

src/main/java/org/devkor/apu/saerok_server/domain/admin/audit/core/entity/AdminAuditAction.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@ public enum AdminAuditAction {
1515
AD_PLACEMENT_DELETED,
1616
ANNOUNCEMENT_CREATED,
1717
ANNOUNCEMENT_UPDATED,
18-
ANNOUNCEMENT_DELETED
18+
ANNOUNCEMENT_DELETED,
19+
FREEBOARD_POST_DELETED,
20+
FREEBOARD_COMMENT_DELETED
1921
}

src/main/java/org/devkor/apu/saerok_server/domain/admin/audit/core/entity/AdminAuditTargetType.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,9 @@ public enum AdminAuditTargetType {
88
AD,
99
SLOT,
1010
AD_PLACEMENT,
11-
ANNOUNCEMENT
11+
ANNOUNCEMENT,
12+
REPORT_FREEBOARD_POST,
13+
REPORT_FREEBOARD_COMMENT,
14+
FREEBOARD_POST,
15+
FREEBOARD_COMMENT
1216
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package org.devkor.apu.saerok_server.domain.admin.report.api;
2+
3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.media.Content;
5+
import io.swagger.v3.oas.annotations.media.Schema;
6+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
7+
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
8+
import io.swagger.v3.oas.annotations.tags.Tag;
9+
import lombok.RequiredArgsConstructor;
10+
import org.devkor.apu.saerok_server.domain.admin.report.api.dto.request.AdminDeleteReasonRequest;
11+
import org.devkor.apu.saerok_server.domain.admin.report.api.dto.response.ReportedFreeBoardCommentDetailResponse;
12+
import org.devkor.apu.saerok_server.domain.admin.report.api.dto.response.ReportedFreeBoardCommentListResponse;
13+
import org.devkor.apu.saerok_server.domain.admin.report.api.dto.response.ReportedFreeBoardPostDetailResponse;
14+
import org.devkor.apu.saerok_server.domain.admin.report.api.dto.response.ReportedFreeBoardPostListResponse;
15+
import org.devkor.apu.saerok_server.domain.admin.report.application.AdminFreeBoardReportCommandService;
16+
import org.devkor.apu.saerok_server.domain.admin.report.application.AdminFreeBoardReportQueryService;
17+
import org.devkor.apu.saerok_server.global.security.principal.UserPrincipal;
18+
import org.devkor.apu.saerok_server.global.shared.exception.BadRequestException;
19+
import org.springframework.http.HttpStatus;
20+
import org.springframework.security.access.prepost.PreAuthorize;
21+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
22+
import org.springframework.web.bind.annotation.*;
23+
24+
@Tag(name = "Admin FreeBoard Reports API", description = "관리자용 자유게시판 신고 관리 API")
25+
@RestController
26+
@RequiredArgsConstructor
27+
@RequestMapping("${api_prefix}/admin/reports/freeboard")
28+
public class AdminFreeBoardReportController {
29+
30+
private final AdminFreeBoardReportQueryService queryService;
31+
private final AdminFreeBoardReportCommandService commandService;
32+
33+
/* ──────────────── 조회 (ADMIN_REPORT_READ) ──────────────── */
34+
35+
@GetMapping("/posts")
36+
@PreAuthorize("@perm.has('ADMIN_REPORT_READ')")
37+
@Operation(
38+
summary = "신고된 자유게시판 게시글 목록 조회",
39+
security = @SecurityRequirement(name = "bearerAuth"),
40+
responses = {
41+
@ApiResponse(responseCode = "200", description = "조회 성공",
42+
content = @Content(schema = @Schema(implementation = ReportedFreeBoardPostListResponse.class))),
43+
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content),
44+
@ApiResponse(responseCode = "403", description = "관리자 권한 없음", content = @Content)
45+
}
46+
)
47+
public ReportedFreeBoardPostListResponse listPostReports() {
48+
return queryService.listPostReports();
49+
}
50+
51+
@GetMapping("/posts/{reportId}")
52+
@PreAuthorize("@perm.has('ADMIN_REPORT_READ')")
53+
@Operation(
54+
summary = "신고된 자유게시판 게시글 상세 조회(게시글 + 댓글 목록)",
55+
security = @SecurityRequirement(name = "bearerAuth"),
56+
responses = {
57+
@ApiResponse(responseCode = "200", description = "조회 성공",
58+
content = @Content(schema = @Schema(implementation = ReportedFreeBoardPostDetailResponse.class))),
59+
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content),
60+
@ApiResponse(responseCode = "403", description = "관리자 권한 없음", content = @Content),
61+
@ApiResponse(responseCode = "404", description = "해당 신고 또는 게시글 없음", content = @Content)
62+
}
63+
)
64+
public ReportedFreeBoardPostDetailResponse getPostReportDetail(@PathVariable Long reportId) {
65+
return queryService.getReportedPostDetail(reportId);
66+
}
67+
68+
@GetMapping("/comments")
69+
@PreAuthorize("@perm.has('ADMIN_REPORT_READ')")
70+
@Operation(
71+
summary = "신고된 자유게시판 댓글 목록 조회",
72+
security = @SecurityRequirement(name = "bearerAuth"),
73+
responses = {
74+
@ApiResponse(responseCode = "200", description = "조회 성공",
75+
content = @Content(schema = @Schema(implementation = ReportedFreeBoardCommentListResponse.class))),
76+
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content),
77+
@ApiResponse(responseCode = "403", description = "관리자 권한 없음", content = @Content)
78+
}
79+
)
80+
public ReportedFreeBoardCommentListResponse listCommentReports() {
81+
return queryService.listCommentReports();
82+
}
83+
84+
@GetMapping("/comments/{reportId}")
85+
@PreAuthorize("@perm.has('ADMIN_REPORT_READ')")
86+
@Operation(
87+
summary = "신고된 자유게시판 댓글 상세 조회(댓글 + 부모 게시글 + 댓글 목록)",
88+
security = @SecurityRequirement(name = "bearerAuth"),
89+
responses = {
90+
@ApiResponse(responseCode = "200", description = "조회 성공",
91+
content = @Content(schema = @Schema(implementation = ReportedFreeBoardCommentDetailResponse.class))),
92+
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content),
93+
@ApiResponse(responseCode = "403", description = "관리자 권한 없음", content = @Content),
94+
@ApiResponse(responseCode = "404", description = "해당 신고 또는 댓글/게시글 없음", content = @Content)
95+
}
96+
)
97+
public ReportedFreeBoardCommentDetailResponse getCommentReportDetail(@PathVariable Long reportId) {
98+
return queryService.getReportedCommentDetail(reportId);
99+
}
100+
101+
/* ──────────────── 처리 (ADMIN_REPORT_WRITE) ──────────────── */
102+
103+
@DeleteMapping("/posts/{reportId}")
104+
@ResponseStatus(HttpStatus.NO_CONTENT)
105+
@PreAuthorize("@perm.has('ADMIN_REPORT_WRITE')")
106+
@Operation(
107+
summary = "신고 대상 자유게시판 게시글 삭제(관련 신고 정리 포함) + 사유 필수",
108+
security = @SecurityRequirement(name = "bearerAuth"),
109+
responses = {
110+
@ApiResponse(responseCode = "204", description = "삭제 성공"),
111+
@ApiResponse(responseCode = "400", description = "잘못된 요청(사유 누락 등)", content = @Content),
112+
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content),
113+
@ApiResponse(responseCode = "403", description = "관리자 권한 없음", content = @Content),
114+
@ApiResponse(responseCode = "404", description = "해당 신고/게시글 없음", content = @Content)
115+
}
116+
)
117+
public void deletePostByReport(@PathVariable Long reportId,
118+
@AuthenticationPrincipal UserPrincipal admin,
119+
@RequestBody AdminDeleteReasonRequest request) {
120+
if (request == null || request.reason() == null || request.reason().isBlank()) {
121+
throw new BadRequestException("삭제 사유를 입력해주세요.");
122+
}
123+
commandService.deletePostByReport(admin.getId(), reportId, request.reason().trim());
124+
}
125+
126+
@PostMapping("/posts/{reportId}/ignore")
127+
@ResponseStatus(HttpStatus.NO_CONTENT)
128+
@PreAuthorize("@perm.has('ADMIN_REPORT_WRITE')")
129+
@Operation(
130+
summary = "자유게시판 게시글 신고 무시(신고 삭제)",
131+
security = @SecurityRequirement(name = "bearerAuth"),
132+
responses = {
133+
@ApiResponse(responseCode = "204", description = "무시 처리 성공(신고 삭제)"),
134+
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content),
135+
@ApiResponse(responseCode = "403", description = "관리자 권한 없음", content = @Content),
136+
@ApiResponse(responseCode = "404", description = "해당 신고 없음", content = @Content)
137+
}
138+
)
139+
public void ignorePostReport(@PathVariable Long reportId,
140+
@AuthenticationPrincipal UserPrincipal admin) {
141+
commandService.ignorePostReport(admin.getId(), reportId);
142+
}
143+
144+
@DeleteMapping("/comments/{reportId}")
145+
@ResponseStatus(HttpStatus.NO_CONTENT)
146+
@PreAuthorize("@perm.has('ADMIN_REPORT_WRITE')")
147+
@Operation(
148+
summary = "신고 대상 자유게시판 댓글 삭제(관련 신고 정리 포함) + 사유 필수",
149+
security = @SecurityRequirement(name = "bearerAuth"),
150+
responses = {
151+
@ApiResponse(responseCode = "204", description = "삭제 성공"),
152+
@ApiResponse(responseCode = "400", description = "잘못된 요청(사유 누락 등)", content = @Content),
153+
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content),
154+
@ApiResponse(responseCode = "403", description = "관리자 권한 없음", content = @Content),
155+
@ApiResponse(responseCode = "404", description = "해당 신고/댓글 없음", content = @Content)
156+
}
157+
)
158+
public void deleteCommentByReport(@PathVariable Long reportId,
159+
@AuthenticationPrincipal UserPrincipal admin,
160+
@RequestBody AdminDeleteReasonRequest request) {
161+
if (request == null || request.reason() == null || request.reason().isBlank()) {
162+
throw new BadRequestException("삭제 사유를 입력해주세요.");
163+
}
164+
commandService.deleteCommentByReport(admin.getId(), reportId, request.reason().trim());
165+
}
166+
167+
@PostMapping("/comments/{reportId}/ignore")
168+
@ResponseStatus(HttpStatus.NO_CONTENT)
169+
@PreAuthorize("@perm.has('ADMIN_REPORT_WRITE')")
170+
@Operation(
171+
summary = "자유게시판 댓글 신고 무시(신고 삭제)",
172+
security = @SecurityRequirement(name = "bearerAuth"),
173+
responses = {
174+
@ApiResponse(responseCode = "204", description = "무시 처리 성공(신고 삭제)"),
175+
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content),
176+
@ApiResponse(responseCode = "403", description = "관리자 권한 없음", content = @Content),
177+
@ApiResponse(responseCode = "404", description = "해당 신고 없음", content = @Content)
178+
}
179+
)
180+
public void ignoreCommentReport(@PathVariable Long reportId,
181+
@AuthenticationPrincipal UserPrincipal admin) {
182+
commandService.ignoreCommentReport(admin.getId(), reportId);
183+
}
184+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.devkor.apu.saerok_server.domain.admin.report.api.dto.response;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import org.devkor.apu.saerok_server.domain.freeboard.api.dto.response.GetFreeBoardPostDetailResponse;
5+
import org.devkor.apu.saerok_server.domain.freeboard.api.dto.response.GetFreeBoardPostCommentsResponse;
6+
7+
import java.time.LocalDateTime;
8+
9+
@Schema(description = "신고된 자유게시판 댓글 상세(댓글 + 부모 게시글 + 댓글 목록)")
10+
public record ReportedFreeBoardCommentDetailResponse(
11+
Long reportId,
12+
ReportedComment comment,
13+
GetFreeBoardPostDetailResponse post,
14+
GetFreeBoardPostCommentsResponse comments
15+
) {
16+
public record ReportedComment(
17+
Long commentId,
18+
Long userId,
19+
String nickname,
20+
String content,
21+
LocalDateTime createdAt,
22+
LocalDateTime updatedAt
23+
) {}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.devkor.apu.saerok_server.domain.admin.report.api.dto.response;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
5+
import java.time.LocalDateTime;
6+
import java.util.List;
7+
8+
@Schema(description = "신고된 자유게시판 댓글 목록 응답")
9+
public record ReportedFreeBoardCommentListResponse(
10+
List<Item> items
11+
) {
12+
public record Item(
13+
Long reportId,
14+
LocalDateTime reportedAt,
15+
Long commentId,
16+
Long postId,
17+
String contentPreview,
18+
UserMini reporter,
19+
UserMini reportedUser
20+
) {}
21+
22+
public record UserMini(
23+
Long userId,
24+
String nickname
25+
) {}
26+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.devkor.apu.saerok_server.domain.admin.report.api.dto.response;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import org.devkor.apu.saerok_server.domain.freeboard.api.dto.response.GetFreeBoardPostDetailResponse;
5+
import org.devkor.apu.saerok_server.domain.freeboard.api.dto.response.GetFreeBoardPostCommentsResponse;
6+
7+
@Schema(description = "신고된 자유게시판 게시글 상세(게시글 + 댓글 목록)")
8+
public record ReportedFreeBoardPostDetailResponse(
9+
Long reportId,
10+
GetFreeBoardPostDetailResponse post,
11+
GetFreeBoardPostCommentsResponse comments
12+
) {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.devkor.apu.saerok_server.domain.admin.report.api.dto.response;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
5+
import java.time.LocalDateTime;
6+
import java.util.List;
7+
8+
@Schema(description = "신고된 자유게시판 게시글 목록 응답")
9+
public record ReportedFreeBoardPostListResponse(
10+
List<Item> items
11+
) {
12+
public record Item(
13+
Long reportId,
14+
LocalDateTime reportedAt,
15+
Long postId,
16+
String contentPreview,
17+
UserMini reporter,
18+
UserMini reportedUser
19+
) {}
20+
21+
public record UserMini(
22+
Long userId,
23+
String nickname
24+
) {}
25+
}

0 commit comments

Comments
 (0)