[Feat] 관리자 및 마이페이지 API 계약 및 Swagger 명세 작성 - #32
Conversation
목록 조회 API에서 공통으로 쓸 페이지네이션 응답 구조가 없어 Spring Page 스타일(content, page, size, totalElements, totalPages, hasNext)로 새로 정의함
RequestParam으로 받는 enum(targetType, status 등)에 잘못된 값이 들어오면 MethodArgumentTypeMismatchException이 처리되지 않아 500으로 응답되던 문제를 수정함
신고 대상을 POST | COMMENT로 통합 관리하기 위해 ReportTargetType을 추가하고, COMMENT 대상은 COPYRIGHT·LOW_QUALITY 사유를 허용하지 않는 도메인 규칙을 ReportReason.isAllowedFor로 추가함. 신고 생성 API가 아직 없어 실제 호출부는 후속 이슈에서 연결함
GET /api/v1/users/me 엔드포인트 골격과 UserProfileResponse(username, profileImageUrl, email, point, gradeName)를 추가함. 실제 조회 로직은 아직 없어 NotImplementedException으로 501을 반환함
prompt/interfaces 패키지를 새로 만들고 GET /api/v1/prompts/me(status=ACTIVE 필터, 페이지네이션), GET /api/v1/prompts/me/insights 엔드포인트 골격을 추가함. 목록 응답은 카드에 필요한 필드만 포함하고 프롬프트 본문은 제외함. 인사이트는 totalViews, totalRecommends, totalCopies를 반환하도록 계약만 정의함
admin/interfaces 패키지에 AdminReportController를 추가해 GET
/api/v1/admin/reports(targetType·status 필터, 페이지네이션), PATCH
/api/v1/admin/reports/{reportId} 엔드포인트 골격을 작성함. 처리 상태는
PENDING으로 되돌릴 수 없도록 검증하며, 신고 생성 API는 이번 범위에서 제외됨을
Swagger 설명에 명시함
admin/interfaces 패키지에 AdminGradeRequestController를 추가해 GET
/api/v1/admin/grade-requests(status 필터, 페이지네이션), PATCH
/api/v1/admin/grade-requests/{requestId} 엔드포인트 골격을 작성함. 처리 결과는
APPROVED 또는 REJECTED만 허용하며, 신청 생성 방식 등 정책이 아직 정해지지
않아 GradeRequestStatus와 응답 필드는 정책 미정으로 Swagger에 표시함
ae2fddd to
c1345b2
Compare
Hanharam
left a comment
There was a problem hiding this comment.
지금은 /api/v1/admin/**는 관리자 전용 경로지만, Security 설정에서는 관리자 권한이 아니라 로그인 여부만 확인하고 있습니다. 그래서 추후에 기능 구현하실 때는
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()이렇게 관리자 api endpoint 의 권한을 확인하면 좋을 것 같습니다!
| String message = "%s 값이 유효하지 않습니다.".formatted(e.getName()); | ||
|
|
||
| log.warn("[TYPE MISMATCH] {}", message); | ||
| return buildResponse(e, CommonErrorCode.BAD_REQUEST, HttpHeaders.EMPTY, request, message); |
There was a problem hiding this comment.
이 예외 핸들러는 RequestParam이나 PathVariable을 타입으로 변환하지 못한 예외를 잡고 있습니다. 그래서 @Valid 예외와 같은 맥락이라고 생각해서 @Valid 핸들러와 같은 예외로 던지는 것이 좋을 것 같습니다!
예를 들어 status=WRONG 처럼 존재하지 않는 enum을 보낸 경우도 page=-1이나 DTO 검증 실패와 동일한 입력값 오류입니다. 지금은 이 경우에만 COMMON-400을 반환해 같은 종류의 오류가 서로 다른 코드로 내려가고 있습니다. 프론트엔드가 입력 오류를 하나의 기준으로 처리할 수 있도록 기존에 @Valid 예외에서 사용하고 있던 INVALID_INPUT_VALUE(COMMON-001)를 사용하는 것이 좋을 것 같습니다!
return buildResponse(
e,
CommonErrorCode.INVALID_INPUT_VALUE,
HttpHeaders.EMPTY,
request,
message
);There was a problem hiding this comment.
말씀하신대로 enum 값이 잘못 들어온 경우도 @Valid 검증 실패와 같은 입력값 오류로 보는 게 맞겠네요MethodArgumentTypeMismatchException 처리 부분을 INVALID_INPUT_VALUE(COMMON-001)로 바꿔서 반영했습니다. 감사합니다!
| if (targetType == ReportTargetType.COMMENT) { | ||
| return !COMMENT_DISALLOWED.contains(this); | ||
| } | ||
| return true; |
There was a problem hiding this comment.
null 또는 추후에 추가될 수 있는 ReportTargetType이 모두 허용되고 있습니다. 신고 대상 타입이 늘어날 때 별도 정책 검토 없이 모든 사유가 허용될 수 있어서 switch로 각 타입을 명시하고 null은 거부하면 확장성 측면에서 좋을 것 같습니다!
public boolean isAllowedFor(ReportTargetType targetType) {
if (targetType == null) {
return false;
}
return switch (targetType) {
case COMMENT -> !COMMENT_DISALLOWED.contains(this);
case PROMPT -> true;
};
}There was a problem hiding this comment.
제안해주신 대로 null은 거부하고 switch로 각 타입을 명시하도록 수정했습니다!
…min-api-contract # Conflicts: # src/main/java/com/promsearch/prompt/interfaces/PromptController.java # src/main/java/com/promsearch/prompt/interfaces/docs/PromptControllerDocs.java # src/main/java/com/promsearch/user/interfaces/UserController.java # src/main/java/com/promsearch/user/interfaces/docs/UserControllerDocs.java
- MethodArgumentTypeMismatchException 처리 시 COMMON-400 대신 @Valid 검증과 동일한 INVALID_INPUT_VALUE(COMMON-001) 반환 - ReportReason.isAllowedFor에서 null 대상 타입을 거부하고 switch로 대상 타입을 명시해 신규 타입 추가 시 누락을 방지
admin 패키지가 develop의 인터페이스 DTO 분리 컨벤션(#39)이 도입되기 전에 작성되어 PackageStructureTest.interfaceDtosAreSeparatedIntoRequestAndResponsePackages를 위반하고 있었습니다. GradeRequestSummaryResponse, ReportSummaryResponse는 dto/response로, ProcessGradeRequestRequest, UpdateReportStatusRequest는 dto/request로 옮겨 다른 도메인과 동일한 구조를 따르도록 정리합니다.
변경 사항
GET /users/me), 게시완료 목록(GET /prompts/me), 게시글 인사이트(GET /prompts/me/insights), 관리자 신고함 조회·처리(GET/PATCH /admin/reports), Origin 등급업 신청 조회·승인/반려(GET/PATCH /admin/grade-requests) 등 7개 API 골격을 추가했습니다.PageResponse)을 Spring Page 스타일로 새로 도입했습니다.targetType: POST | COMMENT로 통합 관리하기 위해ReportTargetType을 추가하고, 대상 타입별 허용 사유 집합을ReportReason.isAllowedFor로 검증하는 도메인 규칙을 추가했습니다.RequestParam으로 받는 enum(targetType,status등)에 잘못된 값이 들어오면 500 대신 400을 반환하도록GlobalExceptionHandler를 보완했습니다.반영 정책
GET /prompts/me의status값은 이슈PUBLISHED였으나, 기존PromptStatusenum의ACTIVE가 이미 게시 완료 상태를 의미하므로 별도 값을 추가하지 않고ACTIVE를 그대로 사용합니다.PENDING으로 되돌릴 수 없고RESOLVED/REJECTED만 허용합니다.GET /prompts/draft를 재사용합니다(이번 PR에서 코드 변경 없음).범위 제외 / 추후 확정
@PreAuthorize) 검증은 후속 이슈로 분리했습니다.PostReport가 현재postId만 지원하므로COMMENT대상 신고는 영속성 계층 확장이 필요합니다.GradeRequestStatus와 관련 응답 필드는 Swagger에 "정책 미정"으로 표시했습니다.publishedAt필드의 실제 매핑은 후속 구현에서 확정이 필요합니다.PromptController/PromptControllerDocs는 먼저 병합된 PR [Feat] 프롬프트 생성·임시저장·삭제 API 계약 및 Swagger 명세 작성 #23(프롬프트 생성·임시저장·삭제 계약)과 같은 파일을 다뤄,origin/develop기준으로 rebase하여 두 기능을 한 컨트롤러/문서로 병합했습니다. Operation 넘버링은 PR #23의PROMPT-005에 이어PROMPT-006/007로 지정했습니다.테스트
./gradlew testUserControllerTest,PromptControllerTest,AdminReportControllerTest,AdminGradeRequestControllerTest)UserOpenApiContractTest,PromptOpenApiContractTest,AdminOpenApiContractTest)ReportReasonTest)Closes #31