[Feat] 권한 모델 개편 - recruitment, user 도메인 적용 - #213
galgalrobot wants to merge 2 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: BOAZ-website/backend/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
seoyeon83
left a comment
There was a problem hiding this comment.
따로 코멘트 남긴 부분에 수정이 필요할 것 같아요. 그 외에는 괜찮아 보입니다.
| scopeGuard.checkTrack(currentAdmin, permissions, applicant.getTrack()); | ||
|
|
||
| // 평가자 풀 = 해당 부문 + 차기 대표진(전 부문 평가 권한). 미작성자도 포함. | ||
| List<Admin> evaluators = adminRepository.findEvaluatorPool( |
There was a problem hiding this comment.
findEvaluatorPool() 함수의 경우, track + team_name 을 기반으로 동작하는 것으로 알고 있습니다.
그런데 이번에 권한 체계가 개편되면서 해당 부문과 차기 대표진이 아닌 운영진도 EVALUATION_ALL_TRACK_WRITE (전부문에 평가 가능) 권한이 부여될 수 있습니다. 이때 기존 findEvaluatorPool() 함수가 유지되면 대시보드 상에서 그 운영진의 평가가 보이지 않는 문제가 생기게 됩니다. (지원자 A에 대한 운영진의 평가는 다른 운영진도 볼 수 있어야 하기 때문)
이 부분의 경우 서비스 로직을 수정하는 것이지만 이번 작업에서 같이 수정해주셔야 할 것 같아요.
수정 관련해 당장 드는 제안 사항은 다음과 같아요. 수정하실 때 참고해 주세요.
- 권한 모델을 개편하면서 기존에 사용했던 findEvaluatorPool()같은 JPQL 대신 EffectivePermission 을 활용하면 좋을 것 같아요.
- 응답 평가자를 산출할 때 현재 평가 가능자 뿐만 아니라 이미 이 지원자를 평가한 admin 으로 두어야 평가 기간 중에 권한이 빠지더라도 평가 결과가 남아 있도록 할 수 있을 것 같습니다.
There was a problem hiding this comment.
말씀해주신 내용 반영했습니다!
- findEvaluatorPool()의 role/teamName 기반 조회를 제거하고 EffectivePermissions 기반으로 평가 가능자를 판정하도록 변경했습니다.
- 또한 권한이 변경되더라도 이미 평가를 작성한 Admin은 평가자 목록에 유지되도록 수정했습니다. 관련 테스트도 함께 보강했습니다.
There was a problem hiding this comment.
그리고 추가적으로 설계문서에 세부 규칙이 없던 엣지 케이스도 함께 보완했습니다.
- soft-delete된 평가자는 새 평가는 할 수 없지만 기존 평가 기록은 집계/상세/면접 질문에 유지하도록 했고, 리뷰에서 말씀해주신 “권한이 변경돼도 기존 평가 결과는 남아 있어야 한다”는 방향이 soft-delete 된 평가자에도 적용을 하는게 맞다고 생각하였습니다.
- 정회원 승격은 사용자 실수로 FAIL·PENDING 지원자가 MEMBER로 승격되는 것을 막기 위해, 기존 MEMBER_PROMOTION_WRITE 인가는 유지하면서 서버에서 finalDecision == PASS 여부를 추가 검증하도록 했습니다
💡 개요
공통 권한 모듈을 활용하여 recruitment, user 도메인의 Admin API에 Permission 기반 인가를 적용하고,
recruitment 평가 영역의 요청자 인가 및 평가 범위 판정을 Permission + ScopeGuard 기반으로 전환했습니다.
PR 리뷰를 반영하여 평가자 조회 기준도 기존 role/teamName 기반에서
EffectivePermissions기반으로 변경했으며,추가 검토 과정에서 확인된 설계문서와 구현 간 불일치 및 일부 엣지 케이스를 함께 보완했습니다.
🪐 주요 변경 사항
RecruitmentAdminControllerRECRUITMENT_NOTICE_READ/WRITE,APPLICANT_CSV_READ,APPLICATION_DELETE_ALL,PRE_NOTIFICATION_READ/DELETE적용ApplicantEvaluationAdminController/RecruitmentServiceEVALUATION_OWN_TRACK_WRITE,EVALUATION_ALL_TRACK_WRITE,FINAL_DECISION_READ/WRITE적용 및 평가 범위에ScopeGuard사용findEvaluatorPool의 role/teamName 기준을 제거하고EffectivePermissions기반으로 현재 평가 가능자 판정UserAdminController/UserAdminServiceMEMBER_PROMOTION_WRITE적용 및finalDecision == PASS검증 추가DefaultPermissionsADMIN_ACCOUNT_SELF_READ제거✅ 상세 내용
1. 평가 권한 및 평가자 조회
평가 API의 기존 role/teamName 기반 판정을 Permission 기반으로 변경했습니다.
EVALUATION_OWN_TRACK_WRITE보유자는 본인 부문만 접근 가능합니다.EVALUATION_ALL_TRACK_WRITE보유자는 전 부문에 접근 가능합니다.ScopeGuard.checkTrack()으로 부문 범위를 검증합니다.EVALUATION_ALL_TRACK_WRITE보유 여부를 기준으로 필터링합니다.PR 리뷰를 반영하여 기존
findEvaluatorPool의 role/teamName 조건도 제거했습니다.현재 평가 가능자는 live Admin의
EffectivePermissions를 기준으로EVALUATION_ALL_TRACK_WRITEEVALUATION_OWN_TRACK_WRITE + 동일 track인 경우에만 포함됩니다.
또한 이후 권한이 REVOKE되거나 변경되더라도,
이미 해당 지원자를 평가한 Admin은 과거 평가 작성자로 계속 유지됩니다.
근거
EffectivePermissions = Default - REVOKE + GRANTScopeGuard기반 범위 판정2. 설계문서와 기존 구현 불일치 수정
최종 합불 수정
기존에는
FINAL_DECISION_WRITE권한이 있어도서류 평가용
checkTrack()을 추가로 검사하고 있었습니다.설계상 track 범위는
EVALUATION_OWN_TRACK_WRITE/EVALUATION_ALL_TRACK_WRITE가 담당하는 서류 평가 범위이고,최종 합불은 별도의
FINAL_DECISION_WRITE권한으로 정의되어 있습니다.따라서 최종 합불 수정에서는 평가용 track 검증을 제거하고,
FINAL_DECISION_WRITE보유 여부만으로 판정하도록 수정했습니다.근거
HOST 기본 권한
기존에는
(HOST, 그룹리더)에게ADMIN_ACCOUNT_SELF_READ,ADMIN_ACCOUNT_SELF_WRITE가 모두 기본 부여되고 있었습니다.설계문서에서는 HOST 기본 권한을
ADMIN_ACCOUNT_SELF_WRITE만으로 정의하고 있어ADMIN_ACCOUNT_SELF_READ를 제거했습니다.GET /accounts/me는 설계 가이드상 별도의 account-read Permission을 요구하지 않는 self endpoint이므로,해당 권한 제거 이후에도 기존대로 접근 가능합니다.
근거
(HOST, 그룹리더) = { ADMIN_ACCOUNT_SELF_WRITE }/accounts/me는 Permission을 요구하지 않는 self endpoint3. 설계문서에 없는 엣지 케이스 보완
아래 내용은 설계문서에 세부 처리 규칙이 명시되어 있지 않아,
추가 검토 과정에서 데이터 정합성 및 비즈니스 무결성을 위해 보완했습니다.
soft-delete 평가자 기록
상세/면접 질문에서는 제외되어 집계 결과와 상세 데이터가 일치하지 않는 문제가 있었습니다.
정회원 승격 대상 검증
합격자 정회원 승격 → MEMBER_PROMOTION_WRITE권한 매핑까지 정의되어 있으며,finalDecision == PASS를 서비스에서 검증하는 세부 규칙은 명시되어 있지 않습니다.SUBMITTED지원서가 존재하면 FAIL / PENDING 지원자도 승격 가능한 경로가 있었습니다.MEMBER_PROMOTION_WRITE는 누가 승격 기능을 사용할 수 있는지에 대한 인가로 그대로 유지하고,별도로
finalDecision == PASS인지 확인하여 실제 승격 대상인지 검증하도록 보완했습니다.APPLICANT_NOT_PASSED로 처리합니다.4. 테스트
Permission Grid, Unit, Integration Test를 통해 다음을 검증했습니다.
SELF_READ제거 및/accounts/me접근 유지전체 테스트 결과:
./gradlew test🔔 참고 사항
SecurityConfig,Permission,EffectivePermissions,ScopeGuard의 기존 구조는 그대로 유지했습니다.DefaultPermissions의 HOST 기본 권한만 설계문서와 일치하도록 수정했습니다.bulkPromote의 사용자별 트랜잭션 / 부분 성공 방식은 기존 API 계약이므로 변경하지 않았습니다.APPLICANT_CSV_READ권한 기준을 유지했습니다.