diff options
author | Raphael Kabo <raphaelkabo@hey.com> | 2023-10-08 12:11:36 +0100 |
---|---|---|
committer | Raphael Kabo <raphaelkabo@hey.com> | 2023-10-08 12:11:36 +0100 |
commit | 6b220e094f215c488eb5102e25506f5b3d371245 (patch) | |
tree | be0abbbf7a0c881d61e6375626f197c4ae124001 /src/routes | |
parent | b8e424a8602b586bbf346cd27171ede570a54973 (diff) |
Refactor: event group form and API, extract JS
Diffstat (limited to 'src/routes')
-rw-r--r-- | src/routes/event.ts | 5 | ||||
-rw-r--r-- | src/routes/frontend.ts | 37 | ||||
-rw-r--r-- | src/routes/group.ts | 240 |
3 files changed, 278 insertions, 4 deletions
diff --git a/src/routes/event.ts b/src/routes/event.ts index 375871b..be27fd4 100644 --- a/src/routes/event.ts +++ b/src/routes/event.ts @@ -74,8 +74,7 @@ router.post( img.resize(920, Jimp.AUTO) // resize .quality(80) // set JPEG quality .write("./public/events/" + eventID + ".jpg"); // save - const filename = eventID + ".jpg"; - return filename; + return eventID + ".jpg"; }) .catch((err) => { addToLog( @@ -280,8 +279,8 @@ router.put( }); } - let submittedEditToken = req.body.editToken; try { + const submittedEditToken = req.body.editToken; const event = await Event.findOne({ id: req.params.eventID, }); diff --git a/src/routes/frontend.ts b/src/routes/frontend.ts index 56ce4db..c9594ef 100644 --- a/src/routes/frontend.ts +++ b/src/routes/frontend.ts @@ -6,7 +6,7 @@ import { renderPlain } from "../util/markdown.js"; import getConfig from "../lib/config.js"; import { addToLog, exportICal } from "../helpers.js"; import Event from "../models/Event.js"; -import EventGroup from "../models/EventGroup.js"; +import EventGroup, { IEventGroup } from "../models/EventGroup.js"; const config = getConfig(); @@ -215,6 +215,31 @@ router.get("/:eventID", async (req: Request, res: Response) => { eventHasConcluded: eventHasConcluded, eventHasBegun: eventHasBegun, metadata: metadata, + jsonData: { + name: event.name, + id: event.id, + description: event.description, + location: event.location, + timezone: event.timezone, + url: event.url, + hostName: event.hostName, + creatorEmail: event.creatorEmail, + eventGroupID: event.eventGroup + ? (event.eventGroup as unknown as IEventGroup).id + : null, + eventGroupEditToken: event.eventGroup + ? (event.eventGroup as unknown as IEventGroup).editToken + : null, + usersCanAttend: event.usersCanAttend, + usersCanComment: event.usersCanComment, + maxAttendees: event.maxAttendees, + startISO: eventStartISO, + endISO: eventEndISO, + startForDateInput: parsedStartForDateInput, + endForDateInput: parsedEndForDateInput, + image: event.image, + editToken: editingEnabled ? eventEditToken : null, + }, }); } } catch (err) { @@ -321,6 +346,16 @@ router.get("/group/:eventGroupID", async (req: Request, res: Response) => { eventGroupHasHost: eventGroupHasHost, firstLoad: firstLoad, metadata: metadata, + jsonData: { + name: eventGroup.name, + id: eventGroup.id, + description: eventGroup.description, + url: eventGroup.url, + hostName: eventGroup.hostName, + creatorEmail: eventGroup.creatorEmail, + image: eventGroup.image, + editToken: editingEnabled ? eventGroupEditToken : null, + }, }); } catch (err) { addToLog( diff --git a/src/routes/group.ts b/src/routes/group.ts new file mode 100644 index 0000000..2801248 --- /dev/null +++ b/src/routes/group.ts @@ -0,0 +1,240 @@ +import { Router, Response, Request } from "express"; +import getConfig from "../lib/config.js"; +import multer from "multer"; +import { generateEditToken, generateEventID } from "../util/generator.js"; +import { validateGroupData } from "../util/validation.js"; +import Jimp from "jimp"; +import { addToLog } from "../helpers.js"; +import EventGroup from "../models/EventGroup.js"; +import { sendEmailFromTemplate } from "../lib/email.js"; + +const config = getConfig(); + +const storage = multer.memoryStorage(); +// Accept only JPEG, GIF or PNG images, up to 10MB +const upload = multer({ + storage: storage, + limits: { fileSize: 10 * 1024 * 1024 }, + fileFilter: function (_, file, cb) { + const filetypes = /jpeg|jpg|png|gif/; + const mimetype = filetypes.test(file.mimetype); + if (!mimetype) { + return cb(new Error("Only JPEG, PNG and GIF images are allowed.")); + } + cb(null, true); + }, +}); + +const router = Router(); + +router.post( + "/group", + upload.single("imageUpload"), + async (req: Request, res: Response) => { + const { data: groupData, errors } = validateGroupData(req.body); + if (errors && errors.length > 0) { + return res.status(400).json({ errors }); + } + if (!groupData) { + return res.status(400).json({ + errors: [ + { + message: "No group data was provided.", + }, + ], + }); + } + + try { + const groupID = generateEventID(); + const editToken = generateEditToken(); + let groupImageFilename; + + if (req.file?.buffer) { + groupImageFilename = await Jimp.read(req.file.buffer) + .then((img) => { + img.resize(920, Jimp.AUTO) // resize + .quality(80) // set JPEG quality + .write("./public/events/" + groupID + ".jpg"); // save + return groupID + ".jpg"; + }) + .catch((err) => { + addToLog( + "Jimp", + "error", + "Attempt to edit image failed with error: " + err, + ); + }); + } + + const eventGroup = new EventGroup({ + id: groupID, + name: groupData.eventGroupName, + description: groupData.eventGroupDescription, + image: groupImageFilename, + creatorEmail: groupData.creatorEmail, + url: groupData.eventGroupURL, + hostName: groupData.hostName, + editToken: editToken, + firstLoad: true, + }); + + await eventGroup.save(); + + addToLog( + "createEventGroup", + "success", + "Event group " + groupID + " created", + ); + + // Send email with edit link + if (groupData.creatorEmail && req.app.locals.sendEmails) { + sendEmailFromTemplate( + groupData.creatorEmail, + `${eventGroup.name}`, + "createEventGroup", + { + eventGroupID: eventGroup.id, + editToken: eventGroup.editToken, + siteName: config.general.site_name, + siteLogo: config.general.email_logo_url, + domain: config.general.domain, + }, + req, + ); + } + + res.status(200).json({ + id: groupID, + editToken: editToken, + url: `/group/${groupID}?e=${editToken}`, + }); + } catch (err) { + console.error(err); + addToLog( + "createEvent", + "error", + "Attempt to create event failed with error: " + err, + ); + return res.status(500).json({ + errors: [ + { + message: err, + }, + ], + }); + } + }, +); + +router.put( + "/group/:eventGroupID", + upload.single("imageUpload"), + async (req: Request, res: Response) => { + const { data: groupData, errors } = validateGroupData(req.body); + if (errors && errors.length > 0) { + return res.status(400).json({ errors }); + } + if (!groupData) { + return res.status(400).json({ + errors: [ + { + message: "No group data was provided.", + }, + ], + }); + } + + try { + const submittedEditToken = req.body.editToken; + const eventGroup = await EventGroup.findOne({ + id: req.params.eventGroupID, + }); + if (!eventGroup) { + return res.status(404).json({ + errors: [ + { + message: "Event group not found.", + }, + ], + }); + } + + if (eventGroup.editToken !== submittedEditToken) { + // Token doesn't match + addToLog( + "editEventGroup", + "error", + `Attempt to edit event group ${req.params.eventGroupID} failed with error: token does not match`, + ); + return res.status(403).json({ + errors: [ + { + message: "Edit token is invalid.", + }, + ], + }); + } + // Token matches + // If there is a new image, upload that first + let eventGroupID = req.params.eventGroupID; + let eventGroupImageFilename = eventGroup.image; + if (req.file?.buffer) { + Jimp.read(req.file.buffer) + .then((img) => { + img.resize(920, Jimp.AUTO) // resize + .quality(80) // set JPEG quality + .write(`./public/events/${eventGroupID}.jpg`); // save + }) + .catch((err) => { + addToLog( + "Jimp", + "error", + "Attempt to edit image failed with error: " + err, + ); + }); + eventGroupImageFilename = eventGroupID + ".jpg"; + } + + const updatedEventGroup = { + name: req.body.eventGroupName, + description: req.body.eventGroupDescription, + url: req.body.eventGroupURL, + hostName: req.body.hostName, + image: eventGroupImageFilename, + }; + + await EventGroup.findOneAndUpdate( + { id: req.params.eventGroupID }, + updatedEventGroup, + ); + + addToLog( + "editEventGroup", + "success", + "Event group " + req.params.eventGroupID + " edited", + ); + + res.sendStatus(200); + } catch (err) { + console.error(err); + addToLog( + "editEventGroup", + "error", + "Attempt to edit event group " + + req.params.eventGroupID + + " failed with error: " + + err, + ); + return res.status(500).json({ + errors: [ + { + message: err, + }, + ], + }); + } + }, +); + +export default router; |