// auth/src/index.js import chalk from 'chalk'; // Colores! import express from 'express'; import expressLayouts from 'express-ejs-layouts'; import cors from 'cors'; import { Pool } from 'pg'; import bcrypt from'bcrypt'; // Rutas import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Variables de Entorno import dotenv, { config } from 'dotenv'; // Obtención de la ruta de la variable de entorno correspondiente a NODE_ENV try { if (process.env.NODE_ENV === 'development') { dotenv.config({ path: path.resolve(__dirname, '../.env.development' )}); console.log(`Activando entorno de ->${chalk.green(` DEVELOPMENT `)}`); } else if (process.env.NODE_ENV === 'stage') { dotenv.config({ path: path.resolve(__dirname, '../.env.test' )}); console.log(`Activando entorno de ->->${chalk.yellow(` TESTING `)}`); } else if (process.env.NODE_ENV === 'production') { dotenv.config({ path: path.resolve(__dirname, '../.env.production' )}); console.log(`Activando entorno de ->->${chalk.red(` PRODUCTION `)}`); } } catch (error) { console.log("A ocurrido un error al seleccionar el entorno. \nError: " + error); } // Renderiado const app = express(); app.use(cors()); app.use(express.json()); app.set('trust proxy', 1); // Configuración de conexión PostgreSQL const dbConfig = { host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, port: process.env.DB_LOCAL_PORT }; const pool = new Pool(dbConfig); async function verificarConexion() { try { const client = await pool.connect(); const res = await client.query('SELECT NOW() AS hora'); console.log(`\nConexión con la base de datos ${chalk.green(process.env.DB_NAME)} fue exitosa.`); console.log('Fecha y hora actual de la base de datos:', res.rows[0].hora); client.release(); // liberar el cliente de nuevo al pool } catch (error) { console.error('Error al conectar con la base de datos al iniciar:', error.message); console.error(`Troubleshooting:\n1. Compruebe que las bases de datos se iniciaron correctamente.\n2. Verifique las credenciales y puertos de acceso a la base de datos.\n3. Si está conectandose a una base de datos externa a localhost, verifique las reglas del firewal de entrada y salida de ambos dispositivos.`); } } // === Servir páginas estáticas === app.set('trust proxy', true); app.use(express.static(path.join(__dirname, 'pages'))); app.get('/',(req, res) => res.sendFile(path.join(__dirname, 'pages', 'index.html'))); app.get('/planes', async (req, res) => { try { const result = await pool.query(` SELECT id, nombre, descripcion, precio FROM plan WHERE activo = true ORDER BY id `); res.json(result.rows); } catch (err) { console.error(err); res.status(500).json({ error: 'Error al cargar planes' }); } }); app.post('/api/registro', async (req, res) => { const { nombre_empresa, rut, correo, telefono, direccion, logo, clave_acceso, plan_id } = req.body; try { const client = await pool.connect(); // 1. Hashear la contraseña const hash = await bcrypt.hash(clave_acceso, 10); // 2. Insertar el tenant const result = await client.query(` INSERT INTO tenant ( nombre_empresa, rut, correo, telefono, direccion, logo, clave_acceso, plan_id, nombre_base_datos ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, 'TEMPORAL' ) RETURNING uuid; `, [ nombre_empresa, rut, correo, telefono, direccion, logo, hash, plan_id ]); const uuid = result.rows[0].uuid; const nombre_base_datos = `tenantdb_${uuid}`.replace(/-/g, '').substring(0, 24); // ajustamos para longitud segura // 3. Actualizar el campo nombre_base_datos await client.query(` UPDATE tenant SET nombre_base_datos = $1 WHERE uuid = $2 `, [nombre_base_datos, uuid]); client.release(); return res.status(201).json({ message: 'Tenant registrado correctamente', uuid, nombre_base_datos }); } catch (err) { console.error(err); return res.status(500).json({ error: 'Error al registrar tenant' }); } }); app.post('/api/login', async (req, res) => { const { correo, clave_acceso } = req.body; try { const client = await pool.connect(); const result = await client.query(` SELECT uuid, clave_acceso, nombre_empresa, nombre_base_datos FROM tenant WHERE correo = $1 AND estado = true `, [correo]); client.release(); if (result.rows.length === 0) { return res.status(401).json({ error: 'Correo no registrado o inactivo' }); } const tenant = result.rows[0]; const coincide = await bcrypt.compare(clave_acceso, tenant.clave_acceso); if (!coincide) { return res.status(401).json({ error: 'Clave incorrecta' }); } return res.status(200).json({ message: 'Login correcto', uuid: tenant.uuid, nombre_empresa: tenant.nombre_empresa, base_datos: tenant.nombre_base_datos }); } catch (err) { console.error(err); return res.status(500).json({ error: 'Error al validar login' }); } }); // Colores personalizados let primaryColor = chalk.hex('#'+`${process.env.COL_PRI}`); let secondaryColor = chalk.hex('#'+`${process.env.COL_SEC}`); // let backgroundColor = chalk.hex('#'+`${process.env.COL_BG}`); app.use(expressLayouts); // Iniciar servidor app.listen( process.env.PORT, () => { console.log(`Servidor de ${chalk.yellow('autenticación')} de ${secondaryColor('SuiteCoffee')} corriendo en ${chalk.yellow(`http://localhost:${process.env.PORT}\n`)}` ); console.log(chalk.grey(`Comprobando accesibilidad a la db ${chalk.green(process.env.DB_NAME)} del host ${chalk.white(`${process.env.DB_HOST}`)} ...`)); verificarConexion(); }); app.get("/health", async (req, res) => { // Podés chequear DB aquí. 200 = healthy; 503 = not ready. res.status(200).json({ status: "ok" }); });