96 lines
3.5 KiB
TypeScript
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
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|