import bcrypt from 'bcryptjs'; import crypto from 'crypto'; import { Prisma } from '@prisma/client'; import prisma from '../lib/prisma'; import { HttpError } from '../lib/httpError'; import type { CreateUserInput, UpdateUserInput } from '../../../shared/schemas/user'; const userSelect = { id: true, username: true, displayName: true, email: true, role: true, apiKey: true, createdAt: true, } as const; const userListSelect = { id: true, username: true, displayName: true, email: true, role: true, createdAt: true, } as const; export function listUsers() { return prisma.user.findMany({ select: userListSelect, orderBy: { displayName: 'asc' }, }); } export async function getCurrentUser(id: string) { const user = await prisma.user.findUnique({ where: { id }, select: userListSelect, }); if (!user) throw new HttpError(404, 'User not found'); return user; } export async function createUser(data: CreateUserInput) { const passwordHash = await bcrypt.hash(data.password, 12); const apiKey = data.role === 'AGENT' ? `sk_${crypto.randomBytes(32).toString('hex')}` : undefined; return prisma.user.create({ data: { username: data.username, email: data.email, displayName: data.displayName, passwordHash, role: data.role, apiKey, }, select: userSelect, }); } export async function updateUser(id: string, data: UpdateUserInput) { const update: Prisma.UserUpdateInput = {}; if (data.displayName) update.displayName = data.displayName; if (data.email) update.email = data.email; if (data.password) update.passwordHash = await bcrypt.hash(data.password, 12); if (data.role) { update.role = data.role; if (data.role === 'AGENT') { const existing = await prisma.user.findUnique({ where: { id }, select: { apiKey: true } }); if (!existing?.apiKey) { update.apiKey = `sk_${crypto.randomBytes(32).toString('hex')}`; } } else { update.apiKey = null; } } if (data.regenerateApiKey) { update.apiKey = `sk_${crypto.randomBytes(32).toString('hex')}`; } return prisma.user.update({ where: { id }, data: update, select: userSelect }); } export async function deleteUser(id: string, actorId: string) { if (id === actorId) { throw new HttpError(400, 'Cannot delete your own account'); } await prisma.user.delete({ where: { id } }); }