Skip to content

Capability / 권한

개요

Q-Framework의 권한 모델은 세 계층으로 구성됩니다.

Client App
    └── Capability (업무 기능 영역)
            └── Privilege (허용 행위)
                    └── Role = Set<Privilege>

@QfCapability 선언

@QfCapability는 논리적 기능 단위와 그에 속하는 Privilege를 정의합니다.

java
@QfCapability(
    key = "user-management",
    name = @QfI18n(
        defaultMessage = "User Management",
        texts = { @QfI18nText(locale = "ko", message = "사용자 관리") }
    ),
    entities = { UserEntity.class },
    privileges = {
        @QfPrivilege(key = "user-management__view-list"),
        @QfPrivilege(key = "user-management__view-detail"),
        @QfPrivilege(key = "user-management__create"),
        @QfPrivilege(key = "user-management__update"),
        @QfPrivilege(key = "user-management__delete")
    }
)
public final class UserManagementCapability {
}

엔티티와 Capability 연결

@QfEntitycapabilityKey를 선언하여 Capability와 연결합니다.

java
@QfEntity(
    appKey = "admin",
    name = @QfI18n(
        defaultMessage = "User",
        texts = { @QfI18nText(locale = "ko", message = "사용자") }
    ),
    capabilityKey = "user-management"
)
public class UserEntity {
    // ...
}

@QfPrivilege 정의

Privilege는 @QfCapability(privileges = {...}) 내부에 배열로 선언합니다. 표시 이름이 필요한 경우 name을 선택적으로 지정할 수 있습니다.

java
@QfCapability(
    key = "user-management",
    name = @QfI18n(
        defaultMessage = "User Management",
        texts = { @QfI18nText(locale = "ko", message = "사용자 관리") }
    ),
    entities = { UserEntity.class },
    privileges = {
        @QfPrivilege(
            key = "user-management__view-list",
            name = @QfI18n(
                defaultMessage = "View User List",
                texts = { @QfI18nText(locale = "ko", message = "사용자 목록 조회") }
            )
        ),
        @QfPrivilege(
            key = "user-management__view-detail",
            name = @QfI18n(
                defaultMessage = "View User Detail",
                texts = { @QfI18nText(locale = "ko", message = "사용자 상세 조회") }
            )
        ),
        @QfPrivilege(
            key = "user-management__create",
            name = @QfI18n(
                defaultMessage = "Create User",
                texts = { @QfI18nText(locale = "ko", message = "사용자 등록") }
            )
        ),
        @QfPrivilege(
            key = "user-management__update",
            name = @QfI18n(
                defaultMessage = "Update User",
                texts = { @QfI18nText(locale = "ko", message = "사용자 수정") }
            )
        ),
        @QfPrivilege(
            key = "user-management__delete",
            name = @QfI18n(
                defaultMessage = "Delete User",
                texts = { @QfI18nText(locale = "ko", message = "사용자 삭제") }
            )
        )
    }
)
public final class UserManagementCapability {
}

Privilege 키 형식

{capability-key}__{privilege-name}
       ↓                  ↓
user-management  __  create

SSOT 보장

Privilege 키는 권한 정책, 런타임 체크, UI 제어에서 사용되는 단일 권위 식별자입니다.


Role 구성

Role은 런타임에 Privilege 집합으로 구성됩니다. Q-Framework는 Role 정의 방식을 강제하지 않으며, SPI를 통해 연동합니다.

QfUserProvider SPI 구현

java
@Component
public class MyUserProvider implements QfUserProvider {

    @Override
    public QfUser getCurrentUser(HttpServletRequest request) {
        // 현재 요청의 사용자 정보 반환
        UserPrincipal principal = SecurityContextHolder.getContext()
            .getAuthentication().getPrincipal();

        return QfUser.builder()
            .id(principal.getId())
            .name(principal.getName())
            .organizationId(principal.getOrganizationId())
            // 사용자에게 부여된 Privilege 목록
            .privileges(Set.of(
                "user-management__view-list",
                "user-management__view-detail",
                "order-management__create"
            ))
            .build();
    }
}

Q-Framework는 반환된 privileges 목록을 기준으로 API 접근을 자동 제어합니다.


화면/데이터 접근 통제 개념

API 레벨 제어

GET  /api/admin/users       → user-management__view-list Privilege 필요
GET  /api/admin/users/{id}  → user-management__view-detail Privilege 필요
POST /api/admin/users       → user-management__create Privilege 필요
PUT  /api/admin/users/{id}  → user-management__update Privilege 필요
DEL  /api/admin/users/{id}  → user-management__delete Privilege 필요

Privilege가 없는 사용자의 요청은 자동으로 403 Forbidden 응답을 반환합니다.

프론트엔드 UI 제어

vue
<template>
  <!-- Privilege에 따라 버튼 자동 표시/숨김 -->
  <QfEntityView
    client-app="admin"
    entity="user"
  />
</template>

Q-Framework UI 컴포넌트는 사용자의 Privilege를 기준으로 등록/수정/삭제 버튼을 자동으로 표시하거나 숨깁니다.


운영 체크리스트

새로운 Capability를 선언했다면 다음을 확인하세요.

  • [ ] @QfCapabilitykey가 다른 Capability와 중복되지 않는가?
  • [ ] 필요한 모든 @QfPrivilegeprivileges = {...} 내부에 선언했는가?
  • [ ] QfUserProvider에서 해당 Privilege를 반환하는 Role이 구성되었는가?
  • [ ] 관리자 계정에 최소 하나의 Privilege가 부여되었는가?
  • [ ] 컴파일 후 메타데이터에 Capability가 등록되었는가?

다음 단계

Released under the Apache 2.0 License.