-
Notifications
You must be signed in to change notification settings - Fork 3
[Feat] 관리자용 신고 상세 내용 조회 API 구현 #302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- 신고 상세 정보를 담을 응답 DTO(ReportDetail) 정의 - 신고 상세 조회 성공 상태 코드(REPORT2002) 추가 - 피신고자의 누적 신고 횟수 합산을 위한 레포지토리 쿼리 추가
- Report 엔티티를 ReportDetail DTO로 변환하는 컨버터 로직 구현 - 신고 상세 정보 및 누적 신고 횟수를 조회하는 서비스 메서드 구현 - ReportService 인터페이스 내 상세 조회 메서드 추가
- 관리자 전용 신고 상세 조회 API 엔드포인트 구현 - @PreAuthorize 활성화를 위한 메서드 보안 설정 추가 - ADMIN 권한을 가진 사용자만 접근 가능하도록 권한 제한 적용
📝 WalkthroughWalkthrough관리자 전용 신고 상세 조회 API가 추가됩니다. 컨트롤러, 서비스 구현과 DTO, 변환기, 저장소 쿼리 및 관련 성공/에러 상태 열거자가 도입되어 신고자 정보, 대상 사용자 통계 및 선택적 Teum 콘텐츠를 반환합니다. Changes
Sequence DiagramsequenceDiagram
participant Admin as Admin (Client)
participant Controller as AdminReportController
participant Service as ReportServiceImpl
participant Repo as ReportRepository
participant Converter as ReportConverter
participant DB as Database
Admin->>Controller: GET /api/v1/admin/reports/{reportId}
Controller->>Service: getReportDetail(reportId)
alt report exists
Service->>Repo: findById(reportId)
Repo->>DB: SELECT report WHERE id=?
DB-->>Repo: Report entity
Repo-->>Service: Report
Service->>Repo: countTotalReportsByUser(targetUser)
Repo->>DB: COUNT(...) by user
DB-->>Repo: totalCount
Repo-->>Service: long
Service->>Converter: toReportDetail(report, totalCount)
Converter-->>Service: ReportDetail DTO
Service-->>Controller: ReportDetail
Controller-->>Admin: ApiResponse(OK, REPORT_DETAIL_FETCHED, ReportDetail)
else not found
Service-->>Controller: throw ReportNotFoundException
Controller-->>Admin: ApiResponse(NOT_FOUND, error)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Test Results49 tests 49 ✅ 3s ⏱️ Results for commit fcaee83. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (8)
src/main/java/umc/teumteum/server/domain/report/controller/AdminReportController.javasrc/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.javasrc/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.javasrc/main/java/umc/teumteum/server/domain/report/exception/status/ReportSuccessStatus.javasrc/main/java/umc/teumteum/server/domain/report/repository/ReportRepository.javasrc/main/java/umc/teumteum/server/domain/report/service/ReportService.javasrc/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.javasrc/main/java/umc/teumteum/server/global/config/SecurityConfig.java
🧰 Additional context used
📓 Path-based instructions (1)
src/**
⚙️ CodeRabbit configuration file
src/**: 다음 항목들을 꼼꼼하게 검토해줘.
- 예외 처리
- 예외가 적절히 처리되었는지 확인해줘. (try-catch, throws, ExceptionAdvice)
- 공통 예외 처리 모듈(예: GlobalHandler, ApiResponse 등)을 잘 활용했는지 확인.
- RuntimeException을 남발하지 않고, 의미 있는 커스텀 예외를 사용하는지 검토.
- 예외 메시지에 민감 정보(DB 정보, 사용자 정보 등)가 노출되지 않게 했는지 점검.
- 코드 품질 & 가독성
- 메소드/클래스가 단일 책임 원칙(SRP)에 맞게 구성되어 있는지.
- 중복 코드가 있는 경우, 유틸/공통 컴포넌트로 추출 가능한지.
- 의미 있는 변수명과 메소드명을 사용했는지.
- 매직 넘버, 하드코딩된 값이 존재하는지 점검.
- 성능 및 효율성
- 불필요한 DB 쿼리 호출, N+1 문제 가능성이 있는지 확인.
- Stream, loop, recursion 사용 시 시간복잡도/메모리 효율성을 고려했는지.
- 캐시 적용 가능성이 있거나, 과도한 연산이 반복되는 구간이 있는지.
- 트랜잭션 관리
- @transactional이 필요한 메소드에 누락되지 않았는지.
- 읽기 전용 트랜잭션(readOnly = true)을 적절히 사용했는지.
- DB 일관성, 롤백 정책이 올바른지 검토.
- 입력 검증 및 보안
- @Valid, Bean Validation 등을 통한 입력값 검증이 되어 있는지.
- 비밀번호, 토큰 등 민감한 정보가 로깅되지 않는지.
- 테스트
- 단위 테스트가 충분히 작성되었는지, 핵심 로직의 검증이 누락되지 않았는지.
- Mocking을 통한 독립 테스트 구조를 유지했는지.
- 경계값 테스트, 예외 케이스 테스트가 포함되어 있는지.
- 구조 및 설계
- Controller, Service, Repository 등 계층 구조가 올바르게 나뉘어 있는지.
- DTO, Entity, Domain 객체 간 변환 로직이 명확하고 중복되지 않는지.
- Config 클래스에서 Bean 등록이 과도하거나 순환 참조 위험이 없는지.
Files:
src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.javasrc/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.javasrc/main/java/umc/teumteum/server/domain/report/service/ReportService.javasrc/main/java/umc/teumteum/server/domain/report/controller/AdminReportController.javasrc/main/java/umc/teumteum/server/domain/report/repository/ReportRepository.javasrc/main/java/umc/teumteum/server/global/config/SecurityConfig.javasrc/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.javasrc/main/java/umc/teumteum/server/domain/report/exception/status/ReportSuccessStatus.java
🧬 Code graph analysis (4)
src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.java (1)
src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java (1)
ReportResponseDto(13-91)
src/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.java (2)
src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java (1)
ReportResponseDto(13-91)src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.java (1)
ReportConverter(11-67)
src/main/java/umc/teumteum/server/domain/report/service/ReportService.java (1)
src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java (1)
ReportResponseDto(13-91)
src/main/java/umc/teumteum/server/domain/report/controller/AdminReportController.java (1)
src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java (1)
ReportResponseDto(13-91)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Continuous Integration
🔇 Additional comments (4)
src/main/java/umc/teumteum/server/global/config/SecurityConfig.java (1)
20-20: LGTM!
@EnableMethodSecurity추가로 메서드 단위 보안(@PreAuthorize)이 활성화되었습니다. AdminReportController의 ADMIN 권한 제어가 정상적으로 동작합니다.src/main/java/umc/teumteum/server/domain/report/service/ReportService.java (1)
9-9: LGTM!신고 상세 조회 메서드 시그니처가 적절하게 정의되었습니다.
src/main/java/umc/teumteum/server/domain/report/controller/AdminReportController.java (1)
15-33: LGTM - 관리자용 컨트롤러 구현이 적절합니다.
- 클래스 레벨
@PreAuthorize("hasRole('ADMIN')")로 모든 엔드포인트에 ADMIN 권한 제한이 적용됩니다.- Swagger 문서화(
@Tag,@Operation)가 적절히 적용되었습니다.- 계층 구조(Controller → Service)가 올바르게 분리되어 있습니다.
src/main/java/umc/teumteum/server/domain/report/repository/ReportRepository.java (1)
12-16: 쿼리는 올바르게 작성되었으며 중복 카운트 우려는 근거 없음createReport 로직에서 if-else 분기를 통해 targetType에 따라 targetUser와 teumRequest 중 정확히 하나만 설정됩니다(lines 56-76). USER 타입이면 targetUser만 설정되고 teumRequest는 null로 유지되며, TEUM_REQUEST 타입이면 teumRequest만 설정되고 targetUser는 null로 유지됩니다. 따라서 단일 Report 레코드에서 두 조건을 동시에 만족할 수 없으며, LEFT JOIN을 통한 null 처리도 올바릅니다. 현재 쿼리는 데이터 정합성상 문제가 없습니다.
| import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
| import org.springframework.security.core.context.SecurityContextHolder; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
사용되지 않는 import 제거 권장
@AuthenticationPrincipal과 SecurityContextHolder가 import되었으나 사용되지 않습니다. 코드 정리를 권장합니다.
🔎 수정 제안
import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.core.annotation.AuthenticationPrincipal;
-import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import org.springframework.security.core.annotation.AuthenticationPrincipal; | |
| import org.springframework.security.core.context.SecurityContextHolder; | |
| import org.springframework.security.access.prepost.PreAuthorize; | |
| import org.springframework.web.bind.annotation.*; |
🤖 Prompt for AI Agents
In
src/main/java/umc/teumteum/server/domain/report/controller/AdminReportController.java
around lines 7 to 8, the imports for
org.springframework.security.core.annotation.AuthenticationPrincipal and
org.springframework.security.core.context.SecurityContextHolder are unused;
remove those two import lines (or run your IDE's "Optimize/Organize Imports") to
clean up the file and then rebuild to ensure no missing references remain.
src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.java
Outdated
Show resolved
Hide resolved
src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.java
Show resolved
Hide resolved
src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java
Show resolved
Hide resolved
src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java
Show resolved
Hide resolved
src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java
Show resolved
Hide resolved
| REPORT_DETAIL_FETCHED(HttpStatus.OK, "REPORT2002", "신고 상세 정보를 성공적으로 조회했습니다."); | ||
| ; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
세미콜론이 중복되어 있습니다.
Line 14에서 enum 상수 선언이 ;로 끝나고, Line 15에도 추가 ;가 있습니다. 불필요한 세미콜론을 제거해 주세요.
🔎 수정 제안
- REPORT_DETAIL_FETCHED(HttpStatus.OK, "REPORT2002", "신고 상세 정보를 성공적으로 조회했습니다.");
- ;
+ REPORT_DETAIL_FETCHED(HttpStatus.OK, "REPORT2002", "신고 상세 정보를 성공적으로 조회했습니다.");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| REPORT_DETAIL_FETCHED(HttpStatus.OK, "REPORT2002", "신고 상세 정보를 성공적으로 조회했습니다."); | |
| ; | |
| REPORT_DETAIL_FETCHED(HttpStatus.OK, "REPORT2002", "신고 상세 정보를 성공적으로 조회했습니다."); |
🤖 Prompt for AI Agents
In
src/main/java/umc/teumteum/server/domain/report/exception/status/ReportSuccessStatus.java
around lines 14 to 15, the enum constant declaration ends with a semicolon on
line 14 and there is an extra redundant semicolon on line 15; remove the
unnecessary semicolon on line 15 so only the single terminating semicolon after
the enum constants remains.
src/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.java
Outdated
Show resolved
Hide resolved
src/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.java
Show resolved
Hide resolved
- ReportServiceImpl에서 TEUM_REQUEST 타입 신고 조회 시 원본 요청 존재 여부를 검증하는 Fail-Fast 로직 추가 - ReportConverter에서 Optional을 활용하여 피신고자(reportedUser) 정보를 안전하게 추출하도록 로직 개선 - 데이터 정합성 오류로 인한 런타임 NullPointerException 방지 및 시스템 안정성 강화
- 신고 내역 부재 시 사용할 REPORT_NOT_FOUND 에러 코드 추가 - 리소스 조회 실패 관련 에러 코드를 404 번대(REPORT4041~4043)로 변경하여 RESTful 규격 준수 - 서비스 레이어의 상세 조회 및 검증 로직에 변경된 에러 코드 적용
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.java (1)
64-64: NPE 방지를 위한 null 체크 필요
teum.getDate()가 null을 반환할 경우toString()호출 시 NPE가 발생할 수 있습니다. 안전한 변환 로직 추가가 필요합니다.🔎 제안하는 수정 방법
- .date(teum.getDate().toString()) + .date(teum.getDate() != null ? teum.getDate().toString() : null)또는 Optional을 활용한 방법:
- .date(teum.getDate().toString()) + .date(Optional.ofNullable(teum.getDate()) + .map(Object::toString) + .orElse(null))src/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.java (1)
103-105: 코드 중복 제거 권장피신고자를 특정하는 로직이
ReportConverter.toReportDetail(lines 35-38)에도 동일하게 존재합니다. DRY 원칙을 위반하며, 향후 로직 변경 시 두 곳을 모두 수정해야 하는 유지보수 리스크가 있습니다.다음 방법 중 하나를 고려해 주세요:
- 공통 유틸리티 메서드로 추출 (예:
ReportUtils.resolveReportedUser(Report))- 서비스에서
reportedUser를 확정한 후 컨버터에 전달 (메서드 시그니처 변경)- 컨버터에서만 해결하고 서비스는 컨버터가 반환한 DTO에서 userId를 추출하여 카운트 조회
Based on coding guidelines: 코드 품질 & 가독성 - 중복 코드는 유틸/공통 컴포넌트로 추출 가능한지 검토 필요
🔎 Option 1: 공통 유틸리티 메서드 추출 예시
+ // ReportUtils.java (new utility class) + public class ReportUtils { + public static User resolveReportedUser(Report report) { + return Optional.ofNullable(report.getTargetUser()) + .orElseGet(() -> Optional.ofNullable(report.getTeumRequest()) + .map(TeumRequest::getUser) + .orElse(null)); + } + } // ReportServiceImpl.java public ReportResponseDto.ReportDetail getReportDetail(Long reportId) { Report report = reportRepository.findById(reportId) .orElseThrow(() -> new ReportException(ReportErrorStatus.REPORT_NOT_FOUND)); if (report.getTargetType() == TargetType.TEUM_REQUEST && report.getTeumRequest() == null) { throw new ReportException(ReportErrorStatus.REPORT_TARGET_NOT_FOUND); } - User reportedUser = (report.getTargetType() == TargetType.USER) - ? report.getTargetUser() - : report.getTeumRequest().getUser(); + User reportedUser = ReportUtils.resolveReportedUser(report); long totalReportCount = reportRepository.countTotalReportsByUser(reportedUser); return ReportConverter.toReportDetail(report, totalReportCount); } // ReportConverter.java public static ReportResponseDto.ReportDetail toReportDetail(Report report, long totalReportCount) { - User reportedUser = Optional.ofNullable(report.getTargetUser()) - .orElseGet(() -> Optional.ofNullable(report.getTeumRequest()) - .map(TeumRequest::getUser) - .orElse(null)); + User reportedUser = ReportUtils.resolveReportedUser(report); // ... rest of the code }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.javasrc/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.javasrc/main/java/umc/teumteum/server/domain/report/exception/status/ReportErrorStatus.javasrc/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.java
🧰 Additional context used
📓 Path-based instructions (1)
src/**
⚙️ CodeRabbit configuration file
src/**: 다음 항목들을 꼼꼼하게 검토해줘.
- 예외 처리
- 예외가 적절히 처리되었는지 확인해줘. (try-catch, throws, ExceptionAdvice)
- 공통 예외 처리 모듈(예: GlobalHandler, ApiResponse 등)을 잘 활용했는지 확인.
- RuntimeException을 남발하지 않고, 의미 있는 커스텀 예외를 사용하는지 검토.
- 예외 메시지에 민감 정보(DB 정보, 사용자 정보 등)가 노출되지 않게 했는지 점검.
- 코드 품질 & 가독성
- 메소드/클래스가 단일 책임 원칙(SRP)에 맞게 구성되어 있는지.
- 중복 코드가 있는 경우, 유틸/공통 컴포넌트로 추출 가능한지.
- 의미 있는 변수명과 메소드명을 사용했는지.
- 매직 넘버, 하드코딩된 값이 존재하는지 점검.
- 성능 및 효율성
- 불필요한 DB 쿼리 호출, N+1 문제 가능성이 있는지 확인.
- Stream, loop, recursion 사용 시 시간복잡도/메모리 효율성을 고려했는지.
- 캐시 적용 가능성이 있거나, 과도한 연산이 반복되는 구간이 있는지.
- 트랜잭션 관리
- @transactional이 필요한 메소드에 누락되지 않았는지.
- 읽기 전용 트랜잭션(readOnly = true)을 적절히 사용했는지.
- DB 일관성, 롤백 정책이 올바른지 검토.
- 입력 검증 및 보안
- @Valid, Bean Validation 등을 통한 입력값 검증이 되어 있는지.
- 비밀번호, 토큰 등 민감한 정보가 로깅되지 않는지.
- 테스트
- 단위 테스트가 충분히 작성되었는지, 핵심 로직의 검증이 누락되지 않았는지.
- Mocking을 통한 독립 테스트 구조를 유지했는지.
- 경계값 테스트, 예외 케이스 테스트가 포함되어 있는지.
- 구조 및 설계
- Controller, Service, Repository 등 계층 구조가 올바르게 나뉘어 있는지.
- DTO, Entity, Domain 객체 간 변환 로직이 명확하고 중복되지 않는지.
- Config 클래스에서 Bean 등록이 과도하거나 순환 참조 위험이 없는지.
Files:
src/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.javasrc/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.javasrc/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.javasrc/main/java/umc/teumteum/server/domain/report/exception/status/ReportErrorStatus.java
🧬 Code graph analysis (2)
src/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.java (2)
src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java (1)
ReportResponseDto(13-97)src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.java (1)
ReportConverter(13-70)
src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.java (1)
src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java (1)
ReportResponseDto(13-97)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Continuous Integration
- GitHub Check: Continuous Integration
🔇 Additional comments (4)
src/main/java/umc/teumteum/server/domain/report/exception/status/ReportErrorStatus.java (1)
13-16: 에러 코드 체계화가 잘 구현되었습니다.404 Not Found 관련 에러들이 REPORT404x 코드 체계로 체계적으로 통일되어 있으며, 새로 추가된
REPORT_NOT_FOUND(REPORT4043)는 ReportServiceImpl의getReportDetail()메소드에서 실제로 활용되고 있습니다.ReportException은 GeneralException을 상속하여 ExceptionAdvice의
@ExceptionHandler(value = GeneralException.class)를 통해 중앙집중식으로 처리되므로, 새로운 에러 코드들이 API 응답에 올바르게 매핑됩니다. 에러 메시지도 사용자 친화적이며 민감 정보가 노출되지 않습니다.src/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.java (1)
97-100: LGTM! Fail-Fast 검증 로직 추가TEUM_REQUEST 타입인데 teumRequest가 null인 경우를 사전에 차단하여 NPE를 방지하는 좋은 방어 로직입니다.
src/main/java/umc/teumteum/server/domain/report/converter/ReportConverter.java (1)
33-55: LGTM! 안전한 null 처리와 명확한 DTO 변환 로직
Optional을 활용한 안전한 피신고자 특정 로직과 null 발생 시 기본값("알 수 없음") 처리가 잘 구현되어 있습니다.src/main/java/umc/teumteum/server/domain/report/dto/ReportResponseDto.java (1)
1-97: LGTM! 일관된 DTO 구조와 명확한 문서화이전 리뷰에서 지적되었던 Lombok 어노테이션(
@NoArgsConstructor,@AllArgsConstructor) 누락 이슈가 모두 해결되었습니다 (lines 52-53, 65-66, 81-82).모든 중첩 DTO 클래스들이 일관된 패턴을 따르고 있으며, Swagger 문서화도 예시와 함께 잘 작성되어 있습니다. Jackson 직렬화/역직렬화 및 테스트 시 안정적으로 동작할 것으로 판단됩니다.
Based on coding guidelines: 구조 및 설계 - DTO 객체 간 변환 로직이 명확하고 중복되지 않음
| // 제한 및 검증 관련 (400 Bad Request) | ||
| REPORT_SELF_NOT_ALLOWED(HttpStatus.BAD_REQUEST, "REPORT4001", "자기 자신은 신고할 수 없습니다."), | ||
| REPORT_OTHER_REASON_REQUIRED(HttpStatus.BAD_REQUEST, "REPORT4002", "기타 사유 선택 시, 구체적인 내용을 입력해야 합니다."), | ||
| REPORT_INVALID_TARGET_TYPE(HttpStatus.BAD_REQUEST, "REPORT4003", "지원하지 않는 신고 대상입니다."), | ||
| REPORT_INVALID_STATUS(HttpStatus.BAD_REQUEST, "REPORT4004", "대기 중인 요청만 신고할 수 있습니다."), | ||
| REPORT_ALREADY_EXISTS(HttpStatus.BAD_REQUEST, "REPORT4005", "이미 신고한 대상입니다."), // 중복 신고 방지용 추가 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find where REPORT_ALREADY_EXISTS is actually used
echo "=== Searching for REPORT_ALREADY_EXISTS usage ==="
rg -n 'REPORT_ALREADY_EXISTS' --type=java
echo -e "\n=== Searching for duplicate check methods in Report-related files ==="
# Search for exists/duplicate check patterns
rg -n 'existsBy|findBy.*Report.*Report' --type=java -g '*Report*'
echo -e "\n=== Searching for createReport or saveReport methods ==="
ast-grep --pattern 'public $_ create($$$) { $$$ }' || rg -n 'public.*create.*Report.*{' --type=java -A 10Repository: UMC8-TeumTeum/BE
Length of output: 558
🏁 Script executed:
#!/bin/bash
# Search more broadly for Report service and repository patterns
echo "=== Looking for ReportRepository ==="
fd -n '*Repository*' --type=f -e java | head -20
echo -e "\n=== Looking for ReportService ==="
fd -n '*Service*' --type=f -e java | head -20Repository: UMC8-TeumTeum/BE
Length of output: 610
🏁 Script executed:
#!/bin/bash
# Find the exact files
echo "=== Locating Report-related repository and service files ==="
find . -type f -name '*Report*Repository.java' 2>/dev/null
find . -type f -name '*Report*Service.java' 2>/dev/nullRepository: UMC8-TeumTeum/BE
Length of output: 369
🏁 Script executed:
#!/bin/bash
echo "=== ReportRepository content ==="
cat -n ./src/main/java/umc/teumteum/server/domain/report/repository/ReportRepository.java
echo -e "\n=== ReportService content ==="
cat -n ./src/main/java/umc/teumteum/server/domain/report/service/ReportService.javaRepository: UMC8-TeumTeum/BE
Length of output: 1402
🏁 Script executed:
#!/bin/bash
echo "=== Finding ReportService implementation ==="
find ./src -type f -name '*ReportService*.java' | grep -v interface
echo -e "\n=== Searching for createReport implementation ==="
rg -n 'createReport' --type=java -B 3 -A 15Repository: UMC8-TeumTeum/BE
Length of output: 4644
🏁 Script executed:
#!/bin/bash
echo "=== Full ReportServiceImpl content ==="
cat -n ./src/main/java/umc/teumteum/server/domain/report/service/ReportServiceImpl.java
echo -e "\n=== Checking if REPORT_ALREADY_EXISTS is thrown anywhere ==="
rg -n 'REPORT_ALREADY_EXISTS|ReportErrorStatus' --type=java -g '*Report*'Repository: UMC8-TeumTeum/BE
Length of output: 9031
REPORT_ALREADY_EXISTS 에러 코드가 정의되었으나 실제 중복 신고 방지 로직이 구현되지 않았습니다.
ReportServiceImpl.createReport() 메서드에는 중복 신고 검증이 전혀 없습니다. 현재 구현된 검증은 신고 사유, 기타 사유 내용, 자기 신고 방지, 대상 유형만 있고, 동일 신고자가 동일 대상을 이미 신고했는지 확인하는 로직이 없습니다.
필수 조치:
ReportRepository에 중복 신고 확인 메서드 추가 (예:existsByReporterAndTargetUserAndTargetType())ReportServiceImpl.createReport()에서 신고 저장 전 중복 여부 확인 로직 구현- 중복 신고 시
REPORT_ALREADY_EXISTS예외 발생
현재 상태로는 동일 사용자가 같은 대상을 여러 번 신고할 수 있습니다.
🤖 Prompt for AI Agents
In
src/main/java/umc/teumteum/server/domain/report/exception/status/ReportErrorStatus.java
around lines 18 to 23, REPORT_ALREADY_EXISTS is defined but duplicate-report
prevention is not implemented; add a repository method to detect duplicates
(e.g., existsByReporterAndTargetUserAndTargetType or appropriate signature for
your domain), call that method in ReportServiceImpl.createReport() before saving
a new report, and if it returns true throw the REPORT_ALREADY_EXISTS exception
(use the existing error status to build the exception) so the service rejects
duplicate reports.
👀 관련 이슈
#301
✨ 작업한 내용
🌀 PR Point
🍰 참고사항
📷 스크린샷 또는 GIF
Summary by CodeRabbit
릴리스 노트
✏️ Tip: You can customize this high-level summary in your review settings.