Skip to content
Branch: master
Find file History
Permalink
Type Name Latest commit message Commit time
..
Failed to load latest commit information.
spec feat(vue): adds `passThrough` prop to `Can` Nov 25, 2018
src
.npmignore
.npmrc Revert "feat(react:can): updates typescript declarations" Sep 3, 2018
CHANGELOG.md
LICENSE docs(packages): updates license year Mar 21, 2018
README.md docs(Vue): fixes grammatical updates. (#120) [skip ci] Oct 19, 2018
index.d.ts
package-lock.json chore(deps): lock file maintenance Mar 25, 2019
package.json

README.md

CASL Vue @casl/vue NPM version CASL Documentation CASL Join the chat at https://gitter.im/stalniy-casl/casl

This package allows integrating @casl/ability into a Vue application. So, you can show or hide UI elements based on user ability to see them.

Installation

npm install @casl/vue @casl/ability

Getting Started

1. Including plugin

This package provides a Vue plugin which defines $ability object and $can method for all components

import { abilitiesPlugin } from '@casl/vue'
import Vue from 'vue'

Vue.use(abilitiesPlugin)

2. Defining Abilities

By default, the $ability object is an empty Ability instance. So you either need to update it or provide your own. In case you want to provide your own, just define it using AbilityBuilder or whatever way you prefer:

// ability.js
import { AbilityBuilder } from '@casl/ability'

export default AbilityBuilder.define(can => {
  can('read', 'all')
})

And just pass it as an argument to abilitiesPlugin:

import { abilitiesPlugin } from '@casl/vue'
import Vue from 'vue'
import ability from './ability'

Vue.use(abilitiesPlugin, ability)

Alternatively, you can just update an existing instance, for example, in the SignIn.vue component when receiving a rules list from a server API (or other sources).

<template>
  <form @submit.prevent="login">
    <input type="email" v-model="email" />
    <input type="password" v-model="password" />
    <button type="submit">Login</button>
  </form>
</template>

<script>
  export default {
    name: 'SignIn',
    data: () => ({
      email: '',
      password: ''
    }),
    methods: {
      login() {
        const { email, password } = this

        return fetch('path/to/api/login', { method: 'POST', body: JSON.stringify({ email, password }) })
          .then(response => response.json())
          .then(session => this.$ability.update(session.rules))
      }
    }
  }
</script>

Obviously, in this case your server API should provide the list of user abilities in the rules field of the response. See the @casl/ability package for more information on how to define abilities.

3. Check permissions in templates

To check permissions in any component you can use the $can method:

<template>
  <div v-if="$can('create', 'Post')">
    <a @click="createPost">Add Post</a>
  </div>
</template>

See casl-vue-example and casl-vuex-example for more examples.

4. Provide ability for a components tree

Another way to provide an Ability instance is to pass it as option into your root component:

// main.js

import App from './App'
import ability from './ability'

new Vue({
  store,
  router,
  ability,
  render: h => h(App)
}).$mount('#app')

That instance will be available under the $ability property, and the $can method will use it to check permissions. That way, you can also provide a different ability for a component's subtree.

// TodoList.vue

<template>...</template>
<script>
  import { AbilityBuilder } from '@casl/ability'

  export default {
    name: 'TodoList',
    ability: AbilityBuilder.define(can => {
      ...
    })
  }
</script>

Note: I don't recommend trying to manage more than one Ability instance in the app because this contradicts to the main goal of CASL: keep all permissions in a single place and manage them from the single location (Ability instance).

5. Can component

There is an alternative way you can check your permissions in the app by using the Can component. To enable this feature you need to register it globally:

import Vue from 'vue'
import { Can } from '@casl/vue'

Vue.component('Can', Can)

Now, instead of using v-if="$can(...)", we can do this:

<template>
  <can I="create" a="Post">
    <a @click="createPost">Add Post</a>
  </can>
</template>

Property names and aliases

As you can see from the code above, the component name and its property names and values create an English sentence, basically a question. For example, the code above reads as Can I create a Post.

There are several other property aliases which allow constructing a readable question:

  • use the a alias when you check by Type
<Can I="read" a="Post">...</Can>
  • use the of alias instead of a when you check by subject field
<Can I="read title" of="Post">...</Can>

<!-- or when checking on instance. `post` is an instance of `Post` class (i.e., model instance) -->

<Can I="read title" :of="post">...</Can>
  • use the this alias instead of of and a when you check action on instance
<!-- `post` is an instance of `Post` class (i.e., model instance) -->

<Can I="read" :this="post">...</Can>
  • use do and on if you are bored and don't want to make your code more readable :)
<!-- `post` is an instance of `Post` class (i.e., model instance) -->

<Can do="read" :on="post">...</Can>

<!-- or per field check -->
<Can do="read title" :on="post">...</Can>
  • use not when you want to invert the render method (renders children only if user can't read a post)
<Can not I="read" a="Post">...</Can>

Want to help?

Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on guidelines for contributing

License

MIT License

You can’t perform that action at this time.