Sails 的政策 (Policies) 設計用於控制特定操作的二元(「是」或「否」)存取權。它們非常適合檢查使用者是否已登入,或其他簡單的「是」或「否」檢查,例如已登入的使用者是否為「超級管理員」。
若要查看實際運作的存取控制範例(以及登入、身份驗證和密碼恢復),請產生入門 Web 應用程式
sails new foo
# Then choose "Web App"
對於更複雜的權限方案,例如請求的使用者代理程式的存取權取決於他們是誰和他們想要做什麼的情況,您會希望使用資料庫。雖然您可以使用政策來完成此操作,但使用 helper 通常更直接且更易於維護。
例如,您可以建立 api/helpers/check-permissions.js
module.exports = {
friendlyName: 'Check permissions',
description: 'Look up a user\'s "rights" within a particular organization.',
inputs: {
userId: { type: 'number', required: true },
orgId: { type: 'number', required: true }
},
exits: {
success: {
outputFriendlyName: 'Rights',
outputDescription: `A user's "rights" within an org.`,
outputType: ['string']
},
orgNotFound: {
description: 'No such organization exists.'
}
},
fn: async function(inputs, exits) {
var org = await Organization.findOne(inputs.orgId)
.populate('adminUsers', { id: inputs.userId })
.populate('regularUsers', { id: inputs.userId });
if (!org) { throw 'orgNotFound'; }
var rights = [];
if (org.regularUsers.length !== 0) {
rights = ['basicAccess', 'inviteRegularUsers'];
} else if (org.adminUsers.length !== 0) {
rights = ['basicAccess', 'inviteRegularUsers', 'removeRegularUsers', 'inviteOrgAdmins'];
} else if (org.owner === inputs.userId) {
rights = ['basicAccess', 'inviteRegularUsers', 'removeRegularUsers', 'inviteOrgAdmins', 'removeOrDemoteOrgAdmins'];
}
// ^^This could be as simple or as granular as you need, e.g.
// ['basicAccess', 'inviteRegularUsers', 'inviteOrgAdmins', 'removeRegularUsers', 'removeOrDemoteOrgAdmins']
return exits.success(rights);
}
};
您的動作—例如 api/controllers/demote-org-admin.js
—可能如下所示
//…
var rights = await checkPermissions(this.req.session.userId, inputs.orgId)
.intercept('orgNotFound', 'notFound');
if (!_.contains(rights, 'removeOrDemoteOrgAdmins')) {
throw 'forbidden';
}
await Organization.removeFromCollection(inputs.orgId, 'adminUsers', inputs.targetUserId);
await Organization.addToCollection(inputs.orgId, 'regularUsers', inputs.targetUserId);
return exits.success();
注意
請記住,雖然我們在這裡使用了
checkPermissions(…,…)
,但我們也可以使用.with()
並切換到具名參數await checkPermissions.with({ userId: this.req.session.userId, orgId: inputs.orgId });
您可以選擇使用不同的方式呼叫 helper,以增強不同情況下的程式碼可讀性。如有疑問,一個好的最佳實踐是首先針對明確性進行最佳化,然後是可讀性,最後是簡潔性。儘管如此,當您更頻繁地實作 helper 並越來越熟悉其用法時,這些優先順序可能會改變。