Vue Access Control List (Vue 2)
Vue-acl is a plugin designed for Vue.js 2 applications to manage user access permissions for components and routes. It provides a structured way to define global and local access rules using a fluent API (`AclRule`) with `or` and `and` conditions. The package, currently at version 4.1.10, facilitates integrating an Access Control List (ACL) system by allowing developers to specify initial permissions, handle unauthorized route access, and dynamically update user permissions via middleware. While effective for Vue 2 projects, the broader Vue ecosystem has largely transitioned to Vue 3, making this package primarily relevant for maintaining existing Vue 2 applications, as its development and compatibility are centered around the older Vue version.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'check')
cause The `$acl` instance was not properly injected into the Vue application context.fixVerify that `acl` is passed to the root Vue instance: `new Vue({ ..., acl, ... }).$mount('#app')`, and that `Vue.use(AclInstaller)` was called. -
Rule 'myRule' not found or not applying correctly in route meta.
cause An `AclRule` instance was not correctly created or generated for the route meta, or a `globalRule` name was misspelled.fixFor direct `AclRule` instances in `meta.rule`, ensure it's `new AclRule('permission').generate()`. For `globalRules`, ensure the string name matches exactly, e.g., `meta: { rule: 'isAdmin' }`. -
Navigation fails or redirects unexpectedly when changing routes.
cause The `notfound` property in `AclCreate` might be misconfigured, or the `middleware` is prematurely calling `acl.change()` with an incorrect permission.fixCheck the `notfound` path and `forwardQueryParams` setting. Debug the `middleware` function to ensure `acl.change()` is called with the intended permission only after successful authentication or role determination.
Warnings
- breaking This package is explicitly designed for Vue.js 2.x. It is not compatible with Vue 3.x due to significant changes in Vue's plugin API and reactivity system (e.g., `Vue.use` vs `app.use`). Attempting to use it in a Vue 3 project will result in runtime errors.
- gotcha Forgetting to call `.generate()` on `AclRule` instances when defining rules (e.g., in `globalRules` or `meta.rule`) will lead to rules not being properly compiled and applied, resulting in unexpected permission checks.
- gotcha The `middleware` function in `AclCreate` is an asynchronous method that executes on every route change. Long-running or inefficient operations within this middleware can significantly impact navigation performance.
- gotcha The `$acl.check()` and `$acl.not.check()` methods in templates rely on the `acl` instance being correctly injected into the root Vue instance. If `acl` is not passed to `new Vue({})`, these methods will be undefined.
Install
-
npm install vue-acl -
yarn add vue-acl -
pnpm add vue-acl
Imports
- AclInstaller
const AclInstaller = require('vue-acl').AclInstallerimport { AclInstaller } from 'vue-acl' - AclCreate
import AclCreate from 'vue-acl'
import { AclCreate } from 'vue-acl' - AclRule
import { Rule } from 'vue-acl'import { AclRule } from 'vue-acl'
Quickstart
import Vue from 'vue';
import Router from 'vue-router';
import App from './App.vue';
import { AclInstaller, AclCreate, AclRule } from 'vue-acl';
// 1. Define your Vue Router instance
Vue.use(Router);
const router = new Router({
routes: [
{
path: '/',
name: 'public',
component: { template: '<div>Public Page <button v-if="$acl.check(\'admin\')">Admin Button</button></div>' },
meta: { rule: 'isPublic' }
},
{
path: '/admin',
name: 'admin',
component: { template: '<div>Admin Page <button v-if="$acl.not.check(\'public\')">Only Admin Button</button></div>' },
meta: { rule: new AclRule('admin').generate() }
},
{
path: '/error',
name: 'notfound',
component: { template: '<div>404 Not Found</div>' },
meta: { rule: '*' }
}
]
});
// 2. Install vue-acl plugin
Vue.use(AclInstaller);
// 3. Create your Acl instance
const acl = new AclCreate({
initial: 'public',
notfound: {
path: '/error',
forwardQueryParams: true
},
router,
acceptLocalRules: true,
globalRules: {
isAdmin: new AclRule('admin').generate(),
isPublic: new AclRule('public').or('admin').generate()
},
middleware: async acl => {
// Simulate API call for user permissions
await new Promise(resolve => setTimeout(resolve, 500));
// In a real app, you'd fetch user roles from an API
const userRole = process.env.VUE_APP_USER_ROLE ?? 'public'; // Example: 'admin' or 'public'
acl.change(userRole);
}
});
// 4. Mount your Vue app with router and acl
Vue.config.productionTip = false;
new Vue({
router,
acl,
render: h => h(App)
}).$mount('#app');
// App.vue (minimal for demonstration)
// <template><div><router-link to="/">Public</router-link> | <router-link to="/admin">Admin</router-link><router-view /></div></template>
// <script>export default { name: 'App' }</script>