触发器管理权限
虽然在Steedos中使用上面介绍过的各种权限配置方法已经能轻松实现精确到字段和记录级的权限控制,但在千奇百怪的实际项目场景中还是会有些权限需求未能企及,所以Steedos权限引擎还结合了 beforeFind 触发器,允许通过编写代码的方式来解决各种个性化的更高级别的权限问题。
原理
Steedos中的对象触发器,按触发的先后时间次序有两种,一种是在操作执行前触发,一种是在操作执行后触发,并且前者是以before
为前缀来命名,后者是以after
为前缀来命名,比如beforeUpdate
和afterUpdate
分别会在执行数据修改前和数据修改成功后触发。
要通过触发器来实现权限控制,我们只要在相关对象上编写操作执行前的触发器,即编写以before
为前缀命名的增、删、改、查触发器,在触发器函数中判断到当前登录用户没有权限时通过有意throw Error
或返回false
值的方式来中断执行相关操作就可以达到权限控制的目的了。
数据操作权限控制
我们可以在beforeInsert/beforeUpdate/beforeDelete
触发器中根据当前用户的身份来决定是否拒绝执行相关操作,当需要拒绝时只要在触发器函数中有意throw Error
或返回false
值就可以中断执行相关操作。
在操作执行前的触发器函数中如果需要返回错误信息可以通过throw Error
来中断执行数据操作,反之可以通过return false
来静默中断执行数据操作。
在触发器函数中可以通过表达式this.doc
变量来获取要修改哪些字段值,我们可以移除该变量中的字段来拒绝保存当前用户没有权限保存的字段值,以下示例代码只允许管理员变更合同记录的owner
字段值。
module.exports = {
listenTo: 'contracts',
beforeInsert: async function () {
const userId = this.userId;
const spaceId = this.spaceId;
if (userId && spaceId) {
const userSession = await auth.getSessionByUserId(userId, spaceId);
var isAdmin = userSession.is_space_admin;
if(!isAdmin && this.doc.owner){
throw new Error("只有系统管理员才能变更合同所有者!");
//return false // 把throw error换成这行,将会新建失败,但是不提示错误信息。
//delete this.doc.owner //把throw error换成这行,将会新建成功,但是新建后的记录owner值为空。
}
}
},
beforeUpdate: async function () {
const userId = this.userId;
const spaceId = this.spaceId;
if (userId && spaceId) {
const userSession = await auth.getSessionByUserId(userId, spaceId);
var isAdmin = userSession.is_space_admin;
if(!isAdmin && this.doc.owner){
throw new Error("只有系统管理员才能变更合同所有者!");
//return false // 把throw error换成这行,将会修改失败,但是不提示错误信息。
//delete this.doc.owner //把throw error换成这行,将会修改成功,但是记录owner值不会被修改。
}
}
}
}