Skip to content

Feat: [FN-329] 내 권한 조회#17

Merged
stoneTiger0912 merged 3 commits intomainfrom
feat/my-permission-info
Mar 1, 2026
Merged

Feat: [FN-329] 내 권한 조회#17
stoneTiger0912 merged 3 commits intomainfrom
feat/my-permission-info

Conversation

@stoneTiger0912
Copy link
Member

@stoneTiger0912 stoneTiger0912 commented Mar 1, 2026

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 그룹 내 사용자 권한 조회 기능이 추가되었습니다. 사용자가 자신의 역할과 관련 권한 목록을 조회할 수 있습니다.
  • Bug Fixes

    • 권한 변경 API의 응답 타입이 개선되었습니다.
  • Chores

    • API 엔드포인트 경로 구조가 재정리되었습니다.

@stoneTiger0912 stoneTiger0912 self-assigned this Mar 1, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 1, 2026

Walkthrough

사용자의 그룹 내 역할과 권한을 조회하는 새로운 MyPermission 엔드포인트를 추가합니다. PermissionController의 기본 경로를 /v1/groups/{groupId}/permissions으로 변경하고, 관련 서비스, 레포지토리 메서드, 커맨드 및 결과 DTO를 도입합니다.

Changes

Cohort / File(s) Summary
Controller & Routing
src/main/java/flipnote/group/adapter/in/web/PermissionController.java
기본 경로를 /v1/groups/{groupId}에서 /v1/groups/{groupId}/permissions으로 변경. MyPermissionUseCase 의존성 추가. 새로운 GET 엔드포인트 findMyPermission 추가로 사용자의 역할 및 권한 반환. 기존 엔드포인트 매핑을 새로운 기본 경로에 맞게 조정 (@PostMapping, @DeleteMapping 경로 수정).
Port & Interface Definitions
src/main/java/flipnote/group/application/port/in/MyPermissionUseCase.java, src/main/java/flipnote/group/application/port/in/command/MyPermissionCommand.java, src/main/java/flipnote/group/application/port/in/result/MyPermissionResult.java, src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java, src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java
MyPermission 조회를 위한 새로운 유스케이스, 커맨드, 결과 타입 정의. 레포지토리 포트에 findMyRolefindMyRolePermission 메서드 추가.
Service Implementation
src/main/java/flipnote/group/application/service/MyPermissionService.java
MyPermissionUseCase를 구현하는 새로운 서비스. 사용자의 역할을 조회하고 해당 역할의 권한을 반환하는 읽기 전용 작업 수행.
Repository Adapters
src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java, src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java
GroupMemberRepositoryAdapter에 findMyRole 메서드 추가. GroupRoleRepositoryAdapter에 특정 역할의 권한을 조회하는 findMyRolePermission 메서드 추가.
Response DTO
src/main/java/flipnote/group/api/dto/response/MyPermissionResponseDto.java
사용자의 역할과 권한 목록을 포함하는 새로운 응답 DTO. MyPermissionResult로부터 변환하는 팩토리 메서드 제공.
Cleanup
src/main/java/flipnote/group/application/service/RemovePermissionService.java
사용하지 않는 import 제거 (AddPermissionResult).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller as PermissionController
    participant Service as MyPermissionService
    participant MemberRepo as GroupMemberRepository
    participant RoleRepo as GroupRoleRepository

    Client->>Controller: GET /v1/groups/{groupId}/permissions
    Note over Controller: X-USER-ID, groupId
    
    Controller->>Service: findMyPermission(command)
    Note over Service: groupId, userId
    
    Service->>MemberRepo: findMyRole(groupId, userId)
    activate MemberRepo
    MemberRepo-->>Service: GroupMemberEntity
    deactivate MemberRepo
    
    Service->>RoleRepo: findMyRolePermission(groupId, role)
    activate RoleRepo
    RoleRepo-->>Service: List<GroupPermission>
    deactivate RoleRepo
    
    Service-->>Controller: MyPermissionResult
    Note over Controller: role, permissions
    
    Controller-->>Client: ResponseEntity<MyPermissionResponseDto>
    Note over Client: HTTP 200 with role & permissions
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 새로운 권한 조회 기능이 생겼네,

사용자의 역할과 권한을 한눈에 볼 수 있어.

깔끔한 인터페이스로 재설계되고,

서비스에서 데이터베이스까지 순서대로 흘러간다네! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% 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 PR 제목은 주요 변경사항을 명확하게 설명합니다. '내 권한 조회' 기능이 추가되었으며, 이는 raw_summary에서 확인할 수 있는 MyPermissionUseCase, MyPermissionService, PermissionController의 새로운 엔드포인트 추가와 정확히 일치합니다.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/my-permission-info

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (6)
src/main/java/flipnote/group/application/port/in/result/MyPermissionResult.java (1)

8-14: 리스트 불변성 보강을 권장합니다.

Line 10/Line 13에서 permissions를 그대로 보관하면 가변 리스트 유입 시 결과 객체가 외부 변경에 노출될 수 있습니다. record 생성 시 List.copyOf(...)로 고정해 두는 편이 안전합니다.

보강 예시
 public record MyPermissionResult(
 	GroupMemberRole role,
 	List<GroupPermission> permissions
 ) {
+	public MyPermissionResult {
+		permissions = List.copyOf(permissions);
+	}
+
 	public static MyPermissionResult of(GroupMemberRole role, List<GroupPermission> permissions) {
 		return new MyPermissionResult(role, permissions);
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/flipnote/group/application/port/in/result/MyPermissionResult.java`
around lines 8 - 14, The MyPermissionResult record currently stores the incoming
mutable permissions list as-is which can lead to external mutation; update the
record to defensively copy the list (e.g., use List.copyOf) when constructing
instances—either add a canonical/compact constructor in MyPermissionResult that
assigns permissions = List.copyOf(permissions) or modify the static factory
MyPermissionResult.of(GroupMemberRole role, List<GroupPermission> permissions)
to pass List.copyOf(permissions) into the record so the internal permissions are
immutable.
src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java (1)

15-15: 메서드명과 반환 타입의 의미를 맞춰 주세요.

Line 15의 findMyRole은 “역할 조회”로 읽히는데 반환은 GroupMemberEntity라 계약 의도가 모호합니다. findMyMembership처럼 이름을 맞추거나, 실제 필요한 값이 역할이면 반환 타입을 더 좁히는 편이 유지보수에 유리합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java`
at line 15, The interface method GroupMemberRepositoryPort.findMyRole has a
misleading name/return type mismatch: rename the method to findMyMembership (or
similar) if it should return the full GroupMemberEntity, or change its return
type to the narrower role type (e.g., GroupRole or Role) if only the role is
required; update the interface declaration, all implementations of
GroupMemberRepositoryPort, and any callers/tests to use the new method name or
return type (ensure method signatures like findMyMembership(Long groupId, Long
userId) or findMyRole(Long groupId, Long userId): GroupRole are consistently
applied).
src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java (1)

83-85: 조회 실패 예외를 도메인 의미에 맞게 분리해 주세요.

Line 84의 IllegalArgumentException("entity not exist")는 “요청 인자 오류”로 오해되기 쉽습니다. 그룹 멤버 미존재는 not-found/권한 예외로 분리하면 API 계층에서 404/403 매핑을 더 명확히 가져갈 수 있습니다.

예시 수정안
- () -> new IllegalArgumentException("entity not exist")
+ () -> new GroupMemberNotFoundException(groupId, userId)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java`
around lines 83 - 85, 현재 GroupMemberRepositoryAdapter에서
groupMemberRepository.findByGroupIdAndUserId(...) 실패 시
IllegalArgumentException("entity not exist")를 던지는데, 이건 요청 인자 오류로 오해되므로 도메인 의미에
맞는 예외로 분리하세요: 실패 시 GroupMemberNotFoundException(또는 GroupMemberNotFoundInGroup)
같은 커스텀 예외를 생성하여 GroupMemberRepositoryAdapter에서 던지도록 바꾸고, 호출부(API/서비스 레이어)가 이 예외를
404/권한 예외로 매핑하도록 처리하세요; 관련 식별자는 GroupMemberRepositoryAdapter,
groupMemberRepository.findByGroupIdAndUserId, GroupMemberEntity입니다.
src/main/java/flipnote/group/adapter/in/web/PermissionController.java (2)

64-64: 메서드명과 실제 동작 의미를 맞추는 것이 좋겠습니다.

Line 64의 changeDownPermission은 삭제 동작(removePermission)을 수행하므로 이름을 맞추면 읽기성이 좋아집니다.

✏️ 제안 수정안
-	public ResponseEntity<RemovePermissionResponseDto> changeDownPermission(
+	public ResponseEntity<RemovePermissionResponseDto> removeDownPermission(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/flipnote/group/adapter/in/web/PermissionController.java` at
line 64, The method name changeDownPermission in PermissionController does not
reflect its delete behavior; rename the method to removePermission to match the
action (and keep the return type RemovePermissionResponseDto), update the
controller method signature and any `@RequestMapping/`@DeleteMapping annotations
if present, and refactor all internal references (calls from services,
unit/integration tests, and any places using
PermissionController.changeDownPermission) to the new name to preserve
compile-time correctness and readability.

100-100: TODO 항목은 이슈로 추적 전환을 권장합니다.

Line 100 TODO가 남아 있어 누락될 수 있습니다. 원하시면 제가 작업 단위를 이슈 형태로 정리해드릴게요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/flipnote/group/adapter/in/web/PermissionController.java` at
line 100, The inline TODO comment "//todo 가입 신청 허가" in PermissionController
should be converted into tracked work: create an issue/ticket describing "가입 신청
허가" (permission approval flow) and any acceptance criteria, then update the code
in PermissionController to either remove the bare TODO or replace it with a
brief comment that references the new issue ID (e.g., "TODO: see ISSUE-123 for
구현 details") so the task isn't lost; ensure the comment references
PermissionController and the relevant method name where the TODO was (or add a
// TODO with the issue ID and a one-line summary) before committing.
src/main/java/flipnote/group/application/service/MyPermissionService.java (1)

8-13: 애플리케이션 계층이 Adapter 엔티티에 직접 의존하고 있습니다.

Line 8에서 MyPermissionServiceflipnote.group.adapter.out.entity.GroupMemberEntity를 직접 참조해 포트 경계가 약해집니다. 포트가 도메인 모델(또는 전용 조회 DTO)을 반환하도록 맞추는 쪽이 유지보수에 유리합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/flipnote/group/application/service/MyPermissionService.java`
around lines 8 - 13, MyPermissionService currently imports and uses the adapter
entity GroupMemberEntity, breaking the port boundary; change
GroupMemberRepositoryPort (and any calls in GroupRoleRepositoryPort if relevant)
to return a domain model or a dedicated DTO instead of the adapter entity,
remove the direct import of flipnote.group.adapter.out.entity.GroupMemberEntity
from MyPermissionService, and update MyPermissionService to consume the domain
model/DTO (e.g., MyPermissionCommand -> MyPermissionResult logic) so mapping
from GroupMemberEntity happens inside the adapter implementation (adapter maps
entity -> domain/DTO before returning). Ensure method signatures on
GroupMemberRepositoryPort and any usages in MyPermissionService are updated
accordingly and that the adapter layer performs the entity-to-domain/DTO
conversion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java`:
- Around line 196-198: The exception message thrown by
groupRoleRepository.findByGroupIdAndRole in GroupRoleRepositoryAdapter
(RoleEntity roleEntity = ... .orElseThrow(...)) incorrectly says "not exists
member"; update the IllegalArgumentException message to reflect the actual
failure (role not found) — e.g., use a message like "role does not exist for
group" or "role not found" when throwing from the orElseThrow in the RoleEntity
lookup so logs correctly indicate a missing role rather than a missing member.

In
`@src/main/java/flipnote/group/application/port/in/command/MyPermissionCommand.java`:
- Around line 3-6: MyPermissionCommand currently accepts a client-supplied
userId which allows header spoofing; remove userId from the public API and
populate the authenticated user ID server-side from the security context.
Specifically: stop reading X-USER-ID into MyPermissionCommand (remove the userId
parameter or make it internal), and instead obtain the user id via
`@AuthenticationPrincipal` (or
SecurityContextHolder.getContext().getAuthentication()) in the controller or a
factory method that constructs MyPermissionCommand using the authenticated
principal’s id; update any usages that construct MyPermissionCommand to use that
server-derived id rather than a request header.

In `@src/main/java/flipnote/group/application/service/MyPermissionService.java`:
- Around line 28-32: The code calls
groupMemberRepository.findMyRole(cmd.groupId(), cmd.userId()) and immediately
dereferences groupMember which can cause NPE for non-members or missing roles;
update the service (around GroupMemberEntity groupMember, findMyRolePermission
and MyPermissionResult.of usage) to null-check the returned GroupMemberEntity
(and its role) and throw a clear domain exception (e.g., NotMemberException or
IllegalArgumentException) when absent; ensure you guard calls to
groupRoleRepository.findMyRolePermission(groupMember.getGroupId(),
groupMember.getRole().getRole()) and MyPermissionResult.of(...) behind that
validation so the method returns a controlled error instead of allowing a
NullPointerException.

---

Nitpick comments:
In `@src/main/java/flipnote/group/adapter/in/web/PermissionController.java`:
- Line 64: The method name changeDownPermission in PermissionController does not
reflect its delete behavior; rename the method to removePermission to match the
action (and keep the return type RemovePermissionResponseDto), update the
controller method signature and any `@RequestMapping/`@DeleteMapping annotations
if present, and refactor all internal references (calls from services,
unit/integration tests, and any places using
PermissionController.changeDownPermission) to the new name to preserve
compile-time correctness and readability.
- Line 100: The inline TODO comment "//todo 가입 신청 허가" in PermissionController
should be converted into tracked work: create an issue/ticket describing "가입 신청
허가" (permission approval flow) and any acceptance criteria, then update the code
in PermissionController to either remove the bare TODO or replace it with a
brief comment that references the new issue ID (e.g., "TODO: see ISSUE-123 for
구현 details") so the task isn't lost; ensure the comment references
PermissionController and the relevant method name where the TODO was (or add a
// TODO with the issue ID and a one-line summary) before committing.

In
`@src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java`:
- Around line 83-85: 현재 GroupMemberRepositoryAdapter에서
groupMemberRepository.findByGroupIdAndUserId(...) 실패 시
IllegalArgumentException("entity not exist")를 던지는데, 이건 요청 인자 오류로 오해되므로 도메인 의미에
맞는 예외로 분리하세요: 실패 시 GroupMemberNotFoundException(또는 GroupMemberNotFoundInGroup)
같은 커스텀 예외를 생성하여 GroupMemberRepositoryAdapter에서 던지도록 바꾸고, 호출부(API/서비스 레이어)가 이 예외를
404/권한 예외로 매핑하도록 처리하세요; 관련 식별자는 GroupMemberRepositoryAdapter,
groupMemberRepository.findByGroupIdAndUserId, GroupMemberEntity입니다.

In
`@src/main/java/flipnote/group/application/port/in/result/MyPermissionResult.java`:
- Around line 8-14: The MyPermissionResult record currently stores the incoming
mutable permissions list as-is which can lead to external mutation; update the
record to defensively copy the list (e.g., use List.copyOf) when constructing
instances—either add a canonical/compact constructor in MyPermissionResult that
assigns permissions = List.copyOf(permissions) or modify the static factory
MyPermissionResult.of(GroupMemberRole role, List<GroupPermission> permissions)
to pass List.copyOf(permissions) into the record so the internal permissions are
immutable.

In
`@src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java`:
- Line 15: The interface method GroupMemberRepositoryPort.findMyRole has a
misleading name/return type mismatch: rename the method to findMyMembership (or
similar) if it should return the full GroupMemberEntity, or change its return
type to the narrower role type (e.g., GroupRole or Role) if only the role is
required; update the interface declaration, all implementations of
GroupMemberRepositoryPort, and any callers/tests to use the new method name or
return type (ensure method signatures like findMyMembership(Long groupId, Long
userId) or findMyRole(Long groupId, Long userId): GroupRole are consistently
applied).

In `@src/main/java/flipnote/group/application/service/MyPermissionService.java`:
- Around line 8-13: MyPermissionService currently imports and uses the adapter
entity GroupMemberEntity, breaking the port boundary; change
GroupMemberRepositoryPort (and any calls in GroupRoleRepositoryPort if relevant)
to return a domain model or a dedicated DTO instead of the adapter entity,
remove the direct import of flipnote.group.adapter.out.entity.GroupMemberEntity
from MyPermissionService, and update MyPermissionService to consume the domain
model/DTO (e.g., MyPermissionCommand -> MyPermissionResult logic) so mapping
from GroupMemberEntity happens inside the adapter implementation (adapter maps
entity -> domain/DTO before returning). Ensure method signatures on
GroupMemberRepositoryPort and any usages in MyPermissionService are updated
accordingly and that the adapter layer performs the entity-to-domain/DTO
conversion.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd65827 and d3b2968.

📒 Files selected for processing (11)
  • src/main/java/flipnote/group/adapter/in/web/PermissionController.java
  • src/main/java/flipnote/group/adapter/out/persistence/GroupMemberRepositoryAdapter.java
  • src/main/java/flipnote/group/adapter/out/persistence/GroupRoleRepositoryAdapter.java
  • src/main/java/flipnote/group/api/dto/response/MyPermissionResponseDto.java
  • src/main/java/flipnote/group/application/port/in/MyPermissionUseCase.java
  • src/main/java/flipnote/group/application/port/in/command/MyPermissionCommand.java
  • src/main/java/flipnote/group/application/port/in/result/MyPermissionResult.java
  • src/main/java/flipnote/group/application/port/out/GroupMemberRepositoryPort.java
  • src/main/java/flipnote/group/application/port/out/GroupRoleRepositoryPort.java
  • src/main/java/flipnote/group/application/service/MyPermissionService.java
  • src/main/java/flipnote/group/application/service/RemovePermissionService.java
💤 Files with no reviewable changes (1)
  • src/main/java/flipnote/group/application/service/RemovePermissionService.java

@stoneTiger0912 stoneTiger0912 merged commit 955b37f into main Mar 1, 2026
1 check passed
@stoneTiger0912 stoneTiger0912 deleted the feat/my-permission-info branch March 1, 2026 11:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant