require('./config/config'); // console.log(" lodash"); console.log('VERSIONE NODE.JS :', process.versions.node); if (process.env.AUTH_MONGODB === undefined) { console.error("AUTH_MONGODB non presente. VARIABILI D'AMBIENTE NON SETTATI!"); process.exit(1); } const _ = require('lodash'); // console.log(" cors"); const cors = require('cors'); // console.log(" 2) fs"); const fs = require('fs'); // 👈 Usa il modulo promises var https = require('https'); var http = require('http'); const WebSocket = require('ws'); const { spawn } = require('child_process'); const helmet = require('helmet'); const morgan = require('morgan'); const apiRouter = require('./routes/index-aa'); const { notFound, errorHandler } = require('./middleware/error'); const rateLimit = require('./middleware/rateLimit').rateLimit; const NUOVO_METODO_TEST = true; const METODO_MULTI_CORS = true; const server_constants = require('./tools/server_constants'); //const throttle = require('express-throttle-bandwidth'); // app.use(throttle(1024 * 128)) // throttling bandwidth // 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'); const cron = require('node-cron'); console.log('Starting mongoose...'); // console.log('Starting pem...'); // const pem = require('pem') const { Settings } = require('./models/settings'); const Site = require('./models/site'); // test const i18n = require('i18n'); const readline = require('readline'); let credentials = null; console.log('DB: ' + process.env.DATABASE); // console.log("PORT: " + port); // console.log("MONGODB_URI: " + process.env.MONGODB_URI); var app = express(); let telegrambot = null; const tools = require('./tools/general'); const shared_consts = require('./tools/shared_nodejs'); const { connectToDatabase, connectionUrl, options } = require('./db/mongoose'); // Avvia la connessione connectToDatabase(connectionUrl, options) .then(() => { console.log('------------------------------------------------------------------'); console.log('--------------- CONNESSIONE AL DB EFFETTUATA ! -----------------'); console.log('------------------------------------------------------------------'); const { CfgServer } = require('./models/cfgserver'); const { ObjectId } = require('mongodb'); const populate = require('./populate/populate'); const { Circuit } = require('./models/circuit'); const printf = require('util').format; myLoad().then((ris) => { const { User } = require('./models/user'); require('./models/todo'); require('./models/project'); require('./models/subscribers'); require('./models/booking'); require('./models/sendmsg'); require('./models/sendnotif'); require('./models/mailinglist'); require('./models/newstosent'); require('./models/mypage'); require('./models/myelem'); require('./models/myscheda'); require('./models/bot'); require('./models/calzoom'); const mysql_func = require('./mysql/mysql_func'); const index_router = require('./router/index_router'); const push_router = require('./router/push_router'); const newsletter_router = require('./router/newsletter_router'); const booking_router = require('./router/booking_router'); const dashboard_router = require('./router/dashboard_router'); const myevent_router = require('./router/myevent_router'); const subscribe_router = require('./router/subscribe_router'); const sendmsg_router = require('./router/sendmsg_router'); const sendnotif_router = require('./router/sendnotif_router'); const email_router = require('./router/email_router'); const todos_router = require('./router/todos_router'); const test_router = require('./router/test_router'); const projects_router = require('./router/projects_router'); const report_router = require('./router/report_router'); const users_router = require('./router/users_router'); const reactions_router = require('./router/reactions_router'); const mygroups_router = require('./router/mygroups_router'); const circuits_router = require('./router/circuits_router'); const accounts_router = require('./router/accounts_router'); const iscrittiConacreis_router = require('./router/iscrittiConacreis_router'); const iscrittiArcadei_router = require('./router/iscrittiArcadei_router'); const site_router = require('./router/site_router'); const admin_router = require('./router/admin_router'); const products_router = require('./router/products_router'); const myscraping_router = require('./router/myscraping_router'); const catalogs_router = require('./router/catalogs_router'); const cart_router = require('./router/cart_router'); const orders_router = require('./router/orders_router'); const city_router = require('./router/city_router'); const myskills_router = require('./router/myskills_router'); const mygoods_router = require('./router/mygoods_router'); const mygen_router = require('./router/mygen_router'); const aitools_router = require('./router/aitools_router'); const article_router = require('./router/articleRoutes'); const api_router = require('./router/api_router'); const { MyEvent } = require('./models/myevent'); app.use(bodyParser.json({ limit: '50mb' })); app.use(bodyParser.urlencoded({ limit: '50mb', extended: true })); app.use(express.static('views')); app.use(express.json({ limit: '100mb' })); app.use(express.urlencoded({ extended: true, limit: '100mb' })); // app.use(express.static(path.join(__dirname, 'client'))); app.use(bodyParser.json()); // app.set('view engine', 'pug'); // Set static folder // app.use(express.static(path.join(__dirname, 'public'))); i18n.configure({ locales: ['it', 'enUs', 'es', 'fr', 'pt', 'si'], defaultLocale: 'it', // cookie: 'cook', directory: __dirname + '/locales', api: { __: 'translate', __n: 'translateN', }, }); // Serve il tuo service worker da una certa directory /*app.get('/service-worker.js', (req, res) => { res.set('Cache-Control', 'no-cache'); // Aggiunge l'intestazione // res.sendFile(path.join(__dirname, 'service-worker.js')); // Modifica il percorso secondo la tua struttura });*/ app.use(bodyParser.json()); // app.use(express.cookieParser()); app.use(i18n.init); console.log('Use Routes ...'); // catch 404 and forward to error handler // app.use(function (req, res, next) { // var err = new Error('Not Found'); // err.status = 404; // next(err); // }); // app.set('views', path.join(__dirname, 'views')); // app.set('view engine', 'pug'); // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function (err, req, res, next) { console.log('Server Error: ', err.message); // console.trace(); res.status(err.status || 500).send({ error: err.message }); // res.render('error', { // message: err.message, // error: err // }); }); } if (process.env.NODE_ENV === 'production') { console.log('*** PRODUCTION! '); } if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test') { } startServer(app, process.env.PORT); // Use Routes app.use('/', index_router); app.use('/subscribe', subscribe_router); app.use('/sendmsg', sendmsg_router); app.use('/sendnotif', sendnotif_router); app.use('/push', push_router); app.use('/news', newsletter_router); app.use('/booking', booking_router); app.use('/dashboard', dashboard_router); app.use('/event', myevent_router); app.use('/email', email_router); app.use('/todos', todos_router); app.use('/test', test_router); app.use('/projects', projects_router); app.use('/users', users_router); app.use('/reactions', reactions_router); app.use('/mygroup', mygroups_router); app.use('/circuit', circuits_router); app.use('/account', accounts_router); app.use('/iscritti_conacreis', iscrittiConacreis_router); app.use('/iscritti_arcadei', iscrittiArcadei_router); app.use('/report', report_router); app.use('/site', site_router); app.use('/admin', admin_router); app.use('/products', products_router); app.use('/myscraping', myscraping_router); app.use('/catalogs', catalogs_router); app.use('/cart', cart_router); app.use('/orders', orders_router); app.use('/city', city_router); app.use('/myskills', myskills_router); app.use('/mygoods', mygoods_router); app.use('/mygen', mygen_router); app.use('/aitools', aitools_router); app.use('/apisqlsrv', article_router); app.use('/api', api_router); mystart(); }); // app.use(throttle(1024 * 128)); // throttling bandwidth async function myLoad() { return tools.loadApps(); } async function mystart() { // await estraiTutteLeImmagini(); console.log('Versione Server: ' + (await tools.getVersServer())); await tools.getApps(); let miapass = ''; if (process.env.PROD !== 1) { testmsgwebpush(); // tools.sendNotifToAdmin('Riparti', 'Riparti'); if (miapass !== '') { let crypt = tools.cryptdata(miapass); let decrypt = tools.decryptdata(crypt); console.log('crypted:', crypt); console.log('decrypted:', decrypt); } mycron(); } miapass = 'PROVA123@'; let crypt = tools.cryptdata(miapass); let decrypt = tools.decryptdata(crypt); telegrambot = require('./telegram/telegrambot'); if (decrypt === miapass) { console.log('✅ Decrypt OK'); // OK FUNZIONA } else { let msgerr = '❌ ERRORE! la decrittazione non funziona! '; console.error(msgerr); await telegrambot.sendMsgTelegramToTheAdminAllSites(msgerr, false); } await inizia(); await resetProcessingJob(); populate.popolaTabelleNuove(); faitest(); // ----------------- MAILCHIMP ----- const querystring = require('querystring'); const mailchimpClientId = 'xxxxxxxxxxxxxxxx'; app.get('/mailchimp/auth/authorize', function (req, res) { res.redirect( 'https://login.mailchimp.com/oauth2/authorize?' + querystring.stringify({ response_type: 'code', client_id: mailchimpClientId, redirect_uri: 'http://127.0.0.1:3000/mailchimp/auth/callback', }) ); }); } // ----------------- function populateDBadmin() { const cfgserv = [ { _id: new ObjectId(), idapp: '9', chiave: 'vers', userId: 'ALL', valore: '0.1.2', }, ]; let cfg = new CfgServer(cfgserv[0]).save(); } async function mycron() { try { const sendemail = require('./sendemail'); const { Cron } = require('./models/cron'); const arr = await tools.getApps(); for (const app of arr) { await sendemail.checkifPendingNewsletter(app.idapp); await sendemail.checkifSentNewsletter(app.idapp); await Cron.startJobCron(app.idapp); } } catch (e) { console.error('Err mycron', e); } } async function mycron_30min() { for (const app of await tools.getApps()) { let enablecrontab = false; enablecrontab = await Settings.getValDbSettings(app.idapp, tools.ENABLE_CRONTAB, false); if (enablecrontab) { // ... } } } async function mycron_everyday() { try { const { User } = require('./models/user'); const arrapps = await tools.getApps(); for (const app of arrapps) { // Azzera le richieste di password: const usersblocked = await User.find({ idapp: app.idapp, retry_pwd: { $exists: true, $gte: 29 } }).lean(); for (const user of usersblocked) { await User.findOneAndUpdate({ _id: user._id }, { $set: { retry_pwd: 20 } }); let text = `⚠️⚠️⚠️ L\'utente ${user.username} (${user.name} ${user.surname}) viene sbloccato dal numero massimo di tentativi di richiesta password!\nTelerlo d\'occhio !\n@${user.profile.username_telegram}`; await telegrambot.sendMsgTelegramToTheAdminAllSites(text, false); } } } catch (e) { console.error('mycron_everyday: ', e); } } function testmsgwebpush() { const { User } = require('./models/user'); // console.log('nomeapp 1: ' , tools.getNomeAppByIdApp(1)); // console.log('nomeapp 2: ' , tools.getNomeAppByIdApp(2)); User.find({ username: 'paoloar77', idapp: '1' }).then(async (arrusers) => { if (arrusers !== null) { for (const user of arrusers) { await tools .sendNotificationToUser(user._id, 'Server', 'Il Server è Ripartito', '/', '', 'server', []) .then((ris) => { if (ris) { } else { // already sent the error on calling sendNotificationToUser } }); } } }); } // Esecuzione ogni 1 minuto (*/1 * * * *) // La sintassi di cron è: // 0 12 * * * comando // che significa: esegui il comando ogni giorno alle 12:00 // La sintassi di node-cron è: // cron.schedule('0 12 * * *', () => { // che significa: esegui il comando ogni giorno alle 12:00 // La sintassi di node-cron con */1 esegue il comando ogni 1 minuto cron.schedule('*/1 * * * *', () => { // console.log('Running Cron Job'); // if (!process.env.VITE_DEBUG) { mycron(); // } }); // Cron every 1 HOUR cron.schedule('*/60 * * * *', async () => { if (!process.env.VITE_DEBUG) { mycron_30min(); } }); // Cron every 21:00 (1 volta al giorno) cron.schedule('0 21 * * *', async () => { mycron_everyday(); }); // mycron_30min(); // tools.writelogfile('test', 'prova.txt'); async function resetProcessingJob() { const { Newstosent } = require('./models/newstosent'); arrrec = await Newstosent.find({}); for (const rec of arrrec) { rec.processing_job = false; await Newstosent.findOneAndUpdate({ _id: rec.id }, { $set: rec }, { new: false }).then((item) => {}); } } //app.listen(port, () => { // console.log(`Server started at port ${port}`); //}); async function inizia() { try { if (true) { const url = 'https://raw.githubusercontent.com/matteocontrini/comuni-json/master/comuni.json'; const outputPath = './comuni_italia_geojson.json'; downloadGeoJSON(url, outputPath); } mycron_everyday(); if (process.env.NODE_ENV === 'development') { await telegrambot.sendMsgTelegram( tools.FREEPLANET, shared_consts.ADMIN_USER_SERVER, `Ciao ${telegrambot.ADMIN_USER_NAME_SERVER}!` ); await telegrambot.sendMsgTelegramByIdTelegram( tools.FREEPLANET, telegrambot.ADMIN_IDTELEGRAM_SERVER, `Ciao ${telegrambot.ADMIN_USER_NAME_SERVER}\n` + `🔅 Il Server ${process.env.DATABASE} è appena ripartito!` ); } else { await telegrambot.sendMsgTelegramToTheAdminAllSites( `Ciao Admin\n` + `🔅🔅🔅 Il Server col BOT di {appname} è appena ripartito!`, false ); } await Site.createFirstUserAdmin(); /*const {Circuit} = require('./models/circuit'); await Circuit.setDeperimentoOff(); */ } catch (e) {} } // // telegrambot.sendMsgTelegramToTheManagers('7', 'PROVAAA!'); // if (process.env.PROD !== 1) { // const reg = require('./reg/registration'); // const link = reg.getlinkregByEmail('7', 'tomasihelen@dasdasgmail.comAAAA' , 'HelenTomasidasdasd'); // const link2 = reg.getlinkregByEmail('7', 'tomasihelen@gmail.com' , 'HelenTomasi'); // //const link2 = reg.getlinkregByEmail('7', 'elenaliubicich@gmail.com' , 'Elenaliu'); // // console.log(link); // console.log(link2); // } async function estraiImmagini(table) { const { User } = require('./models/user'); let idapp = '13'; let arrlist; const globalTables = require('./tools/globalTables'); const mytable = globalTables.getTableByTableName(table); if (!mytable) return; console.log('INIZIO - estraiImmagini', table); arrlist = await mytable.find({ idapp }).lean(); let file = ''; let filetocheck = ''; let dirmain = ''; let filefrom = ''; let filefrom2 = ''; try { if (!tools.sulServer()) { dirmain = server_constants.DIR_PUBLIC_LOCALE; } let dir = tools.getdirByIdApp(idapp) + dirmain + '/upload/'; for (const rec of arrlist) { const myuser = await User.findOne({ idapp, _id: rec.userId }).lean(); if (myuser) { const myphotos = rec.photos; if (myphotos.length > 0) { let folderprof = dir + 'profile/' + myuser.username; try { // console.log('checkdir', folderprof); if (!(await tools.isFileExistsAsync(folderprof))) { console.log('*** Creadir', folderprof); await fs.mkdirSync(folderprof); } folderprof = dir + 'profile/' + myuser.username + '/' + table; // console.log('checkdir', folderprof); if (!(await tools.isFileExistsAsync(folderprof))) { console.log('creadir', folderprof); await fs.mkdirSync(folderprof); } } catch (e) {} } for (const photo of myphotos) { if (photo.imagefile) { file = dir + 'profile/' + myuser.username + '/' + table + '/' + photo.imagefile; filefrom = dir + 'profile/undefined/' + table + '/' + photo.imagefile; filefrom2 = dir + 'profile/' + myuser.username + '/' + photo.imagefile; // console.log('file', file); // console.log('filefrom', filefrom); if (!(await tools.isFileExistsAsync(file))) { // non esiste console.log('non esiste', file); console.log(' filefrom', filefrom); console.log(' filefrom2', filefrom2); } if (!(await tools.isFileExistsAsync(file)) && (await tools.isFileExistsAsync(filefrom))) { console.log('@@@@@@ copia file:', filefrom, 'a', file); tools.copy(filefrom, file); } if (!(await tools.isFileExistsAsync(file)) && (await tools.isFileExistsAsync(filefrom2))) { console.log('@@@@@@ copia file 2:', filefrom2, 'a', file); tools.copy(filefrom2, file); } } } } } console.log('FINE - estraiImmagini', table); } catch (e) { console.error('e', e); } } async function estraiTutteLeImmagini() { await estraiImmagini('myskills'); await estraiImmagini('mygoods'); await estraiImmagini('mybachecas'); } async function faitest() { // console.log('Fai Test:') const testfind = false; // const $vers = tools.getVersionint('1.92.45'); if (true) { // tools.execScript("ls -la"); } if (false) { prova = tools.removeAtChar('@prova'); } if (false) { const prova = tools.getConfSiteOptionEnabledByIdApp('13', shared_consts.ConfSite.Notif_Reg_Push_Admin); console.log('prova', prova); } if (testfind) { const { City } = require('./models/city'); let miacity = 'roma'; const ris = await City.findByCity(miacity); console.log('ris', ris); } const { User } = require('./models/user'); if (false) { let myuser = await User.findOne({ idapp: '1', username: 'paoloar77', }); const langdest = 'it'; telegrambot.askConfirmationUser(myuser.idapp, shared_consts.CallFunz.REGISTRATION, myuser); } if (false) { const user = await User.findOne({ idapp: 12, username: 'paolotest1', }); await sendemail.sendEmail_Registration('it', 'paolo@arcodiluce.it', user, '12', ''); } if (false) { const { User } = require('./models/user'); const idapp = tools.FREEPLANET; const idreg = 0; try { const user = await User.findOne({ idapp, username: 'paoloar773', }); user.aportador_solidario = 'paoloar77'; let mylocalsconf = { idapp, dataemail: null, locale: user.lang, nomeapp: tools.getNomeAppByIdApp(idapp), strlinksito: tools.getHostByIdApp(idapp), strlinkreg: '', username: user.username, name: user.name, surname: user.surname, forgetpwd: tools.getHostByIdApp(idapp) + '/requestresetpwd', emailto: '', user, }; await telegrambot.notifyToTelegram(telegrambot.phase.REGISTRATION, mylocalsconf); } catch (e) { console.log('error ' + e); } } } // Funzione migliorata per ottenere chiave e certificato async function getCredentials(hostname) { try { let keyPath, certPath; if (NUOVO_METODO_TEST) { if (METODO_MULTI_CORS) { // Percorso basato su hostname (Let's Encrypt) keyPath = `/etc/letsencrypt/live/${hostname}/${process.env.PATH_CERT_KEY}`; certPath = `/etc/letsencrypt/live/${hostname}/${process.env.PATH_SERVER_CRT}`; } else { // Percorso relativo keyPath = path.resolve(`./${process.env.PATH_CERT_KEY}`); certPath = path.resolve(`./${process.env.PATH_SERVER_CRT}`); } // Verifica esistenza file if (!(await tools.isFileExistsAsync(keyPath))) { throw new Error(`Chiave privata non trovata: ${keyPath}`); } if (!(await tools.isFileExistsAsync(certPath))) { throw new Error(`Certificato non trovato: ${certPath}`); } // Leggi chiave e certificato const key = fs.readFileSync(keyPath, 'utf8'); const cert = fs.readFileSync(certPath, 'utf8'); // Restituisci oggetto con credenziali + configurazione TLS avanzata return { key, cert, ciphers: 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384', honorCipherOrder: true, secureOptions: require('constants').OPENSSL_OPTIONS_TLS_NODELAY, secureProtocol: 'TLSv1_2_method', // Forza TLS 1.2+ (meglio se usi TLSv1_3) }; } else { // Metodo legacy (opzionale) throw new Error('Metodo legacy non supportato'); } } catch (error) { console.error(`[getCredentials] Errore per ${hostname}:`, error.message); throw error; } } // 🔧 Funzione factory per creare e configurare un server HTTPS function createHttpsServer({ hostname, port, website, app, credentials, timeoutMinutes = 5 }) { const server = https.createServer(credentials, app); const timeoutMs = 1000 * 60 * timeoutMinutes; // ⏱️ Timeout globale per la connessione TCP server.setTimeout(timeoutMs, () => { console.log(`TCP timeout su server: ${hostname}:${port}`); }); // ⏱️ Timeout per singola richiesta HTTP server.on('request', (req, res) => { req.setTimeout(timeoutMs); res.setTimeout(timeoutMs); }); // 📡 Eventuali altri eventi utili server.on('clientError', (err, socket) => { console.error(`Client error su ${hostname}:${port}:`, err.message); }); // Avvia il server server.listen(port, () => { console.log( '⭐️⭐️⭐️⭐️⭐️ HTTPS server: %s Port: %d%s', hostname, port, website ? ' WebSite = ' + website : '' ); }); return server; } function parseDomains() { let domains = []; let domainsAllowed = []; try { if (process.env.DOMAINS) domains = JSON.parse(process.env.DOMAINS); if (process.env.DOMAINS_ALLOWED) domainsAllowed = JSON.parse(process.env.DOMAINS_ALLOWED); } catch (error) { console.error('Errore parsing DOMAINS:', error); } return { domains, domainsAllowed }; } function buildAllowedOrigins(domains, domainsAllowed, isProduction) { if (!isProduction) { return [ 'https://localhost:3000', 'https://localhost:8089', 'https://localhost:8082', 'https://localhost:8083', 'https://localhost:8084', 'https://localhost:8085', 'https://localhost:8088', 'https://localhost:8099', ]; } const baseOrigins = domains.flatMap((domain) => [ `https://${domain.hostname}`, `https://api.${domain.hostname}`, `https://test.${domain.hostname}`, `https://testapi.${domain.hostname}`, `http://${domain.hostname}`, `http://api.${domain.hostname}`, `http://test.${domain.hostname}`, `http://testapi.${domain.hostname}`, ]); const allowedExtra = domainsAllowed.flatMap((domain) => [`https://${domain}`, `http://${domain}`]); return [...baseOrigins, ...allowedExtra]; } function createCorsOptions(domains, domainsAllowed, isProduction, noCors = false) { if (noCors) { console.log('NOCORS mode enabled'); return { exposedHeaders: ['x-auth', 'x-refrtok'], }; } const allowedOrigins = buildAllowedOrigins(domains, domainsAllowed, isProduction); const originValidator = (origin, callback) => { if (!origin) { // console.log('✅ Origin undefined or empty — allowing'); return callback(null, true); } if (typeof origin !== 'string' || !/^https?:\/\/[^\s/$.?#].[^\s]*$/.test(origin)) { console.error('❌ Invalid origin:', origin); return callback(new Error('Origine non valida'), false); } if (allowedOrigins.includes(origin)) { return callback(null, true); } console.warn('❌ Origin blocked:', origin); return callback(new Error('CORS non permesso per questa origine'), false); }; return { origin: originValidator, credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'], allowedHeaders: [ 'Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization', 'x-auth', 'x-refrtok', ], exposedHeaders: ['x-auth', 'x-refrtok'], maxAge: 86400, preflightContinue: false, optionsSuccessStatus: 204, }; } function setupMiddleware(app, corsOptions, isDebug = false) { app.use(helmet()); app.use(cors(corsOptions)); app.set('trust proxy', true); app.use(express.json()); app.use(morgan('dev')); app.use(rateLimit); app.get('/health', (_req, res) => res.json({ ok: true })); app.use('/apinew', apiRouter); // app.use(notFound); app.use(errorHandler); app.options('*', cors(corsOptions)); if (isDebug) { app.use((req, res, next) => { console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`); console.log('Request Headers:', req.headers); const oldSend = res.send; res.send = function (...args) { console.log('Response Headers:', res.getHeaders()); return oldSend.apply(res, args); }; next(); }); } app.use((err, req, res, next) => { if (err.message === 'CORS non permesso per questa origine') { console.error('❌ Errore CORS:', { origin: req.headers.origin, method: req.method, path: req.path, }); return res.status(403).json({ error: `❌ CORS non permesso per questa origine (${req.headers.origin})`, origin: req.headers.origin, }); } next(err); }); } async function createHttpOrHttpsServer(app, port, isProduction, domains) { if (isProduction) { const promises = domains.map(async (domain) => { const credentials = await getCredentials(domain.hostname); return createHttpsServer({ hostname: domain.hostname, port: domain.port, website: domain.website, app, credentials, timeoutMinutes: 6, }); }); await Promise.all(promises); return null; } if (process.env.HTTPS_LOCALHOST === 'true') { try { const key = fs.readFileSync(path.resolve(`./${process.env.PATH_CERT_KEY}`), 'utf8'); const cert = fs.readFileSync(path.resolve(`./${process.env.PATH_SERVER_CRT}`), 'utf8'); const credentials = { key, cert, 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', }; const httpsServer = https.createServer(credentials, app); httpsServer.listen(port); console.log('⭐️ HTTPS server running locally on port', port); return httpsServer; } catch (error) { console.error('Errore caricamento certificati HTTPS locali:', error.message); // fallback HTTP server } } const httpServer = http.createServer(app); httpServer.listen(port); console.log('⭐️ HTTP server running on port', port); return httpServer; } function setupWebSocketServer(httpOrHttpsServer) { if (!httpOrHttpsServer) { console.error('Nessun server HTTP o HTTPS disponibile per WebSocket'); return null; } const wss = new WebSocket.Server({ server: httpOrHttpsServer }); wss.on('connection', (ws) => { console.log('Client socket connected...'); const { User } = require('./models/user'); const pty = require('node-pty'); let scriptProcess = null; ws.on('message', async (message) => { try { const parsed = JSON.parse(message); if (parsed.type === 'start_script' && User.isAdminById(parsed.user_id)) { if (scriptProcess) scriptProcess.kill(); const scriptPath = path.join(__dirname, '..', '..', parsed.scriptName); if (!(await tools.isFileExistsAsync(scriptPath))) { return ws.send(JSON.stringify({ type: 'error', data: 'Script non trovato o non autorizzato' })); } scriptProcess = pty.spawn('bash', [scriptPath], { name: 'xterm-color', cols: 80, rows: 40, cwd: process.cwd(), env: process.env, }); let buffer = ''; scriptProcess.on('data', (data) => { buffer += data; ws.send(JSON.stringify({ type: 'output', data })); if ( buffer.endsWith(': ') || buffer.includes('? ') || buffer.toLowerCase().includes('password') || buffer.includes('Inserisci') || buffer.includes('Inserted') || buffer.includes('(Y)') ) { ws.send(JSON.stringify({ type: 'input_required', prompt: data.trim() })); buffer = ''; } if (buffer.length > 5024) buffer = buffer.slice(-500); }); scriptProcess.on('exit', (code) => { const closeMsg = code === 0 ? '*** FINE SCRIPT ***' : `Script terminato con codice ${code}`; ws.send(JSON.stringify({ type: 'close', data: closeMsg })); }); } else if (parsed.type === 'input') { if (scriptProcess) { scriptProcess.write(parsed.data + '\n'); } } } catch (err) { console.error("Errore durante l'elaborazione del messaggio:", err.message); } }); ws.on('close', () => { console.log('*** Client socket disconnected'); if (scriptProcess) scriptProcess.kill(); }); }); return wss; } async function startServer(app, port) { try { const isProduction = ['production', 'test'].includes(process.env.NODE_ENV); const ISDEBUG = false; const NOCORS = false; const { domains, domainsAllowed } = parseDomains(); console.log('domains:', domains); console.log('isProduction:', isProduction); const corsOptions = createCorsOptions(domains, domainsAllowed, isProduction, NOCORS); setupMiddleware(app, corsOptions, ISDEBUG); const server = await createHttpOrHttpsServer(app, port, isProduction, domains); const wss = setupWebSocketServer(server); return { server, wss }; } catch (error) { console.error('Errore in startServer:', error); } } }) .catch((err) => { console.error('Impossibile connettersi al database dopo diversi tentativi:', err); process.exit(1); // Termina il processo se non riesce a connettersi }); function add_numbers(a, b) {} module.exports = { app };