From fa30e6712ba5d2c6e7c8d29c0d0dd82177cce69b Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Wed, 29 May 2024 19:21:08 -0700 Subject: [PATCH 1/5] attendee/reg route update --- src/services/attendees/attendee-router.ts | 36 ++++++++-------- src/services/attendees/attendee-schema.ts | 8 +--- .../registration/registration-router.ts | 42 ++++++++++++++----- .../registration/registration-schema.ts | 2 +- .../registration/registration-utils.ts | 9 ++++ 5 files changed, 63 insertions(+), 34 deletions(-) create mode 100644 src/services/registration/registration-utils.ts diff --git a/src/services/attendees/attendee-router.ts b/src/services/attendees/attendee-router.ts index 446f121..15ae4c8 100644 --- a/src/services/attendees/attendee-router.ts +++ b/src/services/attendees/attendee-router.ts @@ -42,26 +42,28 @@ attendeeRouter.get( } ); -// Check if a user email exists -attendeeRouter.get("/:email", async (req, res, next) => { - try { - const { email } = req.params; - - // Check if the user exists in the database - const userExists = await Database.ATTENDEES.exists({ email }); +attendeeRouter.get( + "/", + RoleChecker([Role.Enum.USER]), + async (req, res, next) => { + try { + const payload = res.locals.payload; + const userId = payload.userId; - if (!userExists) { - return { error: "DoesNotExist" }; - } + // Check if the user exists in the database + const user = await Database.ATTENDEES.findOne({ userId }); - const user = await Database.ATTENDEES.findOne({ - email, - }); + if (!user) { + return res + .status(StatusCodes.NOT_FOUND) + .json({ error: "UserNotFound" }); + } - return res.status(StatusCodes.OK).json(user); - } catch (error) { - next(error); + return res.status(StatusCodes.OK).json(user); + } catch (error) { + next(error); + } } -}); +); export default attendeeRouter; diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index 358795d..2b7b0db 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -6,9 +6,7 @@ const AttendeeValidator = z.object({ userId: z.string(), name: z.string(), email: z.string().email(), - events: z.array(z.string()), - dietary_restrictions: z.string(), - priority_expiry: z.date().nullable().optional(), + dietaryRestrictions: z.string().array(), points: z.number().min(0).default(0), }); @@ -17,9 +15,7 @@ const AttendeeSchema = new mongoose.Schema({ userId: { type: String, required: true, unique: true }, name: { type: String, required: true }, email: { type: String, required: true, unique: true }, - events: [{ type: mongoose.Schema.Types.ObjectId, ref: "Event" }], - dietary_restrictions: { type: String, required: true }, - priority_expiry: { type: Date, default: null }, + dietaryRestrictions: [{ type: String, required: true }], points: { type: Number, default: 0 }, }); diff --git a/src/services/registration/registration-router.ts b/src/services/registration/registration-router.ts index a2504e4..d2bff97 100644 --- a/src/services/registration/registration-router.ts +++ b/src/services/registration/registration-router.ts @@ -4,19 +4,16 @@ import { RegistrationValidator } from "./registration-schema"; import { Database } from "../../database"; import RoleChecker from "../../middleware/role-checker"; import { Role } from "../auth/auth-models"; +import { AttendeeValidator } from "../attendees/attendee-schema"; +import { registrationExists } from "./registration-utils"; const registrationRouter = Router(); // A database upsert operation to save registration mid-progress registrationRouter.post("/save", RoleChecker([]), async (req, res, next) => { try { - const registrationData = RegistrationValidator.parse(req.body); - - // Check if user already submitted registration before - const existingRegistration = await Database.REGISTRATION.findOne({ - userId: registrationData.userId, - hasSubmitted: true, - }); + const payload = res.locals.payload; + const existingRegistration = await registrationExists(payload.userId); if (existingRegistration) { return res.status(StatusCodes.CONFLICT).json({ @@ -24,6 +21,11 @@ registrationRouter.post("/save", RoleChecker([]), async (req, res, next) => { }); } + const registrationData = RegistrationValidator.parse({ + ...req.body, + userId: payload.userId, + }); + await Database.REGISTRATION.findOneAndUpdate( { userId: res.locals.payload.userId }, { @@ -41,10 +43,22 @@ registrationRouter.post("/save", RoleChecker([]), async (req, res, next) => { registrationRouter.post("/submit", RoleChecker([]), async (req, res, next) => { try { - const registrationData = RegistrationValidator.parse(req.body); + const payload = res.locals.payload; + const existingRegistration = await registrationExists(payload.userId); + + if (existingRegistration) { + return res.status(StatusCodes.CONFLICT).json({ + error: "AlreadySubmitted", + }); + } + + const registrationData = RegistrationValidator.parse({ + ...req.body, + userId: payload.userId, + }); await Database.REGISTRATION.findOneAndUpdate( - { userId: res.locals.payload.userId }, + { userId: payload.userId }, { ...registrationData, hasSubmitted: true, @@ -53,7 +67,7 @@ registrationRouter.post("/submit", RoleChecker([]), async (req, res, next) => { ); await Database.ROLES.findOneAndUpdate( - { userId: res.locals.payload.userId }, + { userId: payload.userId }, { $addToSet: { roles: Role.Values.USER, @@ -62,6 +76,14 @@ registrationRouter.post("/submit", RoleChecker([]), async (req, res, next) => { { upsert: true } ); + const attendeeData = AttendeeValidator.parse(registrationData); + + await Database.ATTENDEES.findOneAndUpdate( + { userId: payload.userId }, + attendeeData, + { upsert: true, setDefaultsOnInsert: true } + ); + return res.status(StatusCodes.OK).json(registrationData); } catch (error) { next(error); diff --git a/src/services/registration/registration-schema.ts b/src/services/registration/registration-schema.ts index c2ebf44..bc5b381 100644 --- a/src/services/registration/registration-schema.ts +++ b/src/services/registration/registration-schema.ts @@ -32,7 +32,7 @@ const RegistrationSchema = new mongoose.Schema({ university: { type: String, required: true }, graduation: { type: String, default: null }, major: { type: String, default: null }, - dietaryRstrictions: { type: String, required: true }, + dietaryRestrictions: [{ type: String, required: true }], age: { type: Number, default: null }, gender: { type: String, default: null }, race: [{ type: String }], diff --git a/src/services/registration/registration-utils.ts b/src/services/registration/registration-utils.ts new file mode 100644 index 0000000..b28e301 --- /dev/null +++ b/src/services/registration/registration-utils.ts @@ -0,0 +1,9 @@ +import { Database } from "../../database"; + +export async function registrationExists(userId: string) { + // Check if user already submitted registration before + return Database.REGISTRATION.exists({ + userId: userId, + hasSubmitted: true, + }); +} From 1b02a241fdd9fc8072a1a3aa3e6bff5c577b447a Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Wed, 29 May 2024 22:00:43 -0700 Subject: [PATCH 2/5] events currentornext --- src/services/events/events-router.ts | 36 ++++++++++++++++++++++++++++ src/services/events/events-schema.ts | 9 +++++++ 2 files changed, 45 insertions(+) diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index ffbb31f..ab29160 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -5,6 +5,42 @@ import { Database } from "../../database"; const eventsRouter = Router(); +// Get current or next event based on current time +eventsRouter.get("/currentOrNext", async (req, res, next) => { + const currentTime = new Date(); + + try { + const events = await Database.EVENTS.find().sort({ startTime: 1 }); + let currentEvent = null; + let nextEvent = null; + + for (const event of events) { + if ( + event.startTime <= currentTime && + event.endTime >= currentTime + ) { + currentEvent = event; + break; + } else if (event.startTime > currentTime) { + nextEvent = event; + break; + } + } + + if (currentEvent) { + return res.status(StatusCodes.OK).json(currentEvent); + } else if (nextEvent) { + return res.status(StatusCodes.OK).json(nextEvent); + } else { + return res + .status(StatusCodes.NO_CONTENT) + .json({ error: "DoesNotExist" }); + } + } catch (error) { + next(error); + } +}); + eventsRouter.post("/", async (req, res, next) => { try { const validatedData = EventValidator.parse(req.body); diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index 7789433..438c3a7 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -2,6 +2,9 @@ import { Schema } from "mongoose"; import { z } from "zod"; import { v4 as uuidv4 } from "uuid"; +const events = ["A", "B", "C"] as const; +export const EventType = z.enum(events); + export const EventValidator = z.object({ eventId: z.coerce.string().optional(), name: z.string(), @@ -12,6 +15,7 @@ export const EventValidator = z.object({ isVirtual: z.boolean(), imageUrl: z.string().nullable().optional(), isVisible: z.boolean().default(false), + eventType: EventType, }); export const EventSchema = new Schema({ @@ -53,4 +57,9 @@ export const EventSchema = new Schema({ type: Boolean, default: false, }, + eventType: { + type: String, + required: true, + enum: events, + }, }); From 7ae1f8eb18ccf8c1660d444fcca4d9aa4808ab7c Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Wed, 29 May 2024 22:06:56 -0700 Subject: [PATCH 3/5] events currentornext --- src/services/events/events-router.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index ab29160..9d0d9e4 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -15,13 +15,13 @@ eventsRouter.get("/currentOrNext", async (req, res, next) => { let nextEvent = null; for (const event of events) { - if ( - event.startTime <= currentTime && - event.endTime >= currentTime - ) { + let startTime: Date = event.startTime as Date; + let endTime: Date = event.endTime as Date; + + if (startTime <= currentTime && endTime >= currentTime) { currentEvent = event; break; - } else if (event.startTime > currentTime) { + } else if (startTime > currentTime) { nextEvent = event; break; } From 381bae14b4d1c00d84d454acd3e2174638d62d46 Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Wed, 29 May 2024 22:08:28 -0700 Subject: [PATCH 4/5] events currentornext --- src/services/events/events-router.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index 9d0d9e4..bbbf876 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -15,8 +15,8 @@ eventsRouter.get("/currentOrNext", async (req, res, next) => { let nextEvent = null; for (const event of events) { - let startTime: Date = event.startTime as Date; - let endTime: Date = event.endTime as Date; + const startTime: Date = event.startTime as Date; + const endTime: Date = event.endTime as Date; if (startTime <= currentTime && endTime >= currentTime) { currentEvent = event; From 31d2ff39c27ed1df870fd35ca6962c3f08a5710c Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Wed, 29 May 2024 22:54:18 -0700 Subject: [PATCH 5/5] qr code changes --- src/services/events/events-router.ts | 25 +++++-------------------- src/services/events/events-schema.ts | 5 ++--- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index bbbf876..4da7327 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -10,27 +10,12 @@ eventsRouter.get("/currentOrNext", async (req, res, next) => { const currentTime = new Date(); try { - const events = await Database.EVENTS.find().sort({ startTime: 1 }); - let currentEvent = null; - let nextEvent = null; + const event = await Database.EVENTS.findOne({ + startTime: { $gte: currentTime }, + }).sort({ startTime: 1 }); - for (const event of events) { - const startTime: Date = event.startTime as Date; - const endTime: Date = event.endTime as Date; - - if (startTime <= currentTime && endTime >= currentTime) { - currentEvent = event; - break; - } else if (startTime > currentTime) { - nextEvent = event; - break; - } - } - - if (currentEvent) { - return res.status(StatusCodes.OK).json(currentEvent); - } else if (nextEvent) { - return res.status(StatusCodes.OK).json(nextEvent); + if (event) { + return res.status(StatusCodes.OK).json(event); } else { return res .status(StatusCodes.NO_CONTENT) diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index 438c3a7..0d447f7 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -2,8 +2,7 @@ import { Schema } from "mongoose"; import { z } from "zod"; import { v4 as uuidv4 } from "uuid"; -const events = ["A", "B", "C"] as const; -export const EventType = z.enum(events); +export const EventType = z.enum(["A", "B", "C"]); export const EventValidator = z.object({ eventId: z.coerce.string().optional(), @@ -60,6 +59,6 @@ export const EventSchema = new Schema({ eventType: { type: String, required: true, - enum: events, + enum: EventType.Values, }, });