feat: Tambahkan fitur pengecekan izin pengguna

main
marszayn 2025-03-10 14:03:38 +07:00
parent 9579f140eb
commit a61eb18e42
7 changed files with 224 additions and 30 deletions

View File

@ -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,

View File

@ -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]
);
}
}
}
}
}

View File

@ -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
// // 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']);
}
}

View File

@ -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<typeof Sidebar>) {
const { auth } = usePage<PageProps>().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 (
<Sidebar variant="inset" {...props}>
@ -201,6 +264,7 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" asChild>
{/* {hasAnyPermission(["Dashboard.index"]) && ( */}
<Link href={route("dashboard")}>
<div className="flex aspect-square size-8 items-center justify-center rounded-lg text-sidebar-primary-foreground">
{/* <Command className="size-4" /> */}
@ -219,13 +283,14 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
</span>
</div>
</Link>
{/* )} */}
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarHeader>
<SidebarContent>
<NavMain items={data.navMain} />
<NavSecondary items={data.navSecondary} className="mt-auto" />
<NavMain items={navMain} />
<NavSecondary items={navSecondary} className="mt-auto" />
</SidebarContent>
<SidebarFooter>
<NavUser user={auth.user} />

View File

@ -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({
>
<SidebarMenuItem>
<SidebarMenuButton asChild tooltip={item.title}>
{item.permissions ? (
hasAnyPermission(item.permissions) ? (
<Link href={item.url}>
<item.icon />
<div>{item.title}</div>
</Link>
) : null
) : (
<Link href={item.url}>
<item.icon />
<div>{item.title}</div>
</Link>
)}
</SidebarMenuButton>
{item.items?.length ? (
<>

View File

@ -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<typeof SidebarGroup>) {
return (
@ -27,10 +29,19 @@ export function NavSecondary({
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild size="sm">
{item.permissions ? (
hasAnyPermission(item.permissions) ? (
<Link href={item.url}>
<item.icon />
<span>{item.title}</span>
<div>{item.title}</div>
</Link>
) : null
) : (
<Link href={item.url}>
<item.icon />
<div>{item.title}</div>
</Link>
)}
</SidebarMenuButton>
</SidebarMenuItem>
))}

View File

@ -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;
}