Reputation: 382
I am using @casl/vue plugin for user permissions management in vue cli project as shown in this sample repo by casl plugin author sample(vue-blog). Here is my code
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
}
})
}
I am getting rules
from rest-api on login and formatting and saving it to localStorage
in casl/vue format {actions: 'someAction', subject: 'someSubject'}
.
Here is
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)
})
}
and 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);
Inside Vue component template I am using it like this
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>
But it is returning false
Some help is really appreciated!
I have saved rules
like this
Upvotes: 2
Views: 3304
Reputation: 382
I was using @casl/[email protected]
and @casl/[email protected]
As said in the comments by @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 ofrule
object is wrong. actions was deprecated in v4 and removed in v5. Try to replaceactions
withaction
After changing actions
to action
that worked.
Thanks @SergiiStotskyi
Casl is a great library
Upvotes: 2