Casl/vue $can 函数返回 false,但用户具有该权限

问题描述

我在 vue cli 项目中使用 @casl/vue 插件进行用户权限管理,如 casl 插件作者 sample(vue-blog) 的示例存储库所示。这是我的代码
ability.js

export default (store) => {
const ability = store.getters.ability
ability.update(store.state.rules);
return store.subscribe((mutation) => {
    switch (mutation.type) {
        case 'ROOT_LOGIN_SUCCESS':
            var formattedRules = [];
            if (mutation.payload.permissions.length > 0) {
                formattedRules = mutation.payload.permissions.map(perm => {
                    let formattedobj = {};
                    formattedobj.actions = perm.substr(0,perm.indexOf(' '));
                    formattedobj.subject = perm.substr(perm.indexOf(' ') + 1);
                    return formattedobj;
                })
            }
            console.log(formattedRules)
            ability.update(formattedRules);
            break
        case 'ROOT_logoUT_SUCCESS':
            ability.update([{actions: 'read',subject: 'all'}])
            break
    }
 })
}

我在登录和格式化时从 rest-api 获取 rules,并以 casl/vue 格式 localStorage 将其保存到 {actions: 'someAction',subject: 'someSubject'}。 这是
storage.js

export default (options) => (store) => {
 if (localStorage.state) {
    const storedState = JSON.parse(localStorage.state)
    store.replaceState(Object.assign(store.state,storedState))
 }
 return store.subscribe((mutation,state) => {
    if (options.destroyOn && options.destroyOn.indexOf(mutation.type) !== -1) {
        return localStorage.removeItem('state')
    }
    const newState = options.storedKeys.reduce((map,key) => {
        map[key] = state[key]
        return map
    },{});
    localStorage.state = JSON.stringify(newState)
 })
}


store.js

/*
 * FOR USER PERMISSIONS MANAGEMENT ON UI */
 import {Ability} from '@casl/ability'
 import abilityPlugin from "@/shared/store/ability"
 import storage from "@/shared/store/storage";
 ...
 export default new Vuex.Store({
    plugins: [
      storage({
        storedKeys: ['token','rules'],destroyOn: ['ROOT_logoUT_SUCCESS']
      }),abilityPlugin
    ],...
 mutations: {
    ROOT_LOGIN_SUCCESS(state,data) {
        let formattedRules = [];
        if (data.permissions.length > 0) {
            formattedRules = data.permissions.map(perm => {
                let formattedobj = {};
                formattedobj.actions = perm.substr(0,perm.indexOf(' '));
                formattedobj.subject = perm.substr(perm.indexOf(' ') + 1);
                return formattedobj;
            })
        }
        state.rules = formattedRules;
        state.token = data.token;
    },ROOT_logoUT_SUCCESS(state) {
        state.rules = [];
    },},...
 getters: {
     ability() {
         return new Ability()
     }
  },}

main.js

/*
* FOR USER PERMISSIONS MANAGEMENT ON UI */
 import {abilitiesPlugin,Can} from '@casl/vue'
 Vue.use(abilitiesPlugin,store.getters.ability)
 Vue.component('Can',Can);

在 Vue 组件模板中我是这样使用的
index.vue

          <v-btn
            v-if="$can('delete','department')"
            color="error"
            dark
            @click="uiShowConfirm({content: 'Are you sure?',callBack: deleteConfirmed})"
        >
            <v-icon class="mr-2">mdi-delete</v-icon>
            Delete
        </v-btn>

但它正在返回 false
非常感谢一些帮助!
我已经像这样保存了 rules

enter image description here

解决方法

我使用的是 win_shell: Start-ScheduledTask -TaskName {{task}} win_shell: Stop-ScheduledTask -TaskName {{task}} @casl/ability@5.2.2
正如@SergiiStotskyi 在评论中所说

如果 @casl/vue@1.2.2 为 null,则表示 casl 不是提供的操作/主题对的规则。据我所知,relevantRuleFor 对象的形状是错误的。动作在 v4 中被弃用,在 v5 中被删除。尝试将 rule 替换为 actions

action 更改为 actions 后有效。

谢谢@SergiiStotskyi
Casl 是一个很棒的库