diff --git a/.env.dev.pcb b/.env.dev.pcb index 86c5b99..076722d 100644 --- a/.env.dev.pcb +++ b/.env.dev.pcb @@ -42,5 +42,5 @@ MIAB_HOST=box.lamiaposta.org MIAB_ADMIN_EMAIL=admin@lamiaposta.org MIAB_ADMIN_PASSWORD=passpao1pabox@1A DS_API_KEY="sk-222e3addb3d8455d8b0516d93906eec7" -API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK" -SERVER_A_URL="http://51.77.156.69:3000" \ No newline at end of file +SERVER_A_URL="http://51.77.156.69:3000" +API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK" \ No newline at end of file diff --git a/.env.prod.pcb b/.env.prod.pcb index 342e5db..c030678 100644 --- a/.env.prod.pcb +++ b/.env.prod.pcb @@ -40,9 +40,5 @@ CLOUDFLARE_TOKENS=[{"label":"Paolo.arena77@gmail.com","value":"M9EM309v8WFquJKpY MIAB_HOST=box.lamiaposta.org MIAB_ADMIN_EMAIL=admin@lamiaposta.org MIAB_ADMIN_PASSWORD=passpao1pabox@1A -#DB_CONNECTION=sqlsrv -DB_HOST_SQLSRVTEST=31.3.180.50 -DB_PORT_SQLSRVTEST=14338 -DB_DATABASE_SQLSRVTEST=ANAG_MACRO -DB_USERNAME_SQLSRVTEST=woo -DB_PASSWORD_SQLSRVTEST=4n4traPe@ +SERVER_A_URL="http://51.77.156.69:3000" +API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK" \ No newline at end of file diff --git a/.env.test.pcb b/.env.test.pcb index e146916..a64124a 100644 --- a/.env.test.pcb +++ b/.env.test.pcb @@ -40,4 +40,6 @@ SCRIPTS_DIR=admin_scripts CLOUDFLARE_TOKENS=[{"label":"Paolo.arena77@gmail.com","value":"M9EM309v8WFquJKpYgZCw-TViM2wX6vB3wlK6GD0"},{"label":"gruppomacro.com","value":"bqmzGShoX7WqOBzkXocoECyBkPq3GfqcM5t6VFd8"}] MIAB_HOST=box.lamiaposta.org MIAB_ADMIN_EMAIL=admin@lamiaposta.org -MIAB_ADMIN_PASSWORD=passpao1pabox@1A \ No newline at end of file +MIAB_ADMIN_PASSWORD=passpao1pabox@1A +SERVER_A_URL="http://51.77.156.69:3000" +API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK" \ No newline at end of file diff --git a/src/server/controllers/articleController.js b/src/server/controllers/articleController.js index db34661..0e95820 100644 --- a/src/server/controllers/articleController.js +++ b/src/server/controllers/articleController.js @@ -4,6 +4,8 @@ const server_constants = require('../tools/server_constants'); const shared_consts = require('../tools/shared_nodejs'); +const tools = require('../tools/general'); + const SERVER_A_URL = process.env.SERVER_A_URL || "http://IP_DI_SERVER_A:3000"; const API_KEY = process.env.API_KEY_MSSQL; @@ -18,7 +20,9 @@ const getArticlesSales = async () => { COALESCE(o.totVen, 0) as totVen, COALESCE(u.totFat, 0) as totFat, COALESCE(p.rank3M, 0) as rank3M, COALESCE(t.fatrank3M, 0) as fatrank3M, COALESCE(q.rank6M, 0) as rank6M, COALESCE(r.rank1Y, 0) as rank1Y, - COALESCE(t.fat3mesi, 0) as fatLast3M, COALESCE(p.venduti3mesi, 0) as vLast3M, + COALESCE(t.fat3mesi, 0) as fatLast3M, + COALESCE(t.fat6mesi, 0) as fatLast6M, + COALESCE(p.venduti3mesi, 0) as vLast3M, COALESCE(q.venduti6mesi, 0) as vLast6M, COALESCE(r.venduti1anno, 0) as vLastY, s.ultimoOrdine as dataUltimoOrdine FROM T_WEB_Articoli a @@ -82,7 +86,7 @@ const getTableContent = async (options) => { const checkResponse = await axios.post(SERVER_A_URL + '/query', { query: checkTableQuery }, { headers: { 'x-api-key': API_KEY } }); - if (!checkResponse.data || checkResponse.data.length === 0 || checkResponse.data[0].tableExists === 0) { + if (!checkResponse?.data || checkResponse?.data.length === 0 || checkResponse?.data[0].tableExists === 0) { return `La tabella '${options.nameTable}' non esiste.`; } @@ -115,7 +119,7 @@ const getTableContent = async (options) => { if (options.nameTable.toLowerCase() === 't_web_articoli') { if (true) { dataQuery = ` - SELECT TOP ${options.numrec} + SELECT TOP ${options.numrec || 10000} ${columnsToShow} ` + (options.campispeciali ? ` ,f.DescrizioneStatoProdotto @@ -236,18 +240,20 @@ const getTableContent = async (options) => { `; } } else { - dataQuery = `SELECT TOP ${options.numrec} * FROM ${options.nameTable} `; + dataQuery = `SELECT TOP ${options.numrec || 10000} * FROM ${options.nameTable} `; } if (options.where && options.where.trim() !== "") { dataQuery += ` WHERE ${options.where} `; } + console.log('dataQuery', dataQuery); + // Esegue la query per recuperare i dati // console.log('dataQuery', dataQuery); const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, { headers: { 'x-api-key': API_KEY } }); - const records = dataResponse.data; + const records = dataResponse?.data; if (!records || records.length === 0) { return `Nessun record trovato nella tabella '${options.nameTable}'.`; } @@ -355,6 +361,7 @@ const getTableContent = async (options) => { return output; } catch (error) { + output = error.message; console.error("Errore nel recupero della tabella: ", error.message); if (options.outhtml) { output = ` @@ -409,6 +416,200 @@ const getTableContent = async (options) => { } }; +const setTableContent = async (options) => { + try { + // checkPermissions() + + const esegui = true + + if (esegui) { + + // Verifica se la tabella esiste + const checkTableQuery = `SELECT COUNT(*) as tableExists FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '${options.nameTable}'`; + const checkResponse = await axios.post(SERVER_A_URL + '/query', { query: checkTableQuery }, { + headers: { 'x-api-key': API_KEY } + }); + + if (!checkResponse.data || checkResponse.data.length === 0 || checkResponse.data[0].tableExists === 0) { + return `La tabella '${options.nameTable}' non esiste.`; + } + + // Costruisce la query per inserire o aggiornare i record + let dataQuery = ""; + if (options.insertMode) { + // Modalità INSERT + const columns = Object.keys(options.data); + const values = columns.map(col => `'${options.data[col]}'`).join(", "); + dataQuery = ` + INSERT INTO ${options.nameTable} (${columns.join(", ")}) + VALUES (${values}); + `; + } else { + // Modalità UPDATE + const updateFields = Object.keys(options.data) + .map(col => `${col} = '${options.data[col]}'`) + .join(", "); + const whereClause = options.where ? `WHERE ${options.where}` : ""; + dataQuery = ` + UPDATE ${options.nameTable} + SET ${updateFields} + ${whereClause}; + `; + } + + console.log('dataQuery', dataQuery); + + // Esegue la query per inserire o aggiornare i dati + const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, { + headers: { 'x-api-key': API_KEY } + }); + + if (dataResponse.data && dataResponse.data.affectedRows > 0) { + return `Operazione completata con successo su '${options.nameTable}'.`; + } else { + return `Nessun record modificato nella tabella '${options.nameTable}'.`; + } + } + } catch (error) { + console.error("Errore nell'inserimento o aggiornamento della tabella: ", error.message); + if (options.outhtml) { + output = ` + + + Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable} + + + +
+
Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}
+
+ ${error.response.data.error || error.stack || error.message} +
+
+ + `; + return output; + } + return "Errore nell'inserimento o aggiornamento della tabella."; + } +}; +const checkPermissions = async (options) => { + try { + const dataQuery = ` + SELECT + dp.name AS UserName, + dp.type_desc AS UserType, + o.name AS ObjectName, + p.permission_name, + p.state_desc AS PermissionState + FROM + sys.database_permissions p + JOIN + sys.objects o ON p.major_id = o.object_id + JOIN + sys.database_principals dp ON p.grantee_principal_id = dp.principal_id + WHERE + o.name = 'T_WEB_Articoli'; + `; + + console.log('checkPermissions query:', dataQuery); + + // Esegue la query per inserire o aggiornare i dati + const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, { + headers: { 'x-api-key': API_KEY } + }); + + console.log('checkPermissions result:', dataResponse.data); + + if (dataResponse.data && dataResponse.data.affectedRows > 0) { + return `Operazione completata con successo.`; + } else { + return `Nessun permesso.`; + } + } catch (error) { + console.error("Errore nel check dei Permessi: ", error.message); + if (options.outhtml) { + output = ` + + + Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable} + + + +
+
Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}
+
+ ${error.response.data.error || error.stack || error.message} +
+
+ + `; + return output; + } + return "Errore nell'inserimento o aggiornamento della tabella."; + } +}; + // Endpoint per mostrare i dati della tabella exports.viewTable = async (req, res) => { try { @@ -429,6 +630,12 @@ exports.viewTable = async (req, res) => { out = tableContent; } + if (tableContent && tableContent.length > 0) { + if (options.updatelocaldb) { + this.updateLocalDb(tableContent[0], options) + } + } + return res.send({ code: server_constants.RIS_CODE_OK, data: out }); } catch (error) { @@ -437,6 +644,82 @@ exports.viewTable = async (req, res) => { } }; +exports.updateLocalDb = async (tableContent, options) => { + try { + + const ProductInfo = require('../models/productInfo'); + const CatProd = require('../models/catprod'); + + let recproductInfo = { + code: tableContent.Ean13.trim(), + }; + + let risrecUpdated = null; + + const recfound = await ProductInfo.findOne({ code: recproductInfo.code }).lean(); + if (recfound) { + + ListaArgomenti = tableContent.ListaArgomenti; + + let arrayPulito = ListaArgomenti + .trim() // Rimuove gli spazi all'inizio e alla fine + .replace(/[\(\)]/g, '') // Rimuove le parentesi tonde + .split(','); // Divide la stringa in un array usando la virgola come separatore + + if (arrayPulito && arrayPulito.length > 0) { + let aggiornacat = false; + const precCatProds = recfound.idCatProds; + let reccatprods = []; + for (let i = 0; i < arrayPulito.length; i++) { + const idArgomento = parseInt(arrayPulito[i]); + reccateg = await CatProd.findOne({ idArgomento }).lean(); + + if (reccateg) { + // aggiungi solo se non esiste già + if (!reccatprods.includes(reccateg._id)) { + reccatprods.push(reccateg._id); + } + } + } + + // ora controlla se l'array reccatprods e' diverso da precCatProds + if (reccatprods.length !== precCatProds.length) { + aggiornacat = true; + } else { + for (let i = 0; i < reccatprods.length; i++) { + if (reccatprods[i].toString() !== precCatProds[i].toString()) { + aggiornacat = true; + break; + } + } + } + + if (aggiornacat) { + recproductInfo.idCatProds = reccatprods; + aggiorna = true; + } + } + + if (tableContent.DataPubblicazione.trim()) { + recproductInfo.date_pub = new Date(tools.convertiDataItaliana(tableContent.DataPubblicazione.trim()).date); + // convert data to timestamp + recproductInfo.date_pub_ts = recproductInfo.date_pub.getTime(); + aggiorna = true; + } + + if (aggiorna) { + risrecUpdated = await ProductInfo.findOneAndUpdate({ code: recproductInfo.code }, { $set: recproductInfo }, { new: true, upsert: true }); + } + + return risrecUpdated; + } + + } catch (e) { + console.error('Error: ', e); + return null; + } +} + // Endpoint per mostrare i dati della tabella exports.queryTable = async (req, res) => { try { @@ -462,3 +745,30 @@ exports.queryTable = async (req, res) => { return res.send({ code: server_constants.RIS_CODE_ERR, error }); } }; +// Endpoint per salvare i dati di una tabella +exports.saveTable = async (req, res) => { + try { + const options = req.body.options; + const tableContent = await setTableContent(options); + + let out = {}; + + if (options.outhtml) { + out = ` +

Tabella: ${options.nameTable}

+
Query: ${options.where}
+
+ ${tableContent} +
+ ` + } else { + out = tableContent; + } + + return res.send({ code: server_constants.RIS_CODE_OK, data: out }); + + } catch (error) { + console.error('Error: ', error); + return res.send({ code: server_constants.RIS_CODE_ERR, error }); + } +}; diff --git a/src/server/models/product.js b/src/server/models/product.js index dd1d2fe..6db85af 100755 --- a/src/server/models/product.js +++ b/src/server/models/product.js @@ -819,6 +819,7 @@ module.exports.getArrCatProds = async function (idapp, cosa) { ] } }] + } else { addquery = [{ $match: { idapp } }]; } @@ -841,7 +842,23 @@ module.exports.getArrCatProds = async function (idapp, cosa) { } }, { $unwind: "$category" }, - { $group: { _id: "$category._id", name: { $first: "$category.name" } } }, + { + $group: { + _id: "$category._id", + name: { $first: "$category.name" }, + idapp: { $first: "$category.idapp" }, + idArgomento: { $first: "$category.idArgomento" } + } + }, + { + $match: { + $or: [ + { idapp: { $ne: tools.MACRO } }, + { idapp: tools.MACRO, idArgomento: { $exists: true, $gt: 0 } } + ] + } + }, + { $sort: { name: 1 } } ]; diff --git a/src/server/router/admin_router.js b/src/server/router/admin_router.js index 436a64c..191cab4 100755 --- a/src/server/router/admin_router.js +++ b/src/server/router/admin_router.js @@ -116,7 +116,7 @@ async function findOrCreateCatProd(idapp, idArgomento, DescrArgomento) { function updateProductInfoCatProds(productInfo, reccatprod) { if (productInfo) { // Controllo che nell'array productInfo.idCatProds ci sia esattamente 1 record e che sia uguale a reccatprod._id - const cond3 = Array.isArray(productInfo.idCatProds) && productInfo.idCatProds[0].toString() !== reccatprod._id.toString(); + const cond3 = Array.isArray(productInfo.idCatProds) && productInfo.idCatProds.length > 0 && productInfo.idCatProds[0].toString() !== reccatprod._id.toString(); const isChanged = !Array.isArray(productInfo.idCatProds) || // Assicurati che sia un array productInfo.idCatProds.length !== 1 || // L'array deve contenere esattamente 1 elemento @@ -903,6 +903,8 @@ router.post('/import', authenticate, async (req, res) => { const trovato = await ImportaIsbn.findOne({ isbn: product.code }).lean(); if (trovato) { + // togli a recisbn l'_id + delete trovato._id; recisbn = trovato; } @@ -916,14 +918,18 @@ router.post('/import', authenticate, async (req, res) => { recisbn.sottotitolo = productInfo.sottotitolo; // recisbn.idapp = idapp; - let risisbn = await ImportaIsbn.findOneAndUpdate({ isbn: product.code }, { $set: recisbn }, { new: true, upsert: true, strict: false }); + try { + let risisbn = await ImportaIsbn.findOneAndUpdate({ isbn: product.code }, { $set: recisbn }, { new: true, upsert: true, strict: false }); - // Update ProductInfo, non crea nuovi record ! - let risrecInfo = await ProductInfo.findOneAndUpdate({ code: productInfo.code }, { $set: productInfo }, { new: true, upsert: false }); + // Update ProductInfo, non crea nuovi record ! + let risrecInfo = await ProductInfo.findOneAndUpdate({ code: productInfo.code }, { $set: productInfo }, { new: true, upsert: false }); - indprod++; - if (indprod % 100 === 0) - console.log(indprod + '/' + numprod); + indprod++; + if (indprod % 100 === 0) + console.log(indprod + '/' + numprod); + } catch (e) { + console.error(e); + } } } @@ -1052,6 +1058,7 @@ router.post('/import', authenticate, async (req, res) => { totFat: product.totFat || 0, vLast3M: product.vLast3M || 0, fatLast3M: product.fatLast3M || 0, + fatLast6M: product.fatLast6M || 0, vLast6M: product.vLast6M || 0, vLastY: product.vLastY || 0, vLast2Y: product.vLast2Y || 0, @@ -1120,7 +1127,7 @@ router.post('/import', authenticate, async (req, res) => { let imported = 0; let errors = 0; - const ripopola = false; //++MODIFICARE! + const ripopola = true; //++MODIFICARE! if (ripopola) { dataObjects = null; @@ -1221,7 +1228,12 @@ router.post('/import', authenticate, async (req, res) => { // se non esiste l'ISBN, allora me lo cerco in base a sku ! - if (!product.isbn) { + let trova = false + if (product._id === '30310') { + trova = true + } + + if (!product.isbn || product.isbn.startsWith('field')) { const rectrovare = await ImportaIsbn.findOne({ sku: product.sku }).lean(); if (rectrovare) { // se l'isbn non inizia con 'field' allora è buono diff --git a/src/server/router/articleRoutes.js b/src/server/router/articleRoutes.js index 0728444..fa328f9 100644 --- a/src/server/router/articleRoutes.js +++ b/src/server/router/articleRoutes.js @@ -1,5 +1,5 @@ const express = require("express"); -const { getArticlesSalesHandler, exportArticlesSalesByJSON, viewTable, queryTable } = require("../controllers/articleController"); +const { getArticlesSalesHandler, exportArticlesSalesByJSON, viewTable, saveTable, queryTable } = require("../controllers/articleController"); const { authenticate } = require("../middleware/authenticate"); const router = express.Router(); @@ -9,6 +9,7 @@ router.post("/articles-sales", authenticate, getArticlesSalesHandler); router.post("/export-articles-sales-json", authenticate, exportArticlesSalesByJSON); router.post("/view-table", authenticate, viewTable); +router.post("/save-table", authenticate, saveTable); router.post("/query", authenticate, queryTable); diff --git a/src/server/router/index_router.js b/src/server/router/index_router.js index a4eb5f4..9a9d8e2 100755 --- a/src/server/router/index_router.js +++ b/src/server/router/index_router.js @@ -1160,6 +1160,7 @@ router.post('/duppage', authenticate, async (req, res) => { } }); + router.post('/exppage', authenticate, async (req, res) => { const params = req.body; const idapp = req.body.idapp; diff --git a/src/server/router/products_router.js b/src/server/router/products_router.js index 069e6c6..673be42 100755 --- a/src/server/router/products_router.js +++ b/src/server/router/products_router.js @@ -89,6 +89,8 @@ router.get('/id/:id', async function (req, res) { var product = await Product.getProductById(id); + console.log('Product ID', id, product); + if (product) { return res.send({ code: server_constants.RIS_CODE_OK, product: product }); } else { diff --git a/src/server/router/users_router.js b/src/server/router/users_router.js index ebac601..8d35c5e 100755 --- a/src/server/router/users_router.js +++ b/src/server/router/users_router.js @@ -789,30 +789,30 @@ router.post('/login', checkBlocked, async (req, res) => { resalreadysent = true; } - res.status(401).send({ code: server_constants.RIS_CODE_LOGIN_ERR }); - resalreadysent = true; + return res.status(401).send({ code: server_constants.RIS_CODE_LOGIN_ERR }); + } else { + const myris = await user.generateAuthToken(req); + + const usertosend = new User(); + + shared_consts.fieldsUserToChange().forEach((field) => { + usertosend[field] = user[field]; + }); + + const subsExistonDb = await existSubScribe(usertosend._id, 'auth', req.get('User-Agent')); + + res + .header('x-auth', myris.token) + .header('x-refrtok', myris.refreshToken) + .send({ + usertosend, + code: server_constants.RIS_CODE_OK, + subsExistonDb, + }); + } - const myris = await user.generateAuthToken(req); - - const usertosend = new User(); - - shared_consts.fieldsUserToChange().forEach((field) => { - usertosend[field] = user[field]; - }); - - const subsExistonDb = await existSubScribe(usertosend._id, 'auth', req.get('User-Agent')); - - res - .header('x-auth', myris.token) - .header('x-refrtok', myris.refreshToken) - .send({ - usertosend, - code: server_constants.RIS_CODE_OK, - subsExistonDb, - }); - } catch (e) { console.error('ERRORE IN LOGIN: ' + e.message); if (!resalreadysent) diff --git a/src/server/sendemail.js b/src/server/sendemail.js index 485be90..f71d8eb 100755 --- a/src/server/sendemail.js +++ b/src/server/sendemail.js @@ -57,6 +57,7 @@ module.exports = { if (to === '') return false; + // console.log('mylocalsconf', mylocalsconf); // console.log("check EMAIL :" + checkifSendEmail()); @@ -88,7 +89,6 @@ module.exports = { // transport = this.getTransport(mylocalsconf); // } - // console.log('1 . transport', transport); if (transport) { paramemail.transport = transport; @@ -700,6 +700,9 @@ module.exports = { }, getdataemail: async (idapp, templemail_id) => { + + const pwd_from = await Settings.getValDbSettings(idapp, 'PWD_FROM'); + // console.log('getdataemail'); const mydata = { content_after_events: await Settings.getValDbSettings(idapp, 'TEXT_AFTER_EV'), @@ -718,7 +721,7 @@ module.exports = { height_logo: await Settings.getValDbSettings(idapp, 'HEIGHT_LOGO'), from: await Settings.getValDbSettings(idapp, 'EMAIL_FROM'), email_reply: await Settings.getValDbSettings(idapp, 'EMAIL_REPLY', ''), - pwd_from: await Settings.getValDbSettings(idapp, 'PWD_FROM'), + pwd_from: pwd_from, email_service: await Settings.getValDbSettings(idapp, 'EMAIL_SERVICE_SEND'), email_port: await Settings.getValDbSettings(idapp, 'EMAIL_PORT'), templemail_id: templemail_id ? templemail_id : await Settings.getValDbSettings(idapp, 'TEMPLEMAIL_ID'), @@ -732,6 +735,8 @@ module.exports = { }, getTransport: (mylocalsconf) => { + console.log('getTransport'); + // Create Transport let smtpTransport = null; diff --git a/src/server/tools/general.js b/src/server/tools/general.js index 6e3a353..0cc9afc 100755 --- a/src/server/tools/general.js +++ b/src/server/tools/general.js @@ -56,8 +56,8 @@ const readline = require('readline'); // Code goes here const keySize = 256; -const ivSize = 128; -const iterations = 100; +// const ivSize = 128; +const iterations = 1000; if (!!process.env.GCM_API_KEY && process.env.GCM_API_KEY !== '') { webpush.setGCMAPIKey(process.env.GCM_API_KEY); @@ -585,6 +585,7 @@ module.exports = { RISO: '13', FIOREDELLAVITA: '15', PIUCHEBUONO: '17', + MACRO: '18', IDAPP_BOTONGROUP: '1000', @@ -3904,47 +3905,79 @@ module.exports = { }, encrypt(msg, pass) { - var salt = CryptoJS.lib.WordArray.random(128 / 8); + try { + // Genera salt e IV casuali + const salt = CryptoJS.lib.WordArray.random(128 / 8); // 16 byte + const iv = CryptoJS.lib.WordArray.random(128 / 8); // 16 byte - var key = CryptoJS.PBKDF2(pass, salt, { - keySize: keySize / 32, - iterations: iterations, - }); + // Deriva la chiave usando PBKDF2 + const key = CryptoJS.PBKDF2(pass, salt, { + keySize: keySize / 32, + iterations: iterations, + }); - var iv = CryptoJS.lib.WordArray.random(128 / 8); + // Critta il messaggio + const encrypted = CryptoJS.AES.encrypt(msg, key, { + iv: iv, + padding: CryptoJS.pad.Pkcs7, + mode: CryptoJS.mode.CBC, + }); - var encrypted = CryptoJS.AES.encrypt(msg, key, { - iv: iv, - padding: CryptoJS.pad.Pkcs7, - mode: CryptoJS.mode.CBC, - - }); - - // salt, iv will be hex 32 in length - // append them to the ciphertext for use in decryption - var transitmessage = salt.toString() + iv.toString() + encrypted.toString(); - return transitmessage; + // Concatena salt, IV e ciphertext con un delimitatore + const transitmessage = `${salt.toString()}|${iv.toString()}|${encrypted.toString()}`; + return transitmessage; + } catch (error) { + console.error('❌❌❌ Errore durante la crittazione:', error.message); + throw error; + } }, decrypt(transitmessage, pass) { - var salt = CryptoJS.enc.Hex.parse(transitmessage.substr(0, 32)); - var iv = CryptoJS.enc.Hex.parse(transitmessage.substr(32, 32)); - var encrypted = transitmessage.substring(64); + try { + let saltHex, ivHex, encrypted; - var key = CryptoJS.PBKDF2(pass, salt, { - keySize: keySize / 32, - iterations: iterations, - }); + // Controlla se il messaggio è nel nuovo formato (con delimitatore) + if (transitmessage.includes('|')) { + const parts = transitmessage.split('|'); + if (parts.length !== 3) { + throw new Error('❌❌❌ Formato del messaggio non valido.'); + } + [saltHex, ivHex, encrypted] = parts; + } else { + // Vecchio formato: salt (32 caratteri), IV (32 caratteri), ciphertext (resto) + saltHex = transitmessage.substr(0, 32); + ivHex = transitmessage.substr(32, 32); + encrypted = transitmessage.substring(64); + } - var decrypted = CryptoJS.AES.decrypt(encrypted, key, { - iv: iv, - padding: CryptoJS.pad.Pkcs7, - mode: CryptoJS.mode.CBC, + // Converte salt e IV da esadecimale + const salt = CryptoJS.enc.Hex.parse(saltHex); + const iv = CryptoJS.enc.Hex.parse(ivHex); - }); - return decrypted; + // Deriva la chiave usando PBKDF2 + const key = CryptoJS.PBKDF2(pass, salt, { + keySize: keySize / 32, + iterations: iterations, + }); + + // Decritta il messaggio + const decrypted = CryptoJS.AES.decrypt(encrypted, key, { + iv: iv, + padding: CryptoJS.pad.Pkcs7, + mode: CryptoJS.mode.CBC, + }); + + // Restituisci il messaggio originale in formato UTF-8 + let ris = decrypted.toString(CryptoJS.enc.Utf8); + + // console.log('RIS', ris); + + return ris; + } catch (error) { + console.error('❌❌❌ Errore durante la decrittazione:', error.message); + throw error; + } }, - cryptdata(mydata) { if (mydata === '') return ''; @@ -3954,13 +3987,17 @@ module.exports = { }, decryptdata(mydatacrypted) { - if (mydatacrypted === '' || mydatacrypted === undefined) + if (!mydatacrypted) return ''; + + try { + // console.log('SECRK', process.env.SECRK); + const decr = this.decrypt(mydatacrypted, process.env.SECRK); + // console.log('decr:', mydatacrypted, '->', decr); + return decr; + } catch (error) { + console.error('❌❌❌❌❌ Decryption error:', error); return ''; - // Decrypt - // const bytes = CryptoJS.AES.decrypt(mydatacrypted.toString(), process.env.SECRK); - // return JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); - return this.decrypt(mydatacrypted, process.env.SECRK). - toString(CryptoJS.enc.Utf8); + } }, BoolToInt(mybool) { @@ -6025,6 +6062,44 @@ module.exports = { // Funzione per implementare il ritardo tra i tentativi sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); + }, + + /** + * Converte una data in formato italiano GG/MM/YYYY in un oggetto Date e restituisce il timestamp. + * @param {string} dateString - La data in formato GG/MM/YYYY. + * @returns {Object} - Un oggetto contenente la data (Date) e il timestamp (number). + * Restituisce null se la data non è valida. + */ + convertiDataItaliana(dateString) { + // Verifica che la data sia una stringa valida + if (!dateString || typeof dateString !== 'string') { + console.error("Input non valido: la data deve essere una stringa."); + return null; + } + + // Rimuovi eventuali spazi bianchi e dividi la data in GG, MM, YYYY + const [giorno, mese, anno] = dateString.trim().split('/').map(Number); + + // Controlla che i valori siano stati estratti correttamente + if (isNaN(giorno) || isNaN(mese) || isNaN(anno)) { + console.error("Formato data non valido:", dateString); + return null; + } + + // Crea un oggetto Date (mese parte da 0 in JavaScript) + const dateObj = new Date(anno, mese - 1, giorno); + + // Verifica che la data sia valida + if (isNaN(dateObj.getTime())) { + console.error("Data non valida:", dateString); + return null; + } + + // Restituisci l'oggetto con la data e il timestamp + return { + date: dateObj, + timestamp: dateObj.getTime() + }; } diff --git a/src/server/version.txt b/src/server/version.txt index 828cb60..7a5b0e5 100644 --- a/src/server/version.txt +++ b/src/server/version.txt @@ -1 +1 @@ -1.2.32 \ No newline at end of file +1.2.33 \ No newline at end of file