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

Casl/vue $can function is returning false, but user has that permission

我在 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

我正在使用 @casl/ability@5.2.2@casl/vue@1.2.2
正如@SergiiStotskyi

的评论中所说

If you get null for relevantRuleFor it means that casl doesn’t a rule for provided action/subject pair. From what I can tell is that the shape of rule object is wrong. actions was deprecated in v4 and removed in v5. Try to replace actions with action

actions 更改为 action 后有效。

谢谢@SergiiStotskyi
Casl 是一个很棒的图书馆