primer cambio

This commit is contained in:
beseira13
2026-01-19 12:12:38 -03:00
parent 5f59dba52d
commit 44990f015a
4759 changed files with 588702 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
import jwt from "jsonwebtoken";
import dotenv from 'dotenv';
import { dbasistente } from "../../db.js";
// Configuración de variables de entorno
dotenv.config();
async function autentificacion(req, res) {
try {
let username, password;
// 1. Intentar obtener de cabecera Authorization (Basic Auth)
const authHeader = req.headers.authorization;
if (authHeader && authHeader.startsWith('Basic ')) {
const base64Credentials = authHeader.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
[username, password] = credentials.split(':');
}
// 2. Si no hay cabecera, intentar obtener del body (JSON)
else if (req.body.username && req.body.password) {
username = req.body.username;
password = req.body.password;
}
// Validar que tengamos credenciales
if (!username || !password) {
return res.status(401).json({
error: "Credenciales faltantes",
mensaje: "Se requiere autenticación básica o un cuerpo JSON con {username, password}"
});
}
// Consulta a la nueva tabla soporte_copy en dbasistente
const [db_user] = await dbasistente.query(
"SELECT CODIGO_SOP, NOMBRE_SOP, USUARIO_SOP, NIVEL_SOP FROM soporte_copy WHERE USUARIO_SOP = ? AND CLAVE_SOP = ? AND ESTADO_SOP = 'V'",
{
replacements: [username, password]
}
);
// Verificar si se encontró el usuario
if (db_user.length === 0) {
return res.status(401).json({
error: "Credenciales inválidas",
mensaje: "Usuario o contraseña incorrectos"
});
}
const userRecord = db_user[0];
// Determinar privilegio basado en NIVEL_SOP
// NIVEL_SOP 1 = solo lectura (READ), 4 = admin (CRUD)
let privilegio = "READ";
if (userRecord.NIVEL_SOP === 4 || userRecord.NIVEL_SOP === '4') {
privilegio = "CRUD";
}
// Verificar clave secreta JWT
if (!process.env.SECRET) {
throw new Error("La clave secreta JWT no está configurada");
}
// Crear payload del token
const payload = {
id: userRecord.CODIGO_SOP,
username: userRecord.USUARIO_SOP,
nombre: userRecord.NOMBRE_SOP,
privilegio: privilegio
};
// Generar token JWT
const token = jwt.sign(
payload,
process.env.SECRET,
{ expiresIn: '3h' }
);
// Respuesta exitosa según el formato solicitado
return res.status(200).json({
success: true,
message: "Login exitoso",
token: token,
user: {
id: userRecord.CODIGO_SOP,
username: userRecord.USUARIO_SOP,
nombre: userRecord.NOMBRE_SOP,
privilegio: privilegio
}
});
} catch (error) {
console.error("Error en autenticación:", error);
// Error genérico
return res.status(500).json({
error: "Error interno del servidor",
detalles: process.env.NODE_ENV === 'development' ? error.message : undefined
});
}
}
export { autentificacion };

View File

@@ -0,0 +1,15 @@
// Locales.controller.js
async function obtener_locales(req, res, dbecommerce) {
try {
const result = await dbecommerce.query("SELECT b.numbodega, b.nombrebodega FROM bodegas_ecommerce b ORDER BY b.numbodega ASC");
// Enviar la respuesta al cliente como JSON
res.status(200).json(result[0]);
} catch (error) {
console.error("Error:", error);
// Enviar un mensaje de error al cliente si ocurre un problema
res.status(500).json({ error: "Hubo un error en el servidor" });
}
}
export { obtener_locales };

View File

@@ -0,0 +1,273 @@
async function sql_inyec(req, res, dbcentral) {
try {
const store_id = req.query.store_id;
const id_cliente = req.query.id_cliente;
if (!store_id) {
return res.status(400).json({ error: "store_id es requerido" });
}
// Validar que store_id sea un número para evitar errores de tipo en la DB
if (isNaN(store_id)) {
return res.status(400).json({
error: "store_id inválido",
message: "El store_id debe ser un valor numérico"
});
}
// Registrar/Actualizar Heartbeat cada vez que una tienda consulta
await dbcentral.query(
`INSERT INTO tb_store_process_heartbeat
(store_id, process_name, instance_id, status, extra_info, id_cliente)
VALUES (?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
status = 'alive',
last_ping = CURRENT_TIMESTAMP;`,
{
replacements: [
store_id,
'sql_inyector',
'sql_inyector',
'alive',
JSON.stringify({ message: 'Consultando comandos', timestamp: new Date() }),
id_cliente || null
]
}
);
// Consultar comandos pendientes para este store_id
const [results] = await dbcentral.query(
"SELECT * FROM tb_sql_inyector WHERE store_id = ? and id_cliente=? AND estado = '0' LIMIT 1",
{
replacements: [store_id, id_cliente]
}
);
if (results.length === 0) {
return res.status(204).json({
message: "No hay comandos pendientes"
});
}
const command = results[0];
// Construir la respuesta solicitada
const response = {
command_id: command.command_id,
sql: command.sql,
privilegio: command.privilegio || "READ" // Valor por defecto si no existe la columna
};
// Respuesta
res.status(200).json(response);
} catch (error) {
console.error("❌ Error al procesar consulta sql_inyec:", error.message);
res.status(500).json({
error: "Error interno del servidor",
message: process.env.NODE_ENV === 'development' ? error.message : 'Error interno'
});
}
}
async function save_result_inyec(req, res, dbcentral) {
try {
let { command_id, result } = req.body;
if (!command_id) {
return res.status(400).json({ error: "command_id es requerido" });
}
// Si no se envía una propiedad 'result' explícita, asumimos que todo el body es la respuesta
if (result === undefined) {
result = req.body;
}
// Serializar el resultado a JSON si es un objeto
const jsonResponse = typeof result === 'object' ? JSON.stringify(result) : result;
const [updateResult] = await dbcentral.query(
`UPDATE tb_sql_inyector SET json_response = ?, estado = '1' WHERE command_id = ?`,
{
replacements: [jsonResponse, command_id]
}
);
// En algunas configuraciones de Sequelize/MySQL, el resultado de un update puede variar.
// Verificamos si hubo cambios (affectedRows) si está disponible en updateResult.
// Nota: updateResult suele ser un objeto con info del resultado en raw query.
res.status(200).json({
success: true,
message: "Resultado guardado correctamente"
});
} catch (error) {
console.error("❌ Error al guardar resultado:", error.message);
res.status(500).json({
error: "Error interno del servidor",
message: process.env.NODE_ENV === 'development' ? error.message : 'Error interno'
});
}
}
async function create_command(req, res, dbcentral) {
try {
const { store_id, sql, privilegio, id_user, id_cliente } = req.body;
if (!store_id || !sql) {
return res.status(400).json({ error: "store_id y sql son requeridos" });
}
if (isNaN(store_id)) {
return res.status(400).json({
error: "store_id inválido",
message: "El store_id debe ser un valor numérico"
});
}
const [commandId] = await dbcentral.query(
"INSERT INTO tb_sql_inyector (store_id, `sql`, privilegio, id_user, id_cliente, estado) VALUES (?, ?, ?, ?, ?, '0')",
{
replacements: [store_id, sql, privilegio || 'READ', id_user || null, id_cliente || null]
}
);
res.status(201).json({
success: true,
message: "Comando creado exitosamente",
command_id: commandId
});
} catch (error) {
console.error("❌ Error al crear comando:", error.message);
res.status(500).json({
error: "Error interno del servidor",
message: process.env.NODE_ENV === 'development' ? error.message : 'Error interno'
});
}
}
async function get_command_status(req, res, dbcentral) {
try {
const command_id = req.params.command_id;
if (!command_id) {
return res.status(400).json({ error: "command_id es requerido" });
}
const [results] = await dbcentral.query(
`SELECT * FROM tb_sql_inyector WHERE command_id = ? AND estado = '1'`,
{
replacements: [command_id]
}
);
if (results.length === 0) {
// Verificamos si existe pero está en otro estado para dar un mensaje más claro,
// o simplemente retornamos 404 si no se encuentra completado.
// Para ser simple y directo como en los otros endpoints:
return res.status(404).json({
message: "Comando no encontrado o aún no completado"
});
}
const command = results[0];
// Intentar parsear el json_response si es un string
let jsonResponse = command.json_response;
try {
if (typeof jsonResponse === 'string') {
jsonResponse = JSON.parse(jsonResponse);
}
} catch (e) {
// Si falla el parseo, dejamos el string original
}
res.status(200).json({
command_id: command.command_id,
status: "completed",
result: jsonResponse,
processed_at: command.fecha_proceso
});
} catch (error) {
console.error("❌ Error al obtener estado del comando:", error.message);
res.status(500).json({
error: "Error interno del servidor",
message: process.env.NODE_ENV === 'development' ? error.message : 'Error interno'
});
}
}
async function get_commands_by_user(req, res, dbcentral) {
try {
const id_user = req.params.id_user;
const limit = req.query.limit || 50;
if (!id_user) {
return res.status(400).json({ error: "id_user es requerido" });
}
const [results] = await dbcentral.query(
`SELECT command_id, store_id, \`sql\`, privilegio, estado, fecha_solicitud, fecha_proceso, json_response
FROM tb_sql_inyector
WHERE id_user = ?
ORDER BY command_id DESC
LIMIT ?`,
{
replacements: [id_user, parseInt(limit)]
}
);
// Parsear cada json_response si es necesario
const formattedResults = results.map(cmd => {
let jsonResponse = cmd.json_response;
try {
if (typeof jsonResponse === 'string') {
jsonResponse = JSON.parse(jsonResponse);
}
} catch (e) { }
return {
...cmd,
json_response: jsonResponse
};
});
res.status(200).json(formattedResults);
} catch (error) {
console.error("❌ Error al obtener comandos por usuario:", error.message);
res.status(500).json({
error: "Error interno del servidor",
message: process.env.NODE_ENV === 'development' ? error.message : 'Error interno'
});
}
}
async function get_online_stores(req, res, dbcentral) {
try {
// Obtenemos los locales y su último ping
// Consideramos "Online" si el ping fue hace menos de 2 minutos
const [results] = await dbcentral.query(
`SELECT
h.store_id,
h.last_ping,
h.status,
IF(TIMESTAMPDIFF(SECOND, h.last_ping, CURRENT_TIMESTAMP) <= 120, 'ONLINE', 'OFFLINE') as connectivity
FROM tb_store_process_heartbeat h
WHERE h.process_name = 'sql_inyector'
ORDER BY h.last_ping DESC`
);
res.status(200).json(results);
} catch (error) {
console.error("❌ Error al obtener tiendas online:", error.message);
res.status(500).json({
error: "Error interno del servidor"
});
}
}
export { sql_inyec, save_result_inyec, create_command, get_command_status, get_commands_by_user, get_online_stores };

View File

@@ -0,0 +1,77 @@
import defineLogHookProcesos from '../../database/modelos/M_webhoock.js';
// Asegurarnos de que el modelo esté definido una sola vez
let modeloDefined = false;
async function webhoock(req, res, dbcentral) {
try {
const body = req.body;
// Validación rápida inicial
if (!body || typeof body !== 'object') {
return res.status(400).json({ error: "El cuerpo del webhook es inválido" });
}
// Validación de contenido
const keys = Object.keys(body);
if (keys.length === 0) {
return res.status(400).json({ error: "El cuerpo del webhook está vacío" });
}
// Definir el modelo solo si no está definido
if (!modeloDefined) {
await defineLogHookProcesos(dbcentral);
modeloDefined = true;
}
// Validar que IdMnt existe antes de procesar
if (!body.IdMnt) {
return res.status(400).json({
error: "Campo requerido faltante",
message: "El campo IdMnt es obligatorio para procesar el webhook"
});
}
// Verificar si el registro ya existe
const existingRecord = await dbcentral.models.log_hook_procesos.findOne({
where: {
OrderId: body.IdMnt.toString()
}
});
if (existingRecord) {
return res.status(409).json({
error: "Registro duplicado",
message: "Ya existe un registro con este OrderId",
id: existingRecord.id
});
}
// Crear el registro directamente sin sanitización redundante
const result = await dbcentral.models.log_hook_procesos.create({
json: JSON.stringify(body),
OrderId: body.IdMnt.toString(),
NroPaquete: body.NroPaquete || null,
estatus: body.estatus || null,
tipo: body.TipoMnt ? body.TipoMnt.toString() : null
}, {
logging: false, // Desactivar logging SQL
returning: ['id'] // Solo retornar el ID
});
// Respuesta rápida
res.status(201).json({
success: true,
message: 'Webhook almacenado correctamente',
id: result.id
});
} catch (error) {
// Log simplificado del error
console.error("❌ Error al procesar webhook:", error.message);
res.status(500).json({
error: "Error al procesar el webhook",
message: process.env.NODE_ENV === 'development' ? error.message : 'Error interno del servidor'
});
}
}
export { webhoock };