Files
2026-02-18 08:21:58 +07:00

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:

  1. Login → User mendapat roles dari Keycloak
  2. Auto-sync → Roles di-sync ke hakAkses.json
  3. Aktifkan hakAkses → Admin mengaktifkan hakAkses dan set pages di UI
  4. Load Sidebar → Sidebar fetch allowed pages dan filter menu
  5. 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:

<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):

  1. Pilih role yang ingin diedit
  2. Set status menjadi Aktif
  3. Pilih pages yang boleh diakses
  4. 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

  1. Login dengan user yang punya role tertentu
  2. Cek console log: Allowed pages for user: [...]
  3. Sidebar akan otomatis filter
  4. Coba akses URL langsung yang tidak ada di allowed pages
  5. Harus redirect ke dashboard atau first allowed page

Troubleshooting

Menu Tidak Muncul di Sidebar

Penyebab:

  1. Status hakAkses masih tidak aktif
  2. Path di pages array tidak match dengan to di sidebarItem.ts
  3. 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:

  1. Buka /setting/hak-akses
  2. Edit hakAkses yang sesuai dengan role user
  3. Set status Aktif
  4. Tambahkan minimal /dashboard di pages
  5. 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:

  1. Role di Keycloak
  2. Auto-sync ke hakAkses.json saat login
  3. Status diaktifkan di UI hak akses
  4. 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

  1. Server-side validation diperlukan untuk API calls yang sensitive
  2. Middleware hanya client-side protection - jangan andalkan untuk security critical operations
  3. Gunakan requireRole() atau requireAnyRole() di server API handlers untuk real protection
  4. 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)