Files
FRASA-CAS/api-gateway/scripts/seed-usuarios.ts
Consult AS Technology de11af985e feat(auth): login JWT en API y las 4 apps
- Modelo Usuario + seed desde lista de vendedores (18 usuarios, bcrypt cost 12)
- POST /api/auth/login + /api/auth/me; middleware Bearer en todo /api
  excepto health, login y webhook Monday; flag AUTH_ENABLED
- Username = nombre completo normalizado (case/acentos insensible),
  password inicial Frasa2026, admin vía ADMIN_PASSWORD
- Apps: LoginScreen + AuthGate (StudioBlank), token en localStorage,
  header Authorization en todas las llamadas, logout en 401
- Tests: api 136, cotizador 71, alta 65, cobranza 71, agente-ia 13, landing 4
2026-08-27 08:20:25 +00:00

124 lines
3.8 KiB
TypeScript

/**
* Siembra los usuarios del ecosistema FRASA.
*
* - Lee reference/vendedores.json (gitignored). Si no existe, solo crea el
* usuario admin y avisa.
* - Username = nombre completo normalizado (minúsculas, sin acentos, espacios
* simples). Password inicial de todos: 'Frasa2026' (bcrypt cost 12).
* - Upsert por username: NO resetea el password de usuarios existentes.
* Con `--reset-passwords` sí lo restablece al inicial.
* - Admin: username 'admin', password de env ADMIN_PASSWORD (default
* 'Frasa2026'), rol 'admin'.
*
* Uso: npm run seed:usuarios [-- --reset-passwords]
*/
import fs from 'node:fs'
import path from 'node:path'
import bcrypt from 'bcryptjs'
import { prisma } from '../src/services/prisma.js'
import { normalizarUsername } from '../src/services/auth.service.js'
import { config } from '../src/config/index.js'
const PASSWORD_INICIAL = 'Frasa2026'
const BCRYPT_COST = 12
export interface DatosUsuarioSeed {
username: string
nombre: string
rol: string
asignacion: string | null
empleadoId: number | null
passwordHash: string
}
/**
* Upsert por username. NO toca el password de un usuario existente salvo que
* resetPasswords sea true (flag --reset-passwords).
*/
export async function upsertUsuario(
datos: DatosUsuarioSeed,
resetPasswords: boolean,
): Promise<'creado' | 'actualizado'> {
const existente = await prisma.usuario.findUnique({ where: { username: datos.username } })
if (!existente) {
await prisma.usuario.create({ data: datos })
return 'creado'
}
await prisma.usuario.update({
where: { username: datos.username },
data: {
nombre: datos.nombre,
rol: datos.rol,
asignacion: datos.asignacion,
empleadoId: datos.empleadoId,
...(resetPasswords ? { passwordHash: datos.passwordHash } : {}),
},
})
return 'actualizado'
}
interface VendedorJson {
empleadoId: number | null
nombre: string
asignacion: string | null
rol: string
}
async function main(): Promise<void> {
const resetPasswords = process.argv.includes('--reset-passwords')
const rutaVendedores = path.resolve(process.cwd(), '..', 'reference', 'vendedores.json')
const hashVendedores = bcrypt.hashSync(PASSWORD_INICIAL, BCRYPT_COST)
const hashAdmin = bcrypt.hashSync(config.auth.adminPassword, BCRYPT_COST)
let creados = 0
let actualizados = 0
if (fs.existsSync(rutaVendedores)) {
const json = JSON.parse(fs.readFileSync(rutaVendedores, 'utf8')) as { vendedores: VendedorJson[] }
for (const v of json.vendedores) {
const resultado = await upsertUsuario(
{
username: normalizarUsername(v.nombre),
nombre: v.nombre,
rol: v.rol,
asignacion: v.asignacion,
empleadoId: v.empleadoId,
passwordHash: hashVendedores,
},
resetPasswords,
)
if (resultado === 'creado') creados++
else actualizados++
}
console.log(`[seed-usuarios] vendedores: ${creados} creados, ${actualizados} actualizados`)
} else {
console.warn(`[seed-usuarios] AVISO: no existe ${rutaVendedores}; se crea solo el admin`)
}
const admin = await upsertUsuario(
{
username: 'admin',
nombre: 'Administrador FRASA',
rol: 'admin',
asignacion: null,
empleadoId: null,
passwordHash: hashAdmin,
},
resetPasswords,
)
console.log(`[seed-usuarios] admin ${admin}${resetPasswords ? ' (password restablecido)' : ''}`)
const total = await prisma.usuario.count()
console.log(`[seed-usuarios] total de usuarios en BD: ${total}`)
}
// Solo se ejecuta como script (npm run seed:usuarios); al importarlo en tests no corre
if (process.argv[1]?.endsWith('seed-usuarios.ts')) {
main()
.catch((err) => {
console.error('[seed-usuarios] falló:', err)
process.exitCode = 1
})
.finally(() => prisma.$disconnect())
}