Sails のポリシーは、特定のアクションへの二者択一(「はい」または「いいえ」)のアクセス制御を行うように設計されています。ユーザーがログインしているかどうかの確認や、ログインしているユーザーが「スーパー管理者」であるかどうかなどの単純な「はい」または「いいえ」のチェックに非常に役立ちます。
アクセス制御が実際に機能する例(ログイン、認証、パスワード回復も含む)を確認するには、スターター Web アプリを生成してください。
sails new foo
# Then choose "Web App"
リクエストするユーザーエージェントのアクセス権が、そのユーザーが誰であるかと何を実行しようとしているかの両方に依存するような、より複雑な権限スキームの場合は、データベースを関与させる必要があります。ポリシーを使用してこれを実現することもできますが、通常は ヘルパー を使用する方がより直接的で保守が容易です。
たとえば、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 });
状況に応じてコードの可読性を高めるために、ヘルパーを呼び出すさまざまな方法を使用することを選択できます。迷った場合は、まず明示性、次に可読性、最後に簡潔性を最適化するのが良いベストプラクティスです。それでも、ヘルパーの実装頻度が高くなり、その使用法に慣れてくると、これらの優先順位がシフトする可能性があります。