import { FastifyInstance } from "fastify"; import prisma from "../../config/database"; import { requirePermission } from "../../middleware/auth"; import { logAudit } from "../../services/audit"; import { success, error, parseId } from "../../utils/response"; import { parseBody } from "../../schemas/common"; import { CreateRoleSchema, UpdateRoleSchema } from "../../schemas/roles.schema"; export default async function rolesRoutes( fastify: FastifyInstance, ): Promise { // GET /api/admin/roles fastify.get( "/", { preHandler: requirePermission("settings.manage") }, async (request, reply) => { const roles = await prisma.roles.findMany({ include: { role_permissions: { include: { permissions: true }, }, }, orderBy: { id: "asc" }, }); const data = roles.map((r) => ({ ...r, permissions: r.role_permissions.map((rp) => rp.permissions), })); return success(reply, data); }, ); // GET /api/admin/roles/permissions fastify.get( "/permissions", { preHandler: requirePermission("settings.manage") }, async (_request, reply) => { const permissions = await prisma.permissions.findMany({ orderBy: { module: "asc" }, }); return success(reply, permissions); }, ); // POST /api/admin/roles fastify.post( "/", { preHandler: requirePermission("settings.manage") }, async (request, reply) => { const parsed = parseBody(CreateRoleSchema, request.body); if ("error" in parsed) return error(reply, parsed.error, 400); const body = parsed.data; const role = await prisma.roles.create({ data: { name: String(body.name), display_name: String(body.display_name), description: body.description ? String(body.description) : null, }, }); if (Array.isArray(body.permission_ids)) { await prisma.$transaction( (body.permission_ids as number[]).map((pid) => prisma.role_permissions.create({ data: { role_id: role.id, permission_id: pid, }, }), ), ); } await logAudit({ request, authData: request.authData, action: "create", entityType: "role", entityId: role.id, description: `Vytvořena role ${role.name}`, }); return success(reply, { id: role.id }, 201, "Role byla vytvořena"); }, ); // PUT /api/admin/roles/:id fastify.put<{ Params: { id: string } }>( "/:id", { preHandler: requirePermission("settings.manage") }, async (request, reply) => { const id = parseId(request.params.id, reply); if (id === null) return; const parsed = parseBody(UpdateRoleSchema, request.body); if ("error" in parsed) return error(reply, parsed.error, 400); const body = parsed.data; const existing = await prisma.roles.findUnique({ where: { id } }); if (!existing) return error(reply, "Role nenalezena", 404); await prisma.roles.update({ where: { id }, data: { display_name: body.display_name ? String(body.display_name) : undefined, description: body.description !== undefined ? String(body.description) : undefined, }, }); if (Array.isArray(body.permission_ids)) { await prisma.$transaction([ prisma.role_permissions.deleteMany({ where: { role_id: id } }), prisma.role_permissions.createMany({ data: (body.permission_ids as number[]).map((pid) => ({ role_id: id, permission_id: pid, })), }), ]); } await logAudit({ request, authData: request.authData, action: "update", entityType: "role", entityId: id, description: `Upravena role ${existing.name}`, }); return success(reply, { id }, 200, "Role byla aktualizována"); }, ); // DELETE /api/admin/roles/:id fastify.delete<{ Params: { id: string } }>( "/:id", { preHandler: requirePermission("settings.manage") }, async (request, reply) => { const id = parseId(request.params.id, reply); if (id === null) return; const existing = await prisma.roles.findUnique({ where: { id } }); if (!existing) return error(reply, "Role nenalezena", 404); if (existing.name === "admin") { return error(reply, "Nelze smazat roli admin", 400); } await prisma.roles.delete({ where: { id } }); await logAudit({ request, authData: request.authData, action: "delete", entityType: "role", entityId: id, description: `Smazána role ${existing.name}`, }); return success(reply, { id }, 200, "Role byla smazána"); }, ); }