diff --git a/emails/newsletter/it/html.pug b/emails/newsletter/it/html.pug index 8001717..36793d4 100644 --- a/emails/newsletter/it/html.pug +++ b/emails/newsletter/it/html.pug @@ -54,7 +54,7 @@ html tr td.testomail - p!= dataemail.templ.testoheadermail + p!= dataemail.templ.testoheadermail_out - if (dataemail.templ.options.includes('SHOW_PROMO')) tr diff --git a/package.json b/package.json index 2079eb0..0f96736 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "test-watch": "nodemon --exec 'npm test'" }, "engines": { - "node": "8.9.0" + "node": "^8.9.0" }, "author": "Paolo Arena", "license": "MIT", diff --git a/src/server/config/config.js b/src/server/config/config.js index 1103205..37837b7 100644 --- a/src/server/config/config.js +++ b/src/server/config/config.js @@ -26,6 +26,7 @@ if (process.env.NODE_ENV === 'production') { replyTo: 'paolo.arena77@gmail.com', host: 'https://freeplanet.app', portapp: '0', + dir: '/var/www/www.freeplanet.app', }, { idapp: '2', @@ -35,6 +36,7 @@ if (process.env.NODE_ENV === 'production') { replyTo: 'info@associazioneshen.it', host: 'http://associazioneshen.it', portapp: '0', + dir: '/var/www/associazioneshen.it', }, { idapp: '3', @@ -44,16 +46,28 @@ if (process.env.NODE_ENV === 'production') { replyTo: '', host: 'http://brigittemgdumont.com', portapp: '0', + dir: '', }, { idapp: '4', + name: 'Mandala Solidale', + adminemail: 'pao.loarena77@gmail.com', + manageremail: '', + replyTo: '', + host: 'https://mandala.freeplanet.app', + portapp: '0', + dir: '/var/www/mandala.freeplanet.app', + }, + { + idapp: '6', name: 'Mandala per l\'Anima', adminemail: '', manageremail: '', replyTo: '', host: 'http://mandalaperlanima.eu', portapp: '0', - } + dir: '', + }, ]; } else if (process.env.NODE_ENV === 'test') { MYAPPS = [ @@ -65,6 +79,7 @@ if (process.env.NODE_ENV === 'production') { replyTo: 'paolo.arena77@gmail.com', host: 'https://test.freeplanet.app', portapp: '0', + dir: '/var/www/www.freeplanet.app', }, { idapp: '2', @@ -74,22 +89,34 @@ if (process.env.NODE_ENV === 'production') { replyTo: 'info@associazioneshen.it', host: 'http://test.associazioneshen.it', portapp: '0', + dir: '/var/www/associazioneshen.it', }, { idapp: '3', name: 'Brigitte MG Dumont', - adminemail: '', + adminemail: 'pao.loarena77@gmail.com', manageremail: '', host: 'http://test.brigittemgdumont.com', portapp: '0', + dir: '', }, { idapp: '4', + name: 'Mandala Solidale', + adminemail: '', + manageremail: '', + host: 'https://mandala.freeplanet.app', + portapp: '0', + dir: '/var/www/mandalatest.freeplanet.app', + }, + { + idapp: '6', name: 'Mandala per l\'Anima', adminemail: '', manageremail: '', host: 'http://test.mandalaperlanima.eu', portapp: '0', + dir: '', } ]; } else { @@ -102,6 +129,7 @@ if (process.env.NODE_ENV === 'production') { replyTo: 'paolo.arena77@gmail.com', host: 'http://localhost', portapp: '8080', + dir: '/home/paolo/myproject/freeplanet/dist/spa', }, { idapp: '2', @@ -111,6 +139,7 @@ if (process.env.NODE_ENV === 'production') { replyTo: 'info@associazioneshen.it', host: 'http://localhost', portapp: '8081', + dir: '/home/paolo/myproject/associazioneShen/dist/spa', }, { idapp: '3', @@ -119,15 +148,26 @@ if (process.env.NODE_ENV === 'production') { manageremail: '', host: 'http://localhost', portapp: '8082', + dir: '', }, { idapp: '4', + name: 'Mandala Solidale', + adminemail: 'paolo.arena77@gmail.com', + manageremail: '', + host: 'http://localhost', + portapp: '8084', + dir: '', + }, + { + idapp: '6', name: 'Mandala per l\'Anima', adminemail: 'paolo.arena77@gmail.com', manageremail: '', host: 'http://localhost', portapp: '8083', - } + dir: '', + }, ]; } diff --git a/src/server/models/gallery.js b/src/server/models/gallery.js new file mode 100644 index 0000000..89310cf --- /dev/null +++ b/src/server/models/gallery.js @@ -0,0 +1,67 @@ +const mongoose = require('mongoose'); +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 GallerySchema = new Schema({ + idapp: { + type: String, + }, + author_username: { + type: String, + }, + title: { + type: String, + }, + directory: { + type: String, + }, + list: [ + { + imagefile: { + type: String + }, + order: { + type: Number + }, + alt: { + type: String + }, + description: { + type: String + } + } + ] +}); + +GallerySchema.statics.getFieldsForSearch = function () { + return ['title'] +}; + +GallerySchema.statics.executeQueryTable = function (idapp, params) { + params.fieldsearch = this.getFieldsForSearch(); + return tools.executeQueryTable(this, idapp, params); +}; + +GallerySchema.statics.findAllIdApp = async function (idapp) { + const Gallery = this; + + const myfind = { idapp }; + + return await Gallery.find(myfind, (err, arrrec) => { + return arrrec + }); +}; + +const Gallery = mongoose.model('Gallery', GallerySchema); + +module.exports = { Gallery }; diff --git a/src/server/models/mailinglist.js b/src/server/models/mailinglist.js index f68a2f5..406ca67 100644 --- a/src/server/models/mailinglist.js +++ b/src/server/models/mailinglist.js @@ -35,6 +35,10 @@ const MailingListSchema = new Schema({ type: Boolean, default: true }, + wrongerr: { + type: Boolean, + default: false + }, lastid_newstosent: { type: String } @@ -52,7 +56,7 @@ MailingListSchema.statics.executeQueryTable = function (idapp, params) { MailingListSchema.statics.findAllIdAppSubscribed = function (idapp) { const MailingList = this; - const myfind = { idapp, statesub: true }; + const myfind = { idapp, statesub: true, wrongerr: {$ne: true} }; // Extract only the Teacher where in the users table the field permissions is set 'Teacher' bit. @@ -61,6 +65,26 @@ MailingListSchema.statics.findAllIdAppSubscribed = function (idapp) { }); }; +MailingListSchema.statics.getnumSent = async function (idapp, idmailinglist) { + const MailingList = this; + + const myfind = { idapp, statesub: true, lastid_newstosent: idmailinglist }; + + // Extract only the Teacher where in the users table the field permissions is set 'Teacher' bit. + + return await MailingList.find(myfind).count(); +}; + +MailingListSchema.statics.isOk = async function (idapp, iduser, idmailinglist) { + const MailingList = this; + + const myfind = { idapp, _id: iduser, statesub: true, lastid_newstosent: {$ne: idmailinglist } }; + + // Extract only the Teacher where in the users table the field permissions is set 'Teacher' bit. + + return await MailingList.find(myfind).count() > 0; +}; + MailingListSchema.statics.findAllIdApp = async function (idapp) { const MailingList = this; diff --git a/src/server/models/newstosent.js b/src/server/models/newstosent.js index 3cad63b..787ba1c 100644 --- a/src/server/models/newstosent.js +++ b/src/server/models/newstosent.js @@ -54,6 +54,10 @@ const NewstosentSchema = new Schema({ type: Boolean, default: false }, + processing_job: { + type: Boolean, + default: false + }, error_job: { type: String, } @@ -76,6 +80,7 @@ NewstosentSchema.statics.findNewsletter_To_Send = function (idapp) { datetoSent: { $gte: tools.IncDateNow(-1000 * 60 * 60) }, activate: true, starting_job: false, + processing_job: false, finish_job: false, idapp }) @@ -85,6 +90,29 @@ NewstosentSchema.statics.findNewsletter_To_Send = function (idapp) { }); }; +NewstosentSchema.statics.endJob = async function (id) { + const Newstosent = this; + + myjobnews = await Newstosent.findOne({ _id: id }); + if (!!myjobnews) { + myjobnews.datefinishJob = new Date(); + myjobnews.finish_job = true; + + await myjobnews.save() + } +}; + +NewstosentSchema.statics.processingJob = async function (id, state) { + const Newstosent = this; + + myjobnews = await Newstosent.findOne({ _id: id }); + if (!!myjobnews) { + myjobnews.processing_job = state; + + await myjobnews.save() + } +}; + NewstosentSchema.statics.findNewsletterPending_To_Send = function (idapp) { const Newstosent = this; @@ -94,6 +122,7 @@ NewstosentSchema.statics.findNewsletterPending_To_Send = function (idapp) { activate: true, starting_job: true, finish_job: false, + processing_job: false, lastemailsent_Job: { $gte: tools.IncDateNow(-1000 * 60 * 60 * 8) }, idapp }).then((rec) => { diff --git a/src/server/router/index_router.js b/src/server/router/index_router.js index ab4c8a5..f3da099 100644 --- a/src/server/router/index_router.js +++ b/src/server/router/index_router.js @@ -13,7 +13,7 @@ const cfgserver = mongoose.model('cfgserver'); const ftp = require('../ftp/FTPClient'), formidable = require('formidable'), - folder = path.join(__dirname, 'files'); + folder = path.join(__dirname, 'upload'); if (!fs.existsSync(folder)) { fs.mkdirSync(folder) @@ -30,6 +30,7 @@ const { Contribtype } = require('../models/contribtype'); const { Discipline } = require('../models/discipline'); const { Newstosent } = require('../models/newstosent'); const { MyPage } = require('../models/mypage'); +const { Gallery } = require('../models/gallery'); const { TemplEmail } = require('../models/templemail'); const { OpzEmail } = require('../models/opzemail'); const { MailingList } = require('../models/mailinglist'); @@ -164,6 +165,8 @@ function getTableByTableName(tablename) { mytable = Discipline; else if (tablename === 'newstosent') mytable = Newstosent; + else if (tablename === 'gallery') + mytable = Gallery; else if (tablename === 'mypage') mytable = MyPage; else if (tablename === 'templemail') @@ -377,11 +380,12 @@ router.get('/loadsite/:userId/:idapp/:sall', authenticate_noerror, (req, res) => let newstosent = Promise.resolve([]); let mailinglist = Promise.resolve([]); let mypage = MyPage.findAllIdApp(idapp); + let gallery = Gallery.findAllIdApp(idapp); if (sall) { newstosent = Newstosent.findAllIdApp(idapp); } - return Promise.all([bookedevent, eventlist, operators, wheres, contribtype, settings, permissions, disciplines, newstosent, mailinglist, mypage]) + return Promise.all([bookedevent, eventlist, operators, wheres, contribtype, settings, permissions, disciplines, newstosent, mailinglist, mypage, gallery]) .then((arrdata) => { // console.table(arrdata); res.send({ @@ -396,6 +400,7 @@ router.get('/loadsite/:userId/:idapp/:sall', authenticate_noerror, (req, res) => newstosent: arrdata[8], mailinglist: arrdata[9], mypage: arrdata[10], + gallery: arrdata[11], }); }) .catch((e) => { @@ -453,10 +458,11 @@ router.get(process.env.LINK_CHECK_UPDATES, authenticate, (req, res) => { }); -router.post('/upload/:dir', authenticate, (req, res) => { +router.post('/upload_from_other_server/:dir', authenticate, (req, res) => { const dir = req.params.dir; const idapp = req.user.idapp; +/* const form = new formidable.IncomingForm(); form.parse(req); @@ -467,7 +473,7 @@ router.post('/upload/:dir', authenticate, (req, res) => { // console.log('client', client); - form.uploadDir = folder; + form.uploadDir = folder + '/' + dir; try { form.on('fileBegin', async function (name, file){ @@ -487,8 +493,66 @@ router.post('/upload/:dir', authenticate, (req, res) => { console.log('Uploaded ' + file.name, 'status:', ret); if (!ret) res.status(400).send(); - else + else { + // Delete file from local directory + fs.unlinkSync(file.path); res.end(); + } + }catch (e) { + console.log('error', e); + res.status(400).send(); + } + }); + + form.on('aborted', () => { + console.error('Request aborted by the user'); + res.status(400).send(); + }); + + form.on('error', (err) => { + console.error('Error Uploading', err); + res.status(400).send(); + }); + + } catch (e) { + console.log('Error', e) + } +*/ + + +}); + + + +router.post('/upload/:dir', authenticate, (req, res) => { + const dir = req.params.dir; + const idapp = req.user.idapp; + + const form = new formidable.IncomingForm(); + + form.parse(req); + + form.uploadDir = folder + '/' + dir; + try { + + form.on('fileBegin', async function (name, file){ + file.path = folder + '/' + file.name; + }); + + form.on('file', async function (name, file){ + try { + console.log('Uploaded ' + file.name); + // ++ Move in the folder application ! + newname = tools.getdirByIdApp(idapp) + '/statics/upload/' + dir + '/' + file.name; + + // For local: ... resolve this... sending through the static folder... + // res.sendFile(path.resolve(file.name)); + + tools.move(file.path, newname, (err) => { + console.log('err', err); + res.end(); + }); + }catch (e) { console.log('error', e); res.status(400).send(); @@ -509,7 +573,6 @@ router.post('/upload/:dir', authenticate, (req, res) => { console.log('Error', e) } - }); diff --git a/src/server/router/newsletter_router.js b/src/server/router/newsletter_router.js index 940ff2d..4de892a 100644 --- a/src/server/router/newsletter_router.js +++ b/src/server/router/newsletter_router.js @@ -46,6 +46,12 @@ const newsletter = [ mailchimpInstance: '', listUniqueId: '', mailchimpApiKey: '' + }, + { + name: 'MandalaSolidale', + mailchimpInstance: '', + listUniqueId: '', + mailchimpApiKey: '' } ]; diff --git a/src/server/router/users_router.js b/src/server/router/users_router.js index 2709ca2..00e2875 100644 --- a/src/server/router/users_router.js +++ b/src/server/router/users_router.js @@ -42,6 +42,7 @@ router.post('/', (req, res) => { user.verified_email = false; user.ipaddr = reg.getiPAddressUser(req); user.lasttimeonline = new Date(); + // user.perm = 3; if (tools.testing()) { user.verified_email = true; } diff --git a/src/server/sendemail.js b/src/server/sendemail.js index e5286da..fa8d335 100644 --- a/src/server/sendemail.js +++ b/src/server/sendemail.js @@ -86,7 +86,7 @@ module.exports = { return !!ris }) .catch((err) => { - console.error(err); + console.error('Error: ', err); return false }); }, @@ -298,7 +298,7 @@ module.exports = { // Check if exist to the Mailing List let myperson = await MailingList.findByHash(idapp, hash); - if (!myperson || !myperson.statesub) { + if (!myperson || !myperson.statesub || !myperson.wrongerr) { if (!myperson) { myperson = new MailingList({ name: mylocalsconf.name, @@ -316,6 +316,7 @@ module.exports = { myperson.idapp = idapp; myperson.statesub = true; // subscription + myperson.wrongerr = false; // Add/save new record to the DB MailingList const res = await myperson.save(); @@ -374,7 +375,7 @@ module.exports = { }, - fieldsloop: function (myvar) { + fieldsloop: function (mylocalsconf, myvar) { const baseurl = tools.getHostByIdApp(mylocalsconf.idapp); const urlunsibscribe = baseurl + '/unsubscribe?em=' + mylocalsconf.hashemail + '&mc=' + mylocalsconf.dataemail.mailchimpactive + '&email=' + mylocalsconf.emailto; @@ -388,14 +389,15 @@ module.exports = { replacefields: function (mylocalsconf) { - mylocalsconf.dataemail.disclaimer_out = this.fieldsloop(mylocalsconf.dataemail.disclaimer); - mylocalsconf.dataemail.disc_bottom_out = this.fieldsloop(mylocalsconf.dataemail.disc_bottom); - mylocalsconf.dataemail.templ.testoheadermail = this.fieldsloop(mylocalsconf.dataemail.templ.testoheadermail); + mylocalsconf.dataemail.disclaimer_out = this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.disclaimer); + mylocalsconf.dataemail.disc_bottom_out = this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.disc_bottom); + mylocalsconf.dataemail.templ.testoheadermail_out = this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.templ.testoheadermail); + return mylocalsconf }, getdataemail: async (idapp) => { - console.log('getdataemail'); + // console.log('getdataemail'); const mydata = { content_after_events: await Settings.getValDbSettings(idapp, 'TEXT_AFTER_EV'), mailchimpactive: tools.BoolToInt(await Settings.getValDbSettings(idapp, 'MAILCHIMP_ON')), @@ -435,8 +437,8 @@ module.exports = { host: mylocalsconf.dataemail.email_service, port: mylocalsconf.dataemail.email_port, auth: { - user: process.env.EMAIL_FROM, - pass: process.env.EMAIL_PW + user: mylocalsconf.dataemail.from, + pass: mylocalsconf.dataemail.pwd_from } }); } else if (mylocalsconf.dataemail.email_service === 'gmail') { @@ -478,73 +480,79 @@ module.exports = { dataemail: await this.getdataemail(idapp) }; + await Newstosent.processingJob(id_newstosent, true); const mynewsrec = await Newstosent.findOne({ _id: id_newstosent }); mynewsrec.numemail_tot = userstosend.length; mynewsrec.templemail_str = mylocalsconf.dataemail.templ.subject; + mynewsrec.numemail_sent = await MailingList.getnumSent(idapp, id_newstosent); const smtpTransport = this.getTransport(); - let secpause = await Settings.getValDbSettings(idapp, 'MSEC_PAUSE_SEND', process.env.DELAY_SENDEMAIL); - if (secpause > process.env.DELAY_SENDEMAIL) - secpause = process.env.DELAY_SENDEMAIL; - // LOOP USERS EMAIL for (const user of userstosend) { - if (process.env.DEBUG) - await tools.snooze(30000); + const isok = await MailingList.isOk(idapp, user._id, id_newstosent); + if (isok) { + let secpause = await Settings.getValDbSettings(idapp, 'MSEC_PAUSE_SEND', process.env.DELAY_SENDEMAIL); + if (secpause > process.env.DELAY_SENDEMAIL) + secpause = process.env.DELAY_SENDEMAIL; - activate = await Newstosent.isActivated(id_newstosent); + activate = await Newstosent.isActivated(id_newstosent); - if (!activate) { - // Invio Newsletter Abortito! - mynewsrec.error_job = 'Invio Newsletter abortito alle ore ' + new Date().toDateString(); - await mynewsrec.save(); - console.log('*** L\'Invio della Newsletter è stato fermato ! '); - return false - } + if (!activate) { + // Invio Newsletter Abortito! + mynewsrec.error_job = 'Invio Newsletter abortito alle ore ' + new Date().toDateString() + new Date().toTimeString(); + await mynewsrec.save(); + await Newstosent.processingJob(id_newstosent, false); + console.log('*** L\'Invio della Newsletter è stato fermato ! '); + return false + } - mylocalsconf.name = user.name; - mylocalsconf.surname = user.surname; - mylocalsconf.emailto = user.email; - mylocalsconf.hashemail = tools.getHash(user.email); + mylocalsconf.name = user.name; + mylocalsconf.surname = user.surname; + mylocalsconf.emailto = user.email; + mylocalsconf.hashemail = tools.getHash(user.email); - await this.replacefields(mylocalsconf); - - // If has already sent, don't send it again! - if (user.lastid_newstosent !== id_newstosent.toString()) { - // Send Email to the User - console.log('-> Invio Email (', mynewsrec.numemail_sent, '/', mynewsrec.numemail_tot, ')'); - const esito = this.sendEmail_base('newsletter/' + lang, mylocalsconf.emailto, mylocalsconf, mylocalsconf.dataemail.email_reply, smtpTransport); - - //Put the result in the database, to check if is sent or not. - const updateml = await MailingList.findOneAndUpdate({ - idapp, - email: user.email - }, { $set: { lastid_newstosent: ObjectID(id_newstosent) } }, { new: false }); + mylocalsconf = this.replacefields(mylocalsconf); - //Delay for send email... - await tools.snooze(secpause); + // If has already sent, don't send it again! + if (user.lastid_newstosent !== id_newstosent.toString()) { + console.log('@@@@@ COMPARE DIVERSI: lastid', user.lastid_newstosent, 'idsent', id_newstosent.toString()); + + if (process.env.DEBUG) + await tools.snooze(5000); + + // Send Email to the User + console.log('-> Invio Email (', mynewsrec.numemail_sent, '/', mynewsrec.numemail_tot, ')'); + const esito = this.sendEmail_base('newsletter/' + lang, mylocalsconf.emailto, mylocalsconf, mylocalsconf.dataemail.email_reply, smtpTransport); + + //Put the result in the database, to check if is sent or not. + const updateml = await MailingList.findOneAndUpdate({ + idapp, + email: user.email + }, { $set: { lastid_newstosent: ObjectID(id_newstosent) } }, { new: false }); - mynewsrec.lastemailsent_Job = new Date(); - mynewsrec.numemail_sent += 1; + //Delay for send email... + await tools.snooze(secpause); - const recsaved = await mynewsrec.save(); + mynewsrec.lastemailsent_Job = new Date(); + mynewsrec.numemail_sent = await MailingList.getnumSent(idapp, id_newstosent); - if (mynewsrec.numemail_sent === mynewsrec.numemail_tot) { - mynewsrec.datefinishJob = new Date(); - mynewsrec.finish_job = true; - await mynewsrec.save().then((ris) => { - console.log('****', tools.getNomeAppByIdApp(idapp), mynewsrec.numemail_sent, 'Email inviate'); - }); + const recsaved = await mynewsrec.save(); + } else { + console.log('*** COMPARE: UGUALI !!!!! lastid', user.lastid_newstosent, 'idsent', id_newstosent.toString()); } } } + await Newstosent.endJob(id_newstosent); + await Newstosent.processingJob(id_newstosent, false); + console.log('****', tools.getNomeAppByIdApp(idapp), mynewsrec.numemail_sent, 'Email inviate'); + console.log('FINE (esco da funz) - sendEmail_Newsletter_Events', tools.getNomeAppByIdApp(idapp)); }, diff --git a/src/server/tools/general.js b/src/server/tools/general.js index e5bb37a..2554c91 100644 --- a/src/server/tools/general.js +++ b/src/server/tools/general.js @@ -1,5 +1,7 @@ var os = require("os"); +const fs = require('fs'); + require('../config/config'); require('../models/subscribers'); @@ -46,6 +48,7 @@ module.exports = { typeinrec: 128, multiselect: 256, password: 512, + listimages: 1024, }, MAX_PHASES: 5, @@ -356,6 +359,16 @@ module.exports = { return ''; }, + getdirByIdApp: function (idapp) { + + const myapp = + MYAPPS.find(item => item.idapp === idapp); + if (myapp) { + return myapp.dir; + } else + return ''; + }, + getAdminEmailByIdApp: function (idapp) { const myapp = MYAPPS.find((item) => item.idapp === idapp); if (myapp) @@ -518,6 +531,34 @@ module.exports = { StrToBool(mystr) { return (mystr === '-1') ? true : false - } + }, + move(oldPath, newPath, callback) { + + fs.rename(oldPath, newPath, function (err) { + if (err) { + if (err.code === 'EXDEV') { + copy(); + } else { + callback(err); + } + return; + } + callback(); + }); + + function copy() { + const readStream = fs.createReadStream(oldPath); + const writeStream = fs.createWriteStream(newPath); + + readStream.on('error', callback); + writeStream.on('error', callback); + + readStream.on('close', function () { + fs.unlink(oldPath, callback); + }); + + readStream.pipe(writeStream); + } + }, };