我们会把权限定义写到一个CommonJS模块里来保证Node的兼容性(Webpack能让这个模块用在客户端)。
resources/ability.js
const casl = require('casl'); module.exports = function defineAbilitiesFor(user) { return casl.AbilityBuilder.define( { subjectName: item => item.type }, can => { can(['read', 'create'], 'Post'); can(['update', 'delete'], 'Post', { user: user }); } ); };
下面我们来剖析这段代码。
define方法的第二个参数,我们通过调用can来定义了权限规则。这个方法的第一个参数是你要允许的CRUD操作,第二个是资源或实例,在这个例子中是Post。
注意第二个can的调用,我们传了一个对象作为第三个参数。这个对象是用来测试user属性是否匹配我们提供的user对象。如果我们不这么做,那不光创建者可以删帖,谁都可以随便删了。
resources/ability.js
... casl.AbilityBuilder.define( ... can => { can(['read', 'create'], 'Post'); can(['update', 'delete'], 'Post', { user: user }); } );
CASL检查实例来分配权限时,需要知道实例的type。一种解决方式是把具有subjectName方法的对象,作为define方法的第一个参数,subjectName方法会返回实例的类型。
我们通过在实例中返回type来达成目的。我们需要保证,在定义Post对象时,这个属性是存在的。
resources/ability.js
... casl.AbilityBuilder.define( { subjectName: item => item.type }, ... );
最后,我们把我们的权限定义封装到一个函数里,这样我们就可以在需要测试权限的时候直接传进一个user对象。在下面的函数中会更易理解。
resources/ability.js
const casl = require('casl'); module.exports = function defineAbilitiesFor(user) { ... };
Vue 中的访问权限规则
现在我们想在前端应用中检查一个对象中,用户具有哪些CRUD权限。我们需要在Vue组件中访问CASL规则。这是方法:
引入Vue和 abilities plugin。这个插件会把CASL加到Vue的原型上,这样我们就能在组件内调用了。
在Vue 应用内引入我们的规则(例: resources/abilities.js)。
定义当前用户。实战中,我们是通过服务器来获取用户数据的,在这个例子中,我们简单地硬编码到到项目里。
牢记,abilities模块export一个函数,我们把它称为defineAbilitiesFor。我们会向这个函数传入用户对象。现在,无论何时,我们可以通过检测一个对象来得出当前用户拥有何种权限。
添加abilities插件,这样我们就可以在组件中像这样来进行测试了:this.$can(...)。