從 Salesforce (SFDC) 拉資料就偶而會被 Field-Level Security (FLS) 打到,而 FLS 那藏地有夠緊的設定頁面、加上從台灣連到美東那精美的連線速度,每每要敲個幾個欄位下來都很有得等...
找到了以程式來直接設定 FLS 的手段,這樣就不用去戳那個有夠煩的 UI 了,記錄一下。
環境設定
以下操作是 SOQL 及 Metadata API 混用;然後實際上我是使用 simple-salesforce 來操作,不過在 workbench 混用 SOQL Query 及 REST Explorer 也能完成。
使用 simple-salesforce 連線的程式大概這樣起頭,其中 Salesforce
的建構子參數都做授權在用,直接看官方文件比較快:
import simple_salesforce
client = simple_salesforce.Salesforce( ... )
列舉欄位清單
先打個 sObject Describe 當作測試:
client.Account.describe()
但取得清單卻意外地沒用——作為管理員帳號明明已經可以在 Object Management 上看到所有的欄位了、甚至在上面調整權限,但是當 FLS 沒有通過,欄位就不會在 API 的回應裡出現。即從這個 API 取得的完整欄位清單會跟實際上有出入。
取得 PermissionSet
稍後查詢需要得到 PermissionSet 的資訊,先打個 SOQL 去查查:
SELECT id
FROM PermissionSet
WHERE
IsOwnedByProfile = true
AND PermissionSet.Profile.Name = 'System Administrator'
這裡 PermissionSet.Profile.Name
顧名思義是需要取得權限的帳號的群組名,例如上面的 System Administrator 或是自訂的群組如 Service Account。
如果也是使用 simple-salesforce 的話就直接透過 query 來執行:
client.query( soql )
確認權限
FLS 背後的物件為 FieldPermissions,一樣透過 SOQL 來查查權限:
SELECT
SobjectType,
Field,
ParentId,
PermissionsRead,
PermissionsEdit
FROM FieldPermissions
WHERE
Field = 'Account.Website'
這裡舉例是以標準物件 Account 下的內建欄位 Website
來檢索並回傳了 FieldPermissions
的全部欄位:
回傳欄位 | 說明 |
---|---|
SobjectType |
所屬 SObject 名稱 |
Field |
欄位的 API 識別名稱,並且它一定要以其所屬 SObject 名稱作為前綴 |
ParentId |
這個 FieldPermissions 物件所對應的 PermissionSet |
PermissionsRead |
具有可讀權限 |
PermissionsEdit |
具有可寫權限 |
另外,不是所有的欄位都可以查詢 FieldPermissions
,以 FieldPermissions 文件底下 Special Properties for Field Permissions 章節所述,一些系統欄位會是永遠唯獨的,包括但不僅於:
Id
CreatedById
CreatedDate
IsDeleted
LastModifiedById
LastModifiedDate
SystemModStamp
這些系統欄位無法查詢、也不可以對那些欄位設定 FieldPermissions
。對於系統欄位,在 sObject Describe 回傳的欄位資料中 permissionable
會是 False
。
開權限
SOQL 只能查資料,所以這塊是 Metadata API 的戰場。這裡要操作的是對 FieldPermissions
打 Create Records:
POST /services/data/v58.0/sobjects/FieldPermissions/
{
"SobjectType": "Account",
"Field": "Account.Website",
"PermissionsEdit": false,
"PermissionsRead": true,
"ParentId": "0xxxxxxxxxxxxxxMUD"
}
依照前面段落說到的規則:Field
一樣需要把 SObject 填在前面,然後 ParentId
就直接填入要開權限的對象。
在 simple-salesforce 中的操作則對應為:
client.FieldPermissions.create({
"SobjectType": "Account",
"Field": "Account.Website",
"PermissionsEdit": False,
"PermissionsRead": True,
"ParentId": "0xxxxxxxxxxxxxxMUD"
})