부모 티켓
3개 티켓

백로그

0
티켓 없음

할 일

0
티켓 없음

진행 중

0
티켓 없음

리뷰

0
티켓 없음

완료 (15일)

3
긴급 02012328
서브 티켓 코드 품질 일괄 개선 (CSRF + N+1 + IDOR)

API CSRF 보호 수정 + 테스트 강화

## 목표 api/bible/highlights_controller.rb의 CSRF 보호를 명시적으로 강화하고 테스트 추가 ## 수정 내용 1. ApplicationController 확인: protect_from_forgery가 활성화되어 있는지 검증 2. api/bible/highlights_controller.rb에 skip_before_action :verify_authenticity_token이 없는지 확인 (없으면 OK) 3. test/controllers/api/bible/highlights_controller_test.rb에 CSRF 토큰 없이 POST/DELETE 시 거부되는지 테스트 추가 4. app/javascript/controllers/bible_passage_controller.js의 fetch 호출이 X-CSRF-Token 헤더를 올바르게 전송하는지 확인 ## 담당 파일 (이 파일들만 수정) - app/controllers/api/bible/highlights_controller.rb - test/controllers/api/bible/highlights_controller_test.rb - app/javascript/controllers/bible_passage_controller.js (필요시만) ## 완료 기준 - CSRF 토큰 없는 POST/DELETE 요청이 422로 거부됨 (테스트 검증) - 기존 테스트 전체 통과 - bin/rails test 실행 결과 0 failures, 0 errors

C
csrf-dev
8 days
높음 1173c5e4
서브 티켓 코드 품질 일괄 개선 (CSRF + N+1 + IDOR)

QT 세션 N+1 쿼리 최적화

## 목표 qt/sessions_controller.rb의 N+1 쿼리 3건 해결 ## 수정 내용 ### 1. members 액션 (L84-101) - 문제: @participants.map에서 각 participant.user.user_meditations → N+1 - 해결: SQL 집계 쿼리로 변환 (COUNT 서브쿼리 또는 joins + group) ```ruby # 예시 접근법 meditations = UserMeditation.joins(:qt_content) .where(qt_contents: { qt_theme_id: theme.id }) .where(user_id: @participants.select(:user_id)) .group(:user_id) .select("user_id, COUNT(*) as total_count, COUNT(CASE WHEN personal_meditation IS NOT NULL AND personal_meditation != '' THEN 1 END) as completed_count") ``` ### 2. rankings 액션 (L103-153) - 문제: users.map에서 각 유저별 meditations, completed, shared, tongtok = N*4+1 - 해결: SQL 집계 쿼리 1개로 4개 통계를 한번에 조회 ```ruby # 예시: 한 번의 쿼리로 모든 통계 집계 stats = UserMeditation.joins(:qt_content) .where(qt_contents: { qt_theme_id: theme.id }) .where(user_id: participant_user_ids) .group(:user_id) .select("user_id, COUNT(*) as meditation_count, COUNT(CASE WHEN personal_meditation IS NOT NULL AND personal_meditation != '' THEN 1 END) as completed_count, COUNT(CASE WHEN is_personal_meditation_shared = 1 THEN 1 END) as shared_count, COUNT(CASE WHEN is_tongtok_completed = 1 THEN 1 END) as tongtok_count") ``` ### 3. _session_card.html.erb:5 - 문제: session.qt_participants.size → 이미 index에서 includes(:qt_participants) 있으므로 .size 사용 시 메모리에서 계산됨 - 확인: index 액션의 includes에 :qt_participants가 포함되어 있는지 확인. @my_sessions에는 없으므로 추가 필요: ```ruby @my_sessions = current_user.qt_sessions.includes(:qt_theme, :creator, :qt_participants).order(created_at: :desc) ``` ## 담당 파일 (이 파일들만 수정) - app/controllers/qt/sessions_controller.rb (members, rankings, index 액션) - test/controllers/qt/sessions_controller_test.rb (기존 테스트 유지 + 최적화 검증) ## 완료 기준 - N+1 쿼리 3건 모두 제거 - members/rankings 액션이 참여자 수에 관계없이 고정 횟수 쿼리 실행 - bin/rails test 실행 결과 0 failures, 0 errors

N
n1-dev
8 days
보통 4e80e385
서브 티켓 코드 품질 일괄 개선 (CSRF + N+1 + IDOR)

QT 세션 IDOR 접근 제어 + select 참여자 검증

## 목표 비참여자의 비공개 세션 접근 차단 + select 액션 참여자 확인 ## 수정 내용 ### 1. before_action :verify_participant 추가 - 적용 대상: show, shared_meditations, members, rankings - 로직: - is_public이면 허용 - 아니면 @session.qt_participants.exists?(user: current_user) 확인 - 비참여자면 redirect_to qt_sessions_path, alert: "비공개 플랜입니다." ### 2. select 액션 참여자 검증 ```ruby def select unless @session.qt_participants.exists?(user: current_user) redirect_to qt_sessions_path, alert: "참여 중인 플랜만 선택할 수 있습니다." return end ensure_user_setting.update!(current_session_id: @session.id) redirect_to root_path, notice: "#{@session.title} 플랜으로 전환했습니다." end ``` ### 3. 테스트 추가 - 비참여자가 비공개 세션에 접근 시 리다이렉트 확인 - 참여자가 비공개 세션에 접근 시 정상 응답 확인 - 공개 세션은 비참여자도 접근 가능 확인 - select 액션: 비참여자 → 리다이렉트, 참여자 → 정상 작동 ## 담당 파일 (이 파일들만 수정) - app/controllers/qt/sessions_controller.rb (verify_participant, select 수정) - test/controllers/qt/sessions_controller_test.rb (IDOR 테스트 추가) ## 주의사항 - n1-dev 에이전트도 같은 파일(qt/sessions_controller.rb)을 수정합니다 - **이 에이전트는 private 메서드 영역과 select/show 등 액션의 접근 제어만 수정합니다** - members, rankings 액션의 쿼리 로직은 건드리지 마세요 (n1-dev 담당) - before_action 라인과 private 메서드, select 액션만 수정하세요 ## 완료 기준 - 비참여자 비공개 세션 접근 차단 (리다이렉트) - select 액션 참여자 검증 - 테스트 추가 + bin/rails test 0 failures, 0 errors

I
idor-dev
8 days