diff options
author | lowercasename <raphaelkabo@gmail.com> | 2020-06-13 13:36:28 +0100 |
---|---|---|
committer | lowercasename <raphaelkabo@gmail.com> | 2020-06-13 13:36:28 +0100 |
commit | b24c5910463453e14be965893cd2a50859a945dd (patch) | |
tree | 8f71651b25c2ab031f4beba40d78d6c1a874d62d /routes.js | |
parent | 030e2b3575a856c6fae65848b82626dde888a8c8 (diff) |
Added Nodemailer as an SMTP service
Diffstat (limited to 'routes.js')
-rwxr-xr-x | routes.js | 1461 |
1 files changed, 803 insertions, 658 deletions
@@ -29,6 +29,7 @@ const request = require('request'); const domain = require('./config/domain.js').domain; const contactEmail = require('./config/domain.js').email; +const mailService = require('./config/domain.js').mailService; const siteName = require('./config/domain.js').sitename; const siteLogo = require('./config/domain.js').logo_url; let isFederated = require('./config/domain.js').isFederated; @@ -41,7 +42,7 @@ const ap = require('./activitypub.js'); // Extra marked renderer (used to render plaintext event description for page metadata) // Adapted from https://dustinpfister.github.io/2017/11/19/nodejs-marked/ // ? to ? helper -function htmlEscapeToText (text) { +function htmlEscapeToText(text) { return text.replace(/\&\#[0-9]*;|&/g, function (escapeCode) { if (escapeCode.match(/amp/)) { return '&'; @@ -50,21 +51,21 @@ function htmlEscapeToText (text) { }); } -function render_plain () { +function render_plain() { var render = new marked.Renderer(); // render just the text of a link, strong, em render.link = function (href, title, text) { return text; }; - render.strong = function(text) { + render.strong = function (text) { return text; } - render.em = function(text) { + render.em = function (text) { return text; } // render just the text of a paragraph render.paragraph = function (text) { - return htmlEscapeToText(text)+'\r\n'; + return htmlEscapeToText(text) + '\r\n'; }; // render nothing for headings, images, and br render.heading = function (text, level) { @@ -87,46 +88,71 @@ const cal = icalGenerator({ }); const sgMail = require('@sendgrid/mail'); +const nodemailer = require("nodemailer"); const apiCredentials = require('./config/api.js'); let sendEmails = false; -if (apiCredentials.sendgrid) { // Only set up Sendgrid if an API key is set - sgMail.setApiKey(apiCredentials.sendgrid); - sendEmails = true; +let nodemailerTransporter; +if (mailService) { + switch (mailService) { + case 'sendgrid': + sgMail.setApiKey(apiCredentials.sendgrid); + console.log("Sendgrid is ready to send emails."); + sendEmails = true; + break; + case 'nodemailer': + nodemailerTransporter = nodemailer.createTransport({ + host: apiCredentials.smtpServer, + port: apiCredentials.smtpPort, + secure: false, // true for 465, false for other ports + auth: { + user: apiCredentials.smtpUsername, // generated ethereal user + pass: apiCredentials.smtpPassword, // generated ethereal password + }, + }); + nodemailerTransporter.verify((error, success) => { + if (error) { + console.log(error); + } else { + console.log("Nodemailer SMTP server is ready to send emails."); + sendEmails = true; + } + }); + break; + default: + console.error('You have not configured this Gathio instance to send emails! This means that event creators will not receive emails when their events are created, which means they may end up locked out of editing events. Consider setting up an email service.') + } } const fileUpload = require('express-fileupload'); var Jimp = require('jimp'); router.use(fileUpload()); - // SCHEDULED DELETION - const schedule = require('node-schedule'); - -const deleteOldEvents = schedule.scheduleJob('59 23 * * *', function(fireDate){ +schedule.scheduleJob('59 23 * * *', function (fireDate) { const too_old = moment.tz('Etc/UTC').subtract(7, 'days').toDate(); console.log("Old event deletion running! Deleting all events concluding before ", too_old); Event.find({ end: { $lte: too_old } }).then((oldEvents) => { oldEvents.forEach(event => { const deleteEventFromDB = (id) => { - Event.remove({"_id": id}) - .then(response => { - addToLog("deleteOldEvents", "success", "Old event "+id+" deleted"); - }).catch((err) => { - addToLog("deleteOldEvents", "error", "Attempt to delete old event "+id+" failed with error: " + err); - }); + Event.remove({ "_id": id }) + .then(response => { + addToLog("deleteOldEvents", "success", "Old event " + id + " deleted"); + }).catch((err) => { + addToLog("deleteOldEvents", "error", "Attempt to delete old event " + id + " failed with error: " + err); + }); } - if (event.image){ + if (event.image) { fs.unlink(global.appRoot + '/public/events/' + event.image, (err) => { if (err) { - addToLog("deleteOldEvents", "error", "Attempt to delete event image for old event "+event.id+" failed with error: " + err); + addToLog("deleteOldEvents", "error", "Attempt to delete event image for old event " + event.id + " failed with error: " + err); } // Image removed - addToLog("deleteOldEvents", "error", "Image deleted for old event "+event.id); + addToLog("deleteOldEvents", "error", "Image deleted for old event " + event.id); }) } // Check if event has ActivityPub fields @@ -136,8 +162,8 @@ const deleteOldEvents = schedule.scheduleJob('59 23 * * *', function(fireDate){ const jsonUpdateObject = JSON.parse(event.activityPubActor); const jsonEventObject = JSON.parse(event.activityPubEvent); // first broadcast AP messages, THEN delete from DB - ap.broadcastDeleteMessage(jsonUpdateObject, event.followers, event.id, function(statuses) { - ap.broadcastDeleteMessage(jsonEventObject, event.followers, event.id, function(statuses) { + ap.broadcastDeleteMessage(jsonUpdateObject, event.followers, event.id, function (statuses) { + ap.broadcastDeleteMessage(jsonEventObject, event.followers, event.id, function (statuses) { deleteEventFromDB(event._id); }); }); @@ -147,7 +173,7 @@ const deleteOldEvents = schedule.scheduleJob('59 23 * * *', function(fireDate){ } }) }).catch((err) => { - addToLog("deleteOldEvents", "error", "Attempt to delete old event "+event.id+" failed with error: " + err); + addToLog("deleteOldEvents", "error", "Attempt to delete old event " + event.id + " failed with error: " + err); }); }); @@ -189,19 +215,19 @@ router.get('/new/event/public', (req, res) => { let isPublic = true; let isOrganisation = false; let isUnknownType = false; -// let eventType = req.params.eventType; -// if (eventType == "private"){ -// isPrivate = true; -// } -// else if (eventType == "public"){ -// isPublic = true; -// } -// else if (eventType == "organisation"){ -// isOrganisation = true; -// } -// else { -// isUnknownType = true; -// } + // let eventType = req.params.eventType; + // if (eventType == "private"){ + // isPrivate = true; + // } + // else if (eventType == "public"){ + // isPublic = true; + // } + // else if (eventType == "organisation"){ + // isOrganisation = true; + // } + // else { + // isUnknownType = true; + // } res.render('newevent', { title: 'New event', isPrivate: isPrivate, @@ -218,7 +244,7 @@ router.get('/new/event/public', (req, res) => { // return the JSON for the featured/pinned post for this event router.get('/:eventID/featured', (req, res) => { if (!isFederated) return res.sendStatus(404); - const {eventID} = req.params; + const { eventID } = req.params; const guidObject = crypto.randomBytes(16).toString('hex'); const featured = { "@context": "https://www.w3.org/ns/activitystreams", @@ -234,34 +260,34 @@ router.get('/:eventID/featured', (req, res) => { // return the JSON for a given activitypub message router.get('/:eventID/m/:hash', (req, res) => { if (!isFederated) return res.sendStatus(404); - const {hash, eventID} = req.params; + const { hash, eventID } = req.params; const id = `https://${domain}/${eventID}/m/${hash}`; Event.findOne({ id: eventID }) - .then((event) => { - if (!event) { - res.status(404); - res.render('404', { url: req.url }); - } - else { - const message = event.activityPubMessages.find(el => el.id === id); - if (message) { - return res.json(JSON.parse(message.content)); + .then((event) => { + if (!event) { + res.status(404); + res.render('404', { url: req.url }); } else { - res.status(404); - return res.render('404', { url: req.url }); + const message = event.activityPubMessages.find(el => el.id === id); + if (message) { + return res.json(JSON.parse(message.content)); + } + else { + res.status(404); + return res.render('404', { url: req.url }); + } } - } - }) - .catch((err) => { - addToLog("getActivityPubMessage", "error", "Attempt to get Activity Pub Message for " + id + " failed with error: " + err); - res.status(404); - res.render('404', { url: req.url }); - return; - }); + }) + .catch((err) => { + addToLog("getActivityPubMessage", "error", "Attempt to get Activity Pub Message for " + id + " failed with error: " + err); + res.status(404); + res.render('404', { url: req.url }); + return; + }); }); // return the webfinger record required for the initial activitypub handshake @@ -273,40 +299,40 @@ router.get('/.well-known/webfinger', (req, res) => { } else { // "foo@domain" - let activityPubAccount = resource.replace('acct:',''); + let activityPubAccount = resource.replace('acct:', ''); // "foo" - let eventID = activityPubAccount.replace(/@.*/,''); + let eventID = activityPubAccount.replace(/@.*/, ''); Event.findOne({ id: eventID }) - .then((event) => { - if (!event) { + .then((event) => { + if (!event) { + res.status(404); + res.render('404', { url: req.url }); + } + else { + res.json(ap.createWebfinger(eventID, domain)); + } + }) + .catch((err) => { + addToLog("renderWebfinger", "error", "Attempt to render webfinger for " + req.params.eventID + " failed with error: " + err); res.status(404); res.render('404', { url: req.url }); - } - else { - res.json(ap.createWebfinger(eventID, domain)); - } - }) - .catch((err) => { - addToLog("renderWebfinger", "error", "Attempt to render webfinger for " + req.params.eventID + " failed with error: " + err); - res.status(404); - res.render('404', { url: req.url }); - return; - }); + return; + }); } }); router.get('/:eventID', (req, res) => { Event.findOne({ id: req.params.eventID - }) + }) .populate('eventGroup') .then((event) => { if (event) { const parsedLocation = event.location.replace(/\s+/g, '+'); let displayDate; - if (moment.tz(event.end, event.timezone).isSame(event.start, 'day')){ + if (moment.tz(event.end, event.timezone).isSame(event.start, 'day')) { // Happening during one day displayDate = moment.tz(event.start, event.timezone).format('dddd D MMMM YYYY [<span class="text-muted">from</span>] h:mm a') + moment.tz(event.end, event.timezone).format(' [<span class="text-muted">to</span>] h:mm a [<span class="text-muted">](z)[</span>]'); } @@ -318,11 +344,11 @@ router.get('/:eventID', (req, res) => { let parsedStart = moment.tz(event.start, event.timezone).format('YYYYMMDD[T]HHmmss'); let parsedEnd = moment.tz(event.end, event.timezone).format('YYYYMMDD[T]HHmmss'); let eventHasConcluded = false; - if (moment.tz(event.end, event.timezone).isBefore(moment.tz(event.timezone))){ + if (moment.tz(event.end, event.timezone).isBefore(moment.tz(event.timezone))) { eventHasConcluded = true; } let eventHasBegun = false; - if (moment.tz(event.start, event.timezone).isBefore(moment.tz(event.timezone))){ + if (moment.tz(event.start, event.timezone).isBefore(moment.tz(event.timezone))) { eventHasBegun = true; } let fromNow = moment.tz(event.start, event.timezone).fromNow(); @@ -332,14 +358,14 @@ router.get('/:eventID', (req, res) => { let escapedName = event.name.replace(/\s+/g, '+'); let eventHasCoverImage = false; - if( event.image ) { + if (event.image) { eventHasCoverImage = true; } else { eventHasCoverImage = false; } let eventHasHost = false; - if( event.hostName ) { + if (event.hostName) { eventHasHost = true; } else { @@ -348,7 +374,7 @@ router.get('/:eventID', (req, res) => { let firstLoad = false; if (event.firstLoad === true) { firstLoad = true; - Event.findOneAndUpdate({id: req.params.eventID}, {firstLoad: false}, function(err, raw) { + Event.findOneAndUpdate({ id: req.params.eventID }, { firstLoad: false }, function (err, raw) { if (err) { res.send(err); } @@ -361,7 +387,7 @@ router.get('/:eventID', (req, res) => { console.log("No edit token set"); } else { - if (req.query.e === eventEditToken){ + if (req.query.e === eventEditToken) { editingEnabled = true; } else { @@ -369,16 +395,16 @@ router.get('/:eventID', (req, res) => { } } } - let eventAttendees = event.attendees.sort((a,b) => (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0)) - .map(el => { - if (!el.id) { - el.id = el._id; - } - return el; - }) - .filter((obj, pos, arr) => { + let eventAttendees = event.attendees.sort((a, b) => (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0)) + .map(el => { + if (!el.id) { + el.id = el._id; + } + return el; + }) + .filter((obj, pos, arr) => { return arr.map(mapObj => mapObj.id).indexOf(obj.id) === pos; - }); + }); let spotsRemaining, noMoreSpots; if (event.maxAttendees) { @@ -389,7 +415,7 @@ router.get('/:eventID', (req, res) => { } let metadata = { title: event.name, - description: marked(event.description, { renderer: render_plain()}).split(" ").splice(0,40).join(" ").trim(), + description: marked(event.description, { renderer: render_plain() }).split(" ").splice(0, 40).join(" ").trim(), image: (eventHasCoverImage ? `https://${domain}/events/` + event.image : null), url: `https://${domain}/` + req.params.eventID }; @@ -448,7 +474,7 @@ router.get('/:eventID/followers', (req, res) => { const eventID = req.params.eventID; Event.findOne({ id: eventID - }) + }) .then((event) => { if (event) { const followers = event.followers.map(el => el.actorId); @@ -463,7 +489,7 @@ router.get('/:eventID/followers', (req, res) => { "orderedItems": followers, "id": `https://${domain}/${eventID}/followers?page=1` }, - "@context":["https://www.w3.org/ns/activitystreams"] + "@context": ["https://www.w3.org/ns/activitystreams"] }; return res.json(followersCollection); } @@ -476,7 +502,7 @@ router.get('/:eventID/followers', (req, res) => { router.get('/group/:eventGroupID', (req, res) => { EventGroup.findOne({ id: req.params.eventGroupID - }) + }) .then(async (eventGroup) => { if (eventGroup) { let parsedDescription = marked(eventGroup.description); @@ -485,31 +511,31 @@ router.get('/group/:eventGroupID', (req, res) => { let escapedName = eventGroup.name.replace(/\s+/g, '+'); let eventGroupHasCoverImage = false; - if( eventGroup.image ) { + if (eventGroup.image) { eventGroupHasCoverImage = true; } else { eventGroupHasCoverImage = false; } let eventGroupHasHost = false; - if( eventGroup.hostName ) { + if (eventGroup.hostName) { eventGroupHasHost = true; } else { eventGroupHasHost = false; } - let events = await Event.find({eventGroup: eventGroup._id}).sort('start') + let events = await Event.find({ eventGroup: eventGroup._id }).sort('start') events.forEach(event => { - if (moment.tz(event.end, event.timezone).isSame(event.start, 'day')){ + if (moment.tz(event.end, event.timezone).isSame(event.start, 'day')) { // Happening during one day event.displayDate = moment.tz(event.start, event.timezone).format('D MMM YYYY'); } else { event.displayDate = moment.tz(event.start, event.timezone).format('D MMM YYYY') + moment.tz(event.end, event.timezone).format(' - D MMM YYYY'); } - if (moment.tz(event.end, event.timezone).isBefore(moment.tz(event.timezone))){ + if (moment.tz(event.end, event.timezone).isBefore(moment.tz(event.timezone))) { event.eventHasConcluded = true; } else { event.eventHasConcluded = false; @@ -524,7 +550,7 @@ router.get('/group/:eventGroupID', (req, res) => { let firstLoad = false; if (eventGroup.firstLoad === true) { firstLoad = true; - EventGroup.findOneAndUpdate({id: req.params.eventGroupID}, {firstLoad: false}, function(err, raw) { + EventGroup.findOneAndUpdate({ id: req.params.eventGroupID }, { firstLoad: false }, function (err, raw) { if (err) { res.send(err); } @@ -537,7 +563,7 @@ router.get('/group/:eventGroupID', (req, res) => { console.log("No edit token set"); } else { - if (req.query.e === eventGroupEditToken){ + if (req.query.e === eventGroupEditToken) { editingEnabled = true; } else { @@ -547,7 +573,7 @@ router.get('/group/:eventGroupID', (req, res) => { } let metadata = { title: eventGroup.name, - description: marked(eventGroup.description, { renderer: render_plain()}).split(" ").splice(0,40).join(" ").trim(), + description: marked(eventGroup.description, { renderer: render_plain() }).split(" ").splice(0, 40).join(" ").trim(), image: (eventGroupHasCoverImage ? `https://${domain}/events/` + eventGroup.image : null), url: `https://${domain}/` + req.params.eventID }; @@ -585,7 +611,7 @@ router.get('/group/:eventGroupID', (req, res) => { router.get('/exportevent/:eventID', (req, res) => { Event.findOne({ id: req.params.eventID - }) + }) .populate('eventGroup') .then((event) => { if (event) { @@ -682,7 +708,7 @@ router.post('/newevent', async (req, res) => { firstLoad: true, activityPubActor: ap.createActivityPubActor(eventID, domain, pair.public, marked(req.body.eventDescription), req.body.eventName, req.body.eventLocation, eventImageFilename, startUTC, endUTC, req.body.timezone), activityPubEvent: ap.createActivityPubEvent(req.body.eventName, startUTC, endUTC, req.body.timezone, req.body.eventDescription, req.body.eventLocation), - activityPubMessages: [ { id: `https://${domain}/${eventID}/m/featuredPost`, content: JSON.stringify(ap.createFeaturedPost(eventID, req.body.eventName, startUTC, endUTC, req.body.timezone, req.body.eventDescription, req.body.eventLocation)) } ], + activityPubMessages: [{ id: `https://${domain}/${eventID}/m/featuredPost`, content: JSON.stringify(ap.createFeaturedPost(eventID, req.body.eventName, startUTC, endUTC, req.body.timezone, req.body.eventDescription, req.body.eventLocation)) }], publicKey: pair.public, privateKey: pair.private }); @@ -691,28 +717,39 @@ router.post('/newevent', async (req, res) => { addToLog("createEvent", "success", "Event " + eventID + "created"); // Send email with edit link if (sendEmails) { - req.app.get('hbsInstance').renderView('./views/emails/createevent.handlebars', {eventID, editToken, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars'}, function(err, html) { + req.app.get('hbsInstance').renderView('./views/emails/createevent.handlebars', { eventID, editToken, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars' }, function (err, html) { const msg = { to: req.body.creatorEmail, from: { name: siteName, email: contactEmail, + address: contactEmail }, subject: `${siteName}: ${req.body.eventName}`, html, }; - sgMail.send(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); - }); + switch (mailService) { + case 'sendgrid': + sgMail.send(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } }); } res.writeHead(302, { - 'Location': '/' + eventID + '?e=' + editToken + 'Location': '/' + eventID + '?e=' + editToken }); res.end(); }) - .catch((err) => { res.status(500).send('Database error, please try again :( - ' + err); addToLog("createEvent", "error", "Attempt to create event failed with error: " + err);}); + .catch((err) => { res.status(500).send('Database error, please try again :( - ' + err); addToLog("createEvent", "error", "Attempt to create event failed with error: " + err); }); }); router.post('/importevent', (req, res) => { @@ -757,20 +794,31 @@ router.post('/importevent', (req, res) => { addToLog("createEvent", "success", "Event " + eventID + " created"); // Send email with edit link if (sendEmails) { - req.app.get('hbsInstance').renderView('./views/emails/createevent.handlebars', {eventID, editToken, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars'}, function(err, html) { + req.app.get('hbsInstance').renderView('./views/emails/createevent.handlebars', { eventID, editToken, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars' }, function (err, html) { const msg = { - to: req.body.creatorEmail, - from: { - name: siteName, - email: contactEmail, - }, - subject: `${siteName}: ${importedEventData.summary}`, - html, + to: req.body.creatorEmail, + from: { + name: siteName, + email: contactEmail, + address: contactEmail + }, + subject: `${siteName}: ${importedEventData.summary}`, + html, }; - sgMail.send(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); - }); + switch (mailService) { + case 'sendgrid': + sgMail.send(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } }); } res.writeHead(302, { @@ -778,7 +826,7 @@ router.post('/importevent', (req, res) => { }); res.end(); }) - .catch((err) => { res.send('Database error, please try again :('); addToLog("createEvent", "error", "Attempt to create event failed with error: " + err);}); + .catch((err) => { res.send('Database error, please try again :('); addToLog("createEvent", "error", "Attempt to create event failed with error: " + err); }); } else { console.log("Files array is empty!") @@ -817,20 +865,31 @@ router.post('/neweventgroup', (req, res) => { addToLog("createEventGroup", "success", "Event group " + eventGroupID + " created"); // Send email with edit link if (sendEmails) { - req.app.get('hbsInstance').renderView('./views/emails/createeventgroup.handlebars', {eventGroupID, editToken, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars'}, function(err, html) { + req.app.get('hbsInstance').renderView('./views/emails/createeventgroup.handlebars', { eventGroupID, editToken, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars' }, function (err, html) { const msg = { to: req.body.creatorEmail, from: { name: siteName, email: contactEmail, + address: contactEmail }, subject: `${siteName}: ${req.body.eventGroupName}`, html, }; - sgMail.send(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); - }); + switch (mailService) { + case 'sendgrid': + sgMail.send(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } }); } res.writeHead(302, { @@ -838,7 +897,7 @@ router.post('/neweventgroup', (req, res) => { }); res.end(); }) - .catch((err) => { res.send('Database error, please try again :( - ' + err); addToLog("createEvent", "error", "Attempt to create event failed with error: " + err);}); + .catch((err) => { res.send('Database error, please try again :( - ' + err); addToLog("createEvent", "error", "Attempt to create event failed with error: " + err); }); }); router.post('/editevent/:eventID/:editToken', (req, res) => { @@ -846,220 +905,231 @@ router.post('/editevent/:eventID/:editToken', (req, res) => { let submittedEditToken = req.params.editToken; Event.findOne(({ id: req.params.eventID, - })) - .then(async (event) => { - if (event.editToken === submittedEditToken) { - // Token matches - - // If there is a new image, upload that first - let eventID = req.params.eventID; - let eventImageFilename = event.image; - if (req.files && Object.keys(req.files).length !== 0) { - let eventImageBuffer = req.files.imageUpload.data; - Jimp.read(eventImageBuffer, (err, img) => { - if (err) throw err; - img - .resize(920, Jimp.AUTO) // resize - .quality(80) // set JPEG - .write('./public/events/' + eventID + '.jpg'); // save - }); - eventImageFilename = eventID + '.jpg'; - } - let startUTC = moment.tz(req.body.eventStart, 'D MMMM YYYY, hh:mm a', req.body.timezone); - let endUTC = moment.tz(req.body.eventEnd, 'D MMMM YYYY, hh:mm a', req.body.timezone); - - let isPartOfEventGroup = false; - let eventGroup; - if (req.body.eventGroupCheckbox) { - eventGroup = await EventGroup.findOne({ - id: req.body.eventGroupID, - editToken: req.body.eventGroupEditToken - }) - if (eventGroup) { - isPartOfEventGroup = true; - } - } - const updatedEvent = { - name: req.body.eventName, - location: req.body.eventLocation, - start: startUTC, - end: endUTC, - timezone: req.body.timezone, - description: req.body.eventDescription, - url: req.body.eventURL, - hostName: req.body.hostName, - image: eventImageFilename, - usersCanAttend: req.body.joinCheckbox ? true : false, - showUsersList: req.body.guestlistCheckbox ? true : false, - usersCanComment: req.body.interactionCheckbox ? true : false, - maxAttendees: req.body.maxAttendeesCheckbox ? req.body.maxAttendees : null, - eventGroup: isPartOfEventGroup ? eventGroup._id : null, - activityPubActor: ap.updateActivityPubActor(JSON.parse(event.activityPubActor || null), req.body.eventDescription, req.body.eventName, req.body.eventLocation, eventImageFilename, startUTC, endUTC, req.body.timezone), - activityPubEvent: ap.updateActivityPubEvent(JSON.parse(event.activityPubEvent || null), req.body.eventName, req.body.startUTC, req.body.endUTC, req.body.timezone), - } - let diffText = '<p>This event was just updated with new information.</p><ul>'; - let displayDate; - if (event.name !== updatedEvent.name) { - diffText += `<li>the event name changed to ${updatedEvent.name}</li>`; - } - if (event.location !== updatedEvent.location) { - diffText += `<li>the location changed to ${updatedEvent.location}</li>`; - } - if (event.start.toISOString() !== updatedEvent.start.toISOString()) { - displayDate = moment.tz(updatedEvent.start, updatedEvent.timezone).format('dddd D MMMM YYYY h:mm a'); - diffText += `<li>the start time changed to ${displayDate}</li>`; - } - if (event.end.toISOString() !== updatedEvent.end.toISOString()) { - displayDate = moment.tz(updatedEvent.end, updatedEvent.timezone).format('dddd D MMMM YYYY h:mm a'); - diffText += `<li>the end time changed to ${displayDate}</li>`; - } - if (event.timezone !== updatedEvent.timezone) { - console.log(typeof event.timezone, JSON.stringify(event.timezone), JSON.stringify(updatedEvent.timezone)) - diffText += `<li>the time zone changed to ${updatedEvent.timezone}</li>`; - } - if (event.description !== updatedEvent.description) { - diffText += `<li>the event description changed</li>`; - } - diffText += `</ul>`; - Event.findOneAndUpdate({id: req.params.eventID}, updatedEvent, function(err, raw) { - if (err) { - addToLog("editEvent", "error", "Attempt to edit event " + req.params.eventID + " failed with error: " + err); - res.send(err); + })) + .then(async (event) => { + if (event.editToken === submittedEditToken) { + // Token matches + + // If there is a new image, upload that first + let eventID = req.params.eventID; + let eventImageFilename = event.image; + if (req.files && Object.keys(req.files).length !== 0) { + let eventImageBuffer = req.files.imageUpload.data; + Jimp.read(eventImageBuffer, (err, img) => { + if (err) throw err; + img + .resize(920, Jimp.AUTO) // resize + .quality(80) // set JPEG + .write('./public/events/' + eventID + '.jpg'); // save + }); + eventImageFilename = eventID + '.jpg'; } - }) - .then(() => { - addToLog("editEvent", "success", "Event " + req.params.eventID + " edited"); - // send update to ActivityPub subscribers - Event.findOne({id: req.params.eventID}, function(err,event) { - if (!event) return; - let attendees = event.attendees.filter(el => el.id); - if (!err) { - // broadcast an identical message to all followers, will show in home timeline - const guidObject = crypto.randomBytes(16).toString('hex'); - const jsonObject = { - "@context": "https://www.w3.org/ns/activitystreams", - "id": `https://${domain}/${req.params.eventID}/m/${guidObject}`, - "name": `RSVP to ${event.name}`, - "type": "Note", - 'cc': 'https://www.w3.org/ns/activitystreams#Public', - "content": `${diffText} See here: <a href="https://${domain}/${req.params.eventID}">https://${domain}/${req.params.eventID}</a>`, - } - ap.broadcastCreateMessage(jsonObject, event.followers, eventID) - // also broadcast an Update profile message to all followers so that at least Mastodon servers will update the local profile information - const jsonUpdateObject = JSON.parse(event.activityPubActor); - ap.broadcastUpdateMessage(jsonUpdateObject, event.followers, eventID) - // also broadcast an Update/Event for any calendar apps that are consuming our Events - const jsonEventObject = JSON.parse(event.activityPubEvent); - ap.broadcastUpdateMessage(jsonEventObject, event.followers, eventID) - - // DM to attendees - for (const attendee of attendees) { - const jsonObject = { - "@context": "https://www.w3.org/ns/activitystreams", - "name": `RSVP to ${event.name}`, - "type": "Note", - "content": `<span class=\"h-card\"><a href="${attendee.id}" class="u-url mention">@<span>${attendee.name}</span></a></span> ${diffText} See here: <a href="https://${domain}/${req.params.eventID}">https://${domain}/${req.params.eventID}</a>`, - "tag":[{"type":"Mention","href":attendee.id,"name":attendee.name}] - } - // send direct message to user - ap.sendDirectMessage(jsonObject, attendee.id, eventID); - } + let startUTC = moment.tz(req.body.eventStart, 'D MMMM YYYY, hh:mm a', req.body.timezone); + let endUTC = moment.tz(req.body.eventEnd, 'D MMMM YYYY, hh:mm a', req.body.timezone); + + let isPartOfEventGroup = false; + let eventGroup; + if (req.body.eventGroupCheckbox) { + eventGroup = await EventGroup.findOne({ + id: req.body.eventGroupID, + editToken: req.body.eventGroupEditToken + }) + if (eventGroup) { + isPartOfEventGroup = true; + } + } + const updatedEvent = { + name: req.body.eventName, + location: req.body.eventLocation, + start: startUTC, + end: endUTC, + timezone: req.body.timezone, + description: req.body.eventDescription, + url: req.body.eventURL, + hostName: req.body.hostName, + image: eventImageFilename, + usersCanAttend: req.body.joinCheckbox ? true : false, + showUsersList: req.body.guestlistCheckbox ? true : false, + usersCanComment: req.body.interactionCheckbox ? true : false, + maxAttendees: req.body.maxAttendeesCheckbox ? req.body.maxAttendees : null, + eventGroup: isPartOfEventGroup ? eventGroup._id : null, + activityPubActor: ap.updateActivityPubActor(JSON.parse(event.activityPubActor || null), req.body.eventDescription, req.body.eventName, req.body.eventLocation, eventImageFilename, startUTC, endUTC, req.body.timezone), + activityPubEvent: ap.updateActivityPubEvent(JSON.parse(event.activityPubEvent || null), req.body.eventName, req.body.startUTC, req.body.endUTC, req.body.timezone), + } + let diffText = '<p>This event was just updated with new information.</p><ul>'; + let displayDate; + if (event.name !== updatedEvent.name) { + diffText += `<li>the event name changed to ${updatedEvent.name}</li>`; + } + if (event.location !== updatedEvent.location) { + diffText += `<li>the location changed to ${updatedEvent.location}</li>`; + } + if (event.start.toISOString() !== updatedEvent.start.toISOString()) { + displayDate = moment.tz(updatedEvent.start, updatedEvent.timezone).format('dddd D MMMM YYYY h:mm a'); + diffText += `<li>the start time changed to ${displayDate}</li>`; + } + if (event.end.toISOString() !== updatedEvent.end.toISOString()) { + displayDate = moment.tz(updatedEvent.end, updatedEvent.timezone).format('dddd D MMMM YYYY h:mm a'); + diffText += `<li>the end time changed to ${displayDate}</li>`; + } + if (event.timezone !== updatedEvent.timezone) { + console.log(typeof event.timezone, JSON.stringify(event.timezone), JSON.stringify(updatedEvent.timezone)) + diffText += `<li>the time zone changed to ${updatedEvent.timezone}</li>`; + } + if (event.description !== updatedEvent.description) { + diffText += `<li>the event description changed</li>`; + } + diffText += `</ul>`; + Event.findOneAndUpdate({ id: req.params.eventID }, updatedEvent, function (err, raw) { + if (err) { + addToLog("editEvent", "error", "Attempt to edit event " + req.params.eventID + " failed with error: " + err); + res.send(err); } }) - if (sendEmails) { - Event.findOne({id: req.params.eventID}).distinct('attendees.email', function(error, ids) { - let attendeeEmails = ids; - if (!error && attendeeEmails !== ""){ - console.log("Sending emails to: " + attendeeEmails); - req.app.get('hbsInstance').renderView('./views/emails/editevent.handlebars', {diffText, eventID: req.params.eventID, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars'}, function(err, html) { - const msg = { - to: attendeeEmails, - from: { - name: siteName, - email: contactEmail, - }, - subject: `${siteName}: ${event.name} was just edited`, - html, - }; - sgMail.sendMultiple(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); - }); - }); - } - else { - console.log("Nothing to send!"); + .then(() => { + addToLog("editEvent", "success", "Event " + req.params.eventID + " edited"); + // send update to ActivityPub subscribers + Event.findOne({ id: req.params.eventID }, function (err, event) { + if (!event) return; + let attendees = event.attendees.filter(el => el.id); + if (!err) { + // broadcast an identical message to all followers, will show in home timeline + const guidObject = crypto.randomBytes(16).toString('hex'); + const jsonObject = { + "@context": "https://www.w3.org/ns/activitystreams", + "id": `https://${domain}/${req.params.eventID}/m/${guidObject}`, + "name": `RSVP to ${event.name}`, + "type": "Note", + 'cc': 'https://www.w3.org/ns/activitystreams#Public', + "content": `${diffText} See here: <a href="https://${domain}/${req.params.eventID}">https://${domain}/${req.params.eventID}</a>`, + } + ap.broadcastCreateMessage(jsonObject, event.followers, eventID) + // also broadcast an Update profile message to all followers so that at least Mastodon servers will update the local profile information + const jsonUpdateObject = JSON.parse(event.activityPubActor); + ap.broadcastUpdateMessage(jsonUpdateObject, event.followers, eventID) + // also broadcast an Update/Event for any calendar apps that are consuming our Events + const jsonEventObject = JSON.parse(event.activityPubEvent); + ap.broadcastUpdateMessage(jsonEventObject, event.followers, eventID) + + // DM to attendees + for (const attendee of attendees) { + const jsonObject = { + "@context": "https://www.w3.org/ns/activitystreams", + "name": `RSVP to ${event.name}`, + "type": "Note", + "content": `<span class=\"h-card\"><a href="${attendee.id}" class="u-url mention">@<span>${attendee.name}</span></a></span> ${diffText} See here: <a href="https://${domain}/${req.params.eventID}">https://${domain}/${req.params.eventID}</a>`, + "tag": [{ "type": "Mention", "href": attendee.id, "name": attendee.name }] + } + // send direct message to user + ap.sendDirectMessage(jsonObject, attendee.id, eventID); + } + } + }) + if (sendEmails) { + Event.findOne({ id: req.params.eventID }).distinct('attendees.email', function (error, ids) { + let attendeeEmails = ids; + if (!error && attendeeEmails !== "") { + console.log("Sending emails to: " + attendeeEmails); + req.app.get('hbsInstance').renderView('./views/emails/editevent.handlebars', { diffText, eventID: req.params.eventID, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars' }, function (err, html) { + const msg = { + to: attendeeEmails, + from: { + name: siteName, + email: contactEmail, + address: contactEmail + }, + subject: `${siteName}: ${event.name} was just edited`, + html, + }; + switch (mailService) { + case 'sendgrid': + sgMail.sendMultiple(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } + }); + } + else { + console.log("Nothing to send!"); + } + }) } + res.writeHead(302, { + 'Location': '/' + req.params.eventID + '?e=' + req.params.editToken + }); + res.end(); }) - } - res.writeHead(302, { - 'Location': '/' + req.params.eventID + '?e=' + req.params.editToken - }); - res.end(); - }) - .catch((err) => { console.error(err); res.send('Sorry! Something went wrong!'); addToLog("editEvent", "error", "Attempt to edit event " + req.params.eventID + " failed with error: " + err);}); - } - else { - // Token doesn't match - res.send('Sorry! Something went wrong'); - addToLog("editEvent", "error", "Attempt to edit event " + req.params.eventID + " failed with error: token does not match"); - } - }) - .catch((err) => { console.error(err); res.send('Sorry! Something went wrong!'); addToLog("editEvent", "error", "Attempt to edit event " + req.params.eventID + " failed with error: " + err);}); + .catch((err) => { console.error(err); res.send('Sorry! Something went wrong!'); addToLog("editEvent", "error", "Attempt to edit event " + req.params.eventID + " failed with error: " + err); }); + } + else { + // Token doesn't match + res.send('Sorry! Something went wrong'); + addToLog("editEvent", "error", "Attempt to edit event " + req.params.eventID + " failed with error: token does not match"); + } + }) + .catch((err) => { console.error(err); res.send('Sorry! Something went wrong!'); addToLog("editEvent", "error", "Attempt to edit event " + req.params.eventID + " failed with error: " + err); }); }); router.post('/editeventgroup/:eventGroupID/:editToken', (req, res) => { let submittedEditToken = req.params.editToken; EventGroup.findOne(({ id: req.params.eventGroupID, - })) - .then((eventGroup) => { - if (eventGroup.editToken === submittedEditToken) { - // Token matches - - // If there is a new image, upload that first - let eventGroupID = req.params.eventGroupID; - let eventGroupImageFilename = eventGroup.image; - if (req.files && Object.keys(req.files).length !== 0) { - let eventImageBuffer = req.files.eventGroupImageUpload.data; - Jimp.read(eventImageBuffer, (err, img) => { - if (err) throw err; - img - .resize(920, Jimp.AUTO) // resize - .quality(80) // set JPEG - .write('./public/events/' + eventGroupID + '.jpg'); // save - }); - eventGroupImageFilename = eventGroupID + '.jpg'; + })) + .then((eventGroup) => { + if (eventGroup.editToken === submittedEditToken) { + // Token matches + + // If there is a new image, upload that first + let eventGroupID = req.params.eventGroupID; + let eventGroupImageFilename = eventGroup.image; + if (req.files && Object.keys(req.files).length !== 0) { + let eventImageBuffer = req.files.eventGroupImageUpload.data; + Jimp.read(eventImageBuffer, (err, img) => { + if (err) throw err; + img + .resize(920, Jimp.AUTO) // resize + .quality(80) // set JPEG + .write('./public/events/' + eventGroupID + '.jpg'); // save + }); + eventGroupImageFilename = eventGroupID + '.jpg'; + } + const updatedEventGroup = { + name: req.body.eventGroupName, + description: req.body.eventGroupDescription, + url: req.body.eventGroupURL, + hostName: req.body.hostName, + image: eventGroupImageFilename + } + EventGroup.findOneAndUpdate({ id: req.params.eventGroupID }, updatedEventGroup, function (err, raw) { + if (err) { + addToLog("editEventGroup", "error", "Attempt to edit event group " + req.params.eventGroupID + " failed with error: " + err); + res.send(err); + } + }) + .then(() => { + addToLog("editEventGroup", "success", "Event group " + req.params.eventGroupID + " edited"); + res.writeHead(302, { + 'Location': '/group/' + req.params.eventGroupID + '?e=' + req.params.editToken + }); + res.end(); + }) + .catch((err) => { console.error(err); res.send('Sorry! Something went wrong!'); addToLog("editEventGroup", "error", "Attempt to edit event group " + req.params.eventGroupID + " failed with error: " + err); }); } - const updatedEventGroup = { - name: req.body.eventGroupName, - description: req.body.eventGroupDescription, - url: req.body.eventGroupURL, - hostName: req.body.hostName, - image: eventGroupImageFilename + else { + // Token doesn't match + res.send('Sorry! Something went wrong'); + addToLog("editEventGroup", "error", "Attempt to edit event group " + req.params.eventGroupID + " failed with error: token does not match"); } - EventGroup.findOneAndUpdate({id: req.params.eventGroupID}, updatedEventGroup, function(err, raw) { - if (err) { - addToLog("editEventGroup", "error", "Attempt to edit event group " + req.params.eventGroupID + " failed with error: " + err); - res.send(err); - } - }) - .then(() => { - addToLog("editEventGroup", "success", "Event group " + req.params.eventGroupID + " edited"); - res.writeHead(302, { - 'Location': '/group/' + req.params.eventGroupID + '?e=' + req.params.editToken - }); - res.end(); - }) - .catch((err) => { console.error(err); res.send('Sorry! Something went wrong!'); addToLog("editEventGroup", "error", "Attempt to edit event group " + req.params.eventGroupID + " failed with error: " + err);}); - } - else { - // Token doesn't match - res.send('Sorry! Something went wrong'); - addToLog("editEventGroup", "error", "Attempt to edit event group " + req.params.eventGroupID + " failed with error: token does not match"); - } - }) - .catch((err) => { console.error(err); res.send('Sorry! Something went wrong!'); addToLog("editEventGroup", "error", "Attempt to edit event group " + req.params.eventGroupID + " failed with error: " + err);}); + }) + .catch((err) => { console.error(err); res.send('Sorry! Something went wrong!'); addToLog("editEventGroup", "error", "Attempt to edit event group " + req.params.eventGroupID + " failed with error: " + err); }); }); router.post('/deleteimage/:eventID/:editToken', (req, res) => { @@ -1067,33 +1137,33 @@ router.post('/deleteimage/:eventID/:editToken', (req, res) => { Event.findOne(({ id: req.params.eventID, })) - .then((event) => { - if (event.editToken === submittedEditToken) { - // Token matches - if (event.image){ - eventImage = event.image; - } else { - res.status(500).send('This event doesn\'t have a linked image. What are you even doing'); - } - fs.unlink(global.appRoot + '/public/events/' + eventImage, (err) => { - if (err) { - res.status(500).send(err); - addToLog("deleteEventImage", "error", "Attempt to delete event image for event " + req.params.eventID + " failed with error: " + err); + .then((event) => { + if (event.editToken === submittedEditToken) { + // Token matches + if (event.image) { + eventImage = event.image; + } else { + res.status(500).send('This event doesn\'t have a linked image. What are you even doing'); } - // Image removed - addToLog("deleteEventImage", "success", "Image for event " + req.params.eventID + " deleted"); - event.image = ""; - event.save() - .then(response => { - res.status(200).send('Success'); - }) - .catch(err => { - res.status(500).send(err); - addToLog("deleteEventImage", "error", "Attempt to delete event image for event " + req.params.eventID + " failed with error: " + err); - }) - }); - } - }); + fs.unlink(global.appRoot + '/public/events/' + eventImage, (err) => { + if (err) { + res.status(500).send(err); + addToLog("deleteEventImage", "error", "Attempt to delete event image for event " + req.params.eventID + " failed with error: " + err); + } + // Image removed + addToLog("deleteEventImage", "success", "Image for event " + req.params.eventID + " deleted"); + event.image = ""; + event.save() + .then(response => { + res.status(200).send('Success'); + }) + .catch(err => { + res.status(500).send(err); + addToLog("deleteEventImage", "error", "Attempt to delete event image for event " + req.params.eventID + " failed with error: " + err); + }) + }); + } + }); }); router.post('/deleteevent/:eventID/:editToken', (req, res) => { @@ -1102,135 +1172,146 @@ router.post('/deleteevent/:eventID/:editToken', (req, res) => { Event.findOne(({ id: req.params.eventID, })) - .then((event) => { - if (event.editToken === submittedEditToken) { - // Token matches + .then((event) => { + if (event.editToken === submittedEditToken) { + // Token matches - let eventImage; - if (event.image){ - eventImage = event.image; - } + let eventImage; + if (event.image) { + eventImage = event.image; + } - // broadcast a Delete profile message to all followers so that at least Mastodon servers will delete their local profile information - const guidUpdateObject = crypto.randomBytes(16).toString('hex'); - const jsonUpdateObject = JSON.parse(event.activityPubActor); - // first broadcast AP messages, THEN delete from DB - ap.broadcastDeleteMessage(jsonUpdateObject, event.followers, req.params.eventID, function(statuses) { - Event.deleteOne({id: req.params.eventID}, function(err, raw) { - if (err) { - res.send(err); - addToLog("deleteEvent", "error", "Attempt to delete event " + req.params.eventID + " failed with error: " + err); - } - }) - .then(() => { - // Delete image - if (eventImage){ - fs.unlink(global.appRoot + '/public/events/' + eventImage, (err) => { - if (err) { + // broadcast a Delete profile message to all followers so that at least Mastodon servers will delete their local profile information + const guidUpdateObject = crypto.randomBytes(16).toString('hex'); + const jsonUpdateObject = JSON.parse(event.activityPubActor); + // first broadcast AP messages, THEN delete from DB + ap.broadcastDeleteMessage(jsonUpdateObject, event.followers, req.params.eventID, function (statuses) { + Event.deleteOne({ id: req.params.eventID }, function (err, raw) { + if (err) { res.send(err); - addToLog("deleteEvent", "error", "Attempt to delete event image for event " + req.params.eventID + " failed with error: " + err); + addToLog("deleteEvent", "error", "Attempt to delete event " + req.params.eventID + " failed with error: " + err); + } + }) + .then(() => { + // Delete image + if (eventImage) { + fs.unlink(global.appRoot + '/public/events/' + eventImage, (err) => { + if (err) { + res.send(err); + addToLog("deleteEvent", "error", "Attempt to delete event image for event " + req.params.eventID + " failed with error: " + err); + } + // Image removed + addToLog("deleteEvent", "success", "Event " + req.params.eventID + " deleted"); + }) } - // Image removed - addToLog("deleteEvent", "success", "Event " + req.params.eventID + " deleted"); + res.writeHead(302, { + 'Location': '/' + }); + res.end(); }) - } - res.writeHead(302, { - 'Location': '/' - }); - res.end(); - }) - .catch((err) => { res.send('Sorry! Something went wrong (error deleting): ' + err); addToLog("deleteEvent", "error", "Attempt to delete event " + req.params.eventID + " failed with error: " + err);}); - }); - // Send emails here otherwise they don't exist lol - if (sendEmails) { - Event.findOne({id: req.params.eventID}).distinct('attendees.email', function(error, ids) { - attendeeEmails = ids; - if (!error){ - console.log("Sending emails to: " + attendeeEmails); - req.app.get('hbsInstance').renderView('./views/emails/deleteevent.handlebars', {siteName, siteLogo, domain, eventName: event.name, cache: true, layout: 'email.handlebars'}, function(err, html) { - const msg = { - to: attendeeEmails, - from: { - name: siteName, - email: contactEmail, - }, - subject: `${siteName}: ${event.name} was deleted`, - html, - }; - sgMail.sendMultiple(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); + .catch((err) => { res.send('Sorry! Something went wrong (error deleting): ' + err); addToLog("deleteEvent", "error", "Attempt to delete event " + req.params.eventID + " failed with error: " + err); }); + }); + // Send emails here otherwise they don't exist lol + if (sendEmails) { + Event.findOne({ id: req.params.eventID }).distinct('attendees.email', function (error, ids) { + attendeeEmails = ids; + if (!error) { + console.log("Sending emails to: " + attendeeEmails); + req.app.get('hbsInstance').renderView('./views/emails/deleteevent.handlebars', { siteName, siteLogo, domain, eventName: event.name, cache: true, layout: 'email.handlebars' }, function (err, html) { + const msg = { + to: attendeeEmails, + from: { + name: siteName, + email: contactEmail, + address: contactEmail + }, + subject: `${siteName}: ${event.name} was deleted`, + html, + }; + switch (mailService) { + case 'sendgrid': + sgMail.sendMultiple(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } }); - }); } - else { - console.log("Nothing to send!"); - } - }); + else { + console.log("Nothing to send!"); + } + }); + } } - } - else { - // Token doesn't match - res.send('Sorry! Something went wrong'); - addToLog("deleteEvent", "error", "Attempt to delete event " + req.params.eventID + " failed with error: token does not match"); - } - }) - .catch((err) => { res.send('Sorry! Something went wrong: ' + err); addToLog("deleteEvent", "error", "Attempt to delete event " + req.params.eventID + " failed with error: " + err);}); + else { + // Token doesn't match + res.send('Sorry! Something went wrong'); + addToLog("deleteEvent", "error", "Attempt to delete event " + req.params.eventID + " failed with error: token does not match"); + } + }) + .catch((err) => { res.send('Sorry! Something went wrong: ' + err); addToLog("deleteEvent", "error", "Attempt to delete event " + req.params.eventID + " failed with error: " + err); }); }); router.post('/deleteeventgroup/:eventGroupID/:editToken', (req, res) => { let submittedEditToken = req.params.editToken; EventGroup.findOne(({ id: req.params.eventGroupID, - })) - .then(async (eventGroup) => { - if (eventGroup.editToken === submittedEditToken) { - // Token matches - - let linkedEvents = await Event.find({eventGroup: eventGroup._id}); + })) + .then(async (eventGroup) => { + if (eventGroup.editToken === submittedEditToken) { + // Token matches - let linkedEventIDs = linkedEvents.map(event => event._id); - let eventGroupImage = false; - if (eventGroup.image){ - eventGroupImage = eventGroup.image; - } + let linkedEvents = await Event.find({ eventGroup: eventGroup._id }); - EventGroup.deleteOne({id: req.params.eventGroupID}, function(err, raw) { - if (err) { - res.send(err); - addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: " + err); + let linkedEventIDs = linkedEvents.map(event => event._id); + let eventGroupImage = false; + if (eventGroup.image) { + eventGroupImage = eventGroup.image; } - }) - .then(() => { - // Delete image - if (eventGroupImage){ - fs.unlink(global.appRoot + '/public/events/' + eventGroupImage, (err) => { - if (err) { + + EventGroup.deleteOne({ id: req.params.eventGroupID }, function (err, raw) { + if (err) { res.send(err); - addToLog("deleteEventGroup", "error", "Attempt to delete event image for event group " + req.params.eventGroupID + " failed with error: " + err); + addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: " + err); + } + }) + .then(() => { + // Delete image + if (eventGroupImage) { + fs.unlink(global.appRoot + '/public/events/' + eventGroupImage, (err) => { + if (err) { + res.send(err); + addToLog("deleteEventGroup", "error", "Attempt to delete event image for event group " + req.params.eventGroupID + " failed with error: " + err); + } + }) } + Event.update({ _id: { $in: linkedEventIDs } }, { $set: { eventGroup: null } }, { multi: true }) + .then(response => { + console.log(response); + addToLog("deleteEventGroup", "success", "Event group " + req.params.eventGroupID + " deleted"); + res.writeHead(302, { + 'Location': '/' + }); + res.end(); + }) + .catch((err) => { res.send('Sorry! Something went wrong (error deleting): ' + err); addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: " + err); }); }) - } - Event.update({_id: {$in: linkedEventIDs}}, { $set: { eventGroup: null } }, { multi: true }) - .then(response => { - console.log(response); - addToLog("deleteEventGroup", "success", "Event group " + req.params.eventGroupID + " deleted"); - res.writeHead(302, { - 'Location': '/' - }); - res.end(); - }) - .catch((err) => { res.send('Sorry! Something went wrong (error deleting): ' + err); addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: " + err);}); - }) - .catch((err) => { res.send('Sorry! Something went wrong (error deleting): ' + err); addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: " + err);}); - } - else { - // Token doesn't match - res.send('Sorry! Something went wrong'); - addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: token does not match"); - } - }) - .catch((err) => { res.send('Sorry! Something went wrong: ' + err); addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: " + err);}); + .catch((err) => { res.send('Sorry! Something went wrong (error deleting): ' + err); addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: " + err); }); + } + else { + // Token doesn't match + res.send('Sorry! Something went wrong'); + addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: token does not match"); + } + }) + .catch((err) => { res.send('Sorry! Something went wrong: ' + err); addToLog("deleteEventGroup", "error", "Attempt to delete event group " + req.params.eventGroupID + " failed with error: " + err); }); }); router.post('/attendevent/:eventID', (req, res) => { @@ -1243,74 +1324,95 @@ router.post('/attendevent/:eventID', (req, res) => { Event.findOne({ id: req.params.eventID, - }, function(err,event) { + }, function (err, event) { if (!event) return; event.attendees.push(newAttendee); event.save() - .then(() => { - addToLog("addEventAttendee", "success", "Attendee added to event " + req.params.eventID); + .then(() => { + addToLog("addEventAttendee", "success", "Attendee added to event " + req.params.eventID); + if (sendEmails) { + if (req.body.attendeeEmail) { + req.app.get('hbsInstance').renderView('./views/emails/addeventattendee.handlebars', { eventID: req.params.eventID, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars' }, function (err, html) { + const msg = { + to: req.body.attendeeEmail, + from: { + name: siteName, + email: contactEmail, + }, + subject: `${siteName}: You're RSVPed to ${event.name}`, + html, + }; + switch (mailService) { + case 'sendgrid': + sgMail.send(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } + }); + } + } + res.writeHead(302, { + 'Location': '/' + req.params.eventID + }); + res.end(); + }) + .catch((err) => { res.send('Database error, please try again :('); addToLog("addEventAttendee", "error", "Attempt to add attendee to event " + req.params.eventID + " failed with error: " + err); }); + }); +}); + +router.post('/unattendevent/:eventID', (req, res) => { + Event.update( + { id: req.params.eventID }, + { $pull: { attendees: { removalPassword: req.body.removeAttendancePassword } } } + ) + .then(response => { + console.log(response) + addToLog("unattendEvent", "success", "Attendee removed self from event " + req.params.eventID); if (sendEmails) { - if (req.body.attendeeEmail){ - req.app.get('hbsInstance').renderView('./views/emails/addeventattendee.handlebars', {eventID: req.params.eventID, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars'}, function(err, html) { + if (req.body.attendeeEmail) { + req.app.get('hbsInstance').renderView('./views/emails/unattendevent.handlebars', { eventID: req.params.eventID, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars' }, function (err, html) { const msg = { to: req.body.attendeeEmail, from: { name: siteName, email: contactEmail, }, - subject: `${siteName}: You're RSVPed to ${event.name}`, + subject: `${siteName}: You have been removed from an event`, html, }; - sgMail.send(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); - }); + switch (mailService) { + case 'sendgrid': + sgMail.send(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } }); } } res.writeHead(302, { 'Location': '/' + req.params.eventID - }); + }); res.end(); }) - .catch((err) => { res.send('Database error, please try again :('); addToLog("addEventAttendee", "error", "Attempt to add attendee to event " + req.params.eventID + " failed with error: " + err); }); - }); -}); - -router.post('/unattendevent/:eventID', (req, res) => { - Event.update( - { id: req.params.eventID }, - { $pull: { attendees: { removalPassword: req.body.removeAttendancePassword } } } - ) - .then(response => { - console.log(response) - addToLog("unattendEvent", "success", "Attendee removed self from event " + req.params.eventID); - if (sendEmails) { - if (req.body.attendeeEmail){ - req.app.get('hbsInstance').renderView('./views/emails/unattendevent.handlebars', {eventID: req.params.eventID, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars'}, function(err, html) { const msg = { - to: req.body.attendeeEmail, - from: { - name: siteName, - email: contactEmail, - }, - subject: `${siteName}: You have been removed from an event`, - html, - }; - sgMail.send(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); - }); - }); - } - } - res.writeHead(302, { - 'Location': '/' + req.params.eventID - }); - res.end(); - }) - .catch((err) => { - res.send('Database error, please try again :('); addToLog("removeEventAttendee", "error", "Attempt to remove attendee from event " + req.params.eventID + " failed with error: " + err); - }); + .catch((err) => { + res.send('Database error, please try again :('); addToLog("removeEventAttendee", "error", "Attempt to remove attendee from event " + req.params.eventID + " failed with error: " + err); + }); }); // this is a one-click unattend that requires a secret URL that only the person who RSVPed over @@ -1322,75 +1424,97 @@ router.get('/oneclickunattendevent/:eventID/:attendeeID', (req, res) => { return res.sendStatus(200); } Event.update( - { id: req.params.eventID }, - { $pull: { attendees: { _id: req.params.attendeeID } } } + { id: req.params.eventID }, + { $pull: { attendees: { _id: req.params.attendeeID } } } ) - .then(response => { - addToLog("oneClickUnattend", "success", "Attendee removed via one click unattend " + req.params.eventID); - if (sendEmails) { - // currently this is never called because we don't have the email address - if (req.body.attendeeEmail){ - req.app.get('hbsInstance').renderView('./views/emails/removeeventattendee.handlebars', {eventName: req.params.eventName, siteName, domain, cache: true, layout: 'email.handlebars'}, function(err, html) { const msg = { - to: req.body.attendeeEmail, - from: { - name: siteName, - email: contactEmail, - }, - subject: `${siteName}: You have been removed from an event`, - html, - }; - sgMail.send(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); + .then(response => { + addToLog("oneClickUnattend", "success", "Attendee removed via one click unattend " + req.params.eventID); + if (sendEmails) { + // currently this is never called because we don't have the email address + if (req.body.attendeeEmail) { + req.app.get('hbsInstance').renderView('./views/emails/removeeventattendee.handlebars', { eventName: req.params.eventName, siteName, domain, cache: true, layout: 'email.handlebars' }, function (err, html) { + const msg = { + to: req.body.attendeeEmail, + from: { + name: siteName, + email: contactEmail, + }, + subject: `${siteName}: You have been removed from an event`, + html, + }; + switch (mailService) { + case 'sendgrid': + sgMail.send(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } }); - }); + } } - } - res.writeHead(302, { - 'Location': '/' + req.params.eventID + res.writeHead(302, { + 'Location': '/' + req.params.eventID }); - res.end(); - }) - .catch((err) => { - res.send('Database error, please try again :('); addToLog("removeEventAttendee", "error", "Attempt to remove attendee by admin from event " + req.params.eventID + " failed with error: " + err); - }); + res.end(); + }) + .catch((err) => { + res.send('Database error, please try again :('); addToLog("removeEventAttendee", "error", "Attempt to remove attendee by admin from event " + req.params.eventID + " failed with error: " + err); + }); }); router.post('/removeattendee/:eventID/:attendeeID', (req, res) => { Event.update( - { id: req.params.eventID }, - { $pull: { attendees: { _id: req.params.attendeeID } } } + { id: req.params.eventID }, + { $pull: { attendees: { _id: req.params.attendeeID } } } ) - .then(response => { - console.log(response) - addToLog("removeEventAttendee", "success", "Attendee removed by admin from event " + req.params.eventID); - if (sendEmails) { - // currently this is never called because we don't have the email address - if (req.body.attendeeEmail){ - req.app.get('hbsInstance').renderView('./views/emails/removeeventattendee.handlebars', {eventName: req.params.eventName, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars'}, function(err, html) { const msg = { - to: req.body.attendeeEmail, - from: { - name: siteName, - email: contactEmail, - }, - subject: `${siteName}: You have been removed from an event`, - html, - }; - sgMail.send(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); + .then(response => { + console.log(response) + addToLog("removeEventAttendee", "success", "Attendee removed by admin from event " + req.params.eventID); + if (sendEmails) { + // currently this is never called because we don't have the email address + if (req.body.attendeeEmail) { + req.app.get('hbsInstance').renderView('./views/emails/removeeventattendee.handlebars', { eventName: req.params.eventName, siteName, siteLogo, domain, cache: true, layout: 'email.handlebars' }, function (err, html) { + const msg = { + to: req.body.attendeeEmail, + from: { + name: siteName, + email: contactEmail, + }, + subject: `${siteName}: You have been removed from an event`, + html, + }; + switch (mailService) { + case 'sendgrid': + sgMail.send(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } }); - }); + } } - } - res.writeHead(302, { - 'Location': '/' + req.params.eventID + res.writeHead(302, { + 'Location': '/' + req.params.eventID }); - res.end(); - }) - .catch((err) => { - res.send('Database error, please try again :('); addToLog("removeEventAttendee", "error", "Attempt to remove attendee by admin from event " + req.params.eventID + " failed with error: " + err); - }); + res.end(); + }) + .catch((err) => { + res.send('Database error, please try again :('); addToLog("removeEventAttendee", "error", "Attempt to remove attendee by admin from event " + req.params.eventID + " failed with error: " + err); + }); }); router.post('/post/comment/:eventID', (req, res) => { @@ -1404,56 +1528,66 @@ router.post('/post/comment/:eventID', (req, res) => { Event.findOne({ id: req.params.eventID, - }, function(err,event) { + }, function (err, event) { if (!event) return; event.comments.push(newComment); event.save() - .then(() => { - addToLog("addEventComment", "success", "Comment added to event " + req.params.eventID); - // broadcast an identical message to all followers, will show in their home timeline - // and in the home timeline of the event - const guidObject = crypto.randomBytes(16).toString('hex'); - const jsonObject = { - "@context": "https://www.w3.org/ns/activitystreams", - "id": `https://${domain}/${req.params.eventID}/m/${guidObject}`, - "name": `Comment on ${event.name}`, - "type": "Note", - 'cc': 'https://www.w3.org/ns/activitystreams#Public', - "content": `<p>${req.body.commentAuthor} commented: ${req.body.commentContent}.</p><p><a href="https://${domain}/${req.params.eventID}/">See the full conversation here.</a></p>`, - } - ap.broadcastCreateMessage(jsonObject, event.followers, req.params.eventID) - if (sendEmails) { - Event.findOne({id: req.params.eventID}).distinct('attendees.email', function(error, ids) { - let attendeeEmails = ids; - if (!error){ - console.log("Sending emails to: " + attendeeEmails); - req.app.get('hbsInstance').renderView('./views/emails/addeventcomment.handlebars', {siteName, siteLogo, domain, eventID: req.params.eventID, commentAuthor: req.body.commentAuthor, cache: true, layout: 'email.handlebars'}, function(err, html) { - const msg = { - to: attendeeEmails, - from: { - name: siteName, - email: contactEmail, - }, - subject: `${siteName}: New comment in ${event.name}`, - html, - }; - sgMail.sendMultiple(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); + .then(() => { + addToLog("addEventComment", "success", "Comment added to event " + req.params.eventID); + // broadcast an identical message to all followers, will show in their home timeline + // and in the home timeline of the event + const guidObject = crypto.randomBytes(16).toString('hex'); + const jsonObject = { + "@context": "https://www.w3.org/ns/activitystreams", + "id": `https://${domain}/${req.params.eventID}/m/${guidObject}`, + "name": `Comment on ${event.name}`, + "type": "Note", + 'cc': 'https://www.w3.org/ns/activitystreams#Public', + "content": `<p>${req.body.commentAuthor} commented: ${req.body.commentContent}.</p><p><a href="https://${domain}/${req.params.eventID}/">See the full conversation here.</a></p>`, + } + ap.broadcastCreateMessage(jsonObject, event.followers, req.params.eventID) + if (sendEmails) { + Event.findOne({ id: req.params.eventID }).distinct('attendees.email', function (error, ids) { + let attendeeEmails = ids; + if (!error) { + console.log("Sending emails to: " + attendeeEmails); + req.app.get('hbsInstance').renderView('./views/emails/addeventcomment.handlebars', { siteName, siteLogo, domain, eventID: req.params.eventID, commentAuthor: req.body.commentAuthor, cache: true, layout: 'email.handlebars' }, function (err, html) { + const msg = { + to: attendeeEmails, + from: { + name: siteName, + email: contactEmail, + }, + subject: `${siteName}: New comment in ${event.name}`, + html, + }; + switch (mailService) { + case 'sendgrid': + sgMail.sendMultiple(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } }); - }); - } - else { - console.log("Nothing to send!"); - } - }); - } - res.writeHead(302, { - 'Location': '/' + req.params.eventID + } + else { + console.log("Nothing to send!"); + } + }); + } + res.writeHead(302, { + 'Location': '/' + req.params.eventID }); - res.end(); - }) - .catch((err) => { res.send('Database error, please try again :(' + err); addToLog("addEventComment", "error", "Attempt to add comment to event " + req.params.eventID + " failed with error: " + err); }); + res.end(); + }) + .catch((err) => { res.send('Database error, please try again :(' + err); addToLog("addEventComment", "error", "Attempt to add comment to event " + req.params.eventID + " failed with error: " + err); }); }); }); @@ -1468,11 +1602,11 @@ router.post('/post/reply/:eventID/:commentID', (req, res) => { }; Event.findOne({ id: req.params.eventID, - }, function(err,event) { - if (!event) return; - var parentComment = event.comments.id(commentID); - parentComment.replies.push(newReply); - event.save() + }, function (err, event) { + if (!event) return; + var parentComment = event.comments.id(commentID); + parentComment.replies.push(newReply); + event.save() .then(() => { addToLog("addEventReply", "success", "Reply added to comment " + commentID + " in event " + req.params.eventID); // broadcast an identical message to all followers, will show in their home timeline @@ -1487,11 +1621,11 @@ router.post('/post/reply/:eventID/:commentID', (req, res) => { } ap.broadcastCreateMessage(jsonObject, event.followers, req.params.eventID) if (sendEmails) { - Event.findOne({id: req.params.eventID}).distinct('attendees.email', function(error, ids) { + Event.findOne({ id: req.params.eventID }).distinct('attendees.email', function (error, ids) { let attendeeEmails = ids; - if (!error){ + if (!error) { console.log("Sending emails to: " + attendeeEmails); - req.app.get('hbsInstance').renderView('./views/emails/addeventcomment.handlebars', {siteName, siteLogo, domain, eventID: req.params.eventID, commentAuthor: req.body.replyAuthor, cache: true, layout: 'email.handlebars'}, function(err, html) { + req.app.get('hbsInstance').renderView('./views/emails/addeventcomment.handlebars', { siteName, siteLogo, domain, eventID: req.params.eventID, commentAuthor: req.body.replyAuthor, cache: true, layout: 'email.handlebars' }, function (err, html) { const msg = { to: attendeeEmails, from: { @@ -1501,10 +1635,20 @@ router.post('/post/reply/:eventID/:commentID', (req, res) => { subject: `${siteName}: New comment in ${event.name}`, html, }; - sgMail.sendMultiple(msg).catch(e => { - console.error(e.toString()); - res.status(500).end(); - }); + switch (mailService) { + case 'sendgrid': + sgMail.sendMultiple(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + case 'nodemailer': + nodemailerTransporter.sendMail(msg).catch(e => { + console.error(e.toString()); + res.status(500).end(); + }); + break; + } }); } else { @@ -1514,39 +1658,39 @@ router.post('/post/reply/:eventID/:commentID', (req, res) => { } res.writeHead(302, { 'Location': '/' + req.params.eventID - }); + }); res.end(); }) .catch((err) => { res.send('Database error, please try again :('); addToLog("addEventReply", "error", "Attempt to add reply to comment " + commentID + " in event " + req.params.eventID + " failed with error: " + err); }); - }); + }); }); router.post('/deletecomment/:eventID/:commentID/:editToken', (req, res) => { let submittedEditToken = req.params.editToken; Event.findOne(({ id: req.params.eventID, - })) - .then((event) => { - if (event.editToken === submittedEditToken) { - // Token matches - event.comments.id(req.params.commentID).remove(); - event.save() - .then(() => { - addToLog("deleteComment", "success", "Comment deleted from event " + req.params.eventID); - res.writeHead(302, { - 'Location': '/' + req.params.eventID + '?e=' + req.params.editToken - }); - res.end(); - }) - .catch((err) => { res.send('Sorry! Something went wrong (error deleting): ' + err); addToLog("deleteComment", "error", "Attempt to delete comment " + req.params.commentID + "from event " + req.params.eventID + " failed with error: " + err);}); - } - else { - // Token doesn't match - res.send('Sorry! Something went wrong'); - addToLog("deleteComment", "error", "Attempt to delete comment " + req.params.commentID + "from event " + req.params.eventID + " failed with error: token does not match"); - } - }) - .catch((err) => { res.send('Sorry! Something went wrong: ' + err); addToLog("deleteComment", "error", "Attempt to delete comment " + req.params.commentID + "from event " + req.params.eventID + " failed with error: " + err);}); + })) + .then((event) => { + if (event.editToken === submittedEditToken) { + // Token matches + event.comments.id(req.params.commentID).remove(); + event.save() + .then(() => { + addToLog("deleteComment", "success", "Comment deleted from event " + req.params.eventID); + res.writeHead(302, { + 'Location': '/' + req.params.eventID + '?e=' + req.params.editToken + }); + res.end(); + }) + .catch((err) => { res.send('Sorry! Something went wrong (error deleting): ' + err); addToLog("deleteComment", "error", "Attempt to delete comment " + req.params.commentID + "from event " + req.params.eventID + " failed with error: " + err); }); + } + else { + // Token doesn't match + res.send('Sorry! Something went wrong'); + addToLog("deleteComment", "error", "Attempt to delete comment " + req.params.commentID + "from event " + req.params.eventID + " failed with error: token does not match"); + } + }) + .catch((err) => { res.send('Sorry! Something went wrong: ' + err); addToLog("deleteComment", "error", "Attempt to delete comment " + req.params.commentID + "from event " + req.params.eventID + " failed with error: " + err); }); }); router.post('/activitypub/inbox', (req, res) => { @@ -1555,7 +1699,7 @@ router.post('/activitypub/inbox', (req, res) => { const signature = req.get('Signature'); let signature_header = signature.split(',').map(pair => { return pair.split('=').map(value => { - return value.replace(/^"/g, '').replace(/"$/g, '') + return value.replace(/^"/g, '').replace(/"$/g, '') }); }).reduce((acc, el) => { acc[el[0]] = el[1]; @@ -1569,7 +1713,8 @@ router.post('/activitypub/inbox', (req, res) => { headers: { 'Accept': 'application/activity+json', 'Content-Type': 'application/activity+json' - }}, function (error, response, actor) { + } + }, function (error, response, actor) { let publicKey = ''; try { @@ -1577,7 +1722,7 @@ router.post('/activitypub/inbox', (req, res) => { publicKey = JSON.parse(actor).publicKey.publicKeyPem; } } - catch(err) { + catch (err) { return res.status(500).send('Actor could not be parsed' + err); } @@ -1604,13 +1749,13 @@ router.post('/activitypub/inbox', (req, res) => { return res.status(401).send('Signature could not be verified.'); } } - catch(err) { + catch (err) { return res.status(401).send('Signature could not be verified: ' + err); } }); }); -router.use(function(req, res, next){ +router.use(function (req, res, next) { res.status(404); res.render('404', { url: req.url }); return; |