Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ public record ProblemDetailResponse(
LocalDateTime modifiedAt,

@Schema(description = "문제 이미지 URL", example = "https://bucket.s3.ap-northeast-2.amazonaws.com/problem/example.jpg")
String imageUrl
String imageUrl,

List<TestcaseResponse> testcases
) {

public static ProblemDetailResponse from(Problem problem, List<Category> categories) {
Expand All @@ -71,6 +72,7 @@ public static ProblemDetailResponse from(Problem problem, List<Category> categor
.createdAt(problem.getCreatedAt())
.modifiedAt(problem.getModifiedAt())
.imageUrl(problem.getImageUrl().isEmpty() ? null : problem.getImageUrl().get(0))
.testcases(problem.top2Testcases().stream().map(TestcaseResponse::from).toList())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.ezcode.codetest.application.problem.dto.response;

import org.ezcode.codetest.domain.problem.model.entity.Problem;
import org.ezcode.codetest.domain.problem.model.entity.Testcase;

import io.swagger.v3.oas.annotations.media.Schema;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.ezcode.codetest.domain.problem.model.entity;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import org.ezcode.codetest.common.base.entity.BaseEntity;
Expand Down Expand Up @@ -154,12 +155,13 @@ public void clearImages() {
this.imageUrl.clear();
}

public void incrementTotalSubmissions() {
totalSubmissions += 1;
}

public void incrementCorrectSubmissions() {
correctSubmissions += 1;

public List<Testcase> top2Testcases() {
if (testcases == null || testcases.isEmpty()) {
return List.of();
}
return testcases.stream()
.sorted(Comparator.comparing(Testcase::getId))
.limit(2)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public Page<Problem> getProblemBySearchCondition(Pageable pageable, ProblemSearc

public Problem getProblem(Long problemId) {

return problemRepository.findByIdNotDeleted(problemId)
return problemRepository.findProblemWithTestcasesById(problemId)
.orElseThrow(() -> new ProblemException(ProblemExceptionCode.PROBLEM_NOT_FOUND));
}
Comment on lines +100 to 102
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

findProblemWithTestcasesById가 soft-delete 필터를 포함하는지 확인 필요

기존 findByIdNotDeleted에서 전환되며 삭제된 문제 노출 위험이 생길 수 있습니다. 리포지토리 쿼리에 isDeleted = false 조건과 테스트케이스 fetch-join이 포함되는지 확인해 주세요. 미보장 시, 리포지토리 수정 또는 방어적 체크 추가가 필요합니다.

검증 스크립트:

추가 제안(옵션):

  • 본 메서드가 다양한 호출처에서 사용된다면, 안전망으로 조회 후 problem.getIsDeleted() 체크를 넣는 것도 고려해 주세요.
  • 읽기 전용 쿼리 메서드(getProblem, getProblemInfo)에 @Transactional(readOnly = true) 부여를 검토하면 LAZY 초기화/성능 측면에서 안전합니다.

🏁 Script executed:

#!/bin/bash
# ProblemRepository 에서 쿼리와 soft-delete 필터 확인
rg -nP --type java -C3 '\binterface\s+ProblemRepository\b'
rg -nP --type java -C6 '\bfindProblemWithTestcasesById\s*\('
# 쿼리 본문/스펙 내 isDeleted 필터 존재 여부 확인
rg -nP --type java -C3 'findProblemWithTestcasesById|isDeleted|fetch\s+join'

Length of output: 57295


ProblemJpaRepository.findProblemWithTestcasesById에 soft-delete 필터(isDeleted = false) 추가
현재 JPA 쿼리에 p.isDeleted = false 조건이 빠져 있어 삭제된(soft-deleted) 문제도 조회될 수 있습니다. where p.isDeleted = false and p.id = :problemId로 쿼리를 수정하거나, 서비스 계층에서 조회 후 problem.getIsDeleted() 방어적 체크를 추가해 주세요.

🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/domain/problem/service/ProblemDomainService.java
around lines 100 to 102, the repository call returns soft-deleted entities
because the JPA query lacks a p.isDeleted = false filter; update the repository
method findProblemWithTestcasesById to include where p.isDeleted = false and
p.id = :problemId so deleted problems are never returned, or if you cannot
change the repository right now, add a defensive check after retrieval to throw
ProblemException(ProblemExceptionCode.PROBLEM_NOT_FOUND) when
problem.getIsDeleted() == true; ensure only non-deleted problems are treated as
found.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ void getProblem_success() {
Long problemId = 1L;
Problem problem = mock(Problem.class);

when(problemRepository.findByIdNotDeleted(problemId)).thenReturn(Optional.ofNullable(problem));
when(problemRepository.findProblemWithTestcasesById(problemId)).thenReturn(Optional.ofNullable(problem));

// when
Problem result = problemDomainService.getProblem(problemId);

// then
assertNotNull(result);
assertEquals(problem, result);
verify(problemRepository).findByIdNotDeleted(problemId);
verify(problemRepository).findProblemWithTestcasesById(problemId);
}

@Test
Expand Down