From 21862f87a17c88bdbf27c40a337415e6c3c6da58 Mon Sep 17 00:00:00 2001 From: Surya Paolo Date: Tue, 23 Jul 2024 12:25:10 +0200 Subject: [PATCH] - MultiDominio: api.riso.app, api.gruppomacro.app --- .DS_Store | Bin 10244 -> 10244 bytes .env.prod.pcb | 5 +- deploynode_on_prod_pcb.sh | 65 ++++++- docs/apache2/riso.app-le.ssl.conf | 26 +++ .../ssl_vhost_api.gruppomacro.app.conf | 34 ++++ docs/apache2/ssl_vhost_api.riso.app.conf | 34 ++++ docs/apache2/vhost.ssl_abitaregliiblei.conf | 22 +++ docs/apache2/vhost.ssl_piuchebuono.conf | 22 +++ ecosystem.config.js | 3 - ecosystem.config.pcb.js | 21 +++ package.json | 1 + src/server/models/myelem.js | 1 + src/server/router/admin_router.js | 45 +++++ src/server/router/users_router.js | 15 +- src/server/server.js | 177 +++++++++++------- src/server/tools/general.js | 74 +++++++- yarn.lock | 36 +++- 17 files changed, 484 insertions(+), 97 deletions(-) create mode 100644 docs/apache2/riso.app-le.ssl.conf create mode 100644 docs/apache2/ssl_vhost_api.gruppomacro.app.conf create mode 100644 docs/apache2/ssl_vhost_api.riso.app.conf create mode 100644 docs/apache2/vhost.ssl_abitaregliiblei.conf create mode 100644 docs/apache2/vhost.ssl_piuchebuono.conf create mode 100755 ecosystem.config.pcb.js diff --git a/.DS_Store b/.DS_Store index 2a0b6a70b227ee7ffc819041ed8c68a97843447d..974caec8b0a8082269e8396fcb5ee869d960b717 100644 GIT binary patch delta 269 zcmZn(XbG6$&nUYwU^hRb>}DQ;N=`{Oh609Ch9rg@hD?U!r1Ii|q@4UD1_p*5lPjbO z>m{nIjm!*m6pT%3brh-%4b2U86wFNxYHK+;M3wcegW|Jua`W=Lfa-yOkr6^O@Iq-A z)eU5z*i#lEUDuVsK?}WN=~d1=4y9xeO_uIr+&+Ig{r}-ed&3#2w@k XBNH73GfRqGve`)bIrC|ojp;Z2 delta 89 zcmV-f0H*(hP=rvBPXQaTP`eKS8?y`$c?pws8u9_Ulb#uIDH?lwF)%VUEFdy9Iejc3 vdoeLGGAtlAIW~QL2?!MA2O#|i;DH=! diff --git a/.env.prod.pcb b/.env.prod.pcb index a926258..79543a8 100644 --- a/.env.prod.pcb +++ b/.env.prod.pcb @@ -26,10 +26,11 @@ PATH_CERT_KEY=key.pem PATH_SERVER_CRT=cert.pem PATH_SSL_ROOT_PEM=root.pem PATH_SSL_CHAIN_PEM=chain.pem -PROD=0 +PROD=1 PROJECT_DESCR_MAIN='__PROJECTS' SECRK=iUUb38v23jjDFaosWj92axkBOXCQ SECRTK=jAxKm02emx5SeJvz2IGmtRf6YqCgope TOKEN_LIFE=2h REFRESH_TOKEN_LIFE=14d -AUTH_NEW_SITES=B234HDSAOJ734ndcsdKWNVZZ \ No newline at end of file +AUTH_NEW_SITES=B234HDSAOJ734ndcsdKWNVZZ +DOMAINS=[{"hostname": "piuchebuono.app","port": 3000 },{"hostname":"gruppomacro.app","port": 3010}] \ No newline at end of file diff --git a/deploynode_on_prod_pcb.sh b/deploynode_on_prod_pcb.sh index 162753f..3858ac8 100755 --- a/deploynode_on_prod_pcb.sh +++ b/deploynode_on_prod_pcb.sh @@ -5,14 +5,59 @@ source ./.env.prod.pcb echo "Sincronizzazione in corso PCB PRODUZIONE ... /var/www/$SERVERDIR_WEBSITE/" echo "" -rsync -avz -e 'ssh -p 8822' css pcbuser@pcb:/var/www/$SERVERDIR_WEBSITE/ -rsync -avz -e 'ssh -p 8822' docs pcbuser@pcb:/var/www/$SERVERDIR_WEBSITE/ -rsync -avz -e 'ssh -p 8822' emails pcbuser@pcb:/var/www/$SERVERDIR_WEBSITE/ -rsync -avz -e 'ssh -p 8822' images pcbuser@pcb:/var/www/$SERVERDIR_WEBSITE/ -rsync -avz -e 'ssh -p 8822' plugins pcbuser@pcb:/var/www/$SERVERDIR_WEBSITE/ -rsync -avz -e 'ssh -p 8822' sass pcbuser@pcb:/var/www/$SERVERDIR_WEBSITE/ -rsync -avz -e 'ssh -p 8822' src pcbuser@pcb:/var/www/$SERVERDIR_WEBSITE/ -rsync -avz -e 'ssh -p 8822' .env.prod.pcb pcbuser@pcb:/var/www/$SERVERDIR_WEBSITE/.env.production -rsync -avz -e 'ssh -p 8822' package.json pcbuser@pcb:/var/www/$SERVERDIR_WEBSITE/package.json +#!/bin/bash + +# Configurazione +REMOTE_USER="pcbuser" +REMOTE_HOST="pcb" +REMOTE_PORT="8822" +REMOTE_DIR="/var/www/$SERVERDIR_WEBSITE" +SSH_OPTIONS="-p $REMOTE_PORT" + +# Array di cartelle e file da sincronizzare +SYNC_ITEMS=( + "css" + "docs" + "emails" + "plugins" + "sass" + "src" +) + +echo $REMOTE_DIR + +echo "" +echo "*** Copia Cartelle ... " + + +# Esegui rsync per le cartelle +rsync -avz --delete \ + --exclude='src/server/router/upload/' \ + -e "ssh $SSH_OPTIONS" \ + "${SYNC_ITEMS[@]}" \ + "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/" + +echo "" +echo "*** Copia del file .env.production ... " + +# Sincronizza i file specifici +rsync -avz -e "ssh $SSH_OPTIONS" \ + .env.prod.pcb "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/.env.production" + +echo "" +echo "*** Copia del file package.json ... " +rsync -avz -e "ssh $SSH_OPTIONS" \ + package.json "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/package.json" + +echo "" +echo "*** Copia del file ecosystem.config.js ... " +rsync -avz -e "ssh $SSH_OPTIONS" \ + ecosystem.config.pcb.js "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/ecosystem.config.js" + +# Verifica il risultato +if [ $? -eq 0 ]; then + echo "Sincronizzazione completata con successo. SERVER PCB! " +else + echo "Errore durante la sincronizzazione. Controlla l'output per i dettagli." +fi -echo "Sincronizzazione TERMINATA! - SERVER PCB!" diff --git a/docs/apache2/riso.app-le.ssl.conf b/docs/apache2/riso.app-le.ssl.conf new file mode 100644 index 0000000..44dd2a4 --- /dev/null +++ b/docs/apache2/riso.app-le.ssl.conf @@ -0,0 +1,26 @@ + + SuexecUserGroup "#1008" "#1008" + ServerName riso.app + ServerAlias www.riso.app + DocumentRoot /var/www/riso.app + + ErrorLog /var/www/riso.app/logs//error.log + CustomLog /var/www/riso.app/logs/access.log combined + + + Options -Indexes +IncludesNOEXEC +SymLinksIfOwnerMatch +ExecCGI + allow from all + AllowOverride All Options=ExecCGI,Includes,IncludesNOEXEC,Indexes,MultiViews,SymLinksIfOwnerMatch + Require all granted + + + + Redirect permanent / https://riso.app/ + + +RewriteEngine on +Include /etc/letsencrypt/options-ssl-apache.conf +SSLCertificateFile /etc/letsencrypt/live/riso.app/fullchain.pem +SSLCertificateKeyFile /etc/letsencrypt/live/riso.app/privkey.pem + + \ No newline at end of file diff --git a/docs/apache2/ssl_vhost_api.gruppomacro.app.conf b/docs/apache2/ssl_vhost_api.gruppomacro.app.conf new file mode 100644 index 0000000..7067dc4 --- /dev/null +++ b/docs/apache2/ssl_vhost_api.gruppomacro.app.conf @@ -0,0 +1,34 @@ + + ServerName api.gruppomacro.app + ServerAlias www.api.gruppomacro.app + ServerAdmin surya@riso.app + + SSLEngine On + SSLProtocol -ALL +TLSv1.2 +TLSv1.3 + SSLCompression Off + SSLHonorCipherOrder off + SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:E> + SSLVerifyDepth 10 + SSLCertificateFile /etc/letsencrypt/live/gruppomacro.app/cert.pem + SSLCertificateKeyFile /etc/letsencrypt/live/gruppomacro.app/privkey.pem + + ProxyPreserveHost On + SSLProxyEngine On + SSLProxyVerify None + SSLProxyCheckPeerCN Off + SSLProxyCheckPeerName Off + ProxyPass / https://localhost:3010/ retry=0 timeout=5 connectiontimeout=2 + ProxyPassReverse / https://localhost:3010/ + + ProxyTimeout 5 + + LogLevel debug proxy:trace5 + ErrorLog "/var/customers/logs/paolouser-error.log" + CustomLog "/var/customers/logs/paolouser-access.log" combined + + + ProxyPassReverse / + SetEnv force-proxy-request-1.0 1 + SetEnv proxy-nokeepalive 1 + + \ No newline at end of file diff --git a/docs/apache2/ssl_vhost_api.riso.app.conf b/docs/apache2/ssl_vhost_api.riso.app.conf new file mode 100644 index 0000000..c3fbc56 --- /dev/null +++ b/docs/apache2/ssl_vhost_api.riso.app.conf @@ -0,0 +1,34 @@ + + ServerName api.riso.app + ServerAlias www.api.riso.app + ServerAdmin surya@riso.app + + SSLEngine On + SSLProtocol -ALL +TLSv1.2 +TLSv1.3 + SSLCompression Off + SSLHonorCipherOrder off + SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:E> + SSLVerifyDepth 10 + SSLCertificateFile /etc/letsencrypt/live/riso.app/cert.pem + SSLCertificateKeyFile /etc/letsencrypt/live/riso.app/privkey.pem + + ProxyPreserveHost On + SSLProxyEngine On + SSLProxyVerify None + SSLProxyCheckPeerCN Off + SSLProxyCheckPeerName Off + ProxyPass / https://localhost:3005/ retry=0 timeout=5 connectiontimeout=2 + ProxyPassReverse / https://localhost:3005/ + + ProxyTimeout 5 + + LogLevel debug proxy:trace5 + ErrorLog "/var/www/riso.app/logs/error.log" + CustomLog "/var/www/riso.app/logs/access.log" combined + + + ProxyPassReverse / + SetEnv force-proxy-request-1.0 1 + SetEnv proxy-nokeepalive 1 + + \ No newline at end of file diff --git a/docs/apache2/vhost.ssl_abitaregliiblei.conf b/docs/apache2/vhost.ssl_abitaregliiblei.conf new file mode 100644 index 0000000..9a7c1df --- /dev/null +++ b/docs/apache2/vhost.ssl_abitaregliiblei.conf @@ -0,0 +1,22 @@ + + ServerName abitaregliiblei.it + ServerAlias *.abitaregliiblei.it + ServerAdmin surya@riso.app + SSLEngine On + SSLProtocol -ALL +TLSv1.2 + SSLCompression Off + SSLHonorCipherOrder off + SSLCipherSuite ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128 + SSLVerifyDepth 10 + SSLCertificateFile /etc/letsencrypt/live/abitaregliiblei.it/cert.pem + SSLCertificateKeyFile /etc/letsencrypt/live/abitaregliiblei.it/privkey.pem + DocumentRoot "/var/customers/webs/paolouser/abitaregliiblei.it" + + CGIPassAuth On + Require all granted + AllowOverride All + + LogLevel warn + ErrorLog "/var/customers/logs/paolouser-error.log" + CustomLog "/var/customers/logs/paolouser-access.log" combined + \ No newline at end of file diff --git a/docs/apache2/vhost.ssl_piuchebuono.conf b/docs/apache2/vhost.ssl_piuchebuono.conf new file mode 100644 index 0000000..154eb5d --- /dev/null +++ b/docs/apache2/vhost.ssl_piuchebuono.conf @@ -0,0 +1,22 @@ + + ServerName piuchebuono.app + ServerAlias *.piuchebuono.app + ServerAdmin surya@riso.app + SSLEngine On + SSLProtocol -ALL +TLSv1.2 + SSLCompression Off + SSLHonorCipherOrder off + SSLCipherSuite ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!DH:!AES128 + SSLVerifyDepth 10 + SSLCertificateFile /etc/letsencrypt/live/piuchebuono.app/cert.pem + SSLCertificateKeyFile /etc/letsencrypt/live/piuchebuono.app/privkey.pem + DocumentRoot "/var/customers/webs/paolouser/piuchebuono.app" + + CGIPassAuth On + Require all granted + AllowOverride All + + LogLevel warn + ErrorLog "/var/customers/logs/paolouser-error.log" + CustomLog "/var/customers/logs/paolouser-access.log" combined + \ No newline at end of file diff --git a/ecosystem.config.js b/ecosystem.config.js index 93e084d..e327849 100755 --- a/ecosystem.config.js +++ b/ecosystem.config.js @@ -9,15 +9,12 @@ module.exports = { //autorestart: true, instances: 1, env: { - "PORT": 3000, "NODE_ENV": "development", }, env_test: { - "PORT": 3001, "NODE_ENV": "test", }, env_production: { - "PORT": 3000, "NODE_ENV": "production", }, log_file: "logs/combined.outerr.log", diff --git a/ecosystem.config.pcb.js b/ecosystem.config.pcb.js new file mode 100755 index 0000000..3ce7fe5 --- /dev/null +++ b/ecosystem.config.pcb.js @@ -0,0 +1,21 @@ +module.exports = { + apps: [ + { + name: "PRODUZIONE PiuCheBuono_ServerSide", + script: "/var/www/www.freeplanet_server/src/server/server.js", + ignore_watch: ["node_modules", "logs"], + interpreter: "/root/.nvm/versions/node/v16.19.0/bin/node", + //autorestart: true, + instances: 1, + watch: false, + env: { + "NODE_ENV": "production" + }, + log_file: "logs/combined.test.outerr.log", + error_file: "logs/errtest.log", + out_file: "logs/outtest.log", + merge_logs: true, + log_date_format: "YYYY-MM-DD HH:mm:ss.SSSS Z" + } + ] +}; \ No newline at end of file diff --git a/package.json b/package.json index c6ad336..1022761 100755 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "superagent": "^8.0.0", "url-parse": "^1.5.10", "validator": "^13.7.0", + "vhost": "^3.0.2", "web-push": "^3.6.7", "xoauth2": "^1.2.0" }, diff --git a/src/server/models/myelem.js b/src/server/models/myelem.js index a711d42..008cd92 100755 --- a/src/server/models/myelem.js +++ b/src/server/models/myelem.js @@ -50,6 +50,7 @@ const catalogo = new Schema( productTypes: [{ type: Number }], excludeproductTypes: [{ type: Number }], Editore: [{ type: String }], + pdf: { type: Boolean }, // formato: [{ type: String, default: '' }], // categoria: [{ type: String, default: '' }], } diff --git a/src/server/router/admin_router.js b/src/server/router/admin_router.js index 2401929..6931972 100755 --- a/src/server/router/admin_router.js +++ b/src/server/router/admin_router.js @@ -7,6 +7,8 @@ const shared_consts = require('../tools/shared_nodejs'); const tools = require('../tools/general'); +const fs = require('fs'); + const { City } = require('../models/city'); const Product = require('../models/product'); const Inventariogm = require('../models/inventariogm'); @@ -18,6 +20,10 @@ const Publisher = require('../models/publisher'); const SubCatProd = require('../models/subcatprod'); const Gasordine = require('../models/gasordine'); +const { ImageDownloader } = require('../tools/general.js'); + +const path = require('path'); + var { authenticate } = require('../middleware/authenticate'); router.post('/updateval', authenticate, async (req, res) => { @@ -45,6 +51,35 @@ function fixURL(url) { return url.replace(/https:\//g, 'https://'); } +async function downloadImgIfMissing(productInfo) { + + if (!productInfo.image_link) + return { prodInfo: null, aggiornatoimg: false }; + + const img = 'upload/products/' + productInfo.image_link.split('/').pop(); + const savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine + + if (!productInfo.img || !fs.existsSync(savePath)) { + // Download image from the URL productInfo.image_link + productInfo.img = img; + + const downloader = new ImageDownloader(); + + const aggiornatoimg = await downloader.downloadImage(productInfo.image_link, savePath).then(result => { + if (result) { + // console.log('Download completato con successo!'); + } else { + console.log('Download non riuscito.'); + } + + return result; + + }); + return { prodInfo: productInfo, aggiornatoimg }; + } + + return { prodInfo: null, aggiornatoimg: false }; +} async function completaSettaggioProduct_AndProductInfo(arrcampi_productInfo, arrcampi_product, rec, product, productInfo) { @@ -329,6 +364,8 @@ router.post('/import', authenticate, async (req, res) => { let indprod = 0; let newprod = 0; + let numprod = dataObjects.length; + for (const product of dataObjects) { let isnuovo = false let setta = false @@ -367,6 +404,8 @@ router.post('/import', authenticate, async (req, res) => { let versione = 0; + console.log(indprod + '/' + numprod); + productInfo.productTypes = []; // console.log('indprod', indprod, 'arrversGM', arrversGM, 'versione', product.Versione); @@ -553,6 +592,12 @@ router.post('/import', authenticate, async (req, res) => { product.idProductInfo = risrecInfo._id; recnewInfo = await ProductInfo.findOne({ code: productInfo.code }).lean(); + let { prodInfo, aggiornatoimg } = await downloadImgIfMissing(recnewInfo); + + if (aggiornatoimg) { + await ProductInfo.findOneAndUpdate({ code: productInfo.code }, { $set: prodInfo }); + } + if (risrecInfo._id) { // Record existed, so it was updated let arrfieldchange = tools.differentObjects(productInfo, recnewInfo); diff --git a/src/server/router/users_router.js b/src/server/router/users_router.js index ca7c2b7..9ff3250 100755 --- a/src/server/router/users_router.js +++ b/src/server/router/users_router.js @@ -721,11 +721,14 @@ router.post('/login', checkBlocked, (req, res) => { failedLoginAttempts[body.username]++; } + let numvolteerrati = 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); + if (numvolteerrati > 2) { + const msg = 'Tentativo (' + numvolteerrati + ') 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); if (failedLoginAttempts[body.username] >= MAX_FAILED_ATTEMPTS) { @@ -1623,7 +1626,7 @@ async function eseguiDbOp(idapp, mydata, locale, req, res) { await Circuit.createCircuitIfNotExist(req, idapp, recprov.prov); } - } else if (mydata.dbop === 'correggiProductTypes') { + } else if (mydata.dbop === 'correggiProductTypes') { await ProductInfo.correggiProductTypes(); @@ -1634,7 +1637,7 @@ async function eseguiDbOp(idapp, mydata, locale, req, res) { {}, { $pull: { "profile.mycircuits": { "circuitname": null } } } ); - + } else if (mydata.dbop === 'ImpostaMinMaxPersonali') { await Account.SetMinMaxPersonali(idapp, mydata.valmin, mydata.valmax, ''); diff --git a/src/server/server.js b/src/server/server.js index 265ee4a..b6758e4 100755 --- a/src/server/server.js +++ b/src/server/server.js @@ -12,18 +12,23 @@ const cors = require('cors'); // console.log(" 2) fs"); const fs = require('fs'); +var https = require('https'); +var http = require('http'); + const NUOVO_METODO_TEST = true; +const METODO_MULTI_CORS = false; + const server_constants = require('./tools/server_constants'); //const throttle = require('express-throttle-bandwidth'); // app.use(throttle(1024 * 128)) // throttling bandwidth -const port = process.env.PORT; - // var cookieParser = require('cookie-parser') // var csrf = require('csurf') const express = require('express'); +const vhost = require('vhost'); + const bodyParser = require('body-parser'); const path = require('path'); @@ -246,79 +251,14 @@ myLoad().then(ris => { if ((process.env.NODE_ENV === 'production') || (process.env.NODE_ENV === 'test')) { - - const keyStream = path.resolve(`./${process.env.PATH_CERT_KEY}`); - const certificateStream = path.resolve(`./${process.env.PATH_SERVER_CRT}`); - - const privateKey = fs.readFileSync(keyStream, "utf8"); - const certificate = fs.readFileSync(certificateStream, "utf8"); - - - if (NUOVO_METODO_TEST) { - credentials = { - key: privateKey, - cert: certificate, - }; - } else { - // NON USATO ! - credentials = { - key: privateKey, - cert: certificate, - ca: [ - fs.readFileSync(process.env.PATH_SSL_ROOT_PEM, 'utf8'), - fs.readFileSync(process.env.PATH_SSL_CHAIN_PEM, 'utf8'), - ], - }; - } - - var https = require('https'); - } else { - if (process.env.HTTPS_LOCALHOST === "true") { - var privateKey = fs.readFileSync(process.env.PATH_CERT_KEY, 'utf8'); - var certificate = fs.readFileSync(process.env.PATH_SERVER_CRT, 'utf8'); - credentials = { - key: privateKey, - cert: certificate, - ciphers: 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES256-SHA384', - honorCipherOrder: true, - secureProtocol: 'TLSv1_2_method', - }; - var https = require('https'); - - } else { - var http = require('http'); - } - } - - - if ((process.env.NODE_ENV === 'production') || - (process.env.NODE_ENV === 'test') || process.env.HTTPS_LOCALHOST === "true") { - - if (false) { - /*pem.createCertificate({ days: 1, selfSigned: true }, (err, keys) => { - if (err) { - throw err - } - const httpsServer = https.createServer({ key: keys.clientKey, cert: keys.certificate }, (req, res) => { - res.end('o hai!') - }).listen(port) - }) */ - } else { - const httpsServer = https.createServer(credentials, app); - - console.log('httpsServer: port ', port); - httpsServer.listen(port); - } - } else { - console.log('httpServer: port ', port); - const httpServer = http.createServer(app); - httpServer.listen(port); } + startServer(app, process.env.PORT); mystart(); }); + // app.use(throttle(1024 * 128)); // throttling bandwidth // app.use((req, res, next) => { @@ -769,5 +709,104 @@ async function faitest() { } } +/*const domains = [ + { hostname: 'piuchebuono.app', port: 3000 }, + { hostname: 'gruppomacro.app', port: 3010 }, +];*/ + +function getCredentials(hostname) { + + if (NUOVO_METODO_TEST) { + if (METODO_MULTI_CORS) { + const fileprivkey = `/etc/letsencrypt/live/${hostname}/privkey.pem`; + const filecert = `/etc/letsencrypt/live/${hostname}/cert.pem`; + + console.log('fileprivkey: ', fileprivkey, ' filecert: ', filecert); + + /* return { + + SNICallback: function (hostname, callback) { + console.log('hostname: ', hostname); + if (domains.includes(hostname)) { + const fileprivkey = `/etc/letsencrypt/live/${hostname}/privkey.pem`; + const filecert = `/etc/letsencrypt/live/${hostname}/fullchain.pem`; + + // console.log('fileprivkey: ', fileprivkey, ' filecert: ', filecert); + + const domainCert = { + key: fs.readFileSync(fileprivkey, "utf8"), + cert: fs.readFileSync(filecert, "utf8"), + }; + callback(null, domainCert); + } else { + callback(null, { key: privateKey, cert: certificate }); + } + } + + };*/ + + return { + key: fs.readFileSync(fileprivkey, "utf8"), + cert: fs.readFileSync(filecert, "utf8") + }; + + } else { + const keyStream = path.resolve(`./${process.env.PATH_CERT_KEY}`); + const certificateStream = path.resolve(`./${process.env.PATH_SERVER_CRT}`); + + const privateKey = fs.readFileSync(keyStream, "utf8"); + const certificate = fs.readFileSync(certificateStream, "utf8"); + + return { key: privateKey, cert: certificate }; + } + } else if (process.env.HTTPS_LOCALHOST === "true") { + try { + return { + key: fs.readFileSync(process.env.PATH_CERT_KEY, 'utf8'), + cert: fs.readFileSync(process.env.PATH_SERVER_CRT, 'utf8'), + ciphers: 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES256-SHA384', + honorCipherOrder: true, + secureProtocol: 'TLSv1_2_method' + }; + } catch (error) { + console.error('Errore durante la lettura dei file di certificazione, error:', error.message); + throw error; + } + } + // Caso di default non specificato, potrebbe essere necessario aggiungere una gestione degli errori qui +} + +function startServer(app, port) { + try { + const isProduction = ['production', 'test'].includes(process.env.NODE_ENV); + + let domains = []; + + try { + domains = JSON.parse(process.env.DOMAINS); + } catch (error) { + console.error("Errore durante la conversione della stringa DOMAINS:", error); + } + + console.log('domains', domains); + + if (isProduction) { + for (let i = 0; i < domains.length; i++) { + const credentials = getCredentials(domains[i].hostname); + // console.log('credentials: ', credentials); + const httpsServer = https.createServer(credentials, app); + console.log('⭐️⭐️⭐️⭐️⭐️ HTTPS server: ' + domains[i].hostname + ' Port:', domains[i].port); + httpsServer.listen(domains[i].port); + } + } else { + const httpServer = http.createServer(app); + console.log('⭐️⭐️⭐️ HTTP server IN LOCALE : port', port); + httpServer.listen(port); + } + } catch (e) { + console.log('error ' + e); + } +} + module.exports = { app }; diff --git a/src/server/tools/general.js b/src/server/tools/general.js index 3c9bdc4..3aeff74 100755 --- a/src/server/tools/general.js +++ b/src/server/tools/general.js @@ -399,6 +399,70 @@ const textlang = { }, }; +/** + * Scarica un'immagine da una URL e la salva in una directory locale + * @param {string} url - L'URL dell'immagine da scaricare + * @param {string} filepath - Il percorso dove salvare l'immagine scaricata + */ +class ImageDownloader { + /** + * Scarica un'immagine da una URL e la salva in una directory locale. + * Tenta di scaricare fino a 3 volte in caso di errore, con un ritardo tra i tentativi. + * + * @param {string} url - L'URL dell'immagine da scaricare + * @param {string} filepath - Il percorso dove salvare l'immagine scaricata + * @param {number} maxRetries - Numero massimo di tentativi in caso di fallimento (default: 3) + * @param {number} delay - Ritardo in millisecondi tra i tentativi (default: 1000) + * @returns {Promise} + */ + async downloadImage(url, filepath, maxRetries = 1, delay = 1000) { + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + const writer = fs.createWriteStream(filepath); + + console.log('url da scaricare:', url); + + const response = await axios({ + url, + method: 'GET', + responseType: 'stream', + headers: { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' + } + }); + + response.data.pipe(writer); + + await new Promise((resolve, reject) => { + writer.on('finish', () => { + console.info('✅ Immagine scaricata ' + url + ' in ' + filepath); + resolve(true); + }); + writer.on('error', reject); + }); + + + return true; + } catch (error) { + console.error(`❌ Tentativo ${attempt} fallito per l'URL ${url}. Errore:`, error.message); + + if (attempt === maxRetries) { + console.error('❌ Tutti i tentativi sono falliti. Scaricamento interrotto.'); + return false; + } else { + console.info(`🔁 Ritentando... (${attempt + 1} di ${maxRetries})`); + await sleep(delay); + } + } + } + } +} + +// Funzione per implementare il ritardo tra i tentativi +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + module.exports = { MYAPPS: [], INITDB_FIRSTIME: true, @@ -1125,10 +1189,10 @@ module.exports = { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_ACCEPTED; } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT_SENT) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_ACCEPTED_SENT; - // } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE) { - // typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED; - //} else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE_SENT) { - // typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED_SENT; + // } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE) { + // typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED; + //} else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE_SENT) { + // typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED_SENT; } } @@ -5195,5 +5259,7 @@ module.exports = { } } }, + ImageDownloader, + }; diff --git a/yarn.lock b/yarn.lock index 640b0bc..d3d1c93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10731,7 +10731,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -10749,6 +10749,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -10805,7 +10814,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -10819,6 +10828,13 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -11611,6 +11627,11 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vhost@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5" + integrity sha512-S3pJdWrpFWrKMboRU4dLYgMrTgoPALsmYwOvyebK2M6X95b9kQrjZy5rwl3uzzpfpENe/XrNYu/2U+e7/bmT5g== + vinyl-contents@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/vinyl-contents/-/vinyl-contents-1.0.0.tgz#f8f3456fe2dfb208a62c85653c2b682f87b5a2d5" @@ -11863,7 +11884,16 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==