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
@@ -0,0 +1,5 @@
package org.ezcode.codetest.application.ranking.dto;

public record PointResponse (
int points
){}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import lombok.Builder;

@Builder
public record RankingResponse(
public record RankingResponse(
Long userId,
String nickname, // 사용자 이름
int ranks,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.ezcode.codetest.application.ranking.service;

import lombok.RequiredArgsConstructor;
import org.ezcode.codetest.domain.submission.repository.UserProblemResultRepository;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class PointService {

private final UserProblemResultRepository userProblemResultRepository;

public int getTotalPoints(Long userId) {
return userProblemResultRepository.sumPointByUserId(userId).orElse(0);
}
Comment on lines +13 to +15
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

입력 검증 및 예외 처리 개선 필요

userId가 null일 경우에 대한 검증이 없습니다. 또한 데이터베이스 호출 시 발생할 수 있는 예외에 대한 명시적인 처리를 고려해보세요.

다음과 같이 입력 검증을 추가하는 것을 권장합니다:

 public int getTotalPoints(Long userId) {
+    if (userId == null) {
+        throw new IllegalArgumentException("사용자 ID는 null일 수 없습니다");
+    }
     return userProblemResultRepository.sumPointByUserId(userId).orElse(0);
 }
📝 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.

Suggested change
public int getTotalPoints(Long userId) {
return userProblemResultRepository.sumPointByUserId(userId).orElse(0);
}
public int getTotalPoints(Long userId) {
if (userId == null) {
throw new IllegalArgumentException("사용자 ID는 null일 수 없습니다");
}
return userProblemResultRepository.sumPointByUserId(userId).orElse(0);
}
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/ranking/service/PointService.java
around lines 13 to 15, add a null check for the userId parameter at the start of
the getTotalPoints method to validate input. If userId is null, throw an
IllegalArgumentException with a clear message. Additionally, wrap the repository
call in a try-catch block to handle potential database exceptions, and handle or
rethrow them appropriately to ensure robust error handling.


}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import org.ezcode.codetest.domain.submission.model.entity.UserProblemResult;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;


public interface UserProblemResultRepository {
Optional<UserProblemResult> findUserProblemResultByUserIdAndProblemId(Long userId, Long problemId);
Expand All @@ -24,4 +26,6 @@ SELECT upr.user.id, SUM(p.score)
GROUP BY upr.user.id
""")
List<Object[]> findScoresBetween(LocalDateTime start, LocalDateTime end);

Optional<Integer> sumPointByUserId(@Param("userId") Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@ public List<Object[]> findScoresBetween(LocalDateTime start, LocalDateTime end)
return userProblemResultJpaRepository.findScoresBetween(start, end);
}

@Override
public Optional<Integer> sumPointByUserId(Long userId) {
return userProblemResultJpaRepository.sumScoreByUserId(userId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.ezcode.codetest.domain.submission.model.entity.UserProblemResult;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface UserProblemResultJpaRepository extends JpaRepository<UserProblemResult, Long> {
Optional<UserProblemResult> findByUserIdAndProblemId(Long userId, Long problemId);
Expand All @@ -22,4 +23,14 @@ SELECT upr.user.id, SUM(p.score)
""")
List<Object[]> findScoresBetween(LocalDateTime start, LocalDateTime end);

@Query("""
SELECT SUM(p.score)
FROM UserProblemResult upr
JOIN upr.problem p
WHERE upr.user.id = :userId
AND upr.isCorrect = true
""")
Optional<Integer> sumScoreByUserId(@Param("userId") Long userId);


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.ezcode.codetest.presentation.ranking;

import lombok.RequiredArgsConstructor;
import org.ezcode.codetest.application.ranking.dto.PointResponse;
import org.ezcode.codetest.application.ranking.service.PointService;
import org.ezcode.codetest.domain.user.model.entity.AuthUser;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/points")
@RequiredArgsConstructor
public class PointController {
private final PointService pointService;

@GetMapping("/me")
public ResponseEntity<PointResponse> getMyPoint(@AuthenticationPrincipal AuthUser authUser) {
Long userId = authUser.getId();
int totalPoints = pointService.getTotalPoints(userId);
return ResponseEntity.ok(new PointResponse(totalPoints));
}

@GetMapping("/{userId}")
public ResponseEntity<PointResponse> getUserPoint(@PathVariable Long userId) {
int totalPoint = pointService.getTotalPoints(userId);
return ResponseEntity.ok(new PointResponse(totalPoint));
}
Comment on lines +27 to +31
Copy link

@coderabbitai coderabbitai bot Jun 22, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

보안 및 입력 검증 개선 필요

다른 사용자의 점수 조회에 대한 권한 검사가 없고, userId 입력 검증이 부족합니다.

다음과 같은 개선사항을 고려해주세요:

  1. 입력 검증 추가:
 @GetMapping("/{userId}")
 public ResponseEntity<PointResponse> getUserPoint(@PathVariable Long userId) {
+    if (userId == null || userId <= 0) {
+        return ResponseEntity.badRequest().build();
+    }
     int totalPoints = pointService.getTotalPoints(userId);
     return ResponseEntity.ok(new PointResponse(totalPoints));
 }
  1. 권한 검사 추가 (필요시):
    • 모든 사용자의 점수를 공개할 것인지, 아니면 특정 권한이 필요한지 정책을 명확히 하고 적절한 보안 검사를 추가해주세요.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/org/ezcode/codetest/presentation/ranking/PointController.java
around lines 27 to 31, the getUserPoint method lacks input validation for userId
and does not perform any authorization checks. Add validation to ensure userId
is a valid positive number before processing. Implement authorization logic to
verify if the requesting user has permission to access the requested user's
points, based on your security policy, and restrict access accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

다른 사람 프로필 들어갔을때 티어 보이게 하려는거라 아무나 조회 가능해

Copy link

Choose a reason for hiding this comment

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

@pokerbearkr 아, 프로필 페이지에서 티어 표시용이군요! 그럼 공개 API로 설계된 것이 맞네요.

권한 검사는 필요 없다는 점 이해했습니다. 다만 기본적인 입력 검증은 여전히 권장합니다:

@GetMapping("/{userId}")
public ResponseEntity<PointResponse> getUserPoint(@PathVariable Long userId) {
    if (userId == null || userId <= 0) {
        return ResponseEntity.badRequest().build();
    }
    int totalPoint = pointService.getTotalPoints(userId);
    return ResponseEntity.ok(new PointResponse(totalPoint));
}

이렇게 하면 잘못된 userId가 들어왔을 때 더 명확한 에러 응답을 줄 수 있어요.

  (\   /)
 ( ._.)
o_(")(")  *understanding hop*

✏️ Learnings added
Learnt from: pokerbearkr
PR: ezcode-my/backend#89
File: src/main/java/org/ezcode/codetest/presentation/ranking/PointController.java:27-31
Timestamp: 2025-06-22T06:01:45.521Z
Learning: PointController의 getUserPoint 엔드포인트는 다른 사용자의 프로필에서 티어 정보를 표시하기 위한 공개 API로, 모든 사용자가 다른 사용자의 점수를 조회할 수 있도록 설계되었다.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.ezcode.codetest.presentation.ranking;

import lombok.RequiredArgsConstructor;
import org.ezcode.codetest.application.ranking.dto.PointResponse;
import org.ezcode.codetest.application.ranking.dto.RankingResponse;
import org.ezcode.codetest.application.ranking.service.RankingFacadeService;
import org.ezcode.codetest.infrastructure.ranking.scheduler.RankingSyncScheduler;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
Expand Down