feat(config): alta de usuarios desde Configuraciones (POST /config/usuarios, solo admin)
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
import { z } from 'zod'
|
||||
import * as configService from '../services/config.service.js'
|
||||
import { esRolValido } from '../config/roles.js'
|
||||
import { AppError, BadRequestError } from '../utils/errors.js'
|
||||
|
||||
// ── Middleware admin ────────────────────────────────────────────────────
|
||||
@@ -95,6 +96,27 @@ export async function actualizarUsuarioEndpoint(req: Request, res: Response): Pr
|
||||
res.status(204).end()
|
||||
}
|
||||
|
||||
// ── POST /api/config/usuarios — dar de alta un usuario (solo admin) ────
|
||||
|
||||
const crearUsuarioSchema = z.object({
|
||||
nombre: z.string().trim().min(3, 'Nombre demasiado corto').max(80),
|
||||
rol: z.string().min(1),
|
||||
asignacion: z.string().nullable().optional(),
|
||||
password: z.string().min(8, 'La contraseña necesita al menos 8 caracteres').max(72),
|
||||
})
|
||||
|
||||
export async function crearUsuarioEndpoint(req: Request, res: Response): Promise<void> {
|
||||
const body = crearUsuarioSchema.parse(req.body)
|
||||
if (!esRolValido(body.rol)) throw new BadRequestError(`Rol inválido: ${body.rol}`)
|
||||
const usuario = await configService.crearUsuario({
|
||||
nombre: body.nombre,
|
||||
rol: body.rol,
|
||||
asignacion: body.asignacion ?? null,
|
||||
password: body.password,
|
||||
})
|
||||
res.status(201).json(usuario)
|
||||
}
|
||||
|
||||
// ── POST /api/config/reset-roles ───────────────────────────────────────
|
||||
|
||||
export async function resetRolesEndpoint(_req: Request, res: Response): Promise<void> {
|
||||
|
||||
@@ -95,6 +95,7 @@ import {
|
||||
actualizarRolConfigEndpoint,
|
||||
obtenerUsuariosEndpoint,
|
||||
actualizarUsuarioEndpoint,
|
||||
crearUsuarioEndpoint,
|
||||
resetRolesEndpoint,
|
||||
obtenerAccionesEndpoint,
|
||||
} from '../controllers/config.controller.js'
|
||||
@@ -276,6 +277,7 @@ apiRouter.get('/config/roles', requireAdmin, obtenerRolesConfigEndpoint)
|
||||
apiRouter.patch('/config/roles/:rol', requireAdmin, actualizarRolConfigEndpoint)
|
||||
apiRouter.get('/config/usuarios', requireAdmin, obtenerUsuariosEndpoint)
|
||||
apiRouter.patch('/config/usuarios/:id', requireAdmin, actualizarUsuarioEndpoint)
|
||||
apiRouter.post('/config/usuarios', requireAdmin, crearUsuarioEndpoint)
|
||||
apiRouter.post('/config/reset-roles', requireAdmin, resetRolesEndpoint)
|
||||
apiRouter.get('/config/acciones', obtenerAccionesEndpoint)
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
*/
|
||||
|
||||
import { prisma } from './prisma.js'
|
||||
import bcrypt from 'bcryptjs'
|
||||
import { Prisma } from '@prisma/client'
|
||||
import { normalizarUsername } from './auth.service.js'
|
||||
import { BadRequestError } from '../utils/errors.js'
|
||||
import { accionesPorRol, type AccionClave } from '../config/acciones.js'
|
||||
import { MATRIZ } from '../config/roles.js'
|
||||
import type { Modulo } from '../config/roles.js'
|
||||
@@ -192,3 +196,44 @@ export async function actualizarUsuario(
|
||||
if (data.activo !== undefined) clean.activo = data.activo
|
||||
await prisma.usuario.update({ where: { id }, data: clean as never })
|
||||
}
|
||||
|
||||
/** Crea un usuario (solo admin): username derivado del nombre, bcrypt cost 12 */
|
||||
export async function crearUsuario(datos: {
|
||||
nombre: string
|
||||
rol: string
|
||||
asignacion: string | null
|
||||
password: string
|
||||
}): Promise<UsuarioListado> {
|
||||
const username = normalizarUsername(datos.nombre)
|
||||
const passwordHash = bcrypt.hashSync(datos.password, 12)
|
||||
try {
|
||||
const u = await prisma.usuario.create({
|
||||
data: {
|
||||
username,
|
||||
nombre: datos.nombre.trim().replace(/\s+/g, ' '),
|
||||
passwordHash,
|
||||
rol: datos.rol,
|
||||
asignacion: datos.asignacion,
|
||||
activo: true,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
nombre: true,
|
||||
rol: true,
|
||||
asignacion: true,
|
||||
activo: true,
|
||||
mondayUserId: true,
|
||||
},
|
||||
})
|
||||
return u
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof Prisma.PrismaClientKnownRequestError &&
|
||||
err.code === 'P2002'
|
||||
) {
|
||||
throw new BadRequestError(`El usuario "${username}" ya existe`)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user