- catalogo avanti, parte 1

This commit is contained in:
Surya Paolo
2024-05-04 14:49:02 +02:00
parent e1f2e799d6
commit 07973fbf0a
14 changed files with 639 additions and 171 deletions

View File

@@ -54,6 +54,7 @@
"pug": "^3.0.2",
"rate-limiter-flexible": "^2.3.9",
"request": "^2.34",
"sanitize-html": "^2.13.0",
"save": "^2.5.0",
"sharp": "^0.30.7",
"superagent": "^8.0.0",

View File

@@ -48,6 +48,7 @@ const authenticate = (req, res, next) => {
if (!!ris.user) {
// Save last time online
ris.user.lasttimeonline = new Date();
ris.user.retry_pwd = 0
ris.user.useragent = req.get('User-Agent');
return ris.user.save().then(() => {

54
src/server/models/author.js Executable file
View File

@@ -0,0 +1,54 @@
mongoose = require('mongoose').set('debug', false)
const Schema = mongoose.Schema;
const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
});
const AuthorSchema = new Schema({
idapp: {
type: String,
},
name: {
type: String,
},
surname: {
type: String,
},
bio: {
type: String,
},
img: {
type: String,
},
});
var Author = module.exports = mongoose.model('Author', AuthorSchema);
module.exports.getFieldsForSearch = function () {
return [
{ field: 'name', type: tools.FieldType.string },
{ field: 'surname', type: tools.FieldType.string },
]
};
module.exports.executeQueryTable = function (idapp, params) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params);
};
module.exports.findAllIdApp = async function (idapp) {
const myfind = { idapp };
return await Author.find(myfind);
};
module.exports.createIndexes((err) => {
if (err) throw err;
});

View File

@@ -743,8 +743,8 @@ CircuitSchema.statics.sendCoins = async function (onlycheck, idapp, usernameOrig
};
await Circuit.updateOne({ _id: circuittable }, { $set: paramstoupdate });
extrarec.saldoOrig = accountorigTable.saldo;
extrarec.saldoDest = accountdestTable.saldo;
extrarec.saldoOrig = tools.arrotondaA2Decimali(accountorigTable.saldo);
extrarec.saldoDest = tools.arrotondaA2Decimali(accountdestTable.saldo);
let orig = usernameOrig;
if (extrarec.grouporig) {

View File

@@ -33,6 +33,9 @@ const productSchema = new Schema({
type: Boolean,
default: true,
},
isbn: {
type: String,
},
idProductInfo: { type: Schema.Types.ObjectId, ref: 'ProductInfo' },
idProducer: { type: Schema.Types.ObjectId, ref: 'Producer' },
idStorehouses: [
@@ -146,6 +149,9 @@ const productSchema = new Schema({
note: {
type: String,
},
versione: {
type: Number,
},
producer_name: {
type: String,
},
@@ -346,6 +352,14 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'authors',
localField: 'productInfo.idAuthors',
foreignField: '_id',
as: 'productInfo.authors'
}
},
{
$lookup: {
from: 'catprods',
@@ -836,8 +850,8 @@ module.exports.singlerecconvert_AfterImport_AndSave = async function (idapp, pro
ris = await Product.updateOne({ _id: ObjectID(prod._id) }, { $unset: objDelete })
if (ris) {
console.log('ris', ris);
if (ris && ris.nModified > 0) {
console.log('Modificato: ', objtoset.name);
}
// const campodarimuovere = 'producer_name';

View File

@@ -88,6 +88,9 @@ const productInfoSchema = new Schema({
img3: {
type: String,
},
img4: {
type: String,
},
ingredienti: {
type: String,
},
@@ -97,18 +100,20 @@ const productInfoSchema = new Schema({
note: {
type: String,
},
author: {
type: String,
},
idAuthors: [{ type: Schema.Types.ObjectId, ref: 'Author' }],
idPublisher: { type: Schema.Types.ObjectId, ref: 'Publisher' },
collezione: {
type: String,
},
publisher: { //editore
type: String,
date_publishing: {
type: Date,
},
numpages: {
type: Number,
},
productType: {
type: Number,
},
});
@@ -163,6 +168,14 @@ module.exports.findAllIdApp = async function (idapp, code, id) {
as: 'catprods'
}
},
{
$lookup: {
from: 'authors',
localField: 'idAuthors',
foreignField: '_id',
as: 'authors'
}
},
{
$lookup: {
from: 'subcatprods',

50
src/server/models/publisher.js Executable file
View File

@@ -0,0 +1,50 @@
mongoose = require('mongoose').set('debug', false)
const Schema = mongoose.Schema;
const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
});
const PublisherSchema = new Schema({
idapp: {
type: String,
},
name: {
type: String,
},
link: {
type: String,
},
img: {
type: String,
},
});
var Publisher = module.exports = mongoose.model('Publisher', PublisherSchema);
module.exports.getFieldsForSearch = function () {
return [
{ field: 'name', type: tools.FieldType.string },
]
};
module.exports.executeQueryTable = function (idapp, params) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params);
};
module.exports.findAllIdApp = async function (idapp) {
const myfind = { idapp };
return await Publisher.find(myfind);
};
module.exports.createIndexes((err) => {
if (err) throw err;
});

View File

@@ -5721,6 +5721,25 @@ UserSchema.statics.tooManyReqPassword = async function (idapp, email, set) {
}
};
UserSchema.statics.tooManyLoginWrong = async function (idapp, username, set) {
const User = this;
const maxnum = 30;
const user = await User.findByUsername(idapp, username, true, false);
if (user) {
if (!user.retry_pwd)
user.retry_pwd = 0
if (set && user.retry_pwd <= maxnum) {
user.retry_pwd++;
await User.findOneAndUpdate({ _id: user._id }, { $set: { retry_pwd: user.retry_pwd } });
}
return {troppilogin: user.retry_pwd > maxnum, retry_pwd: user.retry_pwd};
}
return {troppilogin: false, retry_pwd: 0};
};
UserSchema.statics.setLastCircuitOpened = async function (idapp, username, circuitpath) {

View File

@@ -13,6 +13,8 @@ const Inventariogm = require('../models/inventariogm');
const Importamacro = require('../models/importamacro');
const ProductInfo = require('../models/productInfo');
const CatProd = require('../models/catprod');
const Author = require('../models/author');
const Publisher = require('../models/publisher');
const SubCatProd = require('../models/subcatprod');
const Gasordine = require('../models/gasordine');
@@ -113,6 +115,11 @@ async function completaSettaggioProduct_AndProductInfo(arrcampi_productInfo, arr
productInfo.code = preccode;
}
}
if (rec.hasOwnProperty('productType')) {
productInfo.productType = rec.hasOwnProperty('productType');
} else {
productInfo.productType = shared_consts.PRODUCTTYPE.PRODUCT;
}
return { product, productInfo };
@@ -215,6 +222,17 @@ async function extractArrayDataFromCSV(idapp, rec) {
};
function extractNameAndSurnameByComplete(name_complete) {
if (name_complete) {
const name = name_complete.split(' ')[0];
const surname = name_complete.split(' ')[1];
return { name, surname };
} else {
return { name: '', surname: '' };
}
}
router.post('/import', authenticate, async (req, res) => {
try {
@@ -263,7 +281,7 @@ router.post('/import', authenticate, async (req, res) => {
if (dataObjects && dataObjects[0]) {
// Cancella la collection ImportaMacros
await Importamacro.deleteMany({ idapp });
// Aggiungi i record su ImportaMacros
for (const recinv of dataObjects[0]) {
let isnuovo = false
@@ -297,191 +315,317 @@ router.post('/import', authenticate, async (req, res) => {
if (cancella_categorie) {
await CatProd.deleteMany({ idapp });
}
// Rileggi tutti i record di ImportaMacros
dataObjects = await Importamacro.find({ idapp }).lean();
console.log('*** INIZIO IMPORT PRODOTTI ... ');
let indprod = 0;
let newprod = 0;
for (const product of dataObjects) {
let isnuovo = false
let setta = false
let productInfo = {
idapp: product.idapp,
code: product.isbn,
id_wp: product._id,
name: product.title,
description: product.description,
publish: product.Editore,
collezione: product.Collezione,
numpages: product.NumPagine,
author: product.autore,
link: product.link,
idCatProds: [],
idSubCatProds: [],
//img: 'upload/products/' + product.code + '.jpg',
image_link: product.image_link,
}
let importa = true;
if (product.NumPagine)
productInfo.numpages = product.NumPagine;
if (!product.title || !product.isbn)
importa = false;
let reccateg = null;
if (product.categories) {
arrcat = product.categories.trim().split(',');
for (const mycat of arrcat) {
let mycatstr = mycat.trim();
if (importa) {
let productInfo = {
idapp: product.idapp,
code: product.isbn,
id_wp: product._id,
name: product.title,
description: product.description,
publisher: product.Editore,
collezione: product.Collezione,
// author: product.Autore ? product.Autore : '',
link: product.link ? product.link : '',
idCatProds: [],
idSubCatProds: [],
//img: 'upload/products/' + product.code + '.jpg',
image_link: product.image_link ? product.image_link : '',
img2: product.img2 ? product.img2 : '',
img3: product.img3 ? product.img3 : '',
img4: product.img4 ? product.img4 : '',
// Controlla se ci sono le sottocategorie:
arrsubcat = mycatstr.trim().split('>');
}
if (arrsubcat.length > 1) {
// Ci sono delle sottocategorie
mycatstr = arrsubcat[0].trim();
product.subcat_name = arrsubcat[1].trim();;
productInfo.productType = shared_consts.PRODUCTTYPE.LIBRO;
if (product.Data)
productInfo.date_publishing = new Date(product.Data * 1000);
productInfo.name = productInfo.name.replace(/ - Usato$| - Nuovo$| - Epub$| - Ebook$| - Mobi$| - DVD$| - Streaming$| - Download$/, "");
if (product.Pagine) {
try {
productInfo.numpages = 0;
productInfo.numpages = parseInt(product.Pagine);
} catch (e) {
console.error(e);
}
}
// Cerca la Categoria
reccateg = await CatProd.findOne({ idapp, name: mycatstr }).lean();
if (!reccateg) {
// Non esiste questo produttore, quindi lo creo !
reccateg = new CatProd({ idapp, name: mycatstr });
ris = await reccateg.save();
let reccateg = null;
if (product.categories) {
arrcat = product.categories.trim().split(',');
for (const mycat of arrcat) {
let mycatstr = mycat.trim();
// Controlla se ci sono le sottocategorie:
arrsubcat = mycatstr.trim().split('>');
if (arrsubcat.length > 1) {
// Ci sono delle sottocategorie
mycatstr = arrsubcat[0].trim();
product.subcat_name = arrsubcat[1].trim();;
}
// Cerca la Categoria
reccateg = await CatProd.findOne({ idapp, name: mycatstr }).lean();
}
if (!reccateg) {
// Non esiste questo produttore, quindi lo creo !
reccateg = new CatProd({ idapp, name: mycatstr });
ris = await reccateg.save();
reccateg = await CatProd.findOne({ idapp, name: mycatstr }).lean();
}
if (reccateg) {
productInfo.idCatProds.push(reccateg._id);
}
}
}
if (product.subcat_name) {
arrsubcat = product.subcat_name.trim().split(',');
for (const mysubcat of arrsubcat) {
let mysubcatstr = mysubcat.trim();
// Cerca la Sotto Categoria
let recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr }).lean();
if (!recsubcateg) {
// Non esiste questa Sotto Categoria, quindi la creo !
const idCatProd = reccateg ? reccateg._id : ''
recsubcateg = new SubCatProd({ idapp, name: mysubcatstr, idCatProd });
ris = await recsubcateg.save();
recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr, idCatProd }).lean();
}
if (recsubcateg) {
productInfo.idSubCatProds.push(recsubcateg._id);
}
}
}
if (!product.hasOwnProperty('active')) {
product.active = true;
}
if (product.code)
delete product.code;
if (product.name)
delete product.name;
if (product.link)
delete product.link;
let esisteindb = await ProductInfo.findOne({ code: productInfo.code }).lean();
// Update ProductInfo
let risrecInfo = await ProductInfo.findOneAndUpdate({ code: productInfo.code }, { $set: productInfo }, { new: true, upsert: true });
if (risrecInfo) {
product.idProductInfo = risrecInfo._id;
recnewInfo = await ProductInfo.findOne({ code: productInfo.code }).lean();
if (risrecInfo._id) {
// Record existed, so it was updated
let arrfieldchange = tools.differentObjects(productInfo, recnewInfo);
if (arrfieldchange && arrfieldchange.length > 0) {
// updated++;
console.log('Changed: ', recnewInfo.name + ': ' + arrfieldchange);
if (reccateg) {
productInfo.idCatProds.push(reccateg._id);
}
}
}
// Cerca il GAS
let recGas = null;
if (product.gas_name) {
// Cerca il GAS
recGas = await Gasordine.findOne({ idapp, name: product.gas_name }).lean();
// "Autore" : "Silia,Marucelli, Stefano,Cattinelli",
let arrAuthor = [];
if (product.Autore) {
const arrrecauthor = product.Autore.trim().split(',');
if (arrrecauthor.length >= 1) {
try {
let author = {
name: arrrecauthor[0].trim(),
}
if (arrrecauthor.length === 1) {
author = extractNameAndSurnameByComplete(arrrecauthor[0].trim());
} else {
author.surname = arrrecauthor[1].trim();
}
arrAuthor.push(author);
if (arrrecauthor.length > 1) {
for (let i = 2; i < arrrecauthor.length; i = i + 2) {
try {
author = {
name: arrrecauthor[i].trim()
}
if (arrrecauthor.length > i + 1) {
surname = arrrecauthor[i + 1].trim()
}
arrAuthor.push(author);
} catch (e) {
}
}
}
productInfo.idAuthors = [];
for (const myauthor of arrAuthor) {
// Cerca l'Autore
recauthor = await Author.findOne({ idapp, name: myauthor.name, surname: myauthor.surname }).lean();
if (!recauthor) {
// Non esiste questo Autore, quindi lo creo !
recauthor = new Author({ idapp, name: myauthor.name, surname: myauthor.surname });
ris = await recauthor.save();
recauthor = await Author.findOne({ idapp, name: myauthor.name, surname: myauthor.surname }).lean();
}
if (recauthor) {
productInfo.idAuthors.push(recauthor._id);
}
}
} catch (e) {
console.error(e);
}
}
}
if (!recGas && !!product.gas_name) {
recGas = new Gasordine({ idapp, name: product.gas_name, active: true });
// Non esiste questo GAS, quindi lo creo !
ris = await recGas.save();
recGas = await Gasordine.findOne({ idapp, name: product.gas_name }).lean();
// Cancella l'Autore dal record product
delete product.Autore;
if (product.subcat_name) {
arrsubcat = product.subcat_name.trim().split(',');
for (const mysubcat of arrsubcat) {
let mysubcatstr = mysubcat.trim();
// Cerca la Sotto Categoria
let recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr }).lean();
if (!recsubcateg) {
// Non esiste questa Sotto Categoria, quindi la creo !
const idCatProd = reccateg ? reccateg._id : ''
recsubcateg = new SubCatProd({ idapp, name: mysubcatstr, idCatProd });
ris = await recsubcateg.save();
recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr, idCatProd }).lean();
}
if (recsubcateg) {
productInfo.idSubCatProds.push(recsubcateg._id);
}
}
}
let recProductExist = null;
let queryprod = { idProductInfo: product.idProductInfo };
if (recGas) {
queryprod = { ...queryprod, idGasordine: recGas._id };
if (!product.hasOwnProperty('active')) {
product.active = true;
}
recProductExist = await Product.findOne({ queryprod }).lean();
if (product.code)
delete product.code;
if (product.name)
delete product.name;
if (product.link)
delete product.link;
if (!recProductExist) {
isnuovo = true;
}
let esisteindb = await ProductInfo.findOne({ code: productInfo.code }).lean();
// Update ProductInfo
let risrecInfo = await ProductInfo.findOneAndUpdate({ code: productInfo.code }, { $set: productInfo }, { new: true, upsert: true });
if (risrecInfo) {
product.idProductInfo = risrecInfo._id;
recnewInfo = await ProductInfo.findOne({ code: productInfo.code }).lean();
if (!options.aggiornaStockQty && esisteindb && !isnuovo) {
delete product.stockQty;
delete product.maxbookableGASQty;
}
let myproduct = {
stockQty: product.Quantita,
maxbookableGASQty: product.maxbookableGASQty,
active: product.active,
idGasordine: recGas ? recGas._id : null,
idProductInfo: product.idProductInfo,
idapp,
price: tools.convertPriceEurToValue(product.price),
sale_price: tools.convertPriceEurToValue(product.sale_price),
status: product.status,
}
// AGGIORNA PRODUCT
let risrec = await Product.findOneAndUpdate(queryprod, { $set: myproduct }, { new: true, upsert: true });
let recnew = await Product.findOne(queryprod).lean();
if (risrec) {
if (risrec._id) {
if (risrecInfo._id) {
// Record existed, so it was updated
let arrfieldchange = tools.differentObjects(myproduct, recnew);
if (arrfieldchange.length > 0) {
let arrfieldchange = tools.differentObjects(productInfo, recnewInfo);
if (arrfieldchange && arrfieldchange.length > 0) {
updated++;
console.log('Changed: ', myproduct.idProductInfo + ': ' + arrfieldchange);
console.log('Changed: ', recnewInfo.name + ': ' + arrfieldchange);
}
}
// Cerca il GAS
let recGas = null;
if (product.gas_name) {
// Cerca il GAS
recGas = await Gasordine.findOne({ idapp, name: product.gas_name }).lean();
}
if (!recGas && !!product.gas_name) {
recGas = new Gasordine({ idapp, name: product.gas_name, active: true });
// Non esiste questo GAS, quindi lo creo !
ris = await recGas.save();
recGas = await Gasordine.findOne({ idapp, name: product.gas_name }).lean();
}
let myproduct = {};
// Download, DVD, Epub, Mobi, Nuovo, PDF, Streaming, Usato
if (product.Versione === 'Nuovo')
myproduct.versione = shared_consts.VERSIONE.NUOVO
else if (product.Versione === 'Usato')
myproduct.versione = shared_consts.VERSIONE.USATO;
else if (product.Versione === 'Download')
myproduct.versione = shared_consts.VERSIONE.DOWNLOAD;
else if (product.Versione === 'DVD')
myproduct.versione = shared_consts.VERSIONE.DVD;
else if (product.Versione === 'Epub')
myproduct.versione = shared_consts.VERSIONE.EPUB;
else if (product.Versione === 'Mobi')
myproduct.versione = shared_consts.VERSIONE.MOBI;
else if (product.Versione === 'PDF')
myproduct.versione = shared_consts.VERSIONE.PDF;
else if (product.Versione === 'Streaming')
myproduct.versione = shared_consts.VERSIONE.STREAMING;
else
myproduct.versione = 100;
delete product.Versione;
let recProductExist = null;
// ISBN e versione del prodotto sono le chiavi uniche
let queryprod = { idProductInfo: product.idProductInfo, versione: myproduct.versione };
if (recGas) {
queryprod = { ...queryprod, idGasordine: recGas._id };
}
recProductExist = await Product.findOne({ queryprod }).lean();
if (!recProductExist) {
isnuovo = true;
}
if (!options.aggiornaStockQty && esisteindb && !isnuovo) {
delete product.Quantità;
// delete product.maxbookableGASQty;
}
myproduct.isbn = product.isbn;
myproduct.maxbookableGASQty = product.maxbookableGASQty ? product.maxbookableGASQty : null;
myproduct.active = product.active;
myproduct.idGasordine = recGas ? recGas._id : null;
myproduct.idProductInfo = product.idProductInfo;
myproduct.price = product.price ? parseFloat(tools.convertPriceEurToValue(product.price)) : null;
myproduct.sale_price = product.sale_price ? parseFloat(tools.convertPriceEurToValue(product.sale_price)) : null;
myproduct.idapp = idapp;
myproduct.status = product.status ? product.status : null;
if (product.Quantità) {
myproduct.stockQty = parseInt(product.Quantità);
}
let recold = await Product.findOne(queryprod).lean();
// AGGIORNA PRODUCT
let risrec = await Product.findOneAndUpdate(queryprod, { $set: myproduct }, { new: true, upsert: true });
let recnew = await Product.findOne(queryprod).lean();
if (risrec) {
if (risrec._id) {
if (recold) {
// Record existed, so it was updated
let arrfieldchange = tools.differentObjects(recold, recnew);
if (arrfieldchange.length > 0) {
updated++;
let modif = '';
for (const field of arrfieldchange) {
modif += field + ': ' + recold[field] + ' -> ' + recnew[field] + ' | ';
}
console.log('Changed: [' + indprod + '/' + dataObjects.length + ']', productInfo.name, '[' + myproduct.idProductInfo + '] : ' + modif);
}
} else {
newprod++;
console.log('Nuovo Prodotto : [' + newprod + '/' + dataObjects.length + ']', productInfo.name);
}
} else {
// Record didn't exist, so it was created
imported++;
}
} else {
// Record didn't exist, so it was created
imported++;
// risrec is null or undefined, indicating an error
console.error('Error: ', myproduct.productInfo.name);
errors++;
}
await Product.singlerecconvert_AfterImport_AndSave(idapp, recnew, isnuovo);
} else {
// risrec is null or undefined, indicating an error
console.error('Error: ', myproduct.productInfo.name);
console.error('Error ProductInfo: ', product.code);
errors++;
}
await Product.singlerecconvert_AfterImport_AndSave(idapp, recnew, isnuovo);
} else {
console.error('Error ProductInfo: ', product.code);
errors++;
}
indprod++;
}
console.log('*** IMPORTATI: ', imported);
console.log('*** IMPORTATI: ', imported, 'AGGIORNATI = ' + updated + ' (su ' + dataObjects.length + ' RECORD)');
return res.status(200).send({ updated, imported, errors });
@@ -506,6 +650,7 @@ router.post('/import', authenticate, async (req, res) => {
img: 'upload/products/' + product.code + '.jpg',
weight: product.weight,
unit: tools.getIdUnitsByText(product.unit),
productType: shared_consts.PRODUCTTYPE.PRODUCT,
}
let reccateg = null;
@@ -622,7 +767,7 @@ router.post('/import', authenticate, async (req, res) => {
let arrfieldchange = tools.differentObjects(product, recnew);
if (arrfieldchange.length > 0) {
updated++;
console.log('Changed: ', product.idProductInfo + ': ' + arrfieldchange);
console.log('Changed:', product.idProductInfo + ': ' + arrfieldchange);
}
} else {
// Record didn't exist, so it was created
@@ -669,6 +814,8 @@ router.post('/import', authenticate, async (req, res) => {
let product = risprod.product;
let productInfo = risprod.productInfo;
let isnuovo = false
let setta = false
@@ -811,12 +958,12 @@ router.post('/import', authenticate, async (req, res) => {
// L'opzione ordered: false gestisce gli errori senza interrompere l'inserimento
/*return await Product.insertMany(dataObjects, { ordered: false })
.then((ris) => {
Product.convertAfterImportALLPROD(idapp, dataObjects).then((ris) => {
return res.status(200).send(true);
});
})
.catch((errors) => {
console.error(errors);

View File

@@ -25,6 +25,8 @@ const { CfgServer } = require('../models/cfgserver');
const formidable = require('formidable');
const folder = path.join(__dirname, 'upload');
const sanitizeHtml = require('sanitize-html');
if (!fs.existsSync(folder)) {
fs.mkdirSync(folder);
}
@@ -655,8 +657,11 @@ router.post('/setsubrec', authenticate, (req, res) => {
});
router.post('/gettable', authenticate, (req, res) => {
const params = req.body;
let idapp = req.user ? req.user.idapp : params.idapp;
let params = req.body;
params.table = sanitizeHtml(params.table);
let idapp = req.user ? req.user.idapp : sanitizeHtml(params.idapp);
const mytable = globalTables.getTableByTableName(params.table);
//console.log('mytable', mytable);
if (!mytable) {

View File

@@ -651,7 +651,36 @@ router.post('/newtok', async (req, res) => {
});
router.post('/login', (req, res) => {
// Dizionario per tenere traccia dei tentativi di accesso falliti per ogni utente
const failedLoginAttempts = {};
// Costante per il numero massimo di tentativi di accesso falliti prima del blocco
const MAX_FAILED_ATTEMPTS = 3;
// Costante per la durata del blocco in millisecondi (ad esempio 30 minuti)
const BLOCK_DURATION = 30 * 60 * 1000; // 30 minuti
// Funzione per bloccare un utente per un periodo di tempo dopo un numero specificato di tentativi falliti
function blockUser(username) {
failedLoginAttempts[username] = Date.now() + BLOCK_DURATION;
}
// Middleware per controllare se l'utente è bloccato
function checkBlocked(req, res, next) {
const { username } = req.body;
const now = Date.now();
if (failedLoginAttempts[username] && failedLoginAttempts[username] > now) {
text = 'Utente bloccato. Riprova più tardi. (username=' + username + ')';
console.log(text);
return res.status(403).json({ message: 'Utente bloccato. Riprova più tardi.' });
}
next();
}
router.post('/login', checkBlocked, (req, res) => {
var body = _.pick(req.body,
['username', 'password', 'idapp', 'keyappid', 'lang']);
var user = new User(body);
@@ -668,18 +697,47 @@ router.post('/login', (req, res) => {
const myuser = user;
User.findByCredentials(user.idapp, user.username, user.password).
return User.findByCredentials(user.idapp, user.username, user.password).
then(async (user) => {
// tools.mylog("CREDENZIALI ! ");
if (!user) {
const rislogin = await User.tooManyLoginWrong(body.idapp, body.username, true);
if (rislogin.troppilogin) {
let text = 'Troppe richieste di Login ERRATE: ' + body.username + ' [IP: ' + tools.getiPAddressUser(req) + '] Tentativi: ' + rislogin.retry_pwd;
telegrambot.sendMsgTelegramToTheManagers(body.idapp, text);
console.log('/login', text);
res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: text });
return false;
}
await tools.snooze(3000);
const msg = 'Tentativo di Login ERRATO [' + body.username + ' , ' + ']\n' + '[IP: ' + tools.getiPAddressUser(req) +
']';
if (!failedLoginAttempts[body.username]) {
failedLoginAttempts[body.username] = 1;
} else {
failedLoginAttempts[body.username]++;
}
const msg = 'Tentativo (' + failedLoginAttempts[body.username] + ') di Login ERRATO [' + body.username + ' , ' + ']\n' + '[IP: ' + tools.getiPAddressUser(req) + ']';
tools.mylogshow(msg);
await telegrambot.sendMsgTelegramToTheAdmin(myuser.idapp, msg, true);
tools.writeErrorLog(msg);
// telegrambot.sendMsgTelegramToTheManagers(body.idapp, msg);
res.status(404).send({ code: server_constants.RIS_CODE_LOGIN_ERR });
if (failedLoginAttempts[body.username] >= MAX_FAILED_ATTEMPTS) {
blockUser(body.username);
text = 'Troppi tentativi di accesso falliti. Utente bloccato (' + body.username + ')' + ' [IP: ' + tools.getiPAddressUser(req) + ']';
tools.mylogshow(text);
telegrambot.sendMsgTelegramToTheManagers(req.body.idapp, text);
res.status(403).json({ message: text });
resalreadysent = true;
}
res.status(401).send({ code: server_constants.RIS_CODE_LOGIN_ERR });
resalreadysent = true;
}
return user;
}).

View File

@@ -39,6 +39,8 @@ const privateVapidKey = process.env.PRIVATE_VAPI_KEY;
const FIELDS_REGEX = ['username', 'name', 'surname'];
const sanitizeHtml = require('sanitize-html');
// Code goes here
const keySize = 256;
const ivSize = 128;
@@ -2404,6 +2406,8 @@ module.exports = {
let query = [];
if (params.filter && params.fieldsearch) {
params.filter = sanitizeHtml(params.filter);
params.fieldsearch = sanitizeHtml(params.fieldsearch);
const querytemp = this.getFilterParam(params.filter, params.fieldsearch);
if (querytemp) {
query = [...query, ...querytemp];
@@ -2420,6 +2424,7 @@ module.exports = {
// }
if (params.filterand) {
params.filterand = sanitizeHtml(params.filterand);
if (params.filterand.includes(
shared_consts.FILTER_EXTRALIST_NOT_REGISTERED))
@@ -2540,6 +2545,7 @@ module.exports = {
}
if (params.filtercustom) {
params.filtercustom = sanitizeHtml(params.filtercustom);
let condition = {};
for (const myfilter of params.filtercustom) {
if (myfilter['userId']) {
@@ -2566,6 +2572,7 @@ module.exports = {
}
if (params.filter_gte) {
params.filter_gte = sanitizeHtml(params.filter_gte);
for (let ind = 0; ind < params.filter_gte.length; ind++) {
for (const [key, value] of Object.entries(params.filter_gte[ind])) {
if (value > 0) {
@@ -2578,6 +2585,7 @@ module.exports = {
}
if (params.filtersearch) {
params.filtersearch = sanitizeHtml(params.filtersearch);
filtriadded.push(...params.filtersearch);
}
@@ -2589,11 +2597,13 @@ module.exports = {
if (params.filterextra) {
params.filterextra = sanitizeHtml(params.filterextra);
if (params.filterextra.length > 0)
query = [...query, ...params.filterextra]
}
if (filtriadded) {
filtriadded = sanitizeHtml(filtriadded);
if (filtriadded.length > 0)
query.push({ $match: { $and: filtriadded } });
}
@@ -2844,6 +2854,12 @@ module.exports = {
if (q1p) query = [...query, ...q1p];
}
params.lookup2 = this.sanitizzaLookup(params.lookup2);
params.lookup3 = this.sanitizzaLookup(params.lookup3);
params.lookup4 = this.sanitizzaLookup(params.lookup4);
params.lookup5 = this.sanitizzaLookup(params.lookup5);
const q2 = this.getLookup(params.lookup2, 2, proj, objadd.proj);
if (q2) query = [...query, ...q2];
@@ -4895,8 +4911,9 @@ module.exports = {
commonFields.forEach((field) => {
if (obj1 && obj2 && obj1 && obj2 && ((obj1[field] && obj1[field].toString()) !== (obj2[field] && obj2[field].toString()))) {
fieldsUpdated.push(field);
if (obj1 && obj2 && ((obj1[field] && obj1[field].toString()) !== (obj2[field] && obj2[field].toString()))) {
if (obj1[field] !== undefined && obj2[field] !== undefined)
fieldsUpdated.push(field);
}
});
return fieldsUpdated
@@ -5074,5 +5091,13 @@ module.exports = {
}
},
arrotondaA2Decimali(valore) {
try {
return parseFloat(valore).toFixed(2);
} catch (error) {
return valore;
}
},
// Scriviere qui SOPRA le funzioni
};

View File

@@ -1049,4 +1049,28 @@ module.exports = {
TYPEHOSP_SCAMBIOCASA: 1,
TYPEHOSP_OSPITALITA: 2,
PRODUCTTYPE: {
BENE: 1,
SERVIZIO: 2,
OSPITALITA: 4,
PRODOTTO: 10,
LIBRO: 20,
EBOOK: 21,
AUDIOLIBRO: 22,
VIDEO: 23,
CARTE: 25,
},
// Download, DVD, Epub, Mobi, Nuovo, PDF, Streaming, Usato
VERSIONE: {
NUOVO: 1,
USATO: 2,
DOWNLOAD: 3,
DVD: 4,
EPUB: 5,
MOBI: 6,
PDF: 7,
STREAMING: 8,
},
};

View File

@@ -3898,6 +3898,11 @@ entities@^4.2.0, entities@^4.3.0:
resolved "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz"
integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==
entities@^4.4.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
entities@~1.1.1:
version "1.1.2"
resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz"
@@ -4019,7 +4024,7 @@ escape-string-applescript@^1.0.0:
resolved "https://registry.npmjs.org/escape-string-applescript/-/escape-string-applescript-1.0.0.tgz"
integrity sha512-4/hFwoYaC6TkpDn9A3pTC52zQPArFeXuIfhUtCGYdauTzXVP9H3BDr3oO/QzQehMpLDC7srvYgfwvImPFGfvBA==
escape-string-regexp@4.0.0:
escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
@@ -5284,6 +5289,16 @@ htmlparser2@^6.1.0:
domutils "^2.5.2"
entities "^2.0.0"
htmlparser2@^8.0.0:
version "8.0.2"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21"
integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==
dependencies:
domelementtype "^2.3.0"
domhandler "^5.0.3"
domutils "^3.0.1"
entities "^4.4.0"
htmlparser2@^8.0.1:
version "8.0.1"
resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz"
@@ -5888,6 +5903,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
is-plain-object@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
is-promise@^2.0.0:
version "2.2.2"
resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz"
@@ -7668,6 +7688,11 @@ nanoid@3.3.3:
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz"
integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==
nanoid@^3.3.7:
version "3.3.7"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz"
@@ -8445,6 +8470,11 @@ parse-passwd@^1.0.0:
resolved "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz"
integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==
parse-srcset@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1"
integrity sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==
parse5-htmlparser2-tree-adapter@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz"
@@ -8632,6 +8662,15 @@ posix-character-classes@^0.1.0:
resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz"
integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==
postcss@^8.3.11:
version "8.4.38"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e"
integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
dependencies:
nanoid "^3.3.7"
picocolors "^1.0.0"
source-map-js "^1.2.0"
prebuild-install@^7.1.1:
version "7.1.1"
resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz"
@@ -9401,6 +9440,18 @@ safe-regex@^1.1.0:
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sanitize-html@^2.13.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.13.0.tgz#71aedcdb777897985a4ea1877bf4f895a1170dae"
integrity sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==
dependencies:
deepmerge "^4.2.2"
escape-string-regexp "^4.0.0"
htmlparser2 "^8.0.0"
is-plain-object "^5.0.0"
parse-srcset "^1.0.2"
postcss "^8.3.11"
saslprep@^1.0.0, saslprep@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz"
@@ -9820,6 +9871,11 @@ socks@^2.3.3, socks@^2.6.2, socks@^2.7.1:
ip "^2.0.0"
smart-buffer "^4.2.0"
source-map-js@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
source-map-resolve@^0.5.0:
version "0.5.3"
resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz"
@@ -11071,6 +11127,7 @@ workerpool@6.2.1:
integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
name wrap-ansi-cjs
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==