Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A simple unopinionated Vue plugin for managing user roles and permissions, access-control list (ACL) and role-based access control (RBAC).

NotificationsYou must be signed in to change notification settings

victorybiz/vue-simple-acl

Repository files navigation

A simple unopinionated Vue plugin for managing user roles and permissions, access-control list (ACL) and role-based access control (RBAC).

VersionVue 2Vue 3NPM Total DownloadsNPM Monthly DownloadsNPM bundle size (scoped version)License

Table of Contents


Features

  • Vue 2 and Vue 3 support
  • Simple but robust and power ACL plugin
  • Manage roles and permissions with ease.
  • Lightweight (<3 kB zipped)
  • Componentv-can directive
  • Global$can helper function
  • Sematic alias methods and directives of different verb for directive and helper function. E.gv-role,v-permission,$acl.permission(),$acl.anyRole(), etc.
  • Middleware support forVue Router throughmeta property.
  • Support user data from plain object, pinia/vuex store and asynchronous function.
  • Reactive changes of abilities and permissions
  • Define custom ACL rules
  • Fully Typecript: The source code is written entirely in TypeScript.
  • Fully configurable

Installation

NPM

npm install vue-simple-acl

Yarn

yarn add vue-simple-acl

CDN

UNPKGJSDelivr

Usage

Usage with Vue 3

// src/main.js  OR  src/main.tsimport{createApp}from'vue'importAppfrom'./App.vue'importrouterfrom'./store';importstorefrom'./store';importaclfrom'./acl';// import the instance of the defined ACLconstapp=createApp(App);app.use(router);app.use(store);app.use(acl);// install vue-simple-aclapp.mount("#app");

Usage with Vue 2

In Vue 2, when using User data from reactive Store/Pinia/Vuex wrapped withcomputed() function, which is available in Vue 3 as module by default but not in Vue 2, make sure to install@vue/composition-api first and change the imported module to:import { computed } from '@vue/composition-api'

// src/main.js  OR  src/main.tsimportVuefrom'vue'importAppfrom'./App.vue'importrouterfrom'./router';importstorefrom'./store';importaclfrom'./acl';// import the instance of the defined ACLVue.config.productionTip=false;Vue.use(acl);// install vue-simple-aclnewVue({  router,  store,render:h=>h(App),}).$mount('#app')

ACL Rules File

For readability, it is recommend to defined your ACL rules in a separate file.

// src/acl/index.js  OR  src/acl/index.ts// Import router if you are using the middleware on Vue Routerimportrouterfrom"../router";// Import store if you are using reactive Store/Pinia/Vuex as User data sourceimportstorefrom"../store";// ----- VUE 3 Imports -----import{computed}from'vue';// For VUE 3import{createAcl,defineAclRules}from'vue-simple-acl';// ----- VUE 2 Imports -----importVuefrom'vue';importVueCompositionAPIfrom'@vue/composition-api';// Ensure this is installedVue.use(VueCompositionAPI);// VueCompositionAPI must be used as plugin before any function, otherwise see your console if warning/errprimport{computed}from'@vue/composition-api';// import computed functionimport{createAcl,defineAclRules}from'vue-simple-acl';// ---------------// The Vue Simple ACL option 'user' can be a user OBJECT, FUNCTION returning a user object// or an Asynchronous function returning a PROMISE of user object, suitable for performing fetch from API.// USER EXAMPLE 1: User {OBJECT}constuser={id:1,name:'Victory Osayi',is_editor:true,is_admin:false,// you can have role based permission list or access control list possibly from databasepermissions:['admin','owner','moderator','create-post','edit-post','delete-post']}// USER EXAMPLE 2: User object from a {FUNCTION} or computed property like from Pinia/Vuex Store// Suitable if you already has an existing logics authenticating and saving user data to Pinia/Vuex Storeconstuser2=computed(()=>store.state.auth.user);// USER EXAMPLE 3; User object from an Asynchronous {FUNCTION} / {PROMISE}:// Using Async/Promise requires instance of vue-router, the function will be auto hooked to beforeEach() peroperty of vue-routerconstuser3=()=>{constauthUserId=1;// ID of authenticated userreturnaxios.get(`api/users/${authUserId}`).then((response)=>response.data);}construles=()=>defineAclRules((setRule)=>{// setRule('unique-ability', callbackFunction(user, arg1, arg2, ...) { });// setRule(['unique-ability-1', 'unique-ability-2'], callbackFunction(user, arg1, arg2, ...) { });// Define a simple rule for ability with no argumentsetRule('create-post',(user)=>user.is_admin||user.is_editor);setRule('is-admin',(user)=>user.is_admin);setRule('is-editor',(user)=>user.is_editor);// Define a simple rule for ability with an argumentsetRule('edit-post',(user,post)=>user.id===post.user_id);setRule('delete-post',(user,post)=>{returnuser.id===post.user_id||user.is_admin;});// Define rule for array of multiple abilities that share same arguments and callback functionsetRule(['publish-post','unpublish-post'],(user,post)=>user.id===post.user_id);// Define rule for ability with multiple argumentssetRule('hide-comment',(user,post,comment)=>{returnuser.is_admin||user.id===post.user_id||(user.id===comment.user_id&&post.id===comment.post_id);});setRule('moderator',(user)=>user.permissions&&user.permissions.includes('moderator'));});constsimpleAcl=createAcl({  user,// short for user: user  rules,// short for rules: rules  router,// OPTIONAL, short for router: router// other optional vue-simple-acl options here... See Vue Simple ACL Options below});exportdefaultsimpleAcl;

Usage in component

Thev-can directive can be used in different ways and you can apply one or more modifiers that alters the behaviour of the directive.

<buttonv-can:create-post>Create Post</button><buttonv-can:edit-post="{ id: 100, user_id: 1, title: 'First Post' }">Edit</button><buttonv-can:edit-post="postData">Edit</button>

Alternative you can use the sematic alias;

<buttonv-permission:create-post>Create Post</button><buttonv-role:admin>Create Post</button><buttonv-role-or-permission="['admin', 'create-post']">Edit</button>

hide modifier

This is the default behaviour of thev-can directive, it remove the component or element from the DOM more likev-if.You're not required to apply it unless you want to explicitly state the behavior.

<buttonv-can:edit-post.hide="postData">Edit</button>

disable modifier

Thedisable modifier applies the disabled attribute to the tag, e.g. to disable a button or input that you are not allowed to use or edit respectively.

<buttonv-can:edit-post.disable="postData">Edit</button><inputv-can:edit-post.disable="post"v-model="postTitle"type="text">

readonly modifier

Thereadonly modifier applies the readonly attribute to the tag, e.g. to make an input read only if you don't have permission to edit.

<inputv-can:edit-post.readonly="post"v-model="postTitle"type="text">

not modifier

Thenot modifier reverses the ACL query. In this example only if you cannot delete the post the div element is shown.

<divv-can:delete-post.not="postData">You can not delete post created by you, ask admin for help.</div>

any modifier

By defaultv-can directive with value that contains array of multiple abilities and ability arguments will be authorized if all specified abilities passes.Theany modifier authorized if atleast one or any of specified abilities and ability arguments passes.

<!-- Authorized if both abilities passes --><buttonv-can="['create-post', ['edit-post', post]]">Create Post</button><!-- Authorized if any of the abilities passes --><buttonv-can.any="[['edit-post', post], ['delete-post', post]]">Manage Post</button>

Using helper function in component

You can also use the helper function $can directly in component and #"auto" data-snippet-clipboard-copy-content="<form v-if="$can('edit-post', post)"> <input type="text" :value="post.title"> ...</form>">

<formv-if="$can('edit-post', post)"><inputtype="text":value="post.title">    ...</form>

or in Option API

if(this.$can('edit-post',post)){axios.put(`/api/posts/${post.id}`,postData)}

Using helper function insetup Vue'sComposition API

The introduction ofsetup and Vue'sComposition API, open up new possibilities but to be able to get the full potential out of Vue Simple ACL, we will need to use composable functions to replace access to this.

import{useAcl}from'vue-simple-acl';exportdefault{setup(){constacl=useAcl();if(acl.can('edit-post',post)){axios.put(`/api/posts/${post.id}`,postData)}if(acl.can('hide-comment',[post,comment])){// Execute this block if user can hide comment of a post}if(acl.can.not('edit-post',post)){// Execute this block if user can not edit post}if(acl.can.any(['is-admin','is-editor'])){// Execute this block if user is admin OR is editor}if(acl.can.any(['is-admin',['delete-post',post]])){// Execute this block if user is admin OR can delete post}// Get data of the defined ACL User being validatedconstuser=acl.user;constuser=acl.getUser();}}

Middleware forVue Router

To integrate Vue Router, hook up the instance ofvue-router'screateRouter({..}) during setup of the Vue Simple ACL.

constsimpleAcl=createAcl({  user,// short for user: user  rules,// short for rules: rules  router,// short for router: routeronDeniedRoute:'/unauthorized'// OR { path: '/unauthorized' } OR { name: 'unauthorized', replace: true} or '$from'});app.use(simpleAcl);

You configure routes by addingcan meta property to the route. E.g. if a router requires create post permission:

{path:'posts/create',name:'createPost',component:CreatePost,meta:{can:'create-post',onDeniedRoute:'/unauthorized'// value of onDeniedRoute option will be used if not set}}

If you have a rule that requires multiple abilities, you can do the following:

{path:'posts/create',name:'createPost',component:CreatePost,meta:{can:['is-admin','create-post'],onDeniedRoute:{name:'unauthorizedPage',replace:true}}}

or usingnot modifier

{path:'posts/create',name:'createPost',component:CreatePost,meta:{notCan:'moderator',onDeniedRoute:{name:'unauthorizedPage',replace:true}}}

or usingany modifier

{path:'posts/create',name:'createPost',component:CreatePost,meta:{anyCan:['is-admin','create-post'],onDeniedRoute:{name:'unauthorizedPage',replace:true}}}

You can also have an async evaluation by providing a callback that returns a promise the following:

{path:'posts/:postId',component:PostEditor,meta:{can:(to,from,can)=>{returnaxios.get(`/api/posts/${to.params.id}`).then((response)=>can('edit-post',response.data));},onDeniedRoute:'/unauthorized'}}

or usingany modifier

{path:'posts/:postId/publish',component:ManagePost,meta:{anyCan:(to,from,anyCan)=>{returnaxios.get(`/api/posts/${to.params.id}/publish`).then((response)=>anyCan(['is-admin',['edit-post',response.data]]));},onDeniedRoute:'/unauthorized'}}

or get the data of the defined ACL user in the evaluations by passinguser as the optionalfourth argument to the defined ACL meta function

{path:'posts/:postId/publish',component:ManagePost,meta:{anyCan:(to,from,anyCan,user)=>{returnaxios.get(`/api/users/${user.id}/posts/${to.params.id}/publish`).then((response)=>anyCan(['is-admin',['edit-post',response.data]]));},onDeniedRoute:'/unauthorized'}}

onDeniedRoute meta property

By default if you omit the 'onDeniedRoute' property from the a routes meta a denied check will redirect to a value of Vue Simple Acl'screateAcl optiononDeniedRoute which is/ by default. You can change this behaviour by setting thecreateAcl optiononDeniedRoute. This is useful if you use the package in an authentication or authorization flow by redirecting to unauthorized page if access is denied.

You can also use an object for more options (see guards section in docs):

onDeniedRoute:{ path:'/login': replace:true}

This will use replace rather than push when redirecting to the login page.

$from as valueonDeniedRoute

onDeniedRoute:'$from'

You can set the onDeniedRoute to the special value'$from' which will return the user to wherever they came from

Vue Routermeta Properties

Property NameTypeDefaultDescription
can orallCanstring ORarray of abilities ORfunction of asynchronous evaluation:(to, from, can, user?) => {}NoneEquivalent of$can() andv-can=""
notCan orcanNotstring ORarray of abilities ORfunction of asynchronous evaluation:(to, from, notCan, user?)NoneEquivalent of$can.not() andv-can.not=""
anyCan orcanAnystring ORarray of abilities ORfunction of asynchronous evaluation:(to, from, anyCan, user?)NoneEquivalent of$can.any() andv-can.any=""
onDeniedRoutestring ORobject ofroute() optionValue of the default optiononDeniedRouteA route to redirect to when `can

Semantic Alias directives and methods

Vue Simple ACL also provides some directives and methods in different verb as alias for default directive and helper function. You can use these aliases in place ofv-can directive,$can helper function and vue routercan: meta property for better semantic. See below table.

Alias NameUsage
PermissionAs Directives:
v-permission:create-post
v-permission="'create-post'"
v-permission.not="'create-post'"
v-permission.any="['create-post', ['edit-post', post]]"

In Component:
$acl.permission('create-post')
$acl.notPermission('create-post')
$acl.anyPermission(['create-post', ['edit-post', post]])

In Option API:
this.$acl.permission('create-post')
this.$acl.notPermission('create-post')
this.$acl.anyPermission(['create-post', ['edit-post', post]])

In Composition API/setup():
const acl = useAcl();
acl.permission('create-post')
acl.notPermission('create-post')
acl.anyPermission(['create-post', ['edit-post', post]])

In Vue Routermeta Property:
permission: 'create-post'
notPermission: ['create-post', 'create-category']

anyPermission: (to, from, anyPermission) => {
  return axios.get(`/api/posts/${to.params.id}`)
  .then((response) => anyPermission(['create-post', ['edit-post', response.data]]));
}
RoleAs Directives:
v-role:admin
v-role="'admin'"
v-role.not="'editor'"
v-role.any="['admin', 'editor']"

In Component:
$acl.role('admin')
$acl.notRole('editor')
$acl.anyRole(['admin', 'editor'])

In Option API:
this.$acl.role('admin')
this.$acl.notRole('editor')
this.$acl.anyRole(['admin', 'editor'])

In Composition API/setup():
const acl = useAcl();
acl.role('admin')
acl.notRole('editor')
acl.anyRole(['admin', 'editor'])

In Vue Routermeta Property:
role: 'admin'
notRole: 'editor'
anyRole: ['admin', 'editor']
Role Or PermissionAs Directives:
v-role-or-permission="['admin', 'create-post']"
v-role-or-permission.not="['editor', 'create-post']"
v-role-or-permission.any="['admin', 'create-post', ['edit-post', post]]"

In Component:
$acl.roleOrPermission(['admin', 'create-post'])
$acl.notRoleOrPermission(['editor', 'create-post'])
$acl.anyRoleOrPermission(['admin', 'create-post', ['edit-post', post]])

In Option API:
this.$acl.roleOrPermission(['admin', 'create-post'])
this.$acl.notRoleOrPermission(['editor', 'create-post'])
this.$acl.anyRoleOrPermission(['admin', 'create-post', ['edit-post', post]])

In Composition API/setup():
const acl = useAcl();
acl.roleOrPermission(['admin', 'create-post'])
acl.notRoleOrPermission(['editor', 'create-post'])
acl.anyRoleOrPermission(['admin', 'create-post', ['edit-post', post]])

In Vue Routermeta Property:
roleOrPermission: ['admin', 'create-post']
notRoleOrPermission: ['editor', 'create-post', 'create-category']

anyRoleOrPermission: (to, from, anyRoleOrPermission) => {
  return axios.get(`/api/posts/${to.params.id}`)
  .then((response) => anyRoleOrPermission(['admin', 'create-post', ['edit-post', response.data]]));
}
UserGet the data of the defined ACL user.

In Component:
$acl.user; // returns user object
$acl.getUser(); // returns user object

In Option API:
this.$acl.user; // returns user object
this.$acl.getUser(); // returns user object

In Composition API/setup():
const acl = useAcl();
acl.user; // returns user object
acl.getUser(); // returns user object

In Vue Routermeta Property:
Passuser as the fourth argument to the defined ACL meta function

roleOrPermission: (to, from, roleOrPermission, user) => {
  return axios.get(`/api/users/${user.id}/posts/${to.params.id}`)
  .then((response) => roleOrPermission(['admin', ['edit-post', response.data]]));
}

Vue Simple ACL Options

can be a user OBJECT, FUNCTION returning a user object// or an Asynchronous function returning a PROMISE of user object, suitable for performing fetch from API.

Option NameTypeRequiredDefaultDescription
userobject or a `functionasync function/Promisereturning user object. <br> *Using Async/Promise requires instance ofvue-router, the function will be auto hooked tobeforeEach()` peroperty of vue-router.*YesNone
rulesfunctionYesNonefunction returning instance ofdefineAclRules() e.g() => defineAclRules((setRule) => {...}
directiveNameobject or afunction returning user objectNo'can'You can set a custom directive name if the default name conflicts with other installed plugins. e.g'custom-can' then in component likev-custom-can=""
helperNameobject or afunction returning user objectNo'$can'You can set a custom helper name if the default name conflicts with other installed plugins. e.g'$customCan', then use in component like'$customCan()' or'$customCan.not()'
enableSematicAliasbooleanNotrueYou can enable or disable the sematic alias directives and methods e.gv-role,v-permission,$acl.*, etc.See Semantic Alias
routervue-routerNoNoneInte
onDeniedRoutestring orobjectNo/A route to redirect to whencan evaluation is denied. e.g string path'/unauthorized' OR router option{ path: '/unauthorized' } OR{ name: 'unauthorizedPage', replace: true } OR special value'$from' which returns back to the request URI

TODO

  1. Chore: Write basic tests
  2. A documentation page with vitepress

🤝 Contributing

  1. Fork this repository.
  2. Create new branch with feature name.
  3. Go to example folder and runnpm install andnpm run serve.
  4. The plugin sources files is located in/src/*.
  5. Commit and set commit message with feature name.
  6. Push your code to your fork repository.
  7. Create pull request. 🙂

⭐️ Support

If you like this project, You can support me with starring ⭐ this repository,buy me a coffee orbecome a patron.

📄 License

MIT

Developed byVictory Osayi with ❤️ and ☕️ from Benin City, Edo, Nigeria.

About

A simple unopinionated Vue plugin for managing user roles and permissions, access-control list (ACL) and role-based access control (RBAC).

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors2

  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp