vue-permission-directive
v3.0.6
Published
A flexible Vue 3 directive for managing user permissions with support for AND, OR, regex, and pattern-based checks.
Downloads
42
Maintainers
Keywords
Readme
🔐 v-permission
Vue directive for controlling element visibility based on user permissions.
Supports dynamic permission checks, customizable strategies, Nuxt, and Pinia.
📦 Installation
npm install vue-permission-directive
# or
yarn add vue-permission-directive🚀 Usage
Register globally (main.ts)
import { createApp } from "vue";
import App from "./App.vue";
import vPermission, {
configurePermissionDirective,
} from "vue-permission-directive";
const app = createApp(App);
configurePermissionDirective({
getUserPermissions: () => ["view_dashboard", "edit_profile"],
});
app.directive("permission", vPermission);
app.mount("#app");👁️ Basic Usage
<!-- Will be shown only if user has 'view_dashboard' permission -->
<button v-permission="'view_dashboard'">Dashboard</button>
<!-- Will be shown if user has ANY of the listed permissions -->
<button v-permission="['edit_user', 'delete_user']">Manage User</button>🔄 Dynamic Updates
If user permissions change during runtime, call:
import { clearPermissionCache } from "vue-permission-directive";
clearPermissionCache();🔧 Advanced Configuration
configurePermissionDirective({
getUserPermissions: async () => {
const user = await fetchUser();
return user.permissions;
},
strategy: "some", // or 'every' for AND logic
fallback: "hide", // or 'disable'
});🧪 Development Mode
Enable logging to debug permission checks:
import { setDevelopmentMode } from "vue-permission-directive";
setDevelopmentMode(true);🧠 Custom Strategies
configurePermissionDirective({
strategyFn: (required, userPermissions) => {
return (
userPermissions.includes("super_admin") ||
required.some((p) => userPermissions.includes(p))
);
},
});🎯 Permission Format Types
The directive supports multiple permission formats for flexible permission checking:
1. String Format
<!-- Single permission -->
<button v-permission="'user.read'">View Users</button>
<!-- Wildcard permission (allows everything) -->
<button v-permission="'*'">Super Admin Action</button>2. Array Format (OR Logic)
<!-- User needs ANY of these permissions -->
<button v-permission="['user.edit', 'user.delete', 'admin.manage']">
Manage Users
</button>3. Permission Object Format
For advanced permission logic, use objects with different modes:
<!-- AND Logic: User needs ALL permissions -->
<button
v-permission="{ permissions: ['user.read', 'user.write'], mode: 'and' }"
>
Full User Access
</button>
<!-- OR Logic: User needs ANY permission -->
<button
v-permission="{ permissions: ['admin.dashboard', 'user.manage'], mode: 'or' }"
>
Admin Panel
</button>
<!-- StartWith Logic: Check if user has permissions starting with pattern -->
<button
v-permission="{ permissions: ['admin', 'moderator'], mode: 'startWith' }"
>
Staff Only
</button>
<!-- EndWith Logic: Check if user has permissions ending with pattern -->
<button v-permission="{ permissions: ['.write', '.delete'], mode: 'endWith' }">
Edit Actions
</button>
<!-- Exact Match: Same as 'or' but more explicit -->
<button v-permission="{ permissions: ['posts.publish'], mode: 'exact' }">
Publish Post
</button>
<!-- Regex Logic: Use regex patterns to match permissions -->
<button
v-permission="{ permissions: ['user\\.(read|write|edit)'], mode: 'regex' }"
>
User Operations
</button>4. Mixed Array Format
<!-- Combine strings and objects for complex logic -->
<button
v-permission="[
'super_admin',
{ permissions: ['user.read', 'posts.read'], mode: 'and' },
]"
>
Advanced Access
</button>Permission Modes Reference
| Mode | Description | Example |
| ----------- | ------------------------------------------- | ----------------------------------------------------------- |
| and | ALL permissions must be satisfied | User needs both user.read AND user.write |
| or | ANY permission must be satisfied | User needs admin.dashboard OR user.manage |
| startWith | Any user permission starts with the pattern | User permission admin.users.read matches pattern admin |
| endWith | Any user permission ends with the pattern | User permission posts.create matches pattern .create |
| exact | Exact match (same as basic string check) | User permission must be exactly posts.publish |
| regex | Regular expression matching | User permission matches regex pattern user\.(read\|write) |
🌐 Nuxt Support
Inside plugins/v-permission.client.ts:
import { defineNuxtPlugin } from "#app";
import vPermission, {
configurePermissionDirective,
} from "vue-permission-directive";
export default defineNuxtPlugin((nuxtApp) => {
configurePermissionDirective({
getUserPermissions: () => useAuthStore().permissions,
});
nuxtApp.vueApp.directive("permission", vPermission);
});🧩 Pinia Example
import { useAuthStore } from "@/stores/auth";
configurePermissionDirective({
getUserPermissions: () => useAuthStore().permissions,
});📝 Directive Modifiers
Show/Hide Behavior
<!-- Default: Remove element from DOM when permission denied -->
<button v-permission="'admin.access'">Admin Panel</button>
<!-- Show modifier: Hide element but keep in DOM -->
<button v-permission:show="'user.profile'">Edit Profile</button>Performance Modifiers
<!-- Once modifier: Check permission only once (no reactive updates) -->
<button v-permission.once="'static.permission'">Static Action</button>
<!-- Lazy modifier: Don't watch for permission changes -->
<button v-permission.lazy="'user.read'">User List</button>🔄 Programmatic Permission Checking
You can also check permissions programmatically in your components:
import { hasPermission } from "vue-permission-directive";
export default {
async mounted() {
// Check single permission
const canEdit = await hasPermission("user.edit");
// Check multiple permissions (OR logic)
const canManage = await hasPermission(["user.edit", "user.delete"]);
// Check with advanced logic
const hasAdvancedAccess = await hasPermission({
permissions: ["admin.read", "admin.write"],
mode: "and",
});
if (canEdit) {
this.showEditButton = true;
}
},
};✅ API Reference
v-permission="string | string[] | PermissionObject | (string | PermissionObject)[]"
Required permission(s) to display the element.
configurePermissionDirective(permissions, options?)
| Parameter | Type | Description |
| ------------------------- | --------------------------- | ----------------------------------------------- |
| permissions | string[] \| Ref<string[]> | Array of user permissions or reactive reference |
| options.developmentMode | boolean | Enable debug logging (default: false) |
Core Functions
hasPermission(permission)- Check if user has specific permission(s)setDevelopmentMode(enabled)- Enable/disable debug loggingclearPermissionCache()- Clear cached permissions for dynamic updatesinitPermissionDirectiveIfNeeded()- Initialize permissions from localStorage
Permission Types
export type PermissionMode =
| "and"
| "or"
| "startWith"
| "endWith"
| "exact"
| "regex";
export interface PermissionObject {
permissions: string[];
mode: PermissionMode;
}
export type PermissionValue =
| string
| string[]
| PermissionObject
| (string | PermissionObject)[];🛠️ Best Practices
1. Permission Naming Convention
// ✅ Good: Use hierarchical naming
"user.read";
"user.write";
"user.delete";
"admin.dashboard.view";
"posts.create";
"posts.edit.own";
// ❌ Avoid: Flat or unclear naming
"read";
"edit";
"access";2. Use Appropriate Permission Modes
<!-- ✅ Use 'and' when user needs multiple permissions -->
<button
v-permission="{ permissions: ['user.read', 'user.write'], mode: 'and' }"
>
Full Access
</button>
<!-- ✅ Use 'startWith' for hierarchical permissions -->
<div v-permission="{ permissions: ['admin'], mode: 'startWith' }">
Admin Section
</div>
<!-- ✅ Use regex for complex patterns -->
<button
v-permission="{
permissions: ['posts\\.(create|edit|delete)'],
mode: 'regex',
}"
>
Manage Posts
</button>3. Combine with Route Guards
// router/index.ts
router.beforeEach(async (to, from, next) => {
const requiredPermission = to.meta.permission;
if (requiredPermission && !(await hasPermission(requiredPermission))) {
next("/403");
} else {
next();
}
});4. Handle Permission Updates
// When user permissions change (login, role update, etc.)
const updateUserPermissions = async () => {
// Update permissions in your store
authStore.permissions = await fetchUserPermissions();
// Clear cache to trigger re-evaluation
clearPermissionCache();
};🔍 Debugging
Enable development mode to see detailed permission check logs:
import { setDevelopmentMode } from "vue-permission-directive";
setDevelopmentMode(true);
// Now you'll see logs like:
// [v-permission] Checking permission: user.read
// [v-permission] User permissions: ['user.read', 'user.write']
// [v-permission] Permission granted: true🧪 Testing
Test different permission scenarios:
import { testPermissions } from "vue-permission-directive";
// Run comprehensive tests
await testPermissions();📊 Performance Notes
- Permissions are cached to avoid repeated evaluations
- Use
.oncemodifier for static permissions that don't change - Use
.lazymodifier to disable reactive updates - Clear cache only when permissions actually change
🤝 Contributing
We welcome contributions! Please read our contributing guidelines before submitting PRs.
📄 License
MIT © Kerolos
