- catalogo avanti, parte 1
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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
54
src/server/models/author.js
Executable 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;
|
||||
});
|
||||
@@ -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) {
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
50
src/server/models/publisher.js
Executable 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;
|
||||
});
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}).
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
59
yarn.lock
59
yarn.lock
@@ -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==
|
||||
|
||||
Reference in New Issue
Block a user