diff options
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;  | 
