Fabric Apps 使用 @role 裝飾器,直接將授權規則附加到你的資料模型上。 權限具備型別安全特性、便於重構,並會自動編譯為底層的資料存取組態。
開始之前
內建角色
Fabric Apps 會辨識內建的 authenticated 角色。 必要時,你也可以在政策中定義自訂角色。
| 角色 | Description | 應用案例 |
|---|---|---|
authenticated |
需要有效的使用者會話與 Fabric 認證 | 使用者專屬資料,受保護資源 |
裝飾師@role
在類別層級應用 @role 以控制哪些角色可以對實體執行哪些動作:
@role(roleName, actions, options?)
參數
| 參數 | 類型 | 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主張相符的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 |
使用者角色(若由身份提供者提供) | 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;
}
此配置:
-
創建:只有創作者能創建,且只有
title和content欄位被允許。 - 閱讀:只有創作者能閱讀自己的文件。
-
更新:只有創作者可以更新,但他們無法修改
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;
}
管理員可以修改任何資源,但只有管理員能刪除。
下一步
- 設定認證 以設定身份提供者
- 使用 GraphQL 查詢資料 以測試權限保護的查詢
- 用於綱要產生指令的CLI 指令參考