chore: prepara el proyecto para el primer deploy a produccion
- seed-db.js: los datos de ejemplo (departamentos TI/Finanzas/RRHH/Comercial + usuario admin con clave=usuario) solo se cargan si NODE_ENV != production. En produccion el seed solo carga catalogos (roles, prioridades, estados, tipos de proyecto) — la organizacion real la crea el admin desde la UI. - Nuevo backend/src/scripts/create-admin.js: crea el usuario Administrador inicial de produccion con una clave fuerte generada al azar (nunca clave=usuario, esa convencion es solo para dev). - frontend: agrega "serve" como dependencia de produccion (arquetipo B: el frontend corre como proceso separado sirviendo el build con `serve -s dist`). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,8 @@
|
||||
"dev": "node --watch src/server.js",
|
||||
"start": "node src/server.js",
|
||||
"migrate": "node src/scripts/migrate-db.js",
|
||||
"seed": "node src/scripts/seed-db.js"
|
||||
"seed": "node src/scripts/seed-db.js",
|
||||
"create-admin": "node src/scripts/create-admin.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"bcryptjs": "^2.4.3",
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Crea (o re-activa) el usuario Administrador inicial con una clave fuerte generada al azar,
|
||||
// mostrada UNA sola vez. Para produccion — NUNCA usar la convencion clave=usuario aqui.
|
||||
// Uso: node src/scripts/create-admin.js "Nombre Apellido" correo@dominio.com
|
||||
import crypto from 'node:crypto';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import mysql from 'mysql2/promise';
|
||||
import { env } from '../config/env.js';
|
||||
|
||||
const [name, email] = process.argv.slice(2);
|
||||
if (!name || !email) {
|
||||
console.error('Uso: node src/scripts/create-admin.js "Nombre Apellido" correo@dominio.com');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const db = await mysql.createConnection({
|
||||
host: env.db.host,
|
||||
port: env.db.port,
|
||||
database: env.db.name,
|
||||
user: env.db.user,
|
||||
password: env.db.password,
|
||||
});
|
||||
|
||||
const [adminRole] = await db.query("SELECT id FROM roles WHERE code = 'admin'");
|
||||
if (!adminRole.length) throw new Error('Rol admin no existe — correr primero npm run seed');
|
||||
|
||||
const password = crypto.randomBytes(18).toString('base64').replace(/[/+=]/g, '').slice(0, 20);
|
||||
const passwordHash = await bcrypt.hash(password, 12);
|
||||
|
||||
await db.query(
|
||||
`INSERT INTO users (name, email, password_hash, role_id, department_id, position, is_active)
|
||||
VALUES (?, ?, ?, ?, NULL, NULL, 1)
|
||||
ON DUPLICATE KEY UPDATE password_hash = VALUES(password_hash), is_active = 1`,
|
||||
[name, email, passwordHash, adminRole[0].id]
|
||||
);
|
||||
|
||||
console.log('[create-admin] listo. Guarda esta clave ahora — no se muestra de nuevo:');
|
||||
console.log(` email: ${email}`);
|
||||
console.log(` clave: ${password}`);
|
||||
await db.end();
|
||||
}
|
||||
|
||||
run().catch((err) => {
|
||||
console.error('[create-admin] error:', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -11,7 +11,7 @@ async function run() {
|
||||
password: env.db.password,
|
||||
});
|
||||
|
||||
// Roles fijos del MVP.
|
||||
// Catalogos base — necesarios para que la app funcione en CUALQUIER entorno (dev y produccion).
|
||||
const roles = [
|
||||
['admin', 'Administrador'],
|
||||
['it_manager', 'Jefe de TI'],
|
||||
@@ -70,6 +70,15 @@ async function run() {
|
||||
await db.query('INSERT IGNORE INTO project_types (name) VALUES (?)', [name]);
|
||||
}
|
||||
|
||||
// Datos de ejemplo (departamentos + usuario admin de dev) — SOLO en entornos no productivos.
|
||||
// En produccion los departamentos reales los crea el admin desde Organizacion, y el usuario
|
||||
// admin inicial se crea aparte con scripts/create-admin.js (clave fuerte generada, no "clave=usuario").
|
||||
if (env.nodeEnv === 'production') {
|
||||
console.log('[seed] NODE_ENV=production: solo se cargaron catalogos. Departamentos y usuario admin de ejemplo NO se crean aqui — usar create-admin.js.');
|
||||
await db.end();
|
||||
return;
|
||||
}
|
||||
|
||||
const departments = [
|
||||
['TI', null],
|
||||
['Finanzas', null],
|
||||
|
||||
Reference in New Issue
Block a user