primer cambio
This commit is contained in:
273
src/controladores/sql/C_sql_inyec.js
Normal file
273
src/controladores/sql/C_sql_inyec.js
Normal 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 };
|
||||
Reference in New Issue
Block a user