import type { FastifyRequest, FastifyReply } from 'fastify'; import bcrypt from 'bcryptjs'; import { users } from '@/db/schema.js'; import { eq, and, ne } from 'drizzle-orm'; import type { CreateUserByAdminBody, UpdateUserBody } from './users.schema.js'; export async function listUsersHandler(request: FastifyRequest, reply: FastifyReply) { const db = request.server.db; const allUsers = await db.query.users.findMany({ columns: { password: false, // Don't return passwords }, orderBy: (users, { desc }) => [desc(users.createdAt)], }); return reply.send(allUsers); } export async function createUserHandler( request: FastifyRequest<{ Body: CreateUserByAdminBody }>, reply: FastifyReply, ) { const db = request.server.db; const { name, email, password, role } = request.body; // Verifica se email já existe const existing = await db.query.users.findFirst({ where: eq(users.email, email), }); if (existing) { return reply.conflict('Este e-mail já está cadastrado.'); } const hashedPassword = await bcrypt.hash(password, 12); const [newUser] = await db.insert(users).values({ name, email, password: hashedPassword, role, isActive: true, }).returning({ id: users.id, name: users.name, email: users.email, role: users.role, isActive: users.isActive, createdAt: users.createdAt, }); return reply.code(201).send(newUser); } export async function updateUserHandler( request: FastifyRequest<{ Params: { id: number }; Body: UpdateUserBody }>, reply: FastifyReply, ) { const db = request.server.db; const { id } = request.params; const { name, email, password, role, isActive } = request.body; const existingUser = await db.query.users.findFirst({ where: eq(users.id, id), }); if (!existingUser) { return reply.notFound('Usuário não encontrado.'); } if (email && email !== existingUser.email) { const existingEmail = await db.query.users.findFirst({ where: and(eq(users.email, email), ne(users.id, id)), }); if (existingEmail) { return reply.conflict('Este e-mail já está em uso por outro usuário.'); } } const updates: Partial = { name, email, role, isActive, updatedAt: new Date().toISOString(), }; if (password && password.trim() !== '') { updates.password = await bcrypt.hash(password, 12); } const [updatedUser] = await db.update(users) .set(updates) .where(eq(users.id, id)) .returning({ id: users.id, name: users.name, email: users.email, role: users.role, isActive: users.isActive, createdAt: users.createdAt, }); return reply.send(updatedUser); } export async function deleteUserHandler( request: FastifyRequest<{ Params: { id: number } }>, reply: FastifyReply, ) { const db = request.server.db; const { id } = request.params; const existingUser = await db.query.users.findFirst({ where: eq(users.id, id), }); if (!existingUser) { return reply.notFound('Usuário não encontrado.'); } if (id === request.user?.id) { return reply.badRequest('Você não pode excluir a própria conta.'); } await db.delete(users).where(eq(users.id, id)); return reply.code(204).send(); }