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,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 };