"use client"; import { useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Checkbox } from "@/components/ui/checkbox"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter, } from "@/components/ui/dialog"; import { ChevronDown, ChevronRight, Plus, Trash2 } from "lucide-react"; import { toTitleCase } from "@/lib/utils"; import { useApi } from "@/hooks/use-api"; import request from "@/lib/request"; import IUser from "@/interfaces/IUser"; import hasPermissions from "@/lib/hasPermissions"; type Action = string; interface Permission { resource: string; action: Action; } interface Role { id: string; name: string; permissions?: Permission[]; } interface PermissionsGrouped { [key: string]: string[]; } export default function RolesAndPermissions({ user }: { user: IUser }) { const [newRoleName, setNewRoleName] = useState(""); const [isDialogOpen, setIsDialogOpen] = useState(false); const { data: permissions } = useApi( "/permissions/grouped", {}, true, ); const { data: roles, mutate: rolesMutate } = useApi( "/roles", {}, true, ); const addNewRole = async () => { if (newRoleName.trim() === "") return; const res = await request("/roles/new", { requiresAuth: true, method: "POST", body: { name: newRoleName }, }); if (res.status === "Success") rolesMutate(); setNewRoleName(""); setIsDialogOpen(false); }; const deleteRole = async (id: string) => { const res = await request(`/roles/${id}/delete`, { method: "DELETE", requiresAuth: true, }); if (res.status === "Success") rolesMutate(); }; return (

Rôles et Permissions

{hasPermissions(user.roles, { roles: ["insert"] }) && ( Nouveau rôle
setNewRoleName(e.target.value) } />
)}
{permissions && roles && roles.map((role, index) => ( deleteRole(role.id)} /> ))}
); } interface RoleCardProps { user: IUser; role: Role; onDelete: () => void; permissions: PermissionsGrouped; } function RoleCard({ role, onDelete, permissions, user }: RoleCardProps) { return ( {toTitleCase(role.name)} {Object.entries(permissions).map(([res, actions]) => { return ( ); })} ); } interface ResourceSectionProps { disabled?: boolean; resource: string; defaultActions: string[]; role: Role; } function ResourceSection({ resource, defaultActions, role, disabled = false, }: ResourceSectionProps) { const [isExpanded, setIsExpanded] = useState(false); const a = (role.permissions ?? []) .map((p) => (p.resource === resource ? p.action : null)) .filter((a) => a !== null); const ActionCheckbox = ({ action }: { action: Action }) => { const [checked, setChecked] = useState(a.includes(action)); return (
{ if (typeof e === "boolean") { const res = await request( `/roles/${role.id}/permissions/${resource}/${action}/${e ? "add" : "remove"}`, { method: "PATCH", requiresAuth: true }, ); if (res.status === "Success") setChecked(e); } }} checked={checked} id={`${resource}-${action}`} />
); }; return (
{isExpanded && (
{defaultActions.map((action) => ( ))}
)}
); }