Client side
General
Thanks to the awesome work of stalniy and his isomorphic approach, you can use the packages @casl/ability
, @casl/angular
, @casl/react
, @casl/vue
and @casl/aurelia
. It's pretty straight forward.
Feathers client
Since we defined the ability
and rules
in the authentication:after/create
hook (see: Getting Started), we can use it on the client side.
Angular
npm install @casl/angular @casl/ability
# or
yarn add @casl/angular @casl/ability
You're interested how it works for angular
? Sorry, I can't help with that, since I just use it with Vue
. As a starting point, see #Feathers client and @casl/angular. That will get you closer to the goal. If you got a working example anyway, I would be curious, how it works. Please create a issue or pull request and let me know.
React
npm install @casl/react @casl/ability
# or
yarn add @casl/react @casl/ability
You're interested how it works for react
? Sorry, I can't help with that, since I just use it with Vue
. As a starting point, see #Feathers client and @casl/react. That will get you closer to the goal. If you got a working example anyway, I would be curious, how it works. Please create a issue or pull request and let me know.
FeathersVuex
Installation
npm install @casl/vue @casl/ability
# or
yarn add @casl/vue @casl/ability
FeathersVuex
differs from the general implementation. It's based on the huge amount of sugar @marshallswain has spread on top of that.
There are some things we want to ensure:
- get rules on
authenticate
- delete rules on
logout
The best way to keep the rules, is in our vuex
-store. So first, we add a custom casl
-vuex-plugin.
The vuex-plugin
// src/store/vuex.plugin.casl.js
import { Ability } from '@casl/ability';
import { BaseModel } from '@/src/store/feathers/client.js';
const detectSubjectType = (subject) => {
if (typeof subject === 'string') return subject;
if (!(subject instanceof BaseModel)) return undefined;
return subject.constructor.servicePath;
}
const resolveAction = createAliasResolver({
update: 'patch', // define the same rules for update & patch
read: ['get', 'find'], // use 'read' as a equivalent for 'get' & 'find'
delete: 'remove' // use 'delete' or 'remove'
});
const ability = new Ability([], { detectSubjectType, resolveAction });
const caslPlugin = (store) => {
store.registerModule('casl', {
namespaced: true,
state: {
ability: ability,
rules: []
},
mutations: {
setRules(state, rules) {
state.rules = rules;
state.ability.update(rules);
}
}
});
store.subscribeAction({
after: (action, state) => {
if (action.type === 'auth/responseHandler') {
const { rules } = action.payload;
if (!rules || !state.auth.user) {
store.commit('casl/setRules', []);
return;
}
store.commit('casl/setRules', rules);
} else if (action.type === 'auth/logout') {
store.commit('casl/setRules', []);
}
}
});
};
export {
ability,
caslPlugin
};
Insert the vuex-module
// src/store/index.js
import { caslPlugin } from '@/store/vuex.plugin.casl'; // your previously defined file
export const store = new Vuex.Store({
plugins: [
caslPlugin,
...
],
...
});
register the @casl/vue plugin
Now it's more like conventional @casl/vue
work and we're almost done. It's mostly like the Getting started of @casl/vue
// main.js
import Vue from 'vue';
import { abilitiesPlugin } from '@casl/vue';
import { store } from '@/store';
Vue.use(abilitiesPlugin, store.state.casl.ability );
Just use it
From here on, just follow the instructions at @casl/vue. For example:
<template>
<div v-if="$can('create', 'posts')">
<a @click='createPost'>Add Post</a>
</div>
<!-- or even a specific item -->
<div>{{ post.title }}</div>
<button :disabled="$can('update', post)" @click="task.save"></button>
</template>
<script>
export default {
data() {
return {
task: new this.$$FeathersVuex.api.Task({}),
}
}
}
</script>
Aurelia
npm install @casl/aurelia @casl/ability
# or
yarn add @casl/aurelia @casl/ability
You're interested how it works for aurelia
? Sorry, I can't help with that, since I just use it with Vue
. As a starting point, see #Feathers client and @casl/aurelia. That will get you closer to the goal. If you got a working example anyway, I would be curious, how it works. Please create a issue or pull request and let me know.
Others
The listed examples above don't fit your needs? Sorry, I can't help with that, since I just use it with Vue
. As a starting point, see #Feathers client. That will get you closer to the goal. If you got a working example anyway, I would be curious, how it works. Please create a issue or pull request and let me know.