From a61eb18e4289d03b69419e7318b0e0d13d231e62 Mon Sep 17 00:00:00 2001 From: marszayn Date: Mon, 10 Mar 2025 14:03:38 +0700 Subject: [PATCH] feat: Tambahkan fitur pengecekan izin pengguna --- app/Http/Controllers/Admin/RoleController.php | 19 ++++- database/seeders/PermissionsTableSeeder.php | 79 +++++++++++++++++-- database/seeders/RolesTableSeeder.php | 20 +++-- resources/js/components/app-sidebar.tsx | 79 +++++++++++++++++-- resources/js/components/nav-main.tsx | 19 ++++- resources/js/components/nav-secondary.tsx | 19 ++++- resources/js/utils/hasAnyPermission.js | 19 +++++ 7 files changed, 224 insertions(+), 30 deletions(-) create mode 100644 resources/js/utils/hasAnyPermission.js diff --git a/app/Http/Controllers/Admin/RoleController.php b/app/Http/Controllers/Admin/RoleController.php index 9028512..a715539 100644 --- a/app/Http/Controllers/Admin/RoleController.php +++ b/app/Http/Controllers/Admin/RoleController.php @@ -5,11 +5,24 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Http\Requests\RoleRequest; +use Illuminate\Support\Facades\Log; +use Inertia\Inertia; use Spatie\Permission\Models\Permission; use Spatie\Permission\Models\Role; class RoleController extends Controller { + + public function __invoke(Request $request) + { + try { + $kategori = Role::latest()->get(); + return Inertia::render('admin/kategori/index_kategori', ['kategori' => $kategori]); + } catch (\Exception $e) { + Log::error('Error fetching Kategori: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } public function index() { $roles = Role::with('permissions') @@ -17,7 +30,7 @@ class RoleController extends Controller ->paginate(10); // Kembalikan data ke komponen Inertia 'Admin/Roles/Index' - return inertia('Admin/Roles/Index', compact('roles')); + return Inertia::render('admin/roles/index_roles', compact('roles')); } public function create() { @@ -25,7 +38,7 @@ class RoleController extends Controller $permissions = Permission::all(); // Kembalikan ke Inertia 'Admin/Roles/Create' dengan data permissions - return inertia('Admin/Roles/Create', [ + return Inertia::render('admin/roles/create_roles', [ 'permissions' => $permissions, ]); } @@ -66,7 +79,7 @@ class RoleController extends Controller }); // Kembalikan data ke Inertia 'Admin/Roles/Edit' dengan data role, permissions, dan rolePermissions - return inertia('Admin/Roles/Edit', [ + return Inertia::render('admin/roles/edit_roles', [ 'permissions' => $permissions, 'role' => $role, 'rolePermissions' => $rolePermissions, diff --git a/database/seeders/PermissionsTableSeeder.php b/database/seeders/PermissionsTableSeeder.php index 440b008..f4d3bef 100644 --- a/database/seeders/PermissionsTableSeeder.php +++ b/database/seeders/PermissionsTableSeeder.php @@ -15,17 +15,82 @@ class PermissionsTableSeeder extends Seeder { $resources = [ - 'users' => ['index', 'create', 'edit', 'delete'], - 'roles' => ['index', 'create', 'edit', 'delete'], - 'kategori' => ['index', 'create', 'edit', 'delete'], - 'subkategori' => ['index', 'create', 'edit', 'delete'], + 'Dashboard' => [ + 'index' => 'Lihat Dashboard', + ], + 'Pelaporan' => [ + 'index' => 'Melihat Daftar Pelaporan', + ], + 'Verifikasi' => [ + 'index' => 'Mengakses Verifikasi Pelaporan', + ], + 'Hukum' => [ + 'index' => 'Melihat Data Penegakan Hukum', + ], + 'Perizinan' => [ + 'index' => 'Melihat Data Perizinan Lingkungan', + ], + 'History' => [ + 'index' => 'Melihat History Perusahaan', + ], + 'Post' => [ + 'index' => 'Mengakses Data Postingan', + ], + 'Kategori' => [ + 'index' => 'Melihat Kategori Post', + ], + 'SubKategori' => [ + 'index' => 'Melihat Sub Kategori Post', + ], + 'Verifikator' => [ + 'index' => 'Mengakses Data Dinas LH / Verifikator', + ], + 'JenisKegiatan' => [ + 'index' => 'Melihat Daftar Jenis Kegiatan', + ], + 'JenisDokil' => [ + 'index' => 'Melihat Daftar Jenis Dokumen Izin', + ], + 'Perusahaan' => [ + 'index' => 'Mengakses Data Perusahaan', + ], + 'HistoryKegiatan' => [ + 'index' => 'Melihat History Kegiatan', + ], + 'JenisSanksi' => [ + 'index' => 'Melihat Jenis Sanksi', + ], + 'Penaatan' => [ + 'index' => 'Melihat Status Penaatan', + ], + 'Pengguna' => [ + 'index' => 'Melihat Daftar Pengguna', + ], + 'Role' => [ + 'index' => 'Melihat Kelompok Pengguna', + ], + 'Tentang' => [ + 'index' => 'Melihat Informasi Tentang Aplikasi', + ], + 'Catatan' => [ + 'index' => 'Melihat Catatan Sistem', + ], + 'Backup' => [ + 'index' => 'Mengakses Fitur Backup Data', + ], + 'Restore' => [ + 'index' => 'Mengakses Fitur Restore Data', + ], ]; foreach ($resources as $resource => $actions) { - foreach ($actions as $action) { + foreach ($actions as $action => $description) { $permissionName = "{$resource}.{$action}"; - Permission::firstOrCreate(['name' => $permissionName, 'guard_name' => 'web']); + Permission::updateOrCreate( + ['name' => $permissionName, 'guard_name' => 'web'], + ['description' => $description] + ); } } + } } -} diff --git a/database/seeders/RolesTableSeeder.php b/database/seeders/RolesTableSeeder.php index 1990be4..1dfb64f 100644 --- a/database/seeders/RolesTableSeeder.php +++ b/database/seeders/RolesTableSeeder.php @@ -15,13 +15,23 @@ class RolesTableSeeder extends Seeder public function run(): void { $admin = Role::firstOrCreate(['name' => 'admin', 'guard_name' => 'web']); - $user = Role::firstOrCreate(['name' => 'user', 'guard_name' => 'web']); + // $user = Role::firstOrCreate(['name' => 'user', 'guard_name' => 'web']); - // Assign permissions ke role - $admin->syncPermissions(Permission::all()); // Admin mendapatkan semua akses + // // Assign permissions ke role + $admin->syncPermissions(Permission::all()); // Admin mendapatkan semua akses - // Assign role `admin` ke user - $user->assignRole($admin); + // // Assign role `admin` ke user + // $user->assignRole($admin); + Role::firstOrCreate(['name' => 'Admin']); + Role::firstOrCreate(['name' => 'Verifikator']); + Role::firstOrCreate(['name' => 'Perusahaan']); + Role::firstOrCreate(['name' => 'Admin Suku Dinas LH']); + Role::firstOrCreate(['name' => 'Pedal']); + Role::firstOrCreate(['name' => 'Admin Bidang']); + Role::firstOrCreate(['name' => 'Admin PPU']); + Role::firstOrCreate(['name' => 'Kajian Dampak Lingkungan']); + Role::firstOrCreate(['name' => 'Instansi Umum']); + Role::firstOrCreate(['name' => 'Gakkum']); } } diff --git a/resources/js/components/app-sidebar.tsx b/resources/js/components/app-sidebar.tsx index 1390fbb..37cf5ac 100644 --- a/resources/js/components/app-sidebar.tsx +++ b/resources/js/components/app-sidebar.tsx @@ -36,6 +36,7 @@ import { } from "@/components/ui/sidebar"; import { Link, usePage } from "@inertiajs/react"; import { PageProps } from "@/types"; +import hasAnyPermission from "@/utils/hasAnyPermission"; const data = { user: { @@ -47,36 +48,43 @@ const data = { { title: "Dashboard", url: "/dashboard", + permissions: ["Dashboard.index"], icon: Home, }, { title: "Pelaporan", url: "/admin/pelaporan", + permissions: ["Pelaporan.index"], icon: BookMarked, }, { title: "Verifikasi Pelaporan", url: "/admin/verifikasi", + permissions: ["Verifikasi.index"], icon: BookCheck, }, { title: "Penegakan Hukum", url: "/admin/hukum", + permissions: ["Hukum.index"], icon: Scale, }, { title: "Perizinan Lingkungan", - url: "/admin/perizinan-lingkungan", + url: "/admin/perizinan_lingkungan", + permissions: ["Perizinan.index"], icon: FileKey2, }, { title: "History Perusahaan", - url: "/admin/history-perusahaan", + url: "/admin/history_perusahaan", + permissions: ["History.index"], icon: GalleryVertical, }, { title: "Post", url: "/admin/post", + permissions: ["Post.index"], icon: Frame, }, { @@ -116,38 +124,47 @@ const data = { { title: "Kategori Post", url: "/admin/kategori", + permissions: ["Kategori.index"], }, { title: "Sub Kategori Post", url: "/admin/subkategori", + permissions: ["SubKategori.index"], }, { title: "Dinas LH", url: "/admin/verifikator", + permissions: ["Verifikator.index"], }, { title: "Jenis Kegiatan", url: "/admin/jeniskegiatan", + permissions: ["JenisKegiatan.index"], }, { title: "Jenis Dokumen Izin", url: "/admin/jenisdokil", + permissions: ["JenisDokil.index"], }, { - title: "Perusahaan", + title: "Data Perusahaan", url: "/admin/perusahaan", + permissions: ["Perusahaan.index"], }, { title: "History Kegiatan", url: "/admin/historykegiatan", + permissions: ["HistoryKegiatan.index"], }, { title: "Jenis Sanksi", url: "/admin/jenissanksi", + permissions: ["JenisSanksi.index"], }, { title: "Status Penaatan", url: "/admin/penaatan", + permissions: ["Penaatan.index"], }, ], }, @@ -160,10 +177,12 @@ const data = { { title: "Pengguna", url: "/admin/pengguna", + permissions: ["Pengguna.index"], }, { - title: "Role", - url: "/admin/role", + title: "Kelompok Pengguna", + url: "/admin/roles", + permissions: ["Role.index"], }, ], }, @@ -173,27 +192,71 @@ const data = { title: "Tentang", url: "/admin/tentang", icon: LifeBuoy, + permissions: ["Tentang.index"], }, { title: "Catatan Sistem", url: "#", icon: NotepadText, + permissions: ["Catatan.index"], }, { title: "Backup", url: "#", icon: Archive, + permissions: ["Backup.index"], }, { title: "Restore", url: "#", icon: DatabaseBackup, + permissions: ["Restore.index"], }, ], }; export function AppSidebar({ ...props }: React.ComponentProps) { const { auth } = usePage().props; + const userPermissions = auth?.user?.permissions ?? []; + + const filterMenu = (menu) => { + return menu + .map((item) => { + if (item.items) { + const filteredItems = item.items.filter((subItem) => + subItem.permissions + ? hasAnyPermission( + Array.isArray(subItem.permissions) + ? subItem.permissions + : Object.keys(subItem.permissions) // Pastikan selalu array + ) + : true + ); + + if (filteredItems.length > 0) { + return { ...item, items: filteredItems }; + } + return null; + } + + if (item.permissions) { + // **PERBAIKAN UTAMA**: Pastikan item.permissions selalu dalam bentuk array + const permissionsArray = Array.isArray(item.permissions) + ? item.permissions + : Object.keys(item.permissions); + + const hasPermission = hasAnyPermission(permissionsArray); + + return hasPermission ? item : null; + } + + return item; + }) + .filter(Boolean); + }; + + const navMain = filterMenu(data.navMain); + const navSecondary = filterMenu(data.navSecondary); return ( @@ -201,6 +264,7 @@ export function AppSidebar({ ...props }: React.ComponentProps) { + {/* {hasAnyPermission(["Dashboard.index"]) && ( */}
{/* */} @@ -219,13 +283,14 @@ export function AppSidebar({ ...props }: React.ComponentProps) {
+ {/* )} */}
- - + + diff --git a/resources/js/components/nav-main.tsx b/resources/js/components/nav-main.tsx index 0fb1a15..5bf632d 100644 --- a/resources/js/components/nav-main.tsx +++ b/resources/js/components/nav-main.tsx @@ -19,6 +19,7 @@ import { SidebarMenuSubItem, } from "@/components/ui/sidebar"; import { Link } from "@inertiajs/react"; +import hasAnyPermission from "@/utils/hasAnyPermission"; export function NavMain({ items, @@ -28,6 +29,7 @@ export function NavMain({ url: string; icon: LucideIcon; isActive?: boolean; + permissions?: string[]; items?: { title: string; url: string; @@ -46,10 +48,19 @@ export function NavMain({ > - - -
{item.title}
- + {item.permissions ? ( + hasAnyPermission(item.permissions) ? ( + + +
{item.title}
+ + ) : null + ) : ( + + +
{item.title}
+ + )}
{item.items?.length ? ( <> diff --git a/resources/js/components/nav-secondary.tsx b/resources/js/components/nav-secondary.tsx index ae82194..2d4fec6 100644 --- a/resources/js/components/nav-secondary.tsx +++ b/resources/js/components/nav-secondary.tsx @@ -9,6 +9,7 @@ import { SidebarMenuItem, } from "@/components/ui/sidebar"; import { Link } from "@inertiajs/react"; +import hasAnyPermission from "@/utils/hasAnyPermission"; export function NavSecondary({ items, @@ -18,6 +19,7 @@ export function NavSecondary({ title: string; url: string; icon: LucideIcon; + permissions?: string[]; }[]; } & React.ComponentPropsWithoutRef) { return ( @@ -27,10 +29,19 @@ export function NavSecondary({ {items.map((item) => ( - - - {item.title} - + {item.permissions ? ( + hasAnyPermission(item.permissions) ? ( + + +
{item.title}
+ + ) : null + ) : ( + + +
{item.title}
+ + )}
))} diff --git a/resources/js/utils/hasAnyPermission.js b/resources/js/utils/hasAnyPermission.js new file mode 100644 index 0000000..9ce333f --- /dev/null +++ b/resources/js/utils/hasAnyPermission.js @@ -0,0 +1,19 @@ +import { usePage } from "@inertiajs/react"; +export default function hasAnyPermission(permissions = []) { + const { auth } = usePage().props; + const allPermissions = auth?.user?.permissions ?? {}; + + if (typeof allPermissions !== "object" || allPermissions === null) { + return false; + } + + if (!Array.isArray(permissions) || permissions.length === 0) { + return false; + } + + const result = permissions.some( + (permission) => allPermissions?.[permission] === true + ); + + return result; +}