Fabric 앱은 @role 데코레이터를 사용하여 권한 부여 규칙을 데이터 모델에 직접 연결합니다. 사용 권한은 형식이 안전하며 리팩터링이 가능하며 기본 데이터 액세스 구성으로 자동으로 컴파일됩니다.
시작하기 전 주의 사항:
기본 제공 역할
Fabric 앱은 기본 제공 authenticated 역할을 인식합니다. 필요한 경우 정책에서 사용자 지정 역할을 정의할 수도 있습니다.
| 역할 | Description | 사용 사례 |
|---|---|---|
authenticated |
Fabric 인증을 사용하는 유효한 사용자 세션 필요 | 사용자별 데이터, 보호된 리소스 |
@role 데코레이터
어떤 역할이 엔터티에 대해 어떤 작업을 수행할 수 있는지 제어하려면 클래스 수준에 @role를 적용하세요.
@role(roleName, actions, options?)
매개 변수
| 매개 변수 | Type | Description |
|---|---|---|
roleName |
string |
역할 이름(예: 'authenticated' 사용자 지정 애플리케이션 역할) |
actions |
string \| string[] |
단일 작업 또는 배열: 'create', 'read', 'update'또는 'delete''*' 모두 |
options |
object |
check, include 및 exclude 속성을 가진 선택적 객체 |
기본 예제
인증된 사용자를 자신의 데이터로 제한합니다.
import { entity, role, uuid, text } from '@microsoft/rayfin-core';
@entity()
@role('authenticated', ['create', 'read', 'update', 'delete'], {
policy: (claims, item) => claims.sub.eq(item.userId),
})
export class Todo {
@uuid() id!: string;
@text() title!: string;
@text({ optional: true }) description?: string;
@text() userId!: string;
}
이 예제에서:
- 인증된 사용자는 JWT
userId클레임과 일치하는 Todo 항목sub에만 액세스할 수 있습니다.
타입 안전 정책 표현식
콜백은 policy 클레임 및 엔터티 필드 모두에 대한 형식화된 액세스를 제공합니다. TypeScript는 데코레이팅된 클래스에서 엔터티 형식을 유추하여 자동 완성 및 리팩터링 보안을 제공합니다.
policy: (claims, item) => claims.sub.eq(item.userId)
지원되는 클레임
| 클레임 | Description | 예제 값 |
|---|---|---|
claims.sub |
주체 식별자(사용자 ID) | 00000000-0000-0000-0000-000000000001 |
claims.email |
사용자 전자 메일 주소 | user@contoso.com |
claims.role |
사용자 역할(ID 공급자가 제공하는 경우) | admin |
식 연산자
| Operator | Example | Description |
|---|---|---|
.eq() |
claims.sub.eq(item.userId) |
동일 여부 확인 |
논리 연산자
식과 다음을 결합 .and().or()합니다.
// User must own the item AND item must be active
@role('authenticated', 'read', {
policy: (claims, item) =>
claims.sub.eq(item.userId).and(item.isActive.eq(true))
})
// User is admin OR user owns the item
@role('authenticated', ['update', 'delete'], {
policy: (claims, item) =>
claims.role.eq('admin').or(claims.sub.eq(item.ownerId))
})
양쪽 모두 올바른 그룹화를 위해 자동으로 괄호로 지정됩니다.
필드 수준 권한
역할 옵션에서 include 또는 exclude을 사용하여 역할이 액세스할 수 있는 필드를 지정합니다.
특정 필드 포함
생성 작업 중에는 title 필드만 허용하세요.
@entity()
@role('authenticated', 'create', {
policy: (claims, item) => claims.sub.eq(item.createdBy),
include: ['title'],
})
export class Document {
@uuid() id!: string;
@text() title!: string;
@text({ optional: true }) content?: string;
@text() createdBy!: string;
}
특정 필드 제외
읽기 작업에서 중요한 필드 숨기기:
@entity()
@role('authenticated', 'read', {
exclude: ['lastLogin', 'passwordHash'],
})
export class User {
@uuid() id!: string;
@text() email!: string;
@date({ optional: true }) lastLogin?: Date;
@text() passwordHash!: string;
}
비고
필드 배열은 엔터티의 실제 속성 이름에 입력됩니다. 필드 이름을 바꾸면 필드를 참조하는 모든 include 또는 exclude 목록에서 컴파일 시간 오류가 발생합니다.
작업별 권한
여러 @role 데코레이터를 사용하여 작업당 다른 규칙을 적용합니다.
@entity()
@role('authenticated', 'create', {
policy: (claims, item) => claims.sub.eq(item.createdBy),
include: ['title', 'content'],
})
@role('authenticated', 'read', {
policy: (claims, item) => claims.sub.eq(item.createdBy),
})
@role('authenticated', 'update', {
policy: (claims, item) => claims.sub.eq(item.createdBy),
exclude: ['adminNotes'],
})
@role('authenticated', 'delete', {
policy: (claims, item) => claims.sub.eq(item.createdBy),
})
export class SecureDocument {
@uuid() id!: string;
@text() title!: string;
@text({ optional: true }) content?: string;
@text({ optional: true }) adminNotes?: string;
@text() createdBy!: string;
}
이 구성은 다음과 같습니다.
-
만들기: 작성자만 만들 수 있으며 필드만
titlecontent허용됩니다. - 읽기: 작성자만 자신의 문서를 읽을 수 있습니다.
-
업데이트: 작성자만 업데이트할 수 있지만 수정
adminNotes할 수는 없습니다. - 삭제: 작성자만 삭제할 수 있습니다.
사용 권한의 작동 방식
-
메타데이터 컬렉션: 클래스가
@role정의되면 데코레이터가 사용 권한 메타데이터를 수집합니다. -
스키마 생성: 실행할
db apply때 CLI는 메타데이터를 읽고 권한 구성을 생성합니다. -
정책 컴파일: TypeScript 정책 콜백은 데이터 액세스 정책 식(예
@claims.sub eq @item.userId: )으로 컴파일됩니다. - 런타임 적용: 데이터 액세스 계층은 모든 API 요청에 대한 권한을 적용합니다.
-
충돌 감지: 동일한 클래스의 여러
@role데코레이터가 역할별로 집계되며 충돌 선언에 대한 경고가 표시됩니다.
일반적인 패턴
소유자 전용 액세스
@entity()
@role('authenticated', '*', {
policy: (claims, item) => claims.sub.eq(item.ownerId)
})
export class PrivateNote {
@uuid() id!: string;
@text() ownerId!: string;
@text() content!: string;
}
인증된 사용자에 대한 모든 권한
@entity()
@role('authenticated', '*')
export class BlogPost {
@uuid() id!: string;
@text() title!: string;
@text() content!: string;
}
관리자 재정의
@entity()
@role('authenticated', ['create', 'read', 'update'], {
policy: (claims, item) =>
claims.role.eq('admin').or(claims.sub.eq(item.ownerId))
})
@role('authenticated', 'delete', {
policy: (claims, _item) => claims.role.eq('admin')
})
export class ManagedResource {
@uuid() id!: string;
@text() ownerId!: string;
@text() name!: string;
}
관리자는 모든 리소스를 수정할 수 있지만 관리자만 삭제할 수 있습니다.
다음 단계
- 인증 구성하여 ID 공급자를 설정합니다
- GraphQL을 사용하여 데이터를 쿼리 하여 권한으로 보호된 쿼리 테스트
- 스키마 생성 명령에 대한 CLI 명령 참조