Skip to content

Conversation

@changuii
Copy link
Member

@changuii changuii commented Jan 23, 2026

#️⃣ 이슈 번호

#63


🛠️ 작업 내용

  • organization에 속하는 place만 클론 할 수 있도록 변경
    • 기존에 organization에 속하면서, festival에 속하는 place만 조회해야하지만, organization 없이 festival에 속하는 place만 조회되고 있었다.
  • 모든 권한 예외 응답 메시지를 "접근 권한이 없습니다."로 통일
    • 외부인이 API를 호출했을 때 정확히 어떤 권한 문제인지 파악하기 어렵게 수정
  • 파라미터 변수 이름 및 메서드 이름이 organization이 아닌 Festival로 작성되어있던 버그 수정

Summary by CodeRabbit

릴리스 노트

  • 버그 수정
    • 권한 거부 오류 메시지를 전체 애플리케이션에서 통일하여 일관된 사용자 경험 제공
    • 접근 제어 검증 로직 개선으로 조직 단위의 권한 확인 강화
    • 기존 기능 동작 및 HTTP 상태 코드는 변경 없음

✏️ Tip: You can customize this high-level summary in your review settings.

@changuii changuii self-assigned this Jan 23, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

이 PR은 애플리케이션 전반의 인가(authorization) 관련 에러 메시지를 표준화하는 변경입니다. 기존의 조직별로 구체적인 리소스 소유권 메시지(예: "해당 조직의 축제가 아닙니다", "해당 조직의 플레이스가 아닙니다")를 일관된 일반적 메시지 "접근 권한이 없습니다"로 통일합니다. 동시에 PlaceJpaRepositoryfindAllByIdInAndFestivalId 메서드에 organizationId 파라미터를 추가하여 조직 수준의 데이터 검증을 강화하고, 일부 서비스에서 축제 기반 검증을 조직 기반 검증으로 업그레이드합니다. HTTP 상태 코드는 모두 FORBIDDEN으로 유지되며 제어 흐름은 변하지 않습니다.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes


상세 검토 의견

긍정적 측면

변경 사항이 매우 일관성 있게 구성되어 있습니다. 20개 이상의 파일에서 동일한 패턴을 따르고 있으며, 각 테스트 파일도 해당하는 서비스 파일과 함께 동기화되어 있어 일괄적 리팩토링의 추적성이 뛰어납니다.

식별된 한계점 및 고려사항

1. 에러 메시지 표준화의 정보 손실 문제

기존 메시지들이 사용자에게 더 명확한 컨텍스트를 제공했습니다. 예를 들어:

  • ❌ "해당 조직의 축제가 아닙니다" → "접근 권한이 없습니다"
  • 후자는 사용자가 "본인의 조직에 존재하지 않는 리소스인가", "아니면 순수 권한 부족인가"를 구분할 수 없습니다.

개선 제안:

  • 선택지 A: 현재 방식 유지 + API 응답에 더 상세한 에러 코드 추가

    • 장점: 프론트엔드가 상태에 따라 다른 UI 메시지 표시 가능
    • 단점: 추가 필드 구현 필요
  • 선택지 B: 로그 레벨에서는 구체적 메시지 유지

    • 장점: 서버 로그로 문제 진단 용이
    • 단점: 사용자 경험 개선 없음

2. PlaceJpaRepository 메서드 시그니처 변경의 영향 범위

새 파라미터 organizationId 추가로 모든 호출처를 추적해야 합니다. 다행히 이 PR에서 PlaceServicePlaceServiceTest에서 이미 업데이트되었으나:

  • 향후 다른 곳에서 이 메서드를 호출할 경우 컴파일 오류로 즉시 발견되므로 안정성은 확보됨
  • 다만 마이그레이션 과정이 명확하도록 커밋 메시지나 PR 설명에 강조하면 좋습니다

3. validateTimeTagsBelongsToFestival → validateTimeTagsBelongsToOrganization 메서드 리네이밍

이 변경이 의미론적으로 중요한 로직 변경을 반영합니다:

  • 기존: 특정 축제의 시간 태그 검증
  • 신규: 조직 수준의 시간 태그 검증

고려사항:
시간 태그가 정말 조직 수준에서 관리되어야 하는지 확인 필요. 만약 일부 비즈니스 로직에서 축제별 분리가 필요하다면, 이 변경이 의도치 않은 부작용을 낼 수 있습니다.


권장 확인 항목

  1. 통합 테스트 수행: 메시지 변경과 로직 변경이 섞여있으므로, 실제 데이터베이스 환경에서 PlaceJpaRepository의 새 쿼리가 의도대로 조직 필터링을 수행하는지 검증
  2. 하위 호환성: 이 메서드를 사용하는 다른 모듈이 없는지 확인
  3. 문서화: 조직 수준 검증으로의 전환이 설계 의도라면, 주석이나 README에 반영 권장
🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 변경 사항의 핵심을 정확하게 반영하고 있습니다. 도메인 분리 과정의 버그 수정과 예외 메시지 변경이라는 두 가지 주요 목표가 명확하게 드러나 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @changuii, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 축제 관리 시스템의 보안과 일관성을 향상시키는 데 중점을 둡니다. 장소 복제 기능에서 발생할 수 있는 권한 문제를 해결하여, 오직 해당 조직에 속한 장소만이 복제될 수 있도록 보장합니다. 또한, 시스템 전반에 걸쳐 권한 관련 오류 메시지를 일반적인 '접근 권한이 없습니다.'로 통일하여 잠재적인 정보 노출을 방지하고 사용자에게 일관된 경험을 제공합니다.

Highlights

  • 권한 검증 로직 개선: 조직에 속하는 장소만 복제할 수 있도록 PlaceJpaRepositoryfindAllByIdInAndFestivalId 메서드에 organizationId를 추가하여 권한 검증을 강화했습니다. 이로써 잘못된 조직의 장소가 복제되는 버그를 수정했습니다.
  • 예외 메시지 통일: 모든 권한 관련 예외 응답 메시지를 '접근 권한이 없습니다.'로 통일했습니다. 이는 외부 사용자가 API 호출 시 정확한 권한 문제를 파악하기 어렵게 하여 보안을 강화하기 위함입니다.
  • 메서드 및 파라미터 이름 수정: PlaceServicevalidateTimeTagsBelongsToFestival 메서드 이름을 validateTimeTagsBelongsToOrganization으로 변경하고 관련 파라미터도 festivalId 대신 organizationId를 사용하도록 수정하여, organization 도메인 분리 과정에서 발생한 명명 오류를 바로잡았습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

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

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 focuses on enhancing the security and clarity of the application by standardizing exception messages and refining the logic for place cloning. The primary change involves replacing specific, potentially revealing exception messages with a generic "접근 권한이 없습니다." (Access Denied) message to prevent external observers from gaining insights into the system's internal authorization mechanisms. Additionally, the place cloning functionality is improved to ensure that only places belonging to the same organization are cloned, addressing a bug where places from different organizations could be inadvertently cloned. The changes also include correcting parameter and method names related to Festival, which were incorrectly named as Organization.

private void validateTimeTagBelongsToOrganization(Long timeTagId, Long organizationId) {
if (!timeTagJpaRepository.existsByIdAndFestivalOrganizationId(timeTagId, organizationId)) {
throw new BusinessException("해당 조직의 시간 태그가 아닙니다.", HttpStatus.FORBIDDEN);
throw new BusinessException("접근 권한이 없습니다.", HttpStatus.FORBIDDEN);

Choose a reason for hiding this comment

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

security-medium medium

The exception message is changed to a generic message to avoid exposing internal details. This enhances security by preventing attackers from gaining specific information about authorization failures. Severity: Medium

        if (!timeTagJpaRepository.existsByIdAndFestivalOrganizationId(timeTagId, organizationId)) {
            throw new BusinessException("접근 권한이 없습니다.", HttpStatus.FORBIDDEN);
        }

Copy link
Member Author

Choose a reason for hiding this comment

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

앞으로 이렇게 하기로 정했으니까 학습해

Copy link
Member

@soeun2537 soeun2537 left a comment

Choose a reason for hiding this comment

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

ㅋㅋㅋ 고생하셨어요 ㅎㅎ 화이팅..

"AND p.festival.id = :festivalId " +
"AND p.festival.organization.id = :organizationId")
List<Place> findAllByIdInAndFestivalId(
@Param("placeIds") Collection<Long> places,
Copy link
Member

Choose a reason for hiding this comment

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

오 Collection으로 받는군요..

Comment on lines +16 to +21
@Query("SELECT p FROM Place p " +
"WHERE p.id IN (:placeIds) " +
"AND p.festival.id = :festivalId " +
"AND p.festival.organization.id = :organizationId")
List<Place> findAllByIdInAndFestivalId(
@Param("placeIds") Collection<Long> places,
Copy link
Member

Choose a reason for hiding this comment

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

요게 그때 festivalId -> organizationId로 변경해야 하는 것 때문에 수정하신건가요?

Copy link
Member Author

Choose a reason for hiding this comment

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

네 그때, organization에 포함되어있고, festival에도 포함되어 있는 Place를 조회해와야해요

  • festival만 검증하면 organization에 속하지 않는 다른 festival을 제공했을 때 검증을 통과해요

@changuii changuii merged commit ca23bb5 into refactor/63 Jan 27, 2026
8 checks passed
@changuii changuii deleted the refactor/63-1 branch January 27, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants