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 });
您可以选择使用不同的方式调用帮助程序,以提高不同情况下代码的可读性。如有疑问,最佳做法是首先优化明确性,然后优化可读性,最后优化简洁性。不过,随着您更频繁地实现帮助程序并对其使用更加熟悉,这些优先级可能会发生变化。