Conversation
그룹 서비스 및 이미지 서비스가 사용자 ID 직접 참조를 대체하여 인증 및 권한 부여에 CustomUserDetails를 사용하도록 업데이트합니다. 이를 통해 보안이 강화되고 그룹 관리 기능 내에서 사용자 컨텍스트 검색이 간소화됩니다.
|
Caution Review failedThe pull request is closed. Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Walkthrough인증 방식이 JWT 기반 CustomUserDetails로 통일되었습니다. 컨트롤러와 서비스의 사용자 파라미터가 Long userId에서 Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
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. Comment |
There was a problem hiding this comment.
Pull request overview
This PR migrates the group management controllers from using explicit @RequestParam Long userId to using JWT-based authentication via @AuthenticationPrincipal CustomUserDetails. This change enhances security by leveraging authenticated user context instead of trusting user-provided IDs, and simplifies user context retrieval within group management features.
Key changes include:
- Controllers now extract user information from JWT tokens via
@AuthenticationPrincipal - Service methods updated to accept
CustomUserDetailsand extract user IDs internally - Cursor pagination logic improved to properly handle next page calculations
- New dummy test data generation for testing "my groups" search functionality
- HTTP test files updated to remove userId query parameters and use Bearer tokens
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| GroupController.java | Updated all endpoints to use @AuthenticationPrincipal CustomUserDetails instead of userId query param |
| GroupImageController.java | Updated image endpoints to use @AuthenticationPrincipal CustomUserDetails for authentication |
| GroupService.java | Modified methods to accept CustomUserDetails, extract user IDs internally; improved cursor pagination logic |
| GroupImageService.java | Updated to accept CustomUserDetails for permission checks |
| MyGroupsDummyTest.java | New test for generating dummy data to test current/past/my_post group searches |
| GroupCursorDummyTest.java | Updated to use CustomUserDetails and improved date handling |
| group-*.http files | Refactored to use Bearer token authentication, removed userId query parameters |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Content-Type: application/json | ||
|
|
||
| { | ||
| "email": "test@example.com", |
There was a problem hiding this comment.
The email address used in signup ("testj@example.com") does not match the email used in login ("test@example.com"). This will cause login to fail as the user was registered with a different email address.
| "email": "test@example.com", | |
| "email": "testj@example.com", |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/team/wego/wegobackend/group/application/service/GroupImageService.java (1)
140-232: CustomUserDetails 기반 권한 체크는 적절하지만, 이미지 삭제 순서 때문에 S3 정리가 되지 않습니다
updateGroupImages/deleteGroupImages모두에서Long userId대신CustomUserDetails userDetails를 받아group.getHost().getId().equals(userDetails.getId())로 권한을 검사하는 변경은 이번 PR 의 목표와 잘 맞습니다.다만 두 메서드 모두에서 다음과 같은 순서 문제가 있습니다.
- 먼저
group.getImages().clear();로 컬렉션을 비운 뒤- 그 이후
group.getImages().stream()으로oldUrls를 수집하여imageUploadService.deleteAllByUrls(oldUrls)를 호출이렇게 되면 실제로 S3 에 남아 있는 기존 이미지 URL 들은 삭제 대상 리스트에 포함되지 않아, 이미지 엔티티는 삭제되지만 S3 객체는 계속 남는 상태가 됩니다(스토리지 누수 및 잠재적 개인정보 보관 이슈).
기존 코드에서 내려온 문제일 수 있지만, 이번에 touched 된 메서드인 만큼 아래처럼 URL 수집을 먼저 하고, 그 다음에 컬렉션을 clear/flush 하는 순서로 바꾸는 것을 권장합니다.
- // 4. 기존 GroupImage 엔티티들을 관계에서 제거: DB에서도 삭제됨 - group.getImages().clear(); - groupImageRepository.flush(); // DB 즉시 삭제하기 위해 추가 - - // 5. 기존 이미지 URL 수집 -> S3 삭제 - List<String> oldUrls = group.getImages().stream() + // 4. 기존 이미지 URL 수집 -> S3 삭제 + List<String> oldUrls = group.getImages().stream() .map(GroupImage::getImageUrl) .filter(Objects::nonNull) .toList(); imageUploadService.deleteAllByUrls(oldUrls); + + // 5. 기존 GroupImage 엔티티들을 관계에서 제거: DB에서도 삭제됨 + group.getImages().clear(); + groupImageRepository.flush(); // DB 즉시 삭제하기 위해 추가- // 3. 기존 URL들 수집 후 S3 삭제 - group.getImages().clear(); - groupImageRepository.flush(); // DB 즉시 삭제하기 위해 추가 - - List<String> oldUrls = group.getImages().stream() + // 3. 기존 URL들 수집 후 S3 삭제 + List<String> oldUrls = group.getImages().stream() .map(GroupImage::getImageUrl) .filter(Objects::nonNull) .toList(); imageUploadService.deleteAllByUrls(oldUrls); + + group.getImages().clear(); + groupImageRepository.flush(); // DB 즉시 삭제하기 위해 추가이렇게 하면 DB 엔티티 삭제와 S3 객체 삭제가 모두 의도대로 동작하게 됩니다.
Also applies to: 235-262
🧹 Nitpick comments (2)
src/test/http/group/group-create.http (1)
1-27: 여러 HTTP 스크립트에서 동일 테스트 이메일을 재사용하면 signup 단계가 자주 실패할 수 있습니다이 파일과 다른 *.http 스크립트 모두
test@example.com계정을 사용하고 있어, DB 초기화 없이 여러 스크립트를 반복 실행하면 회원가입이 “이미 존재하는 이메일” 오류로 끝날 수 있습니다. 스크립트별로 이메일을 분리하거나, 해당 오류는 무시해도 된다는 주석을 추가해 두면 이후 디버깅 시 혼란을 줄일 수 있습니다.src/test/http/group/group-me.http (1)
140-164: PAST 모임 생성 시나리오의 날짜가 실제로는 미래라 테스트 의도와 다를 수 있습니다2-2 섹션 주석은 endTime 이 과거인 “PAST” 모임 생성을 의도하는 것처럼 보이지만, 현재 설정된
2026-01-10T19:00:00~21:00:00은 지금(2025-12-10 기준) 미래 시점입니다. /api/v1/groups/me?type=past 호출에서 실제로 과거 모임을 확인하고 싶다면, 충분히 과거인 날짜로 조정해 두는 것이 더 명확한 테스트가 될 것 같습니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (18)
src/main/java/team/wego/wegobackend/group/application/service/GroupImageService.java(4 hunks)src/main/java/team/wego/wegobackend/group/application/service/GroupService.java(12 hunks)src/main/java/team/wego/wegobackend/group/presentation/GroupController.java(8 hunks)src/main/java/team/wego/wegobackend/group/presentation/GroupImageController.java(5 hunks)src/test/http/group/attend.http(0 hunks)src/test/http/group/cancel.http(0 hunks)src/test/http/group/create.http(0 hunks)src/test/http/group/get-cursor.http(0 hunks)src/test/http/group/group-attend.http(1 hunks)src/test/http/group/group-cancel.http(1 hunks)src/test/http/group/group-create.http(1 hunks)src/test/http/group/group-delete.http(9 hunks)src/test/http/group/group-get-cursor.http(1 hunks)src/test/http/group/group-me.http(1 hunks)src/test/http/group/group-update.http(10 hunks)src/test/http/group/me.http(0 hunks)src/test/java/team/wego/wegobackend/group/GroupCursorDummyTest.java(7 hunks)src/test/java/team/wego/wegobackend/group/MyGroupsDummyTest.java(1 hunks)
💤 Files with no reviewable changes (5)
- src/test/http/group/me.http
- src/test/http/group/attend.http
- src/test/http/group/create.http
- src/test/http/group/get-cursor.http
- src/test/http/group/cancel.http
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: CodeQL analysis (java)
- GitHub Check: Agent
🔇 Additional comments (21)
src/test/http/group/group-cancel.http (1)
1-186: 그룹 취소 E2E 시나리오가 CustomUserDetails 기반 인증 흐름과 잘 맞습니다회원/호스트 모두 accessToken 으로만 인증을 수행하고 있어, userId 파라미터 제거 및 JWT 기반 권한 체크로 리팩터링된 서버 구현을 실제 플로우로 잘 검증해 줄 수 있어 보입니다.
src/test/java/team/wego/wegobackend/group/MyGroupsDummyTest.java (1)
53-109: CustomUserDetails 를 사용한 내 모임 더미 데이터 생성 플로우가 PR 목적에 잘 부합합니다
getOrCreateUser로 호스트/회원 더미 유저를 만든 뒤CustomUserDetails로 감싸서GroupService.createGroup/attendGroup에 전달하는 구조가 실제 인증 흐름과 동일해, CURRENT/PAST/MY_POST 타입을 모두 커버하는 내 모임 조회 테스트 데이터 준비 용도로 적절해 보입니다.src/test/http/group/group-attend.http (1)
1-146: 참여/중복 참여/호스트 참여 예외 시나리오가 JWT 기반 인증 흐름을 잘 검증합니다참여 관련 모든 요청이 accessToken(Authorization 헤더)만으로 인증되고 있어, userId 파라미터 제거 후 CustomUserDetails 기반으로 변경된 컨트롤러/서비스 구현을 실제 E2E 플로우로 잘 검증해 줄 수 있습니다.
src/test/java/team/wego/wegobackend/group/GroupCursorDummyTest.java (1)
34-37: GroupCursorDummyTest 의 CustomUserDetails 사용과 createGroup 호출 변경이 타당합니다User 를
CustomUserDetails로 감싸고 이를groupService.createGroup(memberDetails, request)에 넘기도록 수정한 부분이 현재 컨트롤러/서비스의 인증 모델과 일치하며, 커서 기반 모임 리스트 조회를 위한 더미 데이터 생성 로직에도 별다른 부작용 없이 잘 녹아 있습니다.Also applies to: 64-82, 85-121
src/test/http/group/group-update.http (3)
1-94: 테스트 흐름이 잘 구성되어 있습니다.HOST 회원가입/로그인 → 이미지 업로드 → 모임 생성 → 수정 시나리오의 흐름이 명확하고,
hostAccessToken및hostUserId변수명이 역할을 잘 표현합니다.
96-202: 수정 권한 테스트 케이스가 잘 구성되어 있습니다.정상 케이스, 최대 인원 검증 (최소값 1명, 최대값 15명), 그리고 비호스트 회원의 수정 시도에 대한 권한 검증까지 주요 시나리오를 커버합니다.
204-331: 이미지 수정 시나리오가 포괄적입니다.기존 이미지 교체, 새 이미지 3장 업로드, 그리고 최대 3장 제한 초과 테스트까지 이미지 관련 엣지 케이스를 잘 다루고 있습니다.
src/test/http/group/group-delete.http (2)
1-93: 삭제 테스트의 기본 설정이 적절합니다.HOST 회원가입/로그인 → 모임 생성 → MEMBER1 참여 순서로 삭제 테스트에 필요한 사전 조건을 잘 구성했습니다.
163-213: 삭제 시나리오 및 검증 테스트가 잘 설계되었습니다.이미지 전체 삭제 → 삭제 확인 → 권한 없는 회원의 삭제 시도 → 모임 삭제 → 삭제된 모임 조회/참여 실패 확인까지 완전한 삭제 플로우를 검증합니다.
src/main/java/team/wego/wegobackend/group/presentation/GroupImageController.java (2)
33-44:uploadImages에서userDetails파라미터가 사용되지 않습니다.
@AuthenticationPrincipal CustomUserDetails userDetails를 선언했지만 실제로groupImageService.uploadGroupImages(images)에 전달하지 않습니다. 의도적인 경우(인증된 사용자만 업로드 허용 목적)라면 괜찮지만, 업로드한 사용자 추적이 필요하다면 서비스 계층에 전달해야 합니다.
46-71:updateGroupImages와deleteGroupImages가 올바르게 구현되었습니다.
CustomUserDetails를 서비스 계층에 전달하여 권한 검증을 수행하도록 잘 변경되었습니다. PR 목표에 부합합니다.src/main/java/team/wego/wegobackend/group/presentation/GroupController.java (3)
34-46:createGroupResponse엔드포인트가 올바르게 업데이트되었습니다.
@AuthenticationPrincipal CustomUserDetails를 통해 인증된 사용자 정보를 받아 서비스에 전달하는 패턴이 잘 적용되었습니다.
74-86: 익명 사용자 접근 처리가 잘 구현되었습니다.
userDetails == null체크를 통해 비로그인 사용자도 모임 상세를 조회할 수 있도록 분기 처리한 점이 좋습니다. 이는 공개 모임 조회에 적절한 패턴입니다.
101-140: 수정/삭제/내 모임 조회 엔드포인트가 일관되게 구현되었습니다.모든 보호된 엔드포인트에서
CustomUserDetails를 통한 인증 정보 접근 패턴이 일관되게 적용되었습니다.src/main/java/team/wego/wegobackend/group/application/service/GroupService.java (7)
121-157:createGroup메서드가 올바르게 리팩토링되었습니다.
CustomUserDetails에서 사용자 ID를 추출하여 HOST 조회에 사용하고, 에러 메시지에도userDetails.getId()를 사용하는 것이 일관됩니다.
232-272:attendGroup메서드의 인증 정보 처리가 적절합니다.회원 조회, 이미 참여 중인지 검증, 응답 생성까지 모든 단계에서
userDetails.getId()를 일관되게 사용합니다.
274-307:cancelAttendGroup의 권한 검증 로직이 올바릅니다.HOST 탈퇴 방지 및 에러 메시지에
userDetails.getId()가 올바르게 사용되었습니다.
321-336: 페이지네이션 로직이 개선되었습니다.
pageContent변수 도입으로 실제 반환할 데이터와 다음 커서 계산이 명확해졌습니다.size+1개 조회 후 마지막 항목의 ID를 커서로 사용하는 패턴이 올바릅니다.
459-477:getGroup오버로드가 깔끔하게 구현되었습니다.인증된 사용자용과 익명 사용자용 메서드를 분리하여
buildGetGroupResponse에 적절한userId(또는null)를 전달합니다.
510-579:updateGroup과deleteGroup의 권한 검증이 올바릅니다.HOST 권한 체크 시
group.getHost().getId().equals(userDetails.getId())비교를 사용하고, 실패 시 적절한 에러 코드와 함께 사용자 ID를 포함합니다.
581-677:getMyGroups및 관련 헬퍼 메서드가 일관되게 구현되었습니다.
CURRENT,MY_POST,PAST타입별 조회 메서드에서 동일한 페이지네이션 패턴을 사용하며,userDetails.getId()를 통해 사용자 ID를 전달합니다.
| ### 2-1. 첫 페이지 (keyword = 스터디) | ||
| GET http://localhost:8080/api/v1/groups?keyword=스터디&size=5 | ||
| Authorization: Bearer {{hostAccessToken}} | ||
|
|
||
| ... | ||
|
|
||
|
|
||
| ### (선택) 로그인 안 한 상태에서 모임 상세 조회 | ||
| GET http://localhost:8080/api/v1/groups/1 | ||
|
|
||
| ### 로그인 후, 현재 유저 기준 참여 상태 포함하여 상세 조회 | ||
| GET http://localhost:8080/api/v1/groups/1 | ||
| Authorization: Bearer {{hostAccessToken}} |
There was a problem hiding this comment.
라인 71의 ... 는 HTTP 클라이언트에서 잘못된 요청으로 해석될 수 있습니다
단독으로 존재하는 ... 줄은 HTTP 메서드로 파싱되어 실행 시 에러를 유발할 수 있으므로, 해당 줄은 제거하거나 주석(### 또는 #)으로 전환하는 편이 안전합니다.
🤖 Prompt for AI Agents
In src/test/http/group/group-get-cursor.http around lines 67 to 79, the
standalone line containing "..." (line 71) can be parsed by HTTP clients as an
invalid request; remove that line or convert it into a comment (prefix with ###
or #) so the file only contains valid HTTP requests and comment markers and will
not be interpreted as a method or cause parsing errors.
📝 Pull Request
📌 PR 종류
해당하는 항목에 체크해주세요.
✨ 변경 내용
모임 컨트롤러에서 @AuthenticationPrincipal CustomUserDetails userDetails, JWT 파싱 정보 받도록 수정합니다.
모임 서비스 및 이미지 서비스가 사용자 ID 직접 참조를 대체하여 인증 및 권한 부여에 CustomUserDetails를 사용하도록 업데이트합니다.
이를 통해 보안이 강화되고 그룹 관리 기능 내에서 사용자 컨텍스트 검색이 간소화됩니다.
내 모임 조회 검색을 위한 더미 데이터 생성 테스트 코드를 추가했습니다.
🔍 관련 이슈
🧪 테스트
변경된 기능에 대한 테스트 범위 또는 테스트 결과를 작성해주세요.
🚨 확인해야 할 사항 (Checklist)
PR을 제출하기 전에 아래 항목들을 확인해주세요.
🙋 기타 참고 사항
리뷰어가 참고하면 좋을 만한 추가 설명이 있다면 적어주세요.
Summary by CodeRabbit
릴리스 노트
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.