7.3 KiB
7.3 KiB
Implementasi Hak Akses di Sidebar & Pages
Overview
Sistem hak akses sekarang sudah terintegrasi dengan sidebar dan page routing. Menu sidebar akan otomatis difilter berdasarkan pages yang user miliki akses, dan middleware akan mencegah akses langsung ke pages yang tidak diizinkan.
Komponen yang Terbuat
1. Composable useHakAkses() (composables/useHakAkses.ts)
Menyediakan fungsi untuk mengecek akses user ke halaman:
const { getAllowedPages, hasPageAccess, hasAnyPageAccess } = useHakAkses();
// Get all pages user can access
const pages = await getAllowedPages();
// Check single page
const canAccess = await hasPageAccess('/dashboard');
// Check multiple pages
const hasAccess = await hasAnyPageAccess(['/antrean/all', '/dashboard']);
2. Sidebar dengan Filter (components/layout/full/vertical-sidebar/VerticalSidebar.vue)
- ✅ Auto load allowed pages saat mount
- ✅ Filter menu items berdasarkan allowed pages
- ✅ Hanya tampilkan section yang punya minimal 1 menu visible
- ✅ Log allowed pages untuk debugging
3. Middleware Protection (middleware/checkPageAccess.ts)
- ✅ Cek akses user ke page yang dituju
- ✅ Redirect ke dashboard atau first allowed page jika tidak punya akses
- ✅ Skip check untuk public pages (login, register)
Cara Kerja
Flow Akses User:
- Login → User mendapat roles dari Keycloak
- Auto-sync → Roles di-sync ke
hakAkses.json - Aktifkan hakAkses → Admin mengaktifkan hakAkses dan set pages di UI
- Load Sidebar → Sidebar fetch allowed pages dan filter menu
- Navigation → Middleware check setiap navigation ke page baru
Data Structure:
// hakAkses.json
{
"id": "uuid",
"namaHakAkses": "manage-account", // nama role dari Keycloak
"status": "aktif", // harus aktif untuk memberikan akses
"pages": [
"/dashboard",
"/antrean/all",
"/setting/hak-akses"
]
}
Penggunaan
1. Mengaktifkan Middleware di Page
Ada 2 cara:
Option A: Per Page (Recommended)
<script setup lang="ts">
definePageMeta({
middleware: ['auth', 'check-page-access']
});
</script>
Option B: Global di nuxt.config.ts
export default defineNuxtConfig({
router: {
middleware: ['auth', 'check-page-access']
}
})
2. Manual Check di Component
Untuk show/hide content berdasarkan akses:
<script setup lang="ts">
const { hasPageAccess } = useHakAkses();
const canAccessSettings = ref(false);
onMounted(async () => {
canAccessSettings.value = await hasPageAccess('/setting/hak-akses');
});
</script>
<template>
<v-btn v-if="canAccessSettings" to="/setting/hak-akses">
Settings
</v-btn>
</template>
3. Conditional Rendering dengan Allowed Pages
<script setup lang="ts">
const { getAllowedPages } = useHakAkses();
const allowedPages = ref<string[]>([]);
onMounted(async () => {
allowedPages.value = await getAllowedPages();
});
const canManageUsers = computed(() =>
allowedPages.value.includes('/setting/user')
);
</script>
<template>
<div v-if="canManageUsers">
<!-- User management content -->
</div>
</template>
Mengelola Hak Akses
1. Menambah Pages ke Role
Di halaman Hak Akses (/setting/hak-akses):
- Pilih role yang ingin diedit
- Set status menjadi Aktif
- Pilih pages yang boleh diakses
- Simpan
2. Format Path di Pages Array
Path harus exact match dengan route path:
✅ Benar:
/dashboard/antrean/all/setting/hak-akses
❌ Salah:
dashboard(tanpa slash)/dashboard/(dengan trailing slash)/antrean/*(wildcard tidak support)
3. Testing Hak Akses
- Login dengan user yang punya role tertentu
- Cek console log:
Allowed pages for user: [...] - Sidebar akan otomatis filter
- Coba akses URL langsung yang tidak ada di allowed pages
- Harus redirect ke dashboard atau first allowed page
Troubleshooting
Menu Tidak Muncul di Sidebar
Penyebab:
- Status hakAkses masih tidak aktif
- Path di pages array tidak match dengan
todi sidebarItem.ts - User tidak punya role yang sesuai
Solusi:
// Check di console
const { getAllowedPages } = useHakAkses();
const pages = await getAllowedPages();
console.log('Allowed pages:', pages);
// Check role user
const { getRoles } = useRoles();
console.log('User roles:', getRoles());
User Bisa Akses Page Tanpa Permission
Penyebab:
- Middleware belum ditambahkan di page
Solusi:
<script setup lang="ts">
definePageMeta({
middleware: ['auth', 'check-page-access'] // Tambahkan ini
});
</script>
Error "You do not have access to any pages"
Penyebab:
- Semua hakAkses user statusnya tidak aktif
- Pages array kosong di semua hakAkses user
Solusi:
- Buka
/setting/hak-akses - Edit hakAkses yang sesuai dengan role user
- Set status Aktif
- Tambahkan minimal
/dashboarddi pages - Simpan
Best Practices
1. Default Pages untuk Semua Role
Pastikan semua role aktif punya akses ke:
/dashboard- Landing page setelah login
2. Hierarchical Access
Jika user punya akses ke child path, berikan juga akses ke parent:
{
"pages": [
"/setting", // Parent
"/setting/hak-akses", // Child
"/setting/user" // Child
]
}
3. Testing Multiple Roles
Test dengan user yang punya multiple roles untuk pastikan combine pages works:
// User dengan role: ['admin', 'dokter']
// hakAkses admin: ['/dashboard', '/setting/user']
// hakAkses dokter: ['/dashboard', '/antrean/all']
// Result: ['/dashboard', '/setting/user', '/antrean/all'] ✅
4. Sync Status
Selalu pastikan:
- ✅ Role di Keycloak
- ✅ Auto-sync ke hakAkses.json saat login
- ✅ Status diaktifkan di UI hak akses
- ✅ Pages ditambahkan
API Endpoints
Get All Hak Akses
const response = await $fetch('/api/hak-akses');
// Returns all hakAkses with their pages
Get User Allowed Pages (Client Side)
const { getAllowedPages } = useHakAkses();
const pages = await getAllowedPages();
// Returns only pages from active hakAkses that match user's roles
Security Notes
- Server-side validation diperlukan untuk API calls yang sensitive
- Middleware hanya client-side protection - jangan andalkan untuk security critical operations
- Gunakan
requireRole()ataurequireAnyRole()di server API handlers untuk real protection - Pages array di hakAkses.json bisa diedit manual, tapi lebih baik via UI
Example: Complete Setup
// 1. User login dengan role: 'manage-account'
// 2. Auto-sync creates/updates hakAkses.json:
{
"namaHakAkses": "manage-account",
"status": "tidak aktif", // Default
"pages": []
}
// 3. Admin edit via UI:
{
"namaHakAkses": "manage-account",
"status": "aktif", // ← Changed
"pages": [
"/dashboard",
"/antrean/all",
"/setting/hak-akses"
] // ← Added
}
// 4. User refresh/re-login:
// - Sidebar shows: Dashboard, Antrean > Semua, Settings > Hak Akses
// - Can access: /dashboard, /antrean/all, /setting/hak-akses
// - Cannot access: /antrean/list-kategori, /setting/user (will redirect)