tambah menu sideBarMenu , middleware definepagemeta

This commit is contained in:
2025-07-10 12:06:56 +07:00
parent 1b05076317
commit c37759cc8f
16 changed files with 244 additions and 149 deletions
@@ -7,9 +7,9 @@ import { Icon } from '@iconify/vue';
import { useRoute } from 'vue-router';
// MiniSidebar Icons
import MiniSideIcons from './MinIconItems';
//import { useSidebarAccess } from '~/composables/useSidebarAccess'
import { mergeSidebar, mergeSidebarIcon } from '~/composables/sidebarMenu/mergeSidebar';
import sidebarRole from "@/stores/rolePages"; // data dummy
import { useHakAksesStore } from '@/stores/sidebarMenuAkses/useMenuAksesStore'
//import { mergeSidebar, mergeSidebarIcon } from '~/utils/sidebarMenu/mergeSidebar';
//import sidebarRole from "@/stores/rolePages"; // data dummy
const route = useRoute();
@@ -43,18 +43,13 @@ const findTitleByPath = (items: any, path: any) => {
const customizer = useCustomizerStore();
const sidebarMenu = shallowRef(sidebarItems);
//Merge Sidebar dari user api
//sidebarItems dari static sidebar
//sidebarRole dari role user api
const userRole = "admin";
const roleSidebarItems = sidebarRole.filter(item => item.role === userRole);
//filter menu untuk userRole admin
//mergeSidebar (menu awal, menu role user)
const mergedPages = mergeSidebar(sidebarMenu.value, roleSidebarItems[0].pages)
console.log('sidebarMenu', sidebarMenu.value);
console.log('roleSidebarItems', roleSidebarItems[0].pages);
console.log('mergedSidebarMenu', mergedPages);
sidebarMenu.value = mergedPages
const aksesMenuStore = useHakAksesStore();
//ambil data dari store pinia
if (Array.isArray(aksesMenuStore.mergedSidebar) && aksesMenuStore.mergedSidebar.length > 0) {
sidebarMenu.value = aksesMenuStore.mergedSidebar
}
const mergedPages = sidebarMenu.value //ambil data dari store pinia
// sidebarMenu.value = sidebarMenu
const foundId = findTitleByPath(mergedPages, route.path);
@@ -69,12 +64,9 @@ function showData(data: any) {
//Merge Icon dari sidebarMenu api
const sidebarMiniSideIcons = shallowRef(MiniSideIcons);
if (mergedPages !== null) {
sidebarMiniSideIcons.value = mergedPages
const mergedIcon = mergeSidebarIcon(MiniSideIcons, sidebarMiniSideIcons.value)
//console.log('sidebarIcon', MiniSideIcons);
console.log('mergedsidebarIcon', mergedIcon);
sidebarMiniSideIcons.value = mergedIcon
//ambil data dari store pinia
if (Array.isArray(aksesMenuStore.iconItem) && aksesMenuStore.iconItem.length > 0) {
sidebarMiniSideIcons.value = aksesMenuStore.iconItem
}
// MiniSidebar Icons End
@@ -59,10 +59,6 @@ const sidebarItem: menu[] = [
//role: ['admin','user'],
//permission: ['view', 'update', 'create', 'delete'],
},
{
title: 'Blog',
to: '/front-page/blog/posts'
},
{
title: 'Blog Details',
to: '/front-page/blog/early-black-friday-amazon-deals-cheap-tvs-headphones'
@@ -78,6 +74,14 @@ const sidebarItem: menu[] = [
{
title: 'Pricing',
to: '/front-page/pricing'
},
{
title: 'Sample Page',
to: '/sample-page'
},
{
title: 'Sample Page Copy',
to: '/sample-page-copy'
}
]
},
@@ -0,0 +1,5 @@
import { useAccess } from "~/composables/useAccess";
export function usePagePermission(dataUser : string) {
}
+38 -33
View File
@@ -1,47 +1,52 @@
import { useHakAksesStore } from '@/stores/sidebarMenuAkses/useMenuAksesStore'
import { mergeSidebar, mergeSidebarIcon } from '~/composables/sidebarMenu/mergeSidebar';
import { mergeSidebar, mergeSidebarIcon } from '~/utils/sidebarMenu/mergeSidebar';
import sidebarRole from "@/stores/rolePages"; // data dummy
import sidebarItems from '~/components/layout/full/vertical-sidebar/sidebarItem'; //sidebar static dari template
import MiniSideIcons from '~/components/layout/full/vertical-sidebar/MinIconItems';
export function useSidebarAccess(data: any) {
export function useSidebarAccess(dataUser : string) {
const akses = useHakAksesStore()
const sidebarMenu = shallowRef(sidebarItems);
const sidebarMiniSideIcons = shallowRef(MiniSideIcons);
const userRole = "admin";
//console.log('sidebarMenu', sidebarMenu.value);
//userRole = superadmin admin user
const userRole = dataUser;
const roleSidebarItems = sidebarRole.filter(item => item.role === userRole);
const mergedPages = mergeSidebar(sidebarMenu.value, roleSidebarItems[0].pages)
data = mergeSidebarIcon(sidebarMiniSideIcons.value, roleSidebarItems[0].pages)
console.log('mergedPages useSidebarAccess', mergedPages);
return data
//mergeSidebar (menu awal, menu role user)
const mergedPages = mergeSidebar(sidebarMenu.value, roleSidebarItems[0].pages)
//Merge Icon dari sidebarMenu api
let mergedIcons = null;
if (mergedPages !== null) {
//sidebarMiniSideIcons.value = mergedPages
//mergeSidebarIcon (icon awal, icon role user)
mergedIcons = mergeSidebarIcon(sidebarMiniSideIcons.value, mergedPages)
}else{
mergedIcons = sidebarMiniSideIcons.value
}
//console.log('mergedPages useSidebarAccess', mergedPages,mergedIcons);
//insert ke store Pinia
akses.setAccess({ role: userRole, pages: roleSidebarItems[0].pages, icons:mergedIcons })
akses.setMergedSidebar(mergedPages)
//console.log('tes masuk storeMenu', akses.$state)
const getPagesUser = akses.pageAccess
const getMergedPages = akses.mergedSidebar
const getMergedIcons = akses.iconItem
return {
getPagesUser,
getMergedPages,
getMergedIcons,
}
}
// export function useAccess() {
// const store = useHakAksesStore()
// const getRole = () => store.role
// const getPages = () => store.pageAccess
// const getPermissionsByPath = (path: string): string[] => {
// const match = store.pageAccess.find(p => p.path === path)
// return match?.permissions || []
// }
// return {
// getRole,
// getPages,
// getPermissionsByPath
// }
// }
+47 -8
View File
@@ -1,10 +1,49 @@
//import { sidebarMeta } from '@/components/layout/sidebar'
import { mergeSidebar } from '~/composables/sidebarMenu/mergeSidebar'
import { useSidebarAccess } from '~/composables/sidebarMenu/useSidebarAkses'
import { useRoute } from "vue-router";
import { useSidebarAccess } from "~/composables/sidebarMenu/useSidebarAkses";
import { useHakAksesStore } from "@/stores/sidebarMenuAkses/useMenuAksesStore";
import type { PageAccess } from "~/types/menuAkses/access";
export const useAccess = () => {
const result = useSidebarAccess("tes")
export const useAccess = (pageRoute: string , userRole: string) => {
//const route = useRoute();
const getRole = "admin";
//const meta = route.path; //halaman yang sedang diakses
const meta = pageRoute
return result
}
// const getPermissions = ['view'] // belum ambil data
const aksesMenu = useHakAksesStore();
//untuk merge akses menu dan akses ke store
const getMenuStore = useSidebarAccess(getRole);
//console.log("masuk akses", getMenuStore);
const getPagesUser = aksesMenu.pageAccess;
const getMergedPages = aksesMenu.mergedSidebar;
//const result = useSidebarAccess(getRole);
console.log("route dari useAccess", meta);
//console.log("mergerpage", getMergedPages);meta masih salah
//mencari permision per page
const cariPage: PageAccess[] = getPagesUser;
let getPermisionPage = null;
//console.log('cariPage', cariPage);
if (cariPage.length > 0) {
const found = cariPage.find((p) => p.path === meta);
//console.log("permisionPage", found);
if (found?.permissions) {
getPermisionPage = found.permissions;
}
}
//set permission ke pinia
aksesMenu.setPermissionPage(getPermisionPage);
return {
getRole, // role
getPagesUser, // akses menu per role
getMergedPages, // hasil merge akses menu
getPermisionPage, // permission per page
};
};
-25
View File
@@ -1,25 +0,0 @@
// // composables/useAuth.ts
// import { useCookie } from '#app'
// export const useAuth = () => {
// const user = useState('auth_user', () => null)
// const token = useCookie('auth_token')
// const setUser = (data: any, tokenValue: string) => {
// user.value = data
// token.value = tokenValue
// }
// const logout = () => {
// user.value = null
// token.value = null
// }
// return {
// user,
// token,
// setUser,
// logout,
// isLoggedIn: computed(() => !!user.value)
// }
// }
+37 -33
View File
@@ -1,40 +1,44 @@
// middleware/auth.ts
import { useAccess } from '~/composables/useAccess'
import { useAccess } from "~/composables/useAccess";
export default defineNuxtRouteMiddleware((to) => {
const { getRole, getPermissionsByPath } = useAccess()
const role = useAccess()
// const perms = getPermissionsByPath(to.path)
// const meta = to.meta
// const perms = getPermissionsByPath(to.path)
const roleUser = 'admin';
const { getRole, getMergedPages,getPermisionPage } = useAccess(to.path , roleUser);
const mergedPages = getMergedPages
const permisionPage = getPermisionPage
//console.log("role", getRole);
//console.log("meta", path);
// Jika belum login, redirect ke halaman login
const isLoggedIn = !!role // role
if (!isLoggedIn) {
console.log('[ NOT LOGGED IN]', { path: to.path })
//return navigateTo('/login') //
if (!roleUser) {
console.log("[ NOT LOGGED IN]", { path: to.meta });
return navigateTo('/auth/login') //
}
// Validasi permission pada halaman
const meta = to.meta;
const allowedRole = (meta.role || []) as string[]
const rolePass = allowedRole.length === 0 || allowedRole.includes(roleUser)
//const permissionPass = !meta.permission || meta.permission.every(p => perms.includes(p))
console.log('middleware auth jalan di:', allowedRole);
//if (!rolePass || !permisionPage) {
if (!rolePass || !mergedPages) {
console.log('[ ACCESS DENIED]', {
path: to.path,
roleUser,
mergedPages
})
return navigateTo('/403') // Halaman tidak punya akses
}
// // Validasi permission
// const rolePass = !meta.role || meta.role.includes(role)
// const permissionPass = !meta.permission || meta.permission.every(p => perms.includes(p))
// if (!rolePass || !permissionPass) {
// console.log('[ ACCESS DENIED]', {
// path: to.path,
// role,
// requiredRole: meta.role,
// permissions: perms,
// requiredPermission: meta.permission
// })
// return navigateTo('/403') // Halaman tidak punya akses
// }
return navigateTo('/sample-page-copy')
// Semua valid, lanjut ke halaman
// console.log('[ACCESS GRANTED]', {
// path: to.path,
// role,
// permissions
// })
})
console.log('[ACCESS GRANTED]', {
path: to.path,
roleUser,
mergedPages,
permisionPage
})
});
+15 -3
View File
@@ -1,16 +1,28 @@
<script setup lang="ts">
import { ref } from "vue";
import UiParentCard from "@/components/shared/UiParentCard.vue";
import { useRoute } from 'vue-router'
import { useHakAksesStore } from '@/stores/sidebarMenuAkses/useMenuAksesStore'
const route = useRoute()
const aksesMenu = useHakAksesStore();
console.log('masuk pages', route.meta ,aksesMenu.permissionPage);
//const permission = ["view"];
definePageMeta({
middleware: ["auth-menu"],
role: ['admin','staff'],
//permission: [permission],
});
const permissions = route.meta || []
</script>
<template>
<v-row>
<v-col cols="12" md="12">
<v-card elevation="10">
<v-card-item>
<h5 class="text-h5 mb-3">Sample Page Copy</h5>
<h5 class="text-h5 mb-3">Sample Page Copy {{ permissions }}</h5>
<p class="text-body-1">This is a sample page</p>
</v-card-item>
</v-card>
+19
View File
@@ -0,0 +1,19 @@
<script setup lang="ts">
import { ref } from "vue";
import UiParentCard from "@/components/shared/UiParentCard.vue";
</script>
<template>
<v-row>
<v-col cols="12" md="12">
<v-card elevation="10">
<v-card-item>
<h5 class="text-h5 mb-3">Sample Page Copy</h5>
<p class="text-body-1">This is a sample page</p>
</v-card-item>
</v-card>
</v-col>
</v-row>
</template>
+14 -12
View File
@@ -1,30 +1,32 @@
<script setup lang="ts">
import { ref } from "vue";
import UiParentCard from "@/components/shared/UiParentCard.vue";
import { useRoute } from 'vue-router'
import { useHakAksesStore } from '@/stores/sidebarMenuAkses/useMenuAksesStore'
const route = useRoute()
const aksesMenu = useHakAksesStore();
console.log('masuk pages', route.meta ,aksesMenu.permissionPage);
//const permission = ["view"];
definePageMeta({
middleware: ["auth-menu"],
//middleware : ['sidebase-auth']
role: ['superadmin','admin'],
//permission: [permission],
});
const { status, data: session } = useAuth();
if (status.value === "unauthenticated") {
console.log("status", status.value);
} else {
console.log("status", status.value);
}
const permissions = route.meta || []
</script>
<template>
<v-row>
<v-col cols="12" md="12">
<v-card elevation="10">
<v-card-item>
<h5 class="text-h5 mb-3">Sample Page</h5>
<h5 class="text-h5 mb-3">Sample Page {{ permissions }}</h5>
<p class="text-body-1">This is a sample page</p>
</v-card-item>
</v-card>
</v-col>
</v-row>
</template>
+2
View File
@@ -2,6 +2,8 @@
/*-For Set Blank Layout-*/
definePageMeta({
layout: "blank",
middleware: ["auth-menu"],
//role: ['admin'],
});
</script>
<template>
+15
View File
@@ -58,6 +58,21 @@ const rolePages = [
path: "/forms/form-elements/combobox",
permissions: ["view"],
},
{
title: "Level 3",
path: "/barry",
permissions: ["view"],
},
{
title: "Sample Page",
path: "/sample-page",
permissions: ["create", "view", "update"],
},
{
title: "Sample Page Copy",
path: "/sample-page-copy",
permissions: ["create", "view", "update", "delete"],
},
],
},
+14 -7
View File
@@ -1,17 +1,20 @@
import { defineStore } from 'pinia'
import type { PageAccess } from '@/types/menuAkses/access'
import type { PageAccess, minisidebar } from '@/types/menuAkses/access'
export const useHakAksesStore = defineStore('hakAksesMenu', {
state: () => ({
role: '',
pageAccess: [] as PageAccess[], //Array halaman dengan permissions
mergedSidebar: []
pageAccess: [] as PageAccess[], //Array halaman dari backend
iconItem: [] as minisidebar[],
mergedSidebar: [],
permissionPage: [] //hasil merge halaman dengan permissions
}),
actions: {
setAccess(payload: { role: string; pages: PageAccess[] }) {
setAccess(payload: { role: string; pages: PageAccess[]; icons: minisidebar[] }) {
this.role = payload.role
this.pageAccess = payload.pages
this.iconItem = payload.icons
},
resetAccess() {
@@ -19,9 +22,13 @@ export const useHakAksesStore = defineStore('hakAksesMenu', {
this.pageAccess = []
},
setMergedSidebar(data: any) {
this.mergedSidebar = data
}
setMergedSidebar(sidebar: any) {
this.mergedSidebar = sidebar
},
setPermissionPage(permission: any) {
this.permissionPage = permission
},
}
})
+6
View File
@@ -8,3 +8,9 @@ export interface RoleAccess {
role?: string
pages?: PageAccess[]
}
export interface minisidebar {
icon?: string;
id?:number;
tooltip?:string
}
+7
View File
@@ -38,3 +38,10 @@ export interface menu {
role?: string[];
permission?: string[];
}
export interface minisidebar {
icon?: string;
id?:number;
tooltip?:string
}
@@ -14,9 +14,9 @@ export function mergeSidebar(menuItems: SidebarItem[], allowedPages: PageAccess[
//console.log('allowedPages', allowedPages);
if (Array.isArray(item.children)) {
const filteredChildren = mergeSidebar(item.children, allowedPages)
//console.log('ada array item', item);
// console.log('ada array item', item);
// console.log('filteredChildren', filteredChildren);
//console.log('filteredChildren', filteredChildren);
if (filteredChildren.length > 0) {
result.push({
...item,
@@ -28,7 +28,7 @@ export function mergeSidebar(menuItems: SidebarItem[], allowedPages: PageAccess[
// Jika punya path, cocokkan dengan json dummy / backend
else if (item.to) {
const matchPage = allowedPages.find(page => page.title === item.title && page.path === item.to) //cocokkan title dan path link halaman
const matchPage = allowedPages.find(page => page.title === item.title && page.path === item.to) //cocokkan title dan path link path halaman
//console.log('match', matchPage,matchPage?.permissions);
if (matchPage && matchPage.permissions?.includes('view')) {
@@ -38,6 +38,7 @@ export function mergeSidebar(menuItems: SidebarItem[], allowedPages: PageAccess[
} as SidebarItemWithPermissions)
}
}
}