Files
web-antrean/plugins/permission.ts
T

96 lines
3.5 KiB
TypeScript

import { defineNuxtPlugin } from '#app';
import { usePermissionStore } from '~/stores/permissionStore';
import type { HakAksesMenu } from '~/server/utils/schemas/permissionSchema';
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.directive('permission', {
mounted(el, binding) {
const permissionStore = usePermissionStore();
// Determine what action to check based on modifiers or value.
// If it's an array: v-permission="['canEdit', 'canDelete']"
// If it's a string: v-permission="'canEdit'"
const permissionsRequired = Array.isArray(binding.value) ? binding.value : [binding.value];
// Determine the menuKey context.
// In a real app, you might inject this context from the page component.
// For now, we extract it from the current route name.
const currentRoute = useRoute();
let menuKey = "";
if (currentRoute && currentRoute.name) {
// Convert vue-router route name to our menuKey format
menuKey = currentRoute.name.toString().toLowerCase().replace(/_|-/g, '-');
}
let hasPermission = true;
for (const action of permissionsRequired) {
if (!permissionStore.can(menuKey, action as keyof HakAksesMenu)) {
hasPermission = false;
break;
}
}
if (!hasPermission) {
if (binding.arg === 'disable') {
el.disabled = true;
el.classList.add('v-btn--disabled'); // If it's vuetify button
el.setAttribute('title', 'Anda tidak memiliki izin untuk aksi ini');
el.style.opacity = '0.5';
el.style.pointerEvents = 'none';
} else {
// Default: hide
el.style.display = 'none';
// Better hide by removing from DOM if possible,
// but display: none is safer for custom directives that don't want to break layout engines
// To truly remove: el.parentNode?.removeChild(el) (but breaks if Vue tries to update it)
}
}
},
updated(el, binding) {
// Handle reactivity if permissions change or route changes
const permissionStore = usePermissionStore();
const permissionsRequired = Array.isArray(binding.value) ? binding.value : [binding.value];
const currentRoute = useRoute();
let menuKey = "";
if (currentRoute && currentRoute.name) {
menuKey = currentRoute.name.toString().toLowerCase().replace(/_|-/g, '-');
}
let hasPermission = true;
for (const action of permissionsRequired) {
if (!permissionStore.can(menuKey, action as keyof HakAksesMenu)) {
hasPermission = false;
break;
}
}
if (!hasPermission) {
if (binding.arg === 'disable') {
el.disabled = true;
el.classList.add('v-btn--disabled');
el.setAttribute('title', 'Anda tidak memiliki izin untuk aksi ini');
el.style.opacity = '0.5';
el.style.pointerEvents = 'none';
} else {
el.style.display = 'none';
}
} else {
// Restore if permission was granted
if (binding.arg === 'disable') {
el.disabled = false;
el.classList.remove('v-btn--disabled');
el.removeAttribute('title');
el.style.opacity = '1';
el.style.pointerEvents = 'auto';
} else {
el.style.display = ''; // Revert to original display
}
}
}
});
});