Skip to content

[FEAT] 비회원용 테이블정보 조회 메서드 추가#257

Merged
unifolio0 merged 3 commits into
developfrom
feat/#256-audience-api
Jul 2, 2026
Merged

[FEAT] 비회원용 테이블정보 조회 메서드 추가#257
unifolio0 merged 3 commits into
developfrom
feat/#256-audience-api

Conversation

@coli-geonwoo

@coli-geonwoo coli-geonwoo commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

🚩 연관 이슈

closed #256

🗣️ 리뷰 요구사항 (선택)

웹소켓 통신과정에서 비회원의 경우에도 토론 테이블 정보를 조회하기 위한 Rest API가 필요해져 이를 추가합니다.

Summary by CodeRabbit

  • New Features

    • 지정된 테이블을 조회하는 새 공개 API가 추가되었습니다.
    • 조회 결과로 사용자 지정 테이블 정보와 시간박스 목록을 반환합니다.
  • Bug Fixes

    • 테이블 조회 시 존재하지 않는 ID에 대해 적절한 오류가 반환되도록 개선했습니다.
    • 회원 기준 조회와 비회원 기준 조회 경로를 분리해 응답 일관성을 높였습니다.
  • Tests

    • 새 조회 API와 기존 조회 흐름에 대한 테스트 및 문서 검증이 추가/갱신되었습니다.

@coli-geonwoo coli-geonwoo linked an issue Jun 29, 2026 that may be closed by this pull request
@unifolio0 unifolio0 added the feat 기능 추가 label Jun 29, 2026
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

비회원이 테이블 ID만으로 커스텀 토론 시간표를 조회할 수 있도록 SharingRestController에 GET 엔드포인트를 추가했습니다. 기존 멤버 기반 조회 메서드를 findMemberTable/getMemberCustomizeTimeBoxes로 이름을 변경하고, 비회원용 findTable(tableId)getCustomizeTimeBoxes(tableId)를 새로 도입했습니다.

Changes

비회원용 커스텀 테이블 조회 API

Layer / File(s) Summary
레포지토리 조회 메서드 추가
src/main/java/com/debatetimer/repository/customize/CustomizeTableRepository.java, src/main/java/com/debatetimer/domainrepository/customize/CustomizeTableDomainRepository.java
CustomizeTableRepositoryTABLE_NOT_FOUND 예외를 던지는 getById 기본 메서드를 추가하고, CustomizeTableDomainRepositorygetById, getMemberCustomizeTimeBoxes(멤버 기반), getCustomizeTimeBoxes(비회원 기반) 세 메서드를 추가합니다.
서비스 메서드 분리
src/main/java/com/debatetimer/service/customize/CustomizeService.java
멤버 기반 조회를 findMemberTable로 이름을 변경하고 getMemberCustomizeTimeBoxes를 사용하도록 수정하며, 비회원용 findTable(tableId)를 새로 도입합니다. updateUsedAt 내부 호출도 getMemberCustomizeTimeBoxes로 변경됩니다.
컨트롤러 엔드포인트 연결
src/main/java/com/debatetimer/controller/customize/CustomizeController.java, src/main/java/com/debatetimer/controller/sharing/SharingRestController.java
CustomizeControllergetTable 호출을 findMemberTable로 교체하고, SharingRestController/api/live/table/customize/{tableId} GET 엔드포인트를 추가합니다.
테스트 업데이트 및 신규 테스트 추가
src/test/java/com/debatetimer/controller/customize/CustomizeDocumentTest.java, src/test/java/com/debatetimer/service/customize/CustomizeServiceTest.java, src/test/java/com/debatetimer/domainrepository/customize/CustomizeTableDomainRepositoryTest.java, src/test/java/com/debatetimer/controller/sharing/SharingDocumentTest.java, src/test/java/com/debatetimer/controller/sharing/SharingRestControllerTest.java
기존 테스트의 모킹 호출을 findMemberTable/getMemberCustomizeTimeBoxes로 교체하고, SharingDocumentTest에 REST Docs 테스트를 추가하며, SharingRestControllerTest로 통합 테스트를 추가합니다.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • debate-timer/debate-timer-be#184: CustomizeTableRepository에 멤버 포함 단건 조회(getByIdAndMember) 및 관련 서비스 조회 로직을 리팩토링한 PR으로, 이번 PR의 getById 추가 및 멤버 기반 조회 분리와 동일한 코드 경로를 공유합니다.
  • debate-timer/debate-timer-be#214: CustomizeTableDomainRepository의 타임박스 변환 로직을 변경한 PR으로, 이번 PR의 getMemberCustomizeTimeBoxes/getCustomizeTimeBoxes 분리와 같은 파일을 수정합니다.

Suggested reviewers

  • unifolio0
  • leegwichan
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 비회원용 테이블 정보 조회 기능 추가라는 핵심 변경을 정확히 요약합니다.
Description check ✅ Passed 필수 연관 이슈와 리뷰 요구사항 섹션이 포함되어 있고, #256 링크와 목적 설명도 충족합니다.
Linked Issues check ✅ Passed 비회원이 테이블 정보를 조회할 수 있는 새 API와 서비스/리포지토리 경로가 #256의 요구를 충족합니다.
Out of Scope Changes check ✅ Passed 테스트와 호출 경로 변경은 새 비회원 조회 API를 지원하는 범위 안에 있으며 별도 무관 변경은 보이지 않습니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#256-audience-api

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

Test Results

145 files  145 suites   20s ⏱️
307 tests 307 ✅ 0 💤 0 ❌
319 runs  319 ✅ 0 💤 0 ❌

Results for commit 1088eae.

@github-actions

Copy link
Copy Markdown

📝 Test Coverage Report

Overall Project 89.41% 🍏
Files changed 100% 🍏

File Coverage
CustomizeTableRepository.java 100% 🍏
SharingRestController.java 100% 🍏
CustomizeController.java 100% 🍏
CustomizeTableDomainRepository.java 100% 🍏
CustomizeService.java 100% 🍏

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new API endpoint /api/live/table/customize/{tableId} to allow non-members to retrieve customized debate tables, along with the necessary service, repository, and test updates. The review feedback highlights a critical security vulnerability (IDOR/BOLA) due to the use of sequential IDs for the public endpoint, recommending the use of non-sequential identifiers like UUIDs or sharing status validation. Additionally, there is an opportunity to reduce code duplication in CustomizeTableDomainRepository by extracting common time box retrieval logic into a private helper method.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +33 to +39
@GetMapping("/api/live/table/customize/{tableId}")
@ResponseStatus(HttpStatus.OK)
public CustomizeTableResponse getTable(
@PathVariable long tableId
) {
return customizeService.findTable(tableId);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-high high

비회원용 토론 테이블 정보를 조회하기 위해 인증 없이 접근 가능한 /api/live/table/customize/{tableId} 엔드포인트를 추가하셨습니다.

하지만 tableId가 순차적인 long 타입(Sequential ID)이기 때문에, 악의적인 사용자가 ID를 1씩 증가시키며 API를 호출(IDOR/BOLA 공격)할 경우 시스템에 등록된 모든 회원의 커스텀 토론 테이블 정보를 무단으로 조회(Scraping)할 수 있는 심각한 보안 취약점이 존재합니다.

권장 해결 방안:

  1. 비순차적 식별자(UUID 등) 사용: 외부 공유용 API에서는 순차적인 DB PK 대신 예측 불가능한 UUID나 별도의 공유용 토큰(Share Token)을 식별자로 사용하도록 설계합니다.
  2. 공유 상태 검증: 테이블 엔티티에 공유 활성화 여부(예: isShared 또는 status 등)를 나타내는 필드를 추가하고, 비회원 조회 시 해당 테이블이 실제로 공유 가능한 상태인지 검증하는 로직을 추가합니다.

Comment on lines +63 to +76
public List<CustomizeTimeBox> getMemberCustomizeTimeBoxes(long tableId, Member member) {
CustomizeTableEntity tableEntity = tableRepository.getByIdAndMember(tableId, member);
List<CustomizeTimeBoxEntity> timeBoxEntityList = timeBoxRepository.findAllByCustomizeTable(tableEntity);
List<BellEntity> bellEntityList = bellRepository.findAllByCustomizeTimeBoxIn(timeBoxEntityList);
return toCustomizeTimeBoxes(timeBoxEntityList, bellEntityList);
}

@Transactional(readOnly = true)
public List<CustomizeTimeBox> getCustomizeTimeBoxes(long tableId) {
CustomizeTableEntity tableEntity = tableRepository.getById(tableId);
List<CustomizeTimeBoxEntity> timeBoxEntityList = timeBoxRepository.findAllByCustomizeTable(tableEntity);
List<BellEntity> bellEntityList = bellRepository.findAllByCustomizeTimeBoxIn(timeBoxEntityList);
return toCustomizeTimeBoxes(timeBoxEntityList, bellEntityList);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

두 메서드(getMemberCustomizeTimeBoxesgetCustomizeTimeBoxes)에서 CustomizeTableEntity를 기반으로 CustomizeTimeBox 목록을 조회하고 변환하는 로직이 완전히 중복되고 있습니다. 공통 로직을 private 헬퍼 메서드로 분리하여 코드의 재사용성과 유지보수성을 높이는 것을 권장합니다.

    @Transactional(readOnly = true)
    public List<CustomizeTimeBox> getMemberCustomizeTimeBoxes(long tableId, Member member) {
        CustomizeTableEntity tableEntity = tableRepository.getByIdAndMember(tableId, member);
        return getCustomizeTimeBoxes(tableEntity);
    }

    @Transactional(readOnly = true)
    public List<CustomizeTimeBox> getCustomizeTimeBoxes(long tableId) {
        CustomizeTableEntity tableEntity = tableRepository.getById(tableId);
        return getCustomizeTimeBoxes(tableEntity);
    }

    private List<CustomizeTimeBox> getCustomizeTimeBoxes(CustomizeTableEntity tableEntity) {
        List<CustomizeTimeBoxEntity> timeBoxEntityList = timeBoxRepository.findAllByCustomizeTable(tableEntity);
        List<BellEntity> bellEntityList = bellRepository.findAllByCustomizeTimeBoxIn(timeBoxEntityList);
        return toCustomizeTimeBoxes(timeBoxEntityList, bellEntityList);
    }

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/com/debatetimer/controller/sharing/SharingRestController.java`:
- Around line 33-39: The getTable endpoint in SharingRestController currently
exposes customizeService.findTable(tableId) using only tableId, which allows
unauthorized lookup; update this flow to require a valid access constraint such
as a share token, live-session verification, or another public identifier before
calling findTable. Keep the controller method and customizeService.findTable as
the main locations to adjust, and ensure the lookup is scoped so anonymous
access cannot fetch arbitrary table data.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 028117d7-2183-4013-8ca9-13dacdde2649

📥 Commits

Reviewing files that changed from the base of the PR and between fe9716d and 1088eae.

📒 Files selected for processing (10)
  • src/main/java/com/debatetimer/controller/customize/CustomizeController.java
  • src/main/java/com/debatetimer/controller/sharing/SharingRestController.java
  • src/main/java/com/debatetimer/domainrepository/customize/CustomizeTableDomainRepository.java
  • src/main/java/com/debatetimer/repository/customize/CustomizeTableRepository.java
  • src/main/java/com/debatetimer/service/customize/CustomizeService.java
  • src/test/java/com/debatetimer/controller/customize/CustomizeDocumentTest.java
  • src/test/java/com/debatetimer/controller/sharing/SharingDocumentTest.java
  • src/test/java/com/debatetimer/controller/sharing/SharingRestControllerTest.java
  • src/test/java/com/debatetimer/domainrepository/customize/CustomizeTableDomainRepositoryTest.java
  • src/test/java/com/debatetimer/service/customize/CustomizeServiceTest.java

Comment on lines +33 to +39
@GetMapping("/api/live/table/customize/{tableId}")
@ResponseStatus(HttpStatus.OK)
public CustomizeTableResponse getTable(
@PathVariable long tableId
) {
return customizeService.findTable(tableId);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

비회원 조회를 tableId 단독으로 열지 마세요.

Line 33-39는 인증·공유 토큰·라이브 세션 검증 없이 customizeService.findTable(tableId)를 호출합니다. 현재 이 경로는 서비스/도메인 레이어에서 getById(tableId)getCustomizeTimeBoxes(tableId)로 바로 이어지므로, 웹소켓 참가 맥락과 무관하게 tableId만 알면 임의의 사용자 지정 테이블 내용을 조회할 수 있습니다. 비회원 조회가 필요하더라도 공개용 식별자나 세션/공유 토큰 검증으로 범위를 제한하는 편이 안전합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/debatetimer/controller/sharing/SharingRestController.java`
around lines 33 - 39, The getTable endpoint in SharingRestController currently
exposes customizeService.findTable(tableId) using only tableId, which allows
unauthorized lookup; update this flow to require a valid access constraint such
as a share token, live-session verification, or another public identifier before
calling findTable. Keep the controller method and customizeService.findTable as
the main locations to adjust, and ensure the lookup is scoped so anonymous
access cannot fetch arbitrary table data.

@leegwichan leegwichan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/noti approve 합니다

@unifolio0 unifolio0 merged commit cf2f750 into develop Jul 2, 2026
10 checks passed
@unifolio0 unifolio0 deleted the feat/#256-audience-api branch July 2, 2026 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 비회원용 테이블 정보 조회 메서드 추가

4 participants