feat(rbac): add roles and permissions
This commit is contained in:
parent
86a32a942c
commit
694b7bd09a
37 changed files with 2682 additions and 218 deletions
|
|
@ -1,14 +1,22 @@
|
|||
"use client";
|
||||
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
FileText,
|
||||
LayoutDashboard,
|
||||
Package,
|
||||
Settings,
|
||||
Shield,
|
||||
ShoppingCart,
|
||||
Users,
|
||||
Wrench,
|
||||
Package,
|
||||
FileText,
|
||||
Settings,
|
||||
ShoppingCart,
|
||||
} from "lucide-react";
|
||||
|
||||
import { api } from "@/lib/api";
|
||||
import { hasPermission } from "@/lib/permissions";
|
||||
import type { CurrentUser, PermissionName } from "@/types/rbac";
|
||||
|
||||
const menu = [
|
||||
{
|
||||
icon: LayoutDashboard,
|
||||
|
|
@ -19,6 +27,13 @@ const menu = [
|
|||
icon: Users,
|
||||
name: "Benutzer",
|
||||
href: "/users",
|
||||
permission: "users.read",
|
||||
},
|
||||
{
|
||||
icon: Shield,
|
||||
name: "Rollen & Rechte",
|
||||
href: "/roles",
|
||||
permission: "roles.read",
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
|
|
@ -50,21 +65,45 @@ const menu = [
|
|||
name: "Einstellungen",
|
||||
href: "/settings",
|
||||
},
|
||||
];
|
||||
] satisfies Array<{
|
||||
icon: typeof LayoutDashboard;
|
||||
name: string;
|
||||
href: string;
|
||||
permission?: PermissionName;
|
||||
}>;
|
||||
|
||||
export default function Sidebar() {
|
||||
const [currentUser, setCurrentUser] = useState<CurrentUser | null>(null);
|
||||
|
||||
const loadCurrentUser = useCallback(async () => {
|
||||
try {
|
||||
const response = await api.get<CurrentUser>("/me");
|
||||
setCurrentUser(response.data);
|
||||
} catch {
|
||||
setCurrentUser(null);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
queueMicrotask(() => {
|
||||
void loadCurrentUser();
|
||||
});
|
||||
}, [loadCurrentUser]);
|
||||
|
||||
const visibleMenu = menu.filter((item) => (
|
||||
!item.permission || hasPermission(currentUser, item.permission)
|
||||
));
|
||||
|
||||
return (
|
||||
<aside className="w-64 h-screen bg-slate-900 text-white flex flex-col">
|
||||
|
||||
<div className="p-6 border-b border-slate-800">
|
||||
<h1 className="text-3xl font-bold">
|
||||
🏛 Olympus
|
||||
Olympus
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<nav className="flex-1 p-4 space-y-2">
|
||||
|
||||
{menu.map((item) => (
|
||||
{visibleMenu.map((item) => (
|
||||
<Link
|
||||
key={item.name}
|
||||
href={item.href}
|
||||
|
|
@ -74,13 +113,11 @@ export default function Sidebar() {
|
|||
<span>{item.name}</span>
|
||||
</Link>
|
||||
))}
|
||||
|
||||
</nav>
|
||||
|
||||
<div className="border-t border-slate-800 p-4 text-sm text-slate-400">
|
||||
Olympus ERP v0.1
|
||||
Olympus CRM v0.1
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue