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 연결
@QfEntity에 capabilityKey를 선언하여 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 __ createSSOT 보장
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를 선언했다면 다음을 확인하세요.
- [ ]
@QfCapability의key가 다른 Capability와 중복되지 않는가? - [ ] 필요한 모든
@QfPrivilege를privileges = {...}내부에 선언했는가? - [ ]
QfUserProvider에서 해당 Privilege를 반환하는 Role이 구성되었는가? - [ ] 관리자 계정에 최소 하나의 Privilege가 부여되었는가?
- [ ] 컴파일 후 메타데이터에 Capability가 등록되었는가?