질문을 삭제하지 말아주세요.!
 
1
0
-1


권한 관리를 구현하고 있습니다. 연습이라 설계없이 막 구현하다가 다음과 같은 난관에 부딛쳤습니다. 조언, 아이디어, 경험 공유, 역질문 뭐든 환영합니다.

권한 관리와 관련해서 아래 세 개의 모델이 있다고 가정했을 때,

  • User
  • Role: ADMIN, MEMBER, USER
  • Permission: MANAGE_USER, MANAGE_PRODUCT, MANAGE_REVIEW

세 모델간의 관계를 어떻게 설계하면 좋을까요?


1. User *---* Role *---* Permission

  • User와 Permissio간에 직접적인 관계 없음
  • 예) User#1은 MEMBER, USER Role을 가지고 있고, MEMBER Role은 MANAGE_PRODUCT, MANAGE_PRODUCT를 USER Role은 Permission을 가지고 있지 않음.
  • User 권한을 Role로 검사하든, Permission으로 검사하든 항상 일관된 결과가 나온다.
  • 그렇다면, Role과 Permission을 굳이 나눈 이유는?


2. ---* User *---* Role *---* Permission *---

  • User와 Permissio간에 Many to Many 관계
  • 예) User#1은 MEMBER, USER Role을 가지고 있고, MEMBER Role은 MANAGE_PRODUCT, MANAGE_PRODUCT를 USER Role은 Permission을 가지고 있지 않음. User#1은 MANAGE_USER Permission을 가지고 있음.
  • User에게 Role을 오버라이드하는 권한 부여 가능하다.
  • Role? Permission? 무엇을 기준으로 권한 검사를 할 것인가? 유지보수 이슈 발생시 대응이 가능할까?


고맙습니다.

    CommentAdd your comment...

    2 answers

    1.  
      1
      0
      -1

      몇일간 고민하다가 전자로 구현하되, 조회 편의를 위해 User-Permission간 관계도 유지하도록 했습니다. 로직에 헛점이 있으면, 지적해주세요. 



      Service Layer
      <?php // core/Myshop/Application/Service/RoleService.php
      
      class RoleService
      {
          public function assignRoleToUser(User $user, Role $role)
          {
              $user->roles()->attach($role);
      
              // Role이 Permission 보다 상위 개념이므로 사용자에게 Role을 할당하면,
              // Role에 연결된 Permission도 해당 User에게 같이 할당되어야 합니다.
              $permissions = $role->permissions;
              foreach ($permissions as $permission) {
                  $this->permissionService->grantPermissionToUser($user, $permission);
              }
      
              $this->userRepository->save($user);
          }
      }
      
      
      <?php // core/Myshop/Application/Service/PermissionService.php
      
      
      class PermissionService
      {
          // DESIGN NOTE.
          // 1. User에게 다수의 Role을 Assign 할 수 있다.
          // 2. User에게 Role을 통해서만 Permission을 grant/revoke할 수 있다.
          // 3. 그럼에도 불구하고, 조회 편의를 위해 User-Permission간의 Many-to-many 관계를 유지하고,
          //    grantPermissionToRole/revokePermissionToRole/syncPermissionOfRole API를 호출하면,
          //    User-Permission 맵핑 저장소도 User-Role-Permission 관계와 일치하도록 업데이트한다.
          public function attachPermissionToRole(Role $role, Permission $permission)
          {
              $role->permissions()->attach($permission);
              $this->roleRepository->save($role);
      
              // Role이 Permission 보다 상위 개념이므로, Role 할당은 Permission으로 Propagate됨.
              $users = $role->users;
              foreach ($users as $user) {
                  $this->grantPermissionToUser($user, $permission);
                  $this->userRepository->save($user);
              }
          }
      
          public function grantPermissionToUser(User $user, Permission $permission)
          {
              // Role이 Permission 보다 상위 개념이므로, Permission 할당이 Role로 Bubble up 되지 않음.
              $user->permissions()->attach($permission);
          }
      }


      전체 코드는 https://github.com/appkr/db-lock-poc/pull/13/files 에 있습니다.

        CommentAdd your comment...
      1.  
        1
        0
        -1

        1. https://www.contentful.com/r/knowledgebase/roles-and-permissions/

        어떤 제품의 매뉴얼인듯 보이는데, Role과 Permission은 한 셋트로 움직이는 것으로 설명하고 있네요. 기존 Role에 부여된 Permission과 다른 Permission 추가/삭제가 필요하다면 새로운 Role을 만들고 이를 사용자에게 할당하는 식으로 구현한 것으로 보입니다.


        2. https://code.i-harness.com/en/q/345725

        검색하다가 찾은 Q&A인데, 권한 관리 관련 구현 아키텍처에 관한 내용입니다. 원 질문과 전혀 엉뚱한 답으로 나아가고 있는데(오지랖 넣은 개발자들^^), 내용들이 좋아서 남겨 놓습니다.


          CommentAdd your comment...