我正在使用快递和续集制作应用程序。有用户和管理员。现在,我正在通过中间件处理权限。
假设用户可以更改消息:
var Message = sequelize.define('Message', {
content: Sequelize.STRING,
secret: Sequelize.STRING
});
var message = Message.build({
content: 'i like frogs',
secret: 'i like hogs more!'
});
app.put('/message', requireRole('user'), function(request, response) {
message.updateAttributes(request.body.content);
response.writeHead(200);
response.end('secret updated');
});
我想要一些更复杂的权限。
有什么好办法解决这个问题?在这个例子中,我希望用户能够更新消息的content
,但不能更新它的secret
。
我可以将它烘焙到每条路线中,但似乎随着模型的改变而修改会很痛苦。
app.put('/message', requireRole('user'), function(request, response) {
var attrs = {};
var role = request.session.user.role;
if (role == 'user' || role == 'admin') {
attrs.content = request.body.content;
}
if (role == 'admin') {
attrs.secret = request.body.secret;
}
message.updateAttributes(attrs);
response.writeHead(200);
response.end('secret updated');
});
有更好的方法吗?我想我可以把这个逻辑放到定义模型的Sequelize get / set方法中,但是不知道那是否更干净。
在我看来,将这样的逻辑放入模型中是个坏主意。特别是对模型的制定者,因为这与两个OOP SOLID principles冲突(单一责任原则和界面隔离原则)。
通常,有一个名为ACL(访问控制列表)的模式,您可以在其中定义哪些角色可以对某些资源执行任何操作。这个例如:https://www.npmjs.org/package/acl
将ACL注入项目时:
if (role == 'user' || role == 'admin') {
attrs.content = request.body.content;
}
if (role == 'admin') {
attrs.secret = request.body.secret;
}
将被这样的东西取代:
request.body.forEach(
field => {
ACL.isAllowed(
request.session.user.role,
field,
'edit',
( error, response ) => {
if( response ){
attrs[ field ] = request.body[ field ]; /** validate me! */
}
}
);
}
);
正如我从你的例子中看到的,提供npm包应该就够了。
我知道这个问题很老但是如果有人会遇到同样的问题,那么基于快递的应用程序中有一个article which explain how to integrate ACL
看看Passport,它使用起来非常简单,并且允许您在几秒钟内实现本地身份验证和OpenID。