From b780a2e9eae939fbbf671150ec4466f208f1ce4c Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Mon, 1 Apr 2024 18:08:54 -0500 Subject: [PATCH 01/93] starting attendee api routes --- package.json | 4 +-- src/app.ts | 44 +++++++++++++++++++++++ src/services/attendees/attendee-schema.ts | 20 +++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 src/services/attendees/attendee-schema.ts diff --git a/package.json b/package.json index 43f0f88..a0331e9 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "private": true, "version": "0.0.0", "scripts": { - "dev": "ENV=DEVELOPMENT nodemon -w src/ -x tsx src/app.ts", - "start": "ENV=PRODUCTION tsx src/app.ts", + "dev": "nodemon -w src/ -x tsx src/app.ts", + "start": "tsx src/app.ts", "lint": "yarn prettier . --write", "kill": "kill -9 $(lsof -t -i :3000)", "build": "tsc" diff --git a/src/app.ts b/src/app.ts index c4bb74f..5fb6247 100644 --- a/src/app.ts +++ b/src/app.ts @@ -9,6 +9,9 @@ import errorHandler from "./middleware/error-handler"; import authRouter from "./services/auth/auth-router"; +import { CreateAttendeeSchema } from "./services/attendees/attendee-schema"; +import { AttendeeModel } from "./services/attendees/attendee-schema"; + const app = express(); // to prevent server-side caching/returning status code 200 @@ -22,6 +25,47 @@ app.use("/", bodyParser.json()); app.use("/auth", authRouter); +// Create a new attendee +app.post("/attendees", async (req, res) => { + try { + const { name, email } = CreateAttendeeSchema.parse(req.body); + console.log("Name:", name); + console.log("Email:", email); + + // Save attendee to the database + const attendee = new AttendeeModel({ name, email }); + await attendee.save(); + + res.status(201).send("Attendee created successfully."); + } catch (error) { + console.error("Error:", error); + res.status(400).send("Error creating attendee."); + } +}); + +// Check if a user email exists +app.get("/attendees/:email", async (req, res) => { + try { + const { email } = req.params; + + // Check if the user exists in the database + const userExists = await AttendeeModel.exists({ email }); + + if (!userExists) { + return res + .status(StatusCodes.NOT_FOUND) + .send("User with that email does not exist."); + } + + return res.status(StatusCodes.OK).send("User exists."); + } catch (error) { + console.error("Error:", error); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); + } +}); + app.get("/status", (_, res) => { console.log(StatusCodes.OK); return res.status(StatusCodes.OK).send("API is alive!"); diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts new file mode 100644 index 0000000..8e936bc --- /dev/null +++ b/src/services/attendees/attendee-schema.ts @@ -0,0 +1,20 @@ +import mongoose from "mongoose"; +import { z } from "zod"; + + +// Zod schema for attendee +const CreateAttendeeSchema = z.object({ + name: z.string(), + email: z.string().email(), +}); + + +// Mongoose schema for attendee +const AttendeeSchema = new mongoose.Schema({ + name: { type: String, required: true }, + email: { type: String, required: true, unique: true }, +}); + + +export const AttendeeModel = mongoose.model("Attendee", AttendeeSchema); +export { CreateAttendeeSchema }; \ No newline at end of file From 0655b58542fd081643de4884bac59ab11be253a9 Mon Sep 17 00:00:00 2001 From: riyap Date: Tue, 2 Apr 2024 12:08:00 -0500 Subject: [PATCH 02/93] events begin --- package.json | 4 ++-- src/services/events/events-router.ts | 14 ++++++++++++ src/services/events/events-schema.ts | 34 ++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/services/events/events-router.ts create mode 100644 src/services/events/events-schema.ts diff --git a/package.json b/package.json index 43f0f88..a0331e9 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "private": true, "version": "0.0.0", "scripts": { - "dev": "ENV=DEVELOPMENT nodemon -w src/ -x tsx src/app.ts", - "start": "ENV=PRODUCTION tsx src/app.ts", + "dev": "nodemon -w src/ -x tsx src/app.ts", + "start": "tsx src/app.ts", "lint": "yarn prettier . --write", "kill": "kill -9 $(lsof -t -i :3000)", "build": "tsc" diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts new file mode 100644 index 0000000..cebbb2b --- /dev/null +++ b/src/services/events/events-router.ts @@ -0,0 +1,14 @@ +import { Router } from "express"; +import { Database } from "../database"; +import { StatusCodes } from "http-status-codes"; +import { createId } from "@paralleldrive/cuid2"; + +const authRouter = Router(); + +authRouter.get("/", async (req, res) => { +}); + +authRouter.post("/", async (req, res, next) => { +}); + +export default authRouter; \ No newline at end of file diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts new file mode 100644 index 0000000..b47e3ca --- /dev/null +++ b/src/services/events/events-schema.ts @@ -0,0 +1,34 @@ +import { Schema } from "mongoose"; +import { z } from "zod"; + +export const EventInfo = z.object({ + eventId: z.coerce.string().cuid2(), + name: z.string(), + date: z.date(), + start_time: z.date(), + end_time: z.date(), +}); + +export const EventSchema = new Schema({ + eventId: { + type: String, + required: true, + unique: true, + }, + name: { + type: String, + required: true, + }, + date: { + type: Date, + required: true + }, + start_time: { + type: Date, + required: true + }, + end_time: { + type: Date, + required: true + } +}); From d1dc4e26939f6bf743ff94244b10303238f14eab Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Sun, 7 Apr 2024 12:17:19 -0500 Subject: [PATCH 03/93] continuing attendee schema and event schema --- src/app.ts | 49 ++----------- src/services/attendees/attendee-router.ts | 49 +++++++++++++ src/services/attendees/attendee-schema.ts | 43 ++++++++++-- src/services/events/event-router.ts | 86 +++++++++++++++++++++++ src/services/events/event-schema.ts | 50 +++++++++++++ 5 files changed, 228 insertions(+), 49 deletions(-) create mode 100644 src/services/attendees/attendee-router.ts create mode 100644 src/services/events/event-router.ts create mode 100644 src/services/events/event-schema.ts diff --git a/src/app.ts b/src/app.ts index 5fb6247..7bb4ff9 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,9 +8,8 @@ import bodyParser from "body-parser"; import errorHandler from "./middleware/error-handler"; import authRouter from "./services/auth/auth-router"; - -import { CreateAttendeeSchema } from "./services/attendees/attendee-schema"; -import { AttendeeModel } from "./services/attendees/attendee-schema"; +import attendeeRouter from "./services/attendees/attendee-router"; +import eventRouter from "./services/events/event-router"; const app = express(); @@ -23,48 +22,10 @@ app.use("/", morgan("dev")); app.use("/", bodyParser.json()); +// API routes app.use("/auth", authRouter); - -// Create a new attendee -app.post("/attendees", async (req, res) => { - try { - const { name, email } = CreateAttendeeSchema.parse(req.body); - console.log("Name:", name); - console.log("Email:", email); - - // Save attendee to the database - const attendee = new AttendeeModel({ name, email }); - await attendee.save(); - - res.status(201).send("Attendee created successfully."); - } catch (error) { - console.error("Error:", error); - res.status(400).send("Error creating attendee."); - } -}); - -// Check if a user email exists -app.get("/attendees/:email", async (req, res) => { - try { - const { email } = req.params; - - // Check if the user exists in the database - const userExists = await AttendeeModel.exists({ email }); - - if (!userExists) { - return res - .status(StatusCodes.NOT_FOUND) - .send("User with that email does not exist."); - } - - return res.status(StatusCodes.OK).send("User exists."); - } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); - } -}); +app.use("/attendee", attendeeRouter); +app.use("/event", eventRouter); app.get("/status", (_, res) => { console.log(StatusCodes.OK); diff --git a/src/services/attendees/attendee-router.ts b/src/services/attendees/attendee-router.ts new file mode 100644 index 0000000..6c27a72 --- /dev/null +++ b/src/services/attendees/attendee-router.ts @@ -0,0 +1,49 @@ +import { Router } from "express"; +import { StatusCodes } from "http-status-codes"; +import { AttendeeValidator } from "./attendee-schema"; +import { AttendeeModel } from "./attendee-schema"; + +const attendeeRouter = Router(); + +// Create a new attendee +attendeeRouter.post("/", async (req, res) => { + try { + const { name, email } = AttendeeValidator.parse(req.body); + console.log("Name:", name); + console.log("Email:", email); + + // Save attendee to the database + const attendee = new AttendeeModel({ name, email }); + await attendee.save(); + + res.status(201).send("Attendee created successfully."); + } catch (error) { + console.error("Error:", error); + res.status(400).send("Error creating attendee."); + } +}); + +// Check if a user email exists +attendeeRouter.get("/:email", async (req, res) => { + try { + const { email } = req.params; + + // Check if the user exists in the database + const userExists = await AttendeeModel.exists({ email }); + + if (!userExists) { + return res + .status(StatusCodes.NOT_FOUND) + .send("User with that email does not exist."); + } + + return res.status(StatusCodes.OK).send("User exists."); + } catch (error) { + console.error("Error:", error); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); + } +}); + +export default attendeeRouter; diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index 8e936bc..c82a490 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -1,20 +1,53 @@ import mongoose from "mongoose"; import { z } from "zod"; - // Zod schema for attendee -const CreateAttendeeSchema = z.object({ +const AttendeeValidator = z.object({ name: z.string(), email: z.string().email(), + studentInfo: z.object({ + university: z.string().nonempty(), + graduation: z.string().nullable().optional(), + major: z.string().nullable().optional(), + }), + events: z.array(z.string()), + dietary_restrictions: z.string(), + age: z.number().nullable().optional(), + gender: z.string().nullable().optional(), + race: z.array(z.string()).nullable().optional(), + ethnicity: z.string().nullable().optional(), + first_gen: z.string().nullable().optional(), + hear_about_rp: z.array(z.string()).nullable().optional(), + portfolio: z.string().nullable().optional(), + job_interest: z.array(z.string()).nullable().optional(), + interest_mech_puzzle: z.array(z.string()).nullable().optional(), + priority_expiry: z.date().nullable().optional(), + has_resume: z.boolean().optional(), }); - // Mongoose schema for attendee const AttendeeSchema = new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true, unique: true }, + studentInfo: { + university: { type: String, required: true }, + graduation: { type: String, default: null }, + major: { type: String, default: null }, + }, + events: [{ type: mongoose.Schema.Types.ObjectId, ref: "Event" }], + dietary_restrictions: { type: String, required: true }, + age: { type: Number, default: null }, + gender: { type: String, default: null }, + race: [{ type: String }], + ethnicity: { type: String, default: null }, + first_gen: { type: String, default: null }, + hear_about_rp: [{ type: String }], + portfolio: { type: String, default: null }, + job_interest: [{ type: String }], + interest_mech_puzzle: [{ type: String }], + priority_expiry: { type: Date, default: null }, + has_resume: { type: Boolean, default: false }, }); - export const AttendeeModel = mongoose.model("Attendee", AttendeeSchema); -export { CreateAttendeeSchema }; \ No newline at end of file +export { AttendeeValidator }; diff --git a/src/services/events/event-router.ts b/src/services/events/event-router.ts new file mode 100644 index 0000000..360b1b3 --- /dev/null +++ b/src/services/events/event-router.ts @@ -0,0 +1,86 @@ +import { Router } from "express"; +import { StatusCodes } from "http-status-codes"; +import { EventValidator } from "./event-schema"; +import { EventModel } from "./event-schema"; + +const eventRouter = Router(); + +// Create a new event +eventRouter.post("/", async (req, res) => { + try { + const eventData = EventValidator.parse(req.body); + const event = new EventModel(eventData); + await event.save(); + res.status(StatusCodes.CREATED).json(event); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.BAD_REQUEST).send("Error creating event."); + } +}); + +// Get all events +eventRouter.get("/", async (req, res) => { + try { + const events = await EventModel.find(); + res.status(StatusCodes.OK).json(events); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( + "Internal server error." + ); + } +}); + +// Get event by ID +eventRouter.get("/:id", async (req, res) => { + try { + const event = await EventModel.findById(req.params.id); + if (!event) { + return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + } + res.status(StatusCodes.OK).json(event); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( + "Internal server error." + ); + } +}); + +// Update event +eventRouter.patch("/:id", async (req, res) => { + try { + const event = await EventModel.findByIdAndUpdate( + req.params.id, + req.body, + { new: true } + ); + if (!event) { + return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + } + res.status(StatusCodes.OK).json(event); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( + "Internal server error." + ); + } +}); + +// Delete event +eventRouter.delete("/:id", async (req, res) => { + try { + const event = await EventModel.findByIdAndDelete(req.params.id); + if (!event) { + return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + } + res.status(StatusCodes.NO_CONTENT).send(); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( + "Internal server error." + ); + } +}); + +export default eventRouter; diff --git a/src/services/events/event-schema.ts b/src/services/events/event-schema.ts new file mode 100644 index 0000000..db29a3d --- /dev/null +++ b/src/services/events/event-schema.ts @@ -0,0 +1,50 @@ +import mongoose from "mongoose"; +import { z } from "zod"; + +// Zod schema for event +const EventValidator = z.object({ + name: z.string(), + description: z.string(), + start_time: z.date(), + end_time: z.date(), + attendees: z.array(z.string()), + location: z.array( + z.object({ + description: z.string(), + tags: z.array(z.string()), + latitude: z.number(), + longitude: z.number(), + }) + ), + virtual: z.boolean(), + upgrade: z.boolean().default(false), + downgrade: z.boolean().default(false), + imageUrl: z.string().nullable().optional(), + visible: z.boolean().default(false), +}); + +// Mongoose schema for location +const LocationSchema = new mongoose.Schema({ + description: { type: String, required: true }, + tags: [{ type: String }], + latitude: { type: Number, required: true }, + longitude: { type: Number, required: true }, +}); + +// Mongoose schema for event +const EventSchema = new mongoose.Schema({ + name: { type: String, required: true }, + description: { type: String, required: true }, + start_time: { type: Date, required: true }, + end_time: { type: Date, required: true }, + attendees: [{ type: mongoose.Schema.Types.ObjectId, ref: "Attendee" }], + location: [LocationSchema], + virtual: { type: Boolean, required: true }, + upgrade: { type: Boolean, default: false }, + downgrade: { type: Boolean, default: false }, + imageUrl: { type: String, default: null }, + visible: { type: Boolean, default: false }, +}); + +export const EventModel = mongoose.model("Event", EventSchema); +export { EventValidator }; From de0e73f972f95e576d5c95fdd61af8accc579d57 Mon Sep 17 00:00:00 2001 From: riyap Date: Sun, 7 Apr 2024 17:41:02 -0500 Subject: [PATCH 04/93] post events --- src/app.ts | 2 ++ src/services/events/events-router.ts | 18 +++++++++++++----- src/services/events/events-schema.ts | 10 ++++++---- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/app.ts b/src/app.ts index c4bb74f..92c22a8 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,6 +8,7 @@ import bodyParser from "body-parser"; import errorHandler from "./middleware/error-handler"; import authRouter from "./services/auth/auth-router"; +import eventRouter from "./services/events/events-router"; const app = express(); @@ -21,6 +22,7 @@ app.use("/", morgan("dev")); app.use("/", bodyParser.json()); app.use("/auth", authRouter); +app.use('/api', eventRouter); app.get("/status", (_, res) => { console.log(StatusCodes.OK); diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index cebbb2b..471b8b4 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -1,14 +1,22 @@ import { Router } from "express"; -import { Database } from "../database"; +import { Database } from "../../database"; import { StatusCodes } from "http-status-codes"; import { createId } from "@paralleldrive/cuid2"; +import { Event, EventInfo} from './events-schema'; const authRouter = Router(); +// authRouter.get("/", async (req, res) => { +// }); -authRouter.get("/", async (req, res) => { -}); - -authRouter.post("/", async (req, res, next) => { +authRouter.post("/events", async (req, res, next) => { + try { + const validatedData = EventInfo.parse(req.body); + const event = new Event(validatedData); + await event.save(); + res.status(StatusCodes.CREATED).json(event); + } catch (error) { + next(error); + } }); export default authRouter; \ No newline at end of file diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index b47e3ca..8aaff35 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -1,12 +1,13 @@ +import mongoose from "mongoose"; import { Schema } from "mongoose"; import { z } from "zod"; -export const EventInfo = z.object({ +export const EventInfo= z.object({ eventId: z.coerce.string().cuid2(), name: z.string(), - date: z.date(), - start_time: z.date(), - end_time: z.date(), + date: z.string().transform((str) => new Date(str)), + start_time: z.string().transform((str) => new Date(str)), + end_time: z.string().transform((str) => new Date(str)), }); export const EventSchema = new Schema({ @@ -32,3 +33,4 @@ export const EventSchema = new Schema({ required: true } }); +export const Event = mongoose.model('Event', EventSchema); From 5c1e65c409c29500e6e08ec527656e77d2188fa5 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Mon, 8 Apr 2024 01:10:46 -0500 Subject: [PATCH 05/93] Added initial auth workflow --- package.json | 3 ++ src/config.ts | 5 ++ src/services/auth/auth-router.ts | 68 +++++++++++++++++------- src/services/auth/auth-schema.ts | 12 ++++- src/utilities.ts | 9 ++-- yarn.lock | 88 +++++++++++++++++++++++++++++++- 6 files changed, 158 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index dbdbe4f..5706f6d 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@types/express": "^4.17.21", "@types/morgan": "^1.9.9", "@types/node": "^20.9.3", + "@types/passport-google-oauth20": "^2.0.14", "@typescript-eslint/eslint-plugin": "^6.4.0", "eslint": "8.2.0", "eslint-config-airbnb": "19.0.4", @@ -37,6 +38,8 @@ "http-status-codes": "^2.3.0", "mongoose": "^8.2.3", "morgan": "^1.10.0", + "passport": "^0.7.0", + "passport-google-oauth20": "^2.0.0", "tsx": "^4.5.0", "typescript": "*", "zod": "^3.22.4" diff --git a/src/config.ts b/src/config.ts index e3a6f9f..9a065d0 100644 --- a/src/config.ts +++ b/src/config.ts @@ -13,4 +13,9 @@ export const Config = { DATABASE_USERNAME: getEnv("DATABASE_USERNAME"), DATABASE_PASSWORD: getEnv("DATABASE_PASSWORD"), DATABASE_HOST: getEnv("DATABASE_HOST"), + + CLIENT_ID: getEnv("OAUTH_GOOGLE_CLIENT_ID"), + CLIENT_SECRET: getEnv("OAUTH_GOOGLE_CLIENT_SECRET"), + + REDIRECT_URI: "http://localhost:3000/auth/callback", }; diff --git a/src/services/auth/auth-router.ts b/src/services/auth/auth-router.ts index fe85ca2..83cf899 100644 --- a/src/services/auth/auth-router.ts +++ b/src/services/auth/auth-router.ts @@ -1,29 +1,59 @@ import { Router } from "express"; -import { Database } from "../../database"; +import passport, { AuthenticateOptions } from "passport"; +import { Strategy as GoogleStrategy } from "passport-google-oauth20"; +import { Config } from "../../config"; import { StatusCodes } from "http-status-codes"; -import { Role } from "./auth-schema"; -import { createId } from "@paralleldrive/cuid2"; +import { Devices } from "./auth-schema"; + +passport.use( + new GoogleStrategy( + { + clientID: Config.CLIENT_ID, + clientSecret: Config.CLIENT_SECRET, + callbackURL: Config.REDIRECT_URI, + }, + function (_1, _2, profile, cb) { + cb(null, profile); + } + ) +); const authRouter = Router(); -authRouter.get("/", async (req, res) => { - const result = await Database.ROLES.find(); - const mappedResult = result.map((item) => item.toObject()); - return res.status(StatusCodes.OK).send(mappedResult); -}); +authRouter.get("/login/:DEVICE/", (req, res) => { + const device = req.params["DEVICE"]; -authRouter.post("/", async (_, res, next) => { - const user = { - userId: createId(), - roles: [Role.Enum.USER], - }; - - try { - const result = (await Database.ROLES.create(user)).toObject(); - return res.status(StatusCodes.CREATED).send(result); - } catch (err) { - next(err); + console.log(device, Devices.Values); + + if (!Devices.safeParse(device).success) { + return res.status(StatusCodes.BAD_REQUEST).send({ error: "BadDevice" }); } + + const callbackURL = `${Config.REDIRECT_URI}/${device}`; + + console.log(`|${callbackURL}|`); + return passport.authenticate("google", { + callbackURL: callbackURL, + scope: ["profile", "email"], + } as AuthenticateOptions)(req, res); }); +authRouter.get( + "/callback/", + (req, _, next) => { + console.log("HI!!! params be", req.params, req.query); + return next(); + }, + passport.authenticate("google", { + session: false, + }), + function (req, res) { + console.log("IN HERE"); + console.log(req.params); + console.log(req.query); + console.log("redirecting!"); + return res.redirect("/"); + } +); + export default authRouter; diff --git a/src/services/auth/auth-schema.ts b/src/services/auth/auth-schema.ts index 1977d83..144680c 100644 --- a/src/services/auth/auth-schema.ts +++ b/src/services/auth/auth-schema.ts @@ -3,8 +3,11 @@ import { z } from "zod"; export const Role = z.enum(["USER", "ADMIN", "CORPORATE"]); -export const RoleInfo = z.object({ - userId: z.coerce.string().cuid2(), +export const Devices = z.enum(["web"]); + +export const RoleValidator = z.object({ + userId: z.coerce.string().regex(/user[0-9]*/), + email: z.coerce.string().email(), roles: z.array(Role), }); @@ -14,6 +17,11 @@ export const RoleSchema = new Schema({ required: true, unique: true, }, + email: { + type: String, + required: true, + unique: true, + }, roles: { type: [String], enum: Role.Values, diff --git a/src/utilities.ts b/src/utilities.ts index 685ef19..39fc28b 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -29,9 +29,10 @@ export function isDev() { return Config.ENV == Environment.enum.DEVELOPMENT; } -export function getEnv(target: string) { - if (process.env[target] === undefined) { - throw new Error(`env value ${target} not found, exiting...`); +export function getEnv(key: string): string { + const val = process.env[key]; + if (val === undefined) { + throw new Error(`env value ${key} not found, exiting...`); } - return process.env[target]; + return val; } diff --git a/yarn.lock b/yarn.lock index 981781b..7fad951 100644 --- a/yarn.lock +++ b/yarn.lock @@ -255,7 +255,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express@^4.17.21": +"@types/express@*", "@types/express@^4.17.21": version "4.17.21" resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz" integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== @@ -304,6 +304,38 @@ dependencies: undici-types "~5.26.4" +"@types/oauth@*": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@types/oauth/-/oauth-0.9.4.tgz#dcbab5efa2f34f312b915f80685760ccc8111e0a" + integrity sha512-qk9orhti499fq5XxKCCEbd0OzdPZuancneyse3KtR+vgMiHRbh+mn8M4G6t64ob/Fg+GZGpa565MF/2dKWY32A== + dependencies: + "@types/node" "*" + +"@types/passport-google-oauth20@^2.0.14": + version "2.0.14" + resolved "https://registry.yarnpkg.com/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.14.tgz#6facba6f73f0aff3888564ebc907afe295c30fba" + integrity sha512-ZaZpRUAeMl3vy298ulKO1wGLn9SQtj/CyIfZL/Px5xU9pybMiQU3mhXDCBiWSbg0EK9uXT4ZoWC3ktuWY+5fwQ== + dependencies: + "@types/express" "*" + "@types/passport" "*" + "@types/passport-oauth2" "*" + +"@types/passport-oauth2@*": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@types/passport-oauth2/-/passport-oauth2-1.4.15.tgz#34f2684f53aad36e664cd01ca9879224229f47e7" + integrity sha512-9cUTP/HStNSZmhxXGuRrBJfEWzIEJRub2eyJu3CvkA+8HAMc9W3aKdFhVq+Qz1hi42qn+GvSAnz3zwacDSYWpw== + dependencies: + "@types/express" "*" + "@types/oauth" "*" + "@types/passport" "*" + +"@types/passport@*": + version "1.0.16" + resolved "https://registry.yarnpkg.com/@types/passport/-/passport-1.0.16.tgz#5a2918b180a16924c4d75c31254c31cdca5ce6cf" + integrity sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A== + dependencies: + "@types/express" "*" + "@types/qs@*": version "6.9.14" resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz" @@ -596,6 +628,11 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64url@3.x.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" + integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== + basic-auth@~2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz" @@ -2108,6 +2145,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +oauth@0.10.x: + version "0.10.0" + resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.10.0.tgz#3551c4c9b95c53ea437e1e21e46b649482339c58" + integrity sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q== + object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -2220,6 +2262,38 @@ parseurl@~1.3.3: resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +passport-google-oauth20@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz#0d241b2d21ebd3dc7f2b60669ec4d587e3a674ef" + integrity sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ== + dependencies: + passport-oauth2 "1.x.x" + +passport-oauth2@1.x.x: + version "1.8.0" + resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.8.0.tgz#55725771d160f09bbb191828d5e3d559eee079c8" + integrity sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA== + dependencies: + base64url "3.x.x" + oauth "0.10.x" + passport-strategy "1.x.x" + uid2 "0.0.x" + utils-merge "1.x.x" + +passport-strategy@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== + +passport@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.7.0.tgz#3688415a59a48cf8068417a8a8092d4492ca3a05" + integrity sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + utils-merge "^1.0.1" + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" @@ -2245,6 +2319,11 @@ path-type@^4.0.0: resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pause@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" @@ -2783,6 +2862,11 @@ typescript@*: resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz" integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== +uid2@0.0.x: + version "0.0.4" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.4.tgz#033f3b1d5d32505f5ce5f888b9f3b667123c0a44" + integrity sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz" @@ -2815,7 +2899,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -utils-merge@1.0.1: +utils-merge@1.0.1, utils-merge@1.x.x, utils-merge@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== From 24cef556edad2f430fc41824ef73bd6963e119c2 Mon Sep 17 00:00:00 2001 From: riyap Date: Mon, 8 Apr 2024 16:10:00 -0500 Subject: [PATCH 06/93] events but linted --- .github/workflows/build.yml | 48 ++++++++++++++-------------- src/app.ts | 2 +- src/services/events/events-router.ts | 10 +++--- src/services/events/events-schema.ts | 12 +++---- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3b050e5..d837ecb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,24 +1,24 @@ -name: Prettier on Push and PR - -on: - push: - branches: - - 'main' - - 'dev**' - pull_request: - branches: - - 'main' - -jobs: - prettier: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '18.x' - - name: Install dependencies - run: yarn - - name: Run Prettier - run: npx prettier --write . \ No newline at end of file +name: Prettier on Push and PR + +on: + push: + branches: + - "main" + - "dev**" + pull_request: + branches: + - "main" + +jobs: + prettier: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "18.x" + - name: Install dependencies + run: yarn + - name: Run Prettier + run: npx prettier --write . diff --git a/src/app.ts b/src/app.ts index 92c22a8..f59e549 100644 --- a/src/app.ts +++ b/src/app.ts @@ -22,7 +22,7 @@ app.use("/", morgan("dev")); app.use("/", bodyParser.json()); app.use("/auth", authRouter); -app.use('/api', eventRouter); +app.use("/api", eventRouter); app.get("/status", (_, res) => { console.log(StatusCodes.OK); diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index 471b8b4..5259801 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -2,7 +2,7 @@ import { Router } from "express"; import { Database } from "../../database"; import { StatusCodes } from "http-status-codes"; import { createId } from "@paralleldrive/cuid2"; -import { Event, EventInfo} from './events-schema'; +import { Event, EventInfo } from "./events-schema"; const authRouter = Router(); // authRouter.get("/", async (req, res) => { @@ -13,10 +13,10 @@ authRouter.post("/events", async (req, res, next) => { const validatedData = EventInfo.parse(req.body); const event = new Event(validatedData); await event.save(); - res.status(StatusCodes.CREATED).json(event); - } catch (error) { + return res.status(StatusCodes.CREATED).json(event); + } catch (error) { next(error); - } + } }); -export default authRouter; \ No newline at end of file +export default authRouter; diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index 8aaff35..561cbb2 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -2,7 +2,7 @@ import mongoose from "mongoose"; import { Schema } from "mongoose"; import { z } from "zod"; -export const EventInfo= z.object({ +export const EventInfo = z.object({ eventId: z.coerce.string().cuid2(), name: z.string(), date: z.string().transform((str) => new Date(str)), @@ -22,15 +22,15 @@ export const EventSchema = new Schema({ }, date: { type: Date, - required: true + required: true, }, start_time: { type: Date, - required: true + required: true, }, end_time: { type: Date, - required: true - } + required: true, + }, }); -export const Event = mongoose.model('Event', EventSchema); +export const Event = mongoose.model("Event", EventSchema); From de40d35285678c6ee79b91d6dd1993447993d602 Mon Sep 17 00:00:00 2001 From: riyap Date: Tue, 9 Apr 2024 17:31:50 -0500 Subject: [PATCH 07/93] Update src/services/events/events-router.ts Co-authored-by: Aydan Pirani --- src/services/events/events-router.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index 5259801..9a7bfb8 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -1,5 +1,4 @@ import { Router } from "express"; -import { Database } from "../../database"; import { StatusCodes } from "http-status-codes"; import { createId } from "@paralleldrive/cuid2"; import { Event, EventInfo } from "./events-schema"; From 1f54da95471036e58cfdb5dec178c24b038898ca Mon Sep 17 00:00:00 2001 From: riyap Date: Tue, 9 Apr 2024 17:31:57 -0500 Subject: [PATCH 08/93] Update src/services/events/events-router.ts Co-authored-by: Aydan Pirani --- src/services/events/events-router.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index 9a7bfb8..10dd386 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -1,6 +1,5 @@ import { Router } from "express"; import { StatusCodes } from "http-status-codes"; -import { createId } from "@paralleldrive/cuid2"; import { Event, EventInfo } from "./events-schema"; const authRouter = Router(); From 85dccb18303f7a99737324c7f4828d3a6269fc17 Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 17:57:42 -0500 Subject: [PATCH 09/93] request changes --- src/app.ts | 2 +- src/database.ts | 7 +++ src/services/attendees/attendee-router.ts | 24 ++++++----- src/services/attendees/attendee-schema.ts | 3 +- src/services/events/event-router.ts | 52 ++++++++++++----------- src/services/events/event-schema.ts | 3 +- 6 files changed, 51 insertions(+), 40 deletions(-) diff --git a/src/app.ts b/src/app.ts index 7bb4ff9..bcfb50a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -23,8 +23,8 @@ app.use("/", morgan("dev")); app.use("/", bodyParser.json()); // API routes -app.use("/auth", authRouter); app.use("/attendee", attendeeRouter); +app.use("/auth", authRouter); app.use("/event", eventRouter); app.get("/status", (_, res) => { diff --git a/src/database.ts b/src/database.ts index 2e8c4c5..4d58e4f 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,5 +1,10 @@ import mongoose, { Schema } from "mongoose"; import { RoleInfo, RoleSchema } from "./services/auth/auth-schema"; +import { EventValidator, EventSchema } from "./services/events/event-schema"; +import { + AttendeeSchema, + AttendeeValidator, +} from "./services/attendees/attendee-schema"; mongoose.set("toObject", { versionKey: false }); @@ -32,4 +37,6 @@ function initializeModel( // Example usage export const Database = { ROLES: initializeModel("roles", RoleSchema, RoleInfo), + EVENTS: initializeModel("events", EventSchema, EventValidator), + ATTENDEES: initializeModel("attendees", AttendeeSchema, AttendeeValidator), }; diff --git a/src/services/attendees/attendee-router.ts b/src/services/attendees/attendee-router.ts index 6c27a72..a5ebfac 100644 --- a/src/services/attendees/attendee-router.ts +++ b/src/services/attendees/attendee-router.ts @@ -1,25 +1,23 @@ import { Router } from "express"; import { StatusCodes } from "http-status-codes"; import { AttendeeValidator } from "./attendee-schema"; -import { AttendeeModel } from "./attendee-schema"; +import { Database } from "../../database"; const attendeeRouter = Router(); // Create a new attendee attendeeRouter.post("/", async (req, res) => { try { - const { name, email } = AttendeeValidator.parse(req.body); - console.log("Name:", name); - console.log("Email:", email); - - // Save attendee to the database - const attendee = new AttendeeModel({ name, email }); + const attendeeData = AttendeeValidator.parse(req.body); + const attendee = new Database.ATTENDEES(attendeeData); await attendee.save(); - res.status(201).send("Attendee created successfully."); + return res.status(StatusCodes.CREATED).json(attendeeData); } catch (error) { console.error("Error:", error); - res.status(400).send("Error creating attendee."); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Error creating attendee."); } }); @@ -29,7 +27,7 @@ attendeeRouter.get("/:email", async (req, res) => { const { email } = req.params; // Check if the user exists in the database - const userExists = await AttendeeModel.exists({ email }); + const userExists = await Database.ATTENDEES.exists({ email }); if (!userExists) { return res @@ -37,7 +35,11 @@ attendeeRouter.get("/:email", async (req, res) => { .send("User with that email does not exist."); } - return res.status(StatusCodes.OK).send("User exists."); + const user = await Database.ATTENDEES.findOne({ + email, + }); + + return res.status(StatusCodes.OK).json(user); } catch (error) { console.error("Error:", error); return res diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index c82a490..279a125 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -49,5 +49,4 @@ const AttendeeSchema = new mongoose.Schema({ has_resume: { type: Boolean, default: false }, }); -export const AttendeeModel = mongoose.model("Attendee", AttendeeSchema); -export { AttendeeValidator }; +export { AttendeeSchema, AttendeeValidator }; diff --git a/src/services/events/event-router.ts b/src/services/events/event-router.ts index 360b1b3..f365ea1 100644 --- a/src/services/events/event-router.ts +++ b/src/services/events/event-router.ts @@ -1,7 +1,7 @@ import { Router } from "express"; import { StatusCodes } from "http-status-codes"; import { EventValidator } from "./event-schema"; -import { EventModel } from "./event-schema"; +import { Database } from "../../database"; const eventRouter = Router(); @@ -9,77 +9,81 @@ const eventRouter = Router(); eventRouter.post("/", async (req, res) => { try { const eventData = EventValidator.parse(req.body); - const event = new EventModel(eventData); + const event = new Database.EVENTS(eventData); await event.save(); - res.status(StatusCodes.CREATED).json(event); + return res.status(StatusCodes.CREATED).json(event); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.BAD_REQUEST).send("Error creating event."); + return res + .status(StatusCodes.BAD_REQUEST) + .send("Error creating event."); } }); // Get all events eventRouter.get("/", async (req, res) => { try { - const events = await EventModel.find(); - res.status(StatusCodes.OK).json(events); + const events = await Database.EVENTS.find(); + return res.status(StatusCodes.OK).json(events); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( - "Internal server error." - ); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); } }); // Get event by ID eventRouter.get("/:id", async (req, res) => { try { - const event = await EventModel.findById(req.params.id); + const event = await Database.EVENTS.findById(req.params.id); if (!event) { return res.status(StatusCodes.NOT_FOUND).send("Event not found."); } - res.status(StatusCodes.OK).json(event); + return res.status(StatusCodes.OK).json(event); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( - "Internal server error." - ); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); } }); // Update event eventRouter.patch("/:id", async (req, res) => { try { - const event = await EventModel.findByIdAndUpdate( + const event = await Database.EVENTS.findByIdAndUpdate( req.params.id, req.body, { new: true } ); + if (!event) { return res.status(StatusCodes.NOT_FOUND).send("Event not found."); } - res.status(StatusCodes.OK).json(event); + + return res.status(StatusCodes.OK).json(event); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( - "Internal server error." - ); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); } }); // Delete event eventRouter.delete("/:id", async (req, res) => { try { - const event = await EventModel.findByIdAndDelete(req.params.id); + const event = await Database.EVENTS.findByIdAndDelete(req.params.id); if (!event) { return res.status(StatusCodes.NOT_FOUND).send("Event not found."); } - res.status(StatusCodes.NO_CONTENT).send(); + return res.status(StatusCodes.NO_CONTENT).send(); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( - "Internal server error." - ); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); } }); diff --git a/src/services/events/event-schema.ts b/src/services/events/event-schema.ts index db29a3d..768be72 100644 --- a/src/services/events/event-schema.ts +++ b/src/services/events/event-schema.ts @@ -46,5 +46,4 @@ const EventSchema = new mongoose.Schema({ visible: { type: Boolean, default: false }, }); -export const EventModel = mongoose.model("Event", EventSchema); -export { EventValidator }; +export { EventSchema, EventValidator, LocationSchema }; From 5cd4a39ea883d8c70ac2ef4026e8fe357b407920 Mon Sep 17 00:00:00 2001 From: riyap Date: Tue, 9 Apr 2024 17:58:42 -0500 Subject: [PATCH 10/93] pr fixes for basic events --- src/app.ts | 2 +- src/database.ts | 2 ++ src/services/events/events-router.ts | 10 +++++----- src/services/events/events-schema.ts | 11 +++-------- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/app.ts b/src/app.ts index f59e549..81276cb 100644 --- a/src/app.ts +++ b/src/app.ts @@ -22,7 +22,7 @@ app.use("/", morgan("dev")); app.use("/", bodyParser.json()); app.use("/auth", authRouter); -app.use("/api", eventRouter); +app.use("/event", eventRouter); app.get("/status", (_, res) => { console.log(StatusCodes.OK); diff --git a/src/database.ts b/src/database.ts index 2e8c4c5..9394232 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,5 +1,6 @@ import mongoose, { Schema } from "mongoose"; import { RoleInfo, RoleSchema } from "./services/auth/auth-schema"; +import {EventSchema, EventValidator} from "./services/events/events-schema" mongoose.set("toObject", { versionKey: false }); @@ -32,4 +33,5 @@ function initializeModel( // Example usage export const Database = { ROLES: initializeModel("roles", RoleSchema, RoleInfo), + Event: initializeModel("Event", EventSchema, EventValidator), }; diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index 5259801..4b21779 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -2,15 +2,15 @@ import { Router } from "express"; import { Database } from "../../database"; import { StatusCodes } from "http-status-codes"; import { createId } from "@paralleldrive/cuid2"; -import { Event, EventInfo } from "./events-schema"; +import { Event, EventValidator } from "./events-schema"; -const authRouter = Router(); +const eventRouter = Router(); // authRouter.get("/", async (req, res) => { // }); -authRouter.post("/events", async (req, res, next) => { +eventRouter.post("/events", async (req, res, next) => { try { - const validatedData = EventInfo.parse(req.body); + const validatedData = EventValidator.parse(req.body); const event = new Event(validatedData); await event.save(); return res.status(StatusCodes.CREATED).json(event); @@ -19,4 +19,4 @@ authRouter.post("/events", async (req, res, next) => { } }); -export default authRouter; +export default eventRouter; diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index 561cbb2..bc4ba24 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -2,12 +2,11 @@ import mongoose from "mongoose"; import { Schema } from "mongoose"; import { z } from "zod"; -export const EventInfo = z.object({ +export const EventValidator = z.object({ eventId: z.coerce.string().cuid2(), name: z.string(), - date: z.string().transform((str) => new Date(str)), - start_time: z.string().transform((str) => new Date(str)), - end_time: z.string().transform((str) => new Date(str)), + start_time: z.coerce.string().datetime(), + end_time: z.coerce.string().datetime() }); export const EventSchema = new Schema({ @@ -20,10 +19,6 @@ export const EventSchema = new Schema({ type: String, required: true, }, - date: { - type: Date, - required: true, - }, start_time: { type: Date, required: true, From c6c74c97abb26e9232fed84aaeeb21d238e263e2 Mon Sep 17 00:00:00 2001 From: riyap Date: Tue, 9 Apr 2024 18:08:43 -0500 Subject: [PATCH 11/93] linted too --- src/database.ts | 2 +- src/services/events/events-schema.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/database.ts b/src/database.ts index 9394232..471c818 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,6 +1,6 @@ import mongoose, { Schema } from "mongoose"; import { RoleInfo, RoleSchema } from "./services/auth/auth-schema"; -import {EventSchema, EventValidator} from "./services/events/events-schema" +import { EventSchema, EventValidator } from "./services/events/events-schema"; mongoose.set("toObject", { versionKey: false }); diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index bc4ba24..26b4116 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -6,7 +6,7 @@ export const EventValidator = z.object({ eventId: z.coerce.string().cuid2(), name: z.string(), start_time: z.coerce.string().datetime(), - end_time: z.coerce.string().datetime() + end_time: z.coerce.string().datetime(), }); export const EventSchema = new Schema({ From d8841b19bf9af802d7031030713435c54f877b59 Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 18:14:33 -0500 Subject: [PATCH 12/93] error messages --- src/services/attendees/attendee-router.ts | 18 ++------ src/services/events/event-router.ts | 56 ++++++++++------------- 2 files changed, 29 insertions(+), 45 deletions(-) diff --git a/src/services/attendees/attendee-router.ts b/src/services/attendees/attendee-router.ts index a5ebfac..8006361 100644 --- a/src/services/attendees/attendee-router.ts +++ b/src/services/attendees/attendee-router.ts @@ -6,7 +6,7 @@ import { Database } from "../../database"; const attendeeRouter = Router(); // Create a new attendee -attendeeRouter.post("/", async (req, res) => { +attendeeRouter.post("/", async (req, res, next) => { try { const attendeeData = AttendeeValidator.parse(req.body); const attendee = new Database.ATTENDEES(attendeeData); @@ -14,15 +14,12 @@ attendeeRouter.post("/", async (req, res) => { return res.status(StatusCodes.CREATED).json(attendeeData); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Error creating attendee."); + next(error); } }); // Check if a user email exists -attendeeRouter.get("/:email", async (req, res) => { +attendeeRouter.get("/:email", async (req, res, next) => { try { const { email } = req.params; @@ -30,9 +27,7 @@ attendeeRouter.get("/:email", async (req, res) => { const userExists = await Database.ATTENDEES.exists({ email }); if (!userExists) { - return res - .status(StatusCodes.NOT_FOUND) - .send("User with that email does not exist."); + return { error: "DoesNotExist" }; } const user = await Database.ATTENDEES.findOne({ @@ -41,10 +36,7 @@ attendeeRouter.get("/:email", async (req, res) => { return res.status(StatusCodes.OK).json(user); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); diff --git a/src/services/events/event-router.ts b/src/services/events/event-router.ts index f365ea1..f7e154a 100644 --- a/src/services/events/event-router.ts +++ b/src/services/events/event-router.ts @@ -6,84 +6,76 @@ import { Database } from "../../database"; const eventRouter = Router(); // Create a new event -eventRouter.post("/", async (req, res) => { +eventRouter.post("/", async (req, res, next) => { try { const eventData = EventValidator.parse(req.body); const event = new Database.EVENTS(eventData); await event.save(); return res.status(StatusCodes.CREATED).json(event); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.BAD_REQUEST) - .send("Error creating event."); + next(error); } }); // Get all events -eventRouter.get("/", async (req, res) => { +eventRouter.get("/", async (req, res, next) => { try { const events = await Database.EVENTS.find(); return res.status(StatusCodes.OK).json(events); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); // Get event by ID -eventRouter.get("/:id", async (req, res) => { +eventRouter.get("/:id", async (req, res, next) => { try { - const event = await Database.EVENTS.findById(req.params.id); + const event = await Database.EVENTS.findOneAndUpdate( + { _id: req.params.id }, + { new: true } + ); + if (!event) { - return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + return { error: "DoesNotExist" }; } + return res.status(StatusCodes.OK).json(event); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); // Update event -eventRouter.patch("/:id", async (req, res) => { +eventRouter.patch("/:id", async (req, res, next) => { try { - const event = await Database.EVENTS.findByIdAndUpdate( - req.params.id, + const event = await Database.EVENTS.findOneAndUpdate( + { _id: req.params.id }, req.body, { new: true } ); if (!event) { - return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + return { error: "DoesNotExist" }; } return res.status(StatusCodes.OK).json(event); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); // Delete event -eventRouter.delete("/:id", async (req, res) => { +eventRouter.delete("/:id", async (req, res, next) => { try { const event = await Database.EVENTS.findByIdAndDelete(req.params.id); + if (!event) { - return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + return { error: "DoesNotExist" }; } - return res.status(StatusCodes.NO_CONTENT).send(); + + return res.status(StatusCodes.OK).json(event); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); From 0057b2a5b660ca56575779035dcbec2a7adbf65a Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 18:17:35 -0500 Subject: [PATCH 13/93] event points --- src/services/events/event-schema.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/services/events/event-schema.ts b/src/services/events/event-schema.ts index 768be72..73890cd 100644 --- a/src/services/events/event-schema.ts +++ b/src/services/events/event-schema.ts @@ -17,8 +17,7 @@ const EventValidator = z.object({ }) ), virtual: z.boolean(), - upgrade: z.boolean().default(false), - downgrade: z.boolean().default(false), + points: z.number().min(0).default(0), imageUrl: z.string().nullable().optional(), visible: z.boolean().default(false), }); @@ -40,8 +39,7 @@ const EventSchema = new mongoose.Schema({ attendees: [{ type: mongoose.Schema.Types.ObjectId, ref: "Attendee" }], location: [LocationSchema], virtual: { type: Boolean, required: true }, - upgrade: { type: Boolean, default: false }, - downgrade: { type: Boolean, default: false }, + points: { type: Number, default: 0 }, imageUrl: { type: String, default: null }, visible: { type: Boolean, default: false }, }); From 4b1c8ab1fbc9446484ce23ffa9e865c9d87001d7 Mon Sep 17 00:00:00 2001 From: riyap Date: Tue, 9 Apr 2024 18:21:47 -0500 Subject: [PATCH 14/93] Update src/database.ts Co-authored-by: Aydan Pirani --- src/database.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database.ts b/src/database.ts index 471c818..2061d8a 100644 --- a/src/database.ts +++ b/src/database.ts @@ -33,5 +33,5 @@ function initializeModel( // Example usage export const Database = { ROLES: initializeModel("roles", RoleSchema, RoleInfo), - Event: initializeModel("Event", EventSchema, EventValidator), + EVENT: initializeModel("events", EventSchema, EventValidator), }; From 1bc5fa6d90ceb1ae313c15e37e961f5c96ab3837 Mon Sep 17 00:00:00 2001 From: riyap Date: Tue, 9 Apr 2024 18:22:17 -0500 Subject: [PATCH 15/93] Update src/services/events/events-schema.ts Co-authored-by: Aydan Pirani --- src/services/events/events-schema.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index 26b4116..f1a3d59 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -5,8 +5,8 @@ import { z } from "zod"; export const EventValidator = z.object({ eventId: z.coerce.string().cuid2(), name: z.string(), - start_time: z.coerce.string().datetime(), - end_time: z.coerce.string().datetime(), + startTime: z.coerce.string().datetime(), + endTime: z.coerce.string().datetime(), }); export const EventSchema = new Schema({ From fd4ede4720d9e36316da2327e8fefd9a072e14bf Mon Sep 17 00:00:00 2001 From: riyap Date: Tue, 9 Apr 2024 18:22:23 -0500 Subject: [PATCH 16/93] Update src/services/events/events-schema.ts Co-authored-by: Aydan Pirani --- src/services/events/events-schema.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index f1a3d59..91f6b1e 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -19,11 +19,11 @@ export const EventSchema = new Schema({ type: String, required: true, }, - start_time: { + startTime: { type: Date, required: true, }, - end_time: { + endTime: { type: Date, required: true, }, From 4e64b938a0f920a9ab2e07f0f3211f24feeeb10e Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 18:32:52 -0500 Subject: [PATCH 17/93] registration schema --- src/app.ts | 2 ++ src/config.ts | 2 ++ src/database.ts | 9 ++++++++ src/services/attendees/attendee-schema.ts | 2 ++ .../registration/registration-router.ts | 10 +++++++++ .../registration/registration-schema.ts | 22 +++++++++++++++++++ 6 files changed, 47 insertions(+) create mode 100644 src/services/registration/registration-router.ts create mode 100644 src/services/registration/registration-schema.ts diff --git a/src/app.ts b/src/app.ts index bcfb50a..632e8cb 100644 --- a/src/app.ts +++ b/src/app.ts @@ -10,6 +10,7 @@ import errorHandler from "./middleware/error-handler"; import authRouter from "./services/auth/auth-router"; import attendeeRouter from "./services/attendees/attendee-router"; import eventRouter from "./services/events/event-router"; +import registrationRouter from "./services/registration/registration-router"; const app = express(); @@ -26,6 +27,7 @@ app.use("/", bodyParser.json()); app.use("/attendee", attendeeRouter); app.use("/auth", authRouter); app.use("/event", eventRouter); +app.use("/registration", registrationRouter); app.get("/status", (_, res) => { console.log(StatusCodes.OK); diff --git a/src/config.ts b/src/config.ts index e3a6f9f..d6fbe74 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,6 +6,8 @@ import { getEnv } from "./utilities"; export const Environment = z.enum(["PRODUCTION", "DEVELOPMENT", "TESTING"]); +export const ListName = z.enum(["RP_INTEREST"]); + export const Config = { DEFAULT_APP_PORT: 3000, ENV: Environment.parse(getEnv("ENV")), diff --git a/src/database.ts b/src/database.ts index 4d58e4f..15b4aca 100644 --- a/src/database.ts +++ b/src/database.ts @@ -5,6 +5,10 @@ import { AttendeeSchema, AttendeeValidator, } from "./services/attendees/attendee-schema"; +import { + RegistrationSchema, + RegistrationValidator, +} from "./services/registration/registration-schema"; mongoose.set("toObject", { versionKey: false }); @@ -39,4 +43,9 @@ export const Database = { ROLES: initializeModel("roles", RoleSchema, RoleInfo), EVENTS: initializeModel("events", EventSchema, EventValidator), ATTENDEES: initializeModel("attendees", AttendeeSchema, AttendeeValidator), + REGISTRATION: initializeModel( + "registration", + RegistrationSchema, + RegistrationValidator + ), }; diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index 279a125..79baebe 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -23,6 +23,7 @@ const AttendeeValidator = z.object({ interest_mech_puzzle: z.array(z.string()).nullable().optional(), priority_expiry: z.date().nullable().optional(), has_resume: z.boolean().optional(), + points: z.number().min(0).default(0), // }); // Mongoose schema for attendee @@ -47,6 +48,7 @@ const AttendeeSchema = new mongoose.Schema({ interest_mech_puzzle: [{ type: String }], priority_expiry: { type: Date, default: null }, has_resume: { type: Boolean, default: false }, + points: { type: Number, default: 0 }, }); export { AttendeeSchema, AttendeeValidator }; diff --git a/src/services/registration/registration-router.ts b/src/services/registration/registration-router.ts new file mode 100644 index 0000000..18d0210 --- /dev/null +++ b/src/services/registration/registration-router.ts @@ -0,0 +1,10 @@ +import { Router } from "express"; +import { StatusCodes } from "http-status-codes"; +import { RegistrationValidator } from "./registration-schema"; +import { Database } from "../../database"; + +const registrationRouter = Router(); + +// TODO: registration routes + +export default registrationRouter; diff --git a/src/services/registration/registration-schema.ts b/src/services/registration/registration-schema.ts new file mode 100644 index 0000000..2a35c14 --- /dev/null +++ b/src/services/registration/registration-schema.ts @@ -0,0 +1,22 @@ +import mongoose from "mongoose"; +import { z } from "zod"; + +// Zod schema for registration +const RegistrationValidator = z.object({ + name: z.string(), + email: z.string().email(), + events: z.array(z.string()), + dietary_restrictions: z.string(), + points: z.number().min(0).default(0), +}); + +// Mongoose schema for registration +const RegistrationSchema = new mongoose.Schema({ + 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 }, + points: { type: Number, default: 0 }, +}); + +export { RegistrationSchema, RegistrationValidator }; From 01a61c9d9bd1e26aa262b7076afc0fb2fb8b63c4 Mon Sep 17 00:00:00 2001 From: riyap Date: Tue, 9 Apr 2024 18:57:12 -0500 Subject: [PATCH 18/93] hopefully done events --- src/services/events/events-router.ts | 5 +++-- src/services/events/events-schema.ts | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index 29181bf..700e247 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -1,6 +1,7 @@ import { Router } from "express"; import { StatusCodes } from "http-status-codes"; -import { Event, EventValidator } from "./events-schema"; +import { EventValidator } from "./events-schema"; +import { Database } from "../../database"; const eventRouter = Router(); // authRouter.get("/", async (req, res) => { @@ -9,7 +10,7 @@ const eventRouter = Router(); eventRouter.post("/events", async (req, res, next) => { try { const validatedData = EventValidator.parse(req.body); - const event = new Event(validatedData); + const event = new Database.EVENT(validatedData); await event.save(); return res.status(StatusCodes.CREATED).json(event); } catch (error) { diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index 91f6b1e..6df2fef 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -1,12 +1,12 @@ -import mongoose from "mongoose"; +// import mongoose from "mongoose"; import { Schema } from "mongoose"; import { z } from "zod"; export const EventValidator = z.object({ eventId: z.coerce.string().cuid2(), name: z.string(), - startTime: z.coerce.string().datetime(), - endTime: z.coerce.string().datetime(), + startTime: z.coerce.date(), + endTime: z.coerce.date(), }); export const EventSchema = new Schema({ @@ -28,4 +28,4 @@ export const EventSchema = new Schema({ required: true, }, }); -export const Event = mongoose.model("Event", EventSchema); +// export const Event = mongoose.model("Event", EventSchema); From 94c4591b3d2d47dba709e9926574c8bc88c9ed68 Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 19:04:24 -0500 Subject: [PATCH 19/93] subscription basic --- src/app.ts | 2 ++ src/config.ts | 2 +- src/database.ts | 9 +++++++++ .../subscription/subscription-router.ts | 19 +++++++++++++++++++ .../subscription/subscription-schema.ts | 17 +++++++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/services/subscription/subscription-router.ts create mode 100644 src/services/subscription/subscription-schema.ts diff --git a/src/app.ts b/src/app.ts index 632e8cb..642b78d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -11,6 +11,7 @@ import authRouter from "./services/auth/auth-router"; import attendeeRouter from "./services/attendees/attendee-router"; import eventRouter from "./services/events/event-router"; import registrationRouter from "./services/registration/registration-router"; +import subscriptionRouter from "./services/subscription/subscription-router"; const app = express(); @@ -28,6 +29,7 @@ app.use("/attendee", attendeeRouter); app.use("/auth", authRouter); app.use("/event", eventRouter); app.use("/registration", registrationRouter); +app.use("/subscription", subscriptionRouter); app.get("/status", (_, res) => { console.log(StatusCodes.OK); diff --git a/src/config.ts b/src/config.ts index d6fbe74..a0f7e13 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,7 +6,7 @@ import { getEnv } from "./utilities"; export const Environment = z.enum(["PRODUCTION", "DEVELOPMENT", "TESTING"]); -export const ListName = z.enum(["RP_INTEREST"]); +export const MailingListName = z.enum(["RP_INTEREST"]); export const Config = { DEFAULT_APP_PORT: 3000, diff --git a/src/database.ts b/src/database.ts index 15b4aca..dfb71df 100644 --- a/src/database.ts +++ b/src/database.ts @@ -9,6 +9,10 @@ import { RegistrationSchema, RegistrationValidator, } from "./services/registration/registration-schema"; +import { + SubscriptionValidator, + SubscriptionSchema, +} from "./services/subscription/subscription-schema"; mongoose.set("toObject", { versionKey: false }); @@ -48,4 +52,9 @@ export const Database = { RegistrationSchema, RegistrationValidator ), + SUBSCRIPTION: initializeModel( + "subscription", + SubscriptionSchema, + SubscriptionValidator + ), }; diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts new file mode 100644 index 0000000..b7b9517 --- /dev/null +++ b/src/services/subscription/subscription-router.ts @@ -0,0 +1,19 @@ +import { Router } from "express"; +import { StatusCodes } from "http-status-codes"; +import { SubscriptionValidator } from "./subscription-schema"; +import { Database } from "../../database"; + +const subscriptionRouter = Router(); + +// Create a new subscription +subscriptionRouter.post("/subscribe", async (req, res, next) => { + try { + const subscriptionData = SubscriptionValidator.parse(req.body); + await Database.SUBSCRIPTION.create(subscriptionData); + return res.status(StatusCodes.CREATED).json(subscriptionData); + } catch (error) { + next(error); + } +}); + +export default subscriptionRouter; diff --git a/src/services/subscription/subscription-schema.ts b/src/services/subscription/subscription-schema.ts new file mode 100644 index 0000000..a2089e6 --- /dev/null +++ b/src/services/subscription/subscription-schema.ts @@ -0,0 +1,17 @@ +import mongoose from "mongoose"; +import { z } from "zod"; +import { MailingListName } from "../../config"; + +// Zod schema for subscription +const SubscriptionValidator = z.object({ + email: z.string().email(), + mailing_list_name: MailingListName, +}); + +// Mongoose schema for subscription +const SubscriptionSchema = new mongoose.Schema({ + email: { type: String, required: true }, + mailing_list_name: { type: String, required: true }, +}); + +export { SubscriptionValidator, SubscriptionSchema }; From 46af86eb91a60441735adaf3815af65b67824c66 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Tue, 9 Apr 2024 21:46:10 -0500 Subject: [PATCH 20/93] Delete src/services/attendees/attendee-router.ts --- src/services/attendees/attendee-router.ts | 43 ----------------------- 1 file changed, 43 deletions(-) delete mode 100644 src/services/attendees/attendee-router.ts diff --git a/src/services/attendees/attendee-router.ts b/src/services/attendees/attendee-router.ts deleted file mode 100644 index 8006361..0000000 --- a/src/services/attendees/attendee-router.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Router } from "express"; -import { StatusCodes } from "http-status-codes"; -import { AttendeeValidator } from "./attendee-schema"; -import { Database } from "../../database"; - -const attendeeRouter = Router(); - -// Create a new attendee -attendeeRouter.post("/", async (req, res, next) => { - try { - const attendeeData = AttendeeValidator.parse(req.body); - const attendee = new Database.ATTENDEES(attendeeData); - await attendee.save(); - - return res.status(StatusCodes.CREATED).json(attendeeData); - } catch (error) { - next(error); - } -}); - -// 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 }); - - if (!userExists) { - return { error: "DoesNotExist" }; - } - - const user = await Database.ATTENDEES.findOne({ - email, - }); - - return res.status(StatusCodes.OK).json(user); - } catch (error) { - next(error); - } -}); - -export default attendeeRouter; From a354741f58c74c86c12b52b6ef903eb1f8568d35 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Tue, 9 Apr 2024 21:46:19 -0500 Subject: [PATCH 21/93] Delete src/services/attendees/attendee-schema.ts --- src/services/attendees/attendee-schema.ts | 54 ----------------------- 1 file changed, 54 deletions(-) delete mode 100644 src/services/attendees/attendee-schema.ts diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts deleted file mode 100644 index 79baebe..0000000 --- a/src/services/attendees/attendee-schema.ts +++ /dev/null @@ -1,54 +0,0 @@ -import mongoose from "mongoose"; -import { z } from "zod"; - -// Zod schema for attendee -const AttendeeValidator = z.object({ - name: z.string(), - email: z.string().email(), - studentInfo: z.object({ - university: z.string().nonempty(), - graduation: z.string().nullable().optional(), - major: z.string().nullable().optional(), - }), - events: z.array(z.string()), - dietary_restrictions: z.string(), - age: z.number().nullable().optional(), - gender: z.string().nullable().optional(), - race: z.array(z.string()).nullable().optional(), - ethnicity: z.string().nullable().optional(), - first_gen: z.string().nullable().optional(), - hear_about_rp: z.array(z.string()).nullable().optional(), - portfolio: z.string().nullable().optional(), - job_interest: z.array(z.string()).nullable().optional(), - interest_mech_puzzle: z.array(z.string()).nullable().optional(), - priority_expiry: z.date().nullable().optional(), - has_resume: z.boolean().optional(), - points: z.number().min(0).default(0), // -}); - -// Mongoose schema for attendee -const AttendeeSchema = new mongoose.Schema({ - name: { type: String, required: true }, - email: { type: String, required: true, unique: true }, - studentInfo: { - university: { type: String, required: true }, - graduation: { type: String, default: null }, - major: { type: String, default: null }, - }, - events: [{ type: mongoose.Schema.Types.ObjectId, ref: "Event" }], - dietary_restrictions: { type: String, required: true }, - age: { type: Number, default: null }, - gender: { type: String, default: null }, - race: [{ type: String }], - ethnicity: { type: String, default: null }, - first_gen: { type: String, default: null }, - hear_about_rp: [{ type: String }], - portfolio: { type: String, default: null }, - job_interest: [{ type: String }], - interest_mech_puzzle: [{ type: String }], - priority_expiry: { type: Date, default: null }, - has_resume: { type: Boolean, default: false }, - points: { type: Number, default: 0 }, -}); - -export { AttendeeSchema, AttendeeValidator }; From 873ed6df1dfeaa1257c962a576840901d2437bf9 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Tue, 9 Apr 2024 21:46:33 -0500 Subject: [PATCH 22/93] Delete src/services/events/event-router.ts --- src/services/events/event-router.ts | 82 ----------------------------- 1 file changed, 82 deletions(-) delete mode 100644 src/services/events/event-router.ts diff --git a/src/services/events/event-router.ts b/src/services/events/event-router.ts deleted file mode 100644 index f7e154a..0000000 --- a/src/services/events/event-router.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Router } from "express"; -import { StatusCodes } from "http-status-codes"; -import { EventValidator } from "./event-schema"; -import { Database } from "../../database"; - -const eventRouter = Router(); - -// Create a new event -eventRouter.post("/", async (req, res, next) => { - try { - const eventData = EventValidator.parse(req.body); - const event = new Database.EVENTS(eventData); - await event.save(); - return res.status(StatusCodes.CREATED).json(event); - } catch (error) { - next(error); - } -}); - -// Get all events -eventRouter.get("/", async (req, res, next) => { - try { - const events = await Database.EVENTS.find(); - return res.status(StatusCodes.OK).json(events); - } catch (error) { - next(error); - } -}); - -// Get event by ID -eventRouter.get("/:id", async (req, res, next) => { - try { - const event = await Database.EVENTS.findOneAndUpdate( - { _id: req.params.id }, - { new: true } - ); - - if (!event) { - return { error: "DoesNotExist" }; - } - - return res.status(StatusCodes.OK).json(event); - } catch (error) { - next(error); - } -}); - -// Update event -eventRouter.patch("/:id", async (req, res, next) => { - try { - const event = await Database.EVENTS.findOneAndUpdate( - { _id: req.params.id }, - req.body, - { new: true } - ); - - if (!event) { - return { error: "DoesNotExist" }; - } - - return res.status(StatusCodes.OK).json(event); - } catch (error) { - next(error); - } -}); - -// Delete event -eventRouter.delete("/:id", async (req, res, next) => { - try { - const event = await Database.EVENTS.findByIdAndDelete(req.params.id); - - if (!event) { - return { error: "DoesNotExist" }; - } - - return res.status(StatusCodes.OK).json(event); - } catch (error) { - next(error); - } -}); - -export default eventRouter; From 6fa633db24c0340bd299868cfa2e315b46af8086 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Tue, 9 Apr 2024 21:47:25 -0500 Subject: [PATCH 23/93] Delete src/services/registration/registration-schema.ts --- .../registration/registration-schema.ts | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/services/registration/registration-schema.ts diff --git a/src/services/registration/registration-schema.ts b/src/services/registration/registration-schema.ts deleted file mode 100644 index 2a35c14..0000000 --- a/src/services/registration/registration-schema.ts +++ /dev/null @@ -1,22 +0,0 @@ -import mongoose from "mongoose"; -import { z } from "zod"; - -// Zod schema for registration -const RegistrationValidator = z.object({ - name: z.string(), - email: z.string().email(), - events: z.array(z.string()), - dietary_restrictions: z.string(), - points: z.number().min(0).default(0), -}); - -// Mongoose schema for registration -const RegistrationSchema = new mongoose.Schema({ - 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 }, - points: { type: Number, default: 0 }, -}); - -export { RegistrationSchema, RegistrationValidator }; From bb2008795fca9ac2ef4e2974b7ee1c8874b8233e Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Tue, 9 Apr 2024 21:47:39 -0500 Subject: [PATCH 24/93] Delete src/services/registration/registration-router.ts --- src/services/registration/registration-router.ts | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/services/registration/registration-router.ts diff --git a/src/services/registration/registration-router.ts b/src/services/registration/registration-router.ts deleted file mode 100644 index 18d0210..0000000 --- a/src/services/registration/registration-router.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Router } from "express"; -import { StatusCodes } from "http-status-codes"; -import { RegistrationValidator } from "./registration-schema"; -import { Database } from "../../database"; - -const registrationRouter = Router(); - -// TODO: registration routes - -export default registrationRouter; From 4746216d0975a74229265a5d837cda335ed3df72 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Tue, 9 Apr 2024 21:47:52 -0500 Subject: [PATCH 25/93] Delete src/services/events/event-schema.ts --- src/services/events/event-schema.ts | 47 ----------------------------- 1 file changed, 47 deletions(-) delete mode 100644 src/services/events/event-schema.ts diff --git a/src/services/events/event-schema.ts b/src/services/events/event-schema.ts deleted file mode 100644 index 73890cd..0000000 --- a/src/services/events/event-schema.ts +++ /dev/null @@ -1,47 +0,0 @@ -import mongoose from "mongoose"; -import { z } from "zod"; - -// Zod schema for event -const EventValidator = z.object({ - name: z.string(), - description: z.string(), - start_time: z.date(), - end_time: z.date(), - attendees: z.array(z.string()), - location: z.array( - z.object({ - description: z.string(), - tags: z.array(z.string()), - latitude: z.number(), - longitude: z.number(), - }) - ), - virtual: z.boolean(), - points: z.number().min(0).default(0), - imageUrl: z.string().nullable().optional(), - visible: z.boolean().default(false), -}); - -// Mongoose schema for location -const LocationSchema = new mongoose.Schema({ - description: { type: String, required: true }, - tags: [{ type: String }], - latitude: { type: Number, required: true }, - longitude: { type: Number, required: true }, -}); - -// Mongoose schema for event -const EventSchema = new mongoose.Schema({ - name: { type: String, required: true }, - description: { type: String, required: true }, - start_time: { type: Date, required: true }, - end_time: { type: Date, required: true }, - attendees: [{ type: mongoose.Schema.Types.ObjectId, ref: "Attendee" }], - location: [LocationSchema], - virtual: { type: Boolean, required: true }, - points: { type: Number, default: 0 }, - imageUrl: { type: String, default: null }, - visible: { type: Boolean, default: false }, -}); - -export { EventSchema, EventValidator, LocationSchema }; From 1016299b12fc62d0c361a679372a54c6807cc075 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Tue, 9 Apr 2024 21:48:15 -0500 Subject: [PATCH 26/93] Update app.ts --- src/app.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/app.ts b/src/app.ts index 642b78d..0f2e66c 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,9 +8,6 @@ import bodyParser from "body-parser"; import errorHandler from "./middleware/error-handler"; import authRouter from "./services/auth/auth-router"; -import attendeeRouter from "./services/attendees/attendee-router"; -import eventRouter from "./services/events/event-router"; -import registrationRouter from "./services/registration/registration-router"; import subscriptionRouter from "./services/subscription/subscription-router"; const app = express(); @@ -25,10 +22,7 @@ app.use("/", morgan("dev")); app.use("/", bodyParser.json()); // API routes -app.use("/attendee", attendeeRouter); app.use("/auth", authRouter); -app.use("/event", eventRouter); -app.use("/registration", registrationRouter); app.use("/subscription", subscriptionRouter); app.get("/status", (_, res) => { From 62c8190e00c701bb6f1b804f867adce774c60f18 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Tue, 9 Apr 2024 21:49:35 -0500 Subject: [PATCH 27/93] Update database.ts --- src/database.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/database.ts b/src/database.ts index dfb71df..33fa1a2 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,14 +1,5 @@ import mongoose, { Schema } from "mongoose"; import { RoleInfo, RoleSchema } from "./services/auth/auth-schema"; -import { EventValidator, EventSchema } from "./services/events/event-schema"; -import { - AttendeeSchema, - AttendeeValidator, -} from "./services/attendees/attendee-schema"; -import { - RegistrationSchema, - RegistrationValidator, -} from "./services/registration/registration-schema"; import { SubscriptionValidator, SubscriptionSchema, @@ -45,13 +36,6 @@ function initializeModel( // Example usage export const Database = { ROLES: initializeModel("roles", RoleSchema, RoleInfo), - EVENTS: initializeModel("events", EventSchema, EventValidator), - ATTENDEES: initializeModel("attendees", AttendeeSchema, AttendeeValidator), - REGISTRATION: initializeModel( - "registration", - RegistrationSchema, - RegistrationValidator - ), SUBSCRIPTION: initializeModel( "subscription", SubscriptionSchema, From 0eaab828ba56c7c53e64226fef6550c1ded3fd50 Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+DatProJack@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:50:47 -0500 Subject: [PATCH 28/93] codedeploy scripts --- appspec.yml | 18 ++++++++++++++++++ scripts/build.sh | 2 ++ scripts/install_dependencies.sh | 2 ++ scripts/reload_server.sh | 2 ++ 4 files changed, 24 insertions(+) create mode 100644 appspec.yml create mode 100644 scripts/build.sh create mode 100644 scripts/install_dependencies.sh create mode 100644 scripts/reload_server.sh diff --git a/appspec.yml b/appspec.yml new file mode 100644 index 0000000..68f2cd7 --- /dev/null +++ b/appspec.yml @@ -0,0 +1,18 @@ +version: 0.0 +os: linux +files: + - source: / + destination: /home/ubuntu/rp-api +hooks: + BeforeInstall: + - location: scripts/install_dependencies.sh + timeout: 300 + runas: root + AfterInstall: + - location: scripts/build.sh + timeout: 300 + runas: root + ApplicationStart: + - location: scripts/reload_server.sh + timeout: 300 + runas: root \ No newline at end of file diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100644 index 0000000..db96fbc --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,2 @@ +#!/bin/bash +tsc \ No newline at end of file diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh new file mode 100644 index 0000000..434f311 --- /dev/null +++ b/scripts/install_dependencies.sh @@ -0,0 +1,2 @@ +#!/bin/bash +yarn \ No newline at end of file diff --git a/scripts/reload_server.sh b/scripts/reload_server.sh new file mode 100644 index 0000000..4887fc2 --- /dev/null +++ b/scripts/reload_server.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pm2 reload RP_API \ No newline at end of file From 8dcb76cdc48242c440d20ea37a209929e6a87caf Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+aletya@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:03:30 -0500 Subject: [PATCH 29/93] Update app.ts --- src/app.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app.ts b/src/app.ts index c4bb74f..8d7bfb0 100644 --- a/src/app.ts +++ b/src/app.ts @@ -35,5 +35,6 @@ app.use(errorHandler); app.listen(Config.DEFAULT_APP_PORT, async () => { await connectToDatabase(); + process.send?.('ready'); console.log("Server is listening on port 3000..."); }); From 3dd715f4752c42246306add68116e1956681af65 Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+aletya@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:07:04 -0500 Subject: [PATCH 30/93] Update app.ts --- src/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.ts b/src/app.ts index 8d7bfb0..6d6793d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -35,6 +35,6 @@ app.use(errorHandler); app.listen(Config.DEFAULT_APP_PORT, async () => { await connectToDatabase(); - process.send?.('ready'); + process.send?.("ready"); console.log("Server is listening on port 3000..."); }); From affd7da17cd7042215a709b52bd06942d1b01aaf Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+DatProJack@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:15:33 -0500 Subject: [PATCH 31/93] install dependencies fr --- appspec.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appspec.yml b/appspec.yml index 68f2cd7..345e630 100644 --- a/appspec.yml +++ b/appspec.yml @@ -13,6 +13,9 @@ hooks: timeout: 300 runas: root ApplicationStart: + - location: scripts/install_dependencies.sh + timeout: 300 + runas: root - location: scripts/reload_server.sh timeout: 300 runas: root \ No newline at end of file From 6fbbf29ef47b25828c97ac5506044d3e6fb3ab45 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Wed, 10 Apr 2024 12:33:50 -0500 Subject: [PATCH 32/93] Update utilities.ts --- src/utilities.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utilities.ts b/src/utilities.ts index 685ef19..ffb1dd8 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -13,7 +13,7 @@ function getDatabaseUrl() { const host = Config.DATABASE_HOST; let database; if (isProd()) { - return ""; + database = `prod`; } else if (isDev()) { database = `dev-${username}`; } From 9263ab3bf47d237922cf30a7d74002541e718c17 Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+DatProJack@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:47:30 -0500 Subject: [PATCH 33/93] farming prs --- appspec.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appspec.yml b/appspec.yml index 345e630..2e74e8d 100644 --- a/appspec.yml +++ b/appspec.yml @@ -3,6 +3,7 @@ os: linux files: - source: / destination: /home/ubuntu/rp-api +file_exists_behavior: OVERWRITE hooks: BeforeInstall: - location: scripts/install_dependencies.sh From cc472e7f9638beceecd6641815cabc037f0359c7 Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+DatProJack@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:58:20 -0500 Subject: [PATCH 34/93] change directory scripts --- scripts/build.sh | 1 + scripts/install_dependencies.sh | 1 + scripts/reload_server.sh | 1 + 3 files changed, 3 insertions(+) diff --git a/scripts/build.sh b/scripts/build.sh index db96fbc..95a91f4 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,2 +1,3 @@ #!/bin/bash +cd /home/ubuntu/rp-api tsc \ No newline at end of file diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index 434f311..c51f6f2 100644 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -1,2 +1,3 @@ #!/bin/bash +cd /home/ubuntu/rp-api yarn \ No newline at end of file diff --git a/scripts/reload_server.sh b/scripts/reload_server.sh index 4887fc2..99a600d 100644 --- a/scripts/reload_server.sh +++ b/scripts/reload_server.sh @@ -1,2 +1,3 @@ #!/bin/bash +cd /home/ubuntu/rp-api pm2 reload RP_API \ No newline at end of file From 7b98e8c62fb7fe34335474218c935454af315981 Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+DatProJack@users.noreply.github.com> Date: Wed, 10 Apr 2024 13:06:30 -0500 Subject: [PATCH 35/93] debugging --- scripts/reload_server.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/reload_server.sh b/scripts/reload_server.sh index 99a600d..ad6ac5c 100644 --- a/scripts/reload_server.sh +++ b/scripts/reload_server.sh @@ -1,3 +1,4 @@ #!/bin/bash cd /home/ubuntu/rp-api +pm2 list pm2 reload RP_API \ No newline at end of file From 9e07a13f26218fded4f12c7296a311d55192e649 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Wed, 10 Apr 2024 13:15:17 -0500 Subject: [PATCH 36/93] Update reload_server.sh --- scripts/reload_server.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/reload_server.sh b/scripts/reload_server.sh index ad6ac5c..df3780a 100644 --- a/scripts/reload_server.sh +++ b/scripts/reload_server.sh @@ -1,4 +1,6 @@ #!/bin/bash cd /home/ubuntu/rp-api +ifconfig +uname -a pm2 list -pm2 reload RP_API \ No newline at end of file +pm2 reload RP_API From f8ef8e76c672ca6b01588913ae91df31b60dd13c Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Wed, 10 Apr 2024 13:19:19 -0500 Subject: [PATCH 37/93] Update reload_server.sh --- scripts/reload_server.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/reload_server.sh b/scripts/reload_server.sh index df3780a..8f8257b 100644 --- a/scripts/reload_server.sh +++ b/scripts/reload_server.sh @@ -1,6 +1,4 @@ #!/bin/bash cd /home/ubuntu/rp-api -ifconfig -uname -a pm2 list pm2 reload RP_API From 861276fd72a14762f6b17cff27b6a1e0c07e2ad5 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Wed, 10 Apr 2024 13:26:47 -0500 Subject: [PATCH 38/93] Update reload_server.sh --- scripts/reload_server.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/reload_server.sh b/scripts/reload_server.sh index 8f8257b..bb152c1 100644 --- a/scripts/reload_server.sh +++ b/scripts/reload_server.sh @@ -1,4 +1,3 @@ #!/bin/bash cd /home/ubuntu/rp-api -pm2 list pm2 reload RP_API From 024fa8e634e141518f36525c4c8bf865319885b8 Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Wed, 10 Apr 2024 19:12:22 -0500 Subject: [PATCH 39/93] pr changes subscription --- src/config.ts | 2 +- src/services/subscription/subscription-router.ts | 8 ++++++-- src/services/subscription/subscription-schema.ts | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/config.ts b/src/config.ts index a0f7e13..ed601c8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,7 +6,7 @@ import { getEnv } from "./utilities"; export const Environment = z.enum(["PRODUCTION", "DEVELOPMENT", "TESTING"]); -export const MailingListName = z.enum(["RP_INTEREST"]); +export const MailingListName = z.enum(["rp_interest"]); export const Config = { DEFAULT_APP_PORT: 3000, diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts index b7b9517..6806ab3 100644 --- a/src/services/subscription/subscription-router.ts +++ b/src/services/subscription/subscription-router.ts @@ -6,10 +6,14 @@ import { Database } from "../../database"; const subscriptionRouter = Router(); // Create a new subscription -subscriptionRouter.post("/subscribe", async (req, res, next) => { +subscriptionRouter.post("/", async (req, res, next) => { try { const subscriptionData = SubscriptionValidator.parse(req.body); - await Database.SUBSCRIPTION.create(subscriptionData); + await Database.SUBSCRIPTION.findOneAndUpdate( + { email: subscriptionData.email }, + { mailingList: subscriptionData.mailingList }, + { upsert: true, new: true } + ); return res.status(StatusCodes.CREATED).json(subscriptionData); } catch (error) { next(error); diff --git a/src/services/subscription/subscription-schema.ts b/src/services/subscription/subscription-schema.ts index a2089e6..32579bf 100644 --- a/src/services/subscription/subscription-schema.ts +++ b/src/services/subscription/subscription-schema.ts @@ -5,13 +5,13 @@ import { MailingListName } from "../../config"; // Zod schema for subscription const SubscriptionValidator = z.object({ email: z.string().email(), - mailing_list_name: MailingListName, + mailingList: MailingListName, }); // Mongoose schema for subscription const SubscriptionSchema = new mongoose.Schema({ email: { type: String, required: true }, - mailing_list_name: { type: String, required: true }, + mailingList: { type: String, required: true }, }); export { SubscriptionValidator, SubscriptionSchema }; From 1cdd1d9bcdba23b68dd6a5494d9bb1c85b83950b Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Wed, 10 Apr 2024 23:26:16 -0500 Subject: [PATCH 40/93] minor change to subscription format --- src/services/subscription/subscription-router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts index 6806ab3..d847061 100644 --- a/src/services/subscription/subscription-router.ts +++ b/src/services/subscription/subscription-router.ts @@ -10,8 +10,8 @@ subscriptionRouter.post("/", async (req, res, next) => { try { const subscriptionData = SubscriptionValidator.parse(req.body); await Database.SUBSCRIPTION.findOneAndUpdate( - { email: subscriptionData.email }, { mailingList: subscriptionData.mailingList }, + { $push: { subscriptions: data.email } }, { upsert: true, new: true } ); return res.status(StatusCodes.CREATED).json(subscriptionData); From a3745c9e457a1f9b77f8e3cda218645ebddd3250 Mon Sep 17 00:00:00 2001 From: riyap Date: Wed, 10 Apr 2024 23:27:47 -0500 Subject: [PATCH 41/93] added points --- src/services/events/events-router.ts | 2 +- src/services/events/events-schema.ts | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index 700e247..4aa29c6 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -12,7 +12,7 @@ eventRouter.post("/events", async (req, res, next) => { const validatedData = EventValidator.parse(req.body); const event = new Database.EVENT(validatedData); await event.save(); - return res.status(StatusCodes.CREATED).json(event); + return res.status(StatusCodes.CREATED).json(event.toObject()); } catch (error) { next(error); } diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index 6df2fef..22eef8a 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -7,6 +7,7 @@ export const EventValidator = z.object({ name: z.string(), startTime: z.coerce.date(), endTime: z.coerce.date(), + points: z.number().min(0), }); export const EventSchema = new Schema({ @@ -27,5 +28,10 @@ export const EventSchema = new Schema({ type: Date, required: true, }, + + points: { + type: Number, + required: true, + }, }); // export const Event = mongoose.model("Event", EventSchema); From 6303fcec65ebae2ad5c92176a6f4f680d3cfd6d7 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Wed, 10 Apr 2024 23:39:49 -0500 Subject: [PATCH 42/93] Update subscription-router.ts --- src/services/subscription/subscription-router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts index d847061..b503fbe 100644 --- a/src/services/subscription/subscription-router.ts +++ b/src/services/subscription/subscription-router.ts @@ -11,7 +11,7 @@ subscriptionRouter.post("/", async (req, res, next) => { const subscriptionData = SubscriptionValidator.parse(req.body); await Database.SUBSCRIPTION.findOneAndUpdate( { mailingList: subscriptionData.mailingList }, - { $push: { subscriptions: data.email } }, + { $push: { subscriptions: subscriptionData.email } }, { upsert: true, new: true } ); return res.status(StatusCodes.CREATED).json(subscriptionData); From 51bfcfce11732a095c649c237ba9d66383ef9247 Mon Sep 17 00:00:00 2001 From: riyap Date: Wed, 10 Apr 2024 23:48:48 -0500 Subject: [PATCH 43/93] made rest of suggestions im silly --- src/database.ts | 2 +- src/services/events/events-router.ts | 6 ++---- src/services/events/events-schema.ts | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/database.ts b/src/database.ts index 2061d8a..cb789e3 100644 --- a/src/database.ts +++ b/src/database.ts @@ -33,5 +33,5 @@ function initializeModel( // Example usage export const Database = { ROLES: initializeModel("roles", RoleSchema, RoleInfo), - EVENT: initializeModel("events", EventSchema, EventValidator), + EVENTS: initializeModel("events", EventSchema, EventValidator), }; diff --git a/src/services/events/events-router.ts b/src/services/events/events-router.ts index 4aa29c6..ea035a8 100644 --- a/src/services/events/events-router.ts +++ b/src/services/events/events-router.ts @@ -4,13 +4,11 @@ import { EventValidator } from "./events-schema"; import { Database } from "../../database"; const eventRouter = Router(); -// authRouter.get("/", async (req, res) => { -// }); -eventRouter.post("/events", async (req, res, next) => { +eventRouter.post("/", async (req, res, next) => { try { const validatedData = EventValidator.parse(req.body); - const event = new Database.EVENT(validatedData); + const event = new Database.EVENTS(validatedData); await event.save(); return res.status(StatusCodes.CREATED).json(event.toObject()); } catch (error) { diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index 22eef8a..e1b6aac 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -3,7 +3,7 @@ import { Schema } from "mongoose"; import { z } from "zod"; export const EventValidator = z.object({ - eventId: z.coerce.string().cuid2(), + eventId: z.coerce.string(), name: z.string(), startTime: z.coerce.date(), endTime: z.coerce.date(), @@ -34,4 +34,3 @@ export const EventSchema = new Schema({ required: true, }, }); -// export const Event = mongoose.model("Event", EventSchema); From e4072a8fa58659fcb7faa9c8736723af5822c8cf Mon Sep 17 00:00:00 2001 From: Divya Koya <90989518+divyack2@users.noreply.github.com> Date: Thu, 11 Apr 2024 00:13:22 -0500 Subject: [PATCH 44/93] Update src/services/events/events-schema.ts removed the import mongoose statement Co-authored-by: Aydan Pirani --- src/services/events/events-schema.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/events/events-schema.ts b/src/services/events/events-schema.ts index e1b6aac..b9731e2 100644 --- a/src/services/events/events-schema.ts +++ b/src/services/events/events-schema.ts @@ -1,4 +1,3 @@ -// import mongoose from "mongoose"; import { Schema } from "mongoose"; import { z } from "zod"; From 149d707ab9c5a73aeada1a4b360d2a607d9fa905 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Thu, 11 Apr 2024 02:07:00 -0500 Subject: [PATCH 45/93] Auth template working --- src/config.ts | 8 +++- src/services/auth/auth-router.ts | 66 +++++++++++++------------------- src/services/auth/auth-schema.ts | 2 - src/services/auth/auth-utils.ts | 18 +++++++++ 4 files changed, 52 insertions(+), 42 deletions(-) create mode 100644 src/services/auth/auth-utils.ts diff --git a/src/config.ts b/src/config.ts index 9a065d0..228dcc8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -17,5 +17,11 @@ export const Config = { CLIENT_ID: getEnv("OAUTH_GOOGLE_CLIENT_ID"), CLIENT_SECRET: getEnv("OAUTH_GOOGLE_CLIENT_SECRET"), - REDIRECT_URI: "http://localhost:3000/auth/callback", + // REDIRECT_URI: "http://localhost:3000/auth/callback", + AUTH_CALLBACK_URI_BASE: "http://localhost:3000/auth/callback/", + // AUTH_CALLBACK_URI_BASE: "https://api.reflectionsprojections.org/auth/callback", +}; + +export const DeviceRedirects: Record = { + web: `https://www.reflectionsprojections.org/`, }; diff --git a/src/services/auth/auth-router.ts b/src/services/auth/auth-router.ts index 83cf899..8642907 100644 --- a/src/services/auth/auth-router.ts +++ b/src/services/auth/auth-router.ts @@ -1,58 +1,46 @@ import { Router } from "express"; -import passport, { AuthenticateOptions } from "passport"; -import { Strategy as GoogleStrategy } from "passport-google-oauth20"; -import { Config } from "../../config"; +import passport from "passport"; +import { DeviceRedirects } from "../../config"; import { StatusCodes } from "http-status-codes"; -import { Devices } from "./auth-schema"; - -passport.use( - new GoogleStrategy( - { - clientID: Config.CLIENT_ID, - clientSecret: Config.CLIENT_SECRET, - callbackURL: Config.REDIRECT_URI, - }, - function (_1, _2, profile, cb) { - cb(null, profile); - } - ) -); +import { Strategy as GoogleStrategy } from "passport-google-oauth20"; +import { createGoogleStrategy } from "./auth-utils"; + +const authStrategies: Record = {}; const authRouter = Router(); authRouter.get("/login/:DEVICE/", (req, res) => { - const device = req.params["DEVICE"]; + const device = req.params.DEVICE; - console.log(device, Devices.Values); - - if (!Devices.safeParse(device).success) { + // Check if this is a valid device (i.e. does a redirectURI exist for it) + if (!(device in DeviceRedirects)) { return res.status(StatusCodes.BAD_REQUEST).send({ error: "BadDevice" }); } - const callbackURL = `${Config.REDIRECT_URI}/${device}`; + // Check if we've already created an auth strategy for the device + // If not, create a new one + if (!(device in authStrategies)) { + authStrategies[device] = createGoogleStrategy(device); + } + + // Use the pre-created strategy + passport.use(device, authStrategies[device]); - console.log(`|${callbackURL}|`); - return passport.authenticate("google", { - callbackURL: callbackURL, + return passport.authenticate(device, { scope: ["profile", "email"], - } as AuthenticateOptions)(req, res); + })(req, res); }); authRouter.get( - "/callback/", - (req, _, next) => { - console.log("HI!!! params be", req.params, req.query); - return next(); - }, - passport.authenticate("google", { - session: false, - }), + "/callback/:DEVICE", + (req, res, next) => + // Check based on the pre-existing strategy name + passport.authenticate(req.params.DEVICE, { + session: false, + })(req, res, next), function (req, res) { - console.log("IN HERE"); - console.log(req.params); - console.log(req.query); - console.log("redirecting!"); - return res.redirect("/"); + const redirectUri = `${DeviceRedirects[req.params.DEVICE]}` + return res.redirect(redirectUri); } ); diff --git a/src/services/auth/auth-schema.ts b/src/services/auth/auth-schema.ts index 144680c..15a2e8d 100644 --- a/src/services/auth/auth-schema.ts +++ b/src/services/auth/auth-schema.ts @@ -3,8 +3,6 @@ import { z } from "zod"; export const Role = z.enum(["USER", "ADMIN", "CORPORATE"]); -export const Devices = z.enum(["web"]); - export const RoleValidator = z.object({ userId: z.coerce.string().regex(/user[0-9]*/), email: z.coerce.string().email(), diff --git a/src/services/auth/auth-utils.ts b/src/services/auth/auth-utils.ts new file mode 100644 index 0000000..5b512bf --- /dev/null +++ b/src/services/auth/auth-utils.ts @@ -0,0 +1,18 @@ +// Create a function to generate GoogleStrategy instances +import { Strategy as GoogleStrategy } from "passport-google-oauth20"; +import { Config } from "../../config"; + +export function createGoogleStrategy(device: string) { + return new GoogleStrategy( + { + clientID: Config.CLIENT_ID, + clientSecret: Config.CLIENT_SECRET, + callbackURL: `${Config.AUTH_CALLBACK_URI_BASE}${device}`, + }, + async function (_1, _2, profile, cb) { + // Add profile to database here + console.log(profile); + cb(null, profile); + } + ); +} From 87e2d3a40d045de53cf775bd787713948a96b2e1 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Thu, 11 Apr 2024 02:22:25 -0500 Subject: [PATCH 46/93] Added changes for database insertion --- src/database.ts | 4 +-- src/services/auth/auth-router.ts | 2 +- src/services/auth/auth-schema.ts | 42 +++++++++++++++++++------------- src/services/auth/auth-utils.ts | 19 ++++++++++++--- 4 files changed, 44 insertions(+), 23 deletions(-) diff --git a/src/database.ts b/src/database.ts index 2e8c4c5..63c5d12 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,5 +1,5 @@ import mongoose, { Schema } from "mongoose"; -import { RoleInfo, RoleSchema } from "./services/auth/auth-schema"; +import { RoleValidator, RoleSchema } from "./services/auth/auth-schema"; mongoose.set("toObject", { versionKey: false }); @@ -31,5 +31,5 @@ function initializeModel( // Example usage export const Database = { - ROLES: initializeModel("roles", RoleSchema, RoleInfo), + ROLES: initializeModel("roles", RoleSchema, RoleValidator), }; diff --git a/src/services/auth/auth-router.ts b/src/services/auth/auth-router.ts index 8642907..148ebfa 100644 --- a/src/services/auth/auth-router.ts +++ b/src/services/auth/auth-router.ts @@ -39,7 +39,7 @@ authRouter.get( session: false, })(req, res, next), function (req, res) { - const redirectUri = `${DeviceRedirects[req.params.DEVICE]}` + const redirectUri = `${DeviceRedirects[req.params.DEVICE]}`; return res.redirect(redirectUri); } ); diff --git a/src/services/auth/auth-schema.ts b/src/services/auth/auth-schema.ts index 15a2e8d..619cf7a 100644 --- a/src/services/auth/auth-schema.ts +++ b/src/services/auth/auth-schema.ts @@ -5,25 +5,33 @@ export const Role = z.enum(["USER", "ADMIN", "CORPORATE"]); export const RoleValidator = z.object({ userId: z.coerce.string().regex(/user[0-9]*/), + name: z.coerce.string(), email: z.coerce.string().email(), roles: z.array(Role), }); -export const RoleSchema = new Schema({ - userId: { - type: String, - required: true, - unique: true, +export const RoleSchema = new Schema( + { + userId: { + type: String, + required: true, + unique: true, + }, + name: { + type: String, + required: true, + }, + email: { + type: String, + required: true, + unique: true, + }, + roles: { + type: [String], + enum: Role.Values, + default: [], + required: true, + }, }, - email: { - type: String, - required: true, - unique: true, - }, - roles: { - type: [String], - enum: Role.Values, - default: [], - required: true, - }, -}); + { timestamps: { createdAt: "createdAt" } } +); diff --git a/src/services/auth/auth-utils.ts b/src/services/auth/auth-utils.ts index 5b512bf..129940c 100644 --- a/src/services/auth/auth-utils.ts +++ b/src/services/auth/auth-utils.ts @@ -1,6 +1,8 @@ // Create a function to generate GoogleStrategy instances import { Strategy as GoogleStrategy } from "passport-google-oauth20"; import { Config } from "../../config"; +import { Role } from "./auth-schema"; +import { Database } from "../../database"; export function createGoogleStrategy(device: string) { return new GoogleStrategy( @@ -9,10 +11,21 @@ export function createGoogleStrategy(device: string) { clientSecret: Config.CLIENT_SECRET, callbackURL: `${Config.AUTH_CALLBACK_URI_BASE}${device}`, }, + + // Strategy -> insert user into database if they don't exist async function (_1, _2, profile, cb) { - // Add profile to database here - console.log(profile); - cb(null, profile); + const userId = `user${profile.id}`; + const name = profile.displayName; + const email = profile._json.email; + const roles = [Role.Enum.USER]; + + Database.ROLES.findOneAndUpdate( + { userId: userId }, + { userId, name, email, roles }, + { upsert: true } + ) + .then(() => cb(null, profile)) + .catch((err) => cb(err, profile)); } ); } From a8b2cd6064711381c77b225990026c0de7078df8 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Thu, 11 Apr 2024 02:41:54 -0500 Subject: [PATCH 47/93] Added JWT integration --- package.json | 2 + src/config.ts | 5 +- src/services/auth/auth-router.ts | 27 +++++++--- src/services/auth/auth-utils.ts | 10 ++++ yarn.lock | 89 +++++++++++++++++++++++++++++++- 5 files changed, 125 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 5706f6d..e064d03 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "devDependencies": { "@types/dotenv": "^8.2.0", "@types/express": "^4.17.21", + "@types/jsonwebtoken": "^9.0.6", "@types/morgan": "^1.9.9", "@types/node": "^20.9.3", "@types/passport-google-oauth20": "^2.0.14", @@ -36,6 +37,7 @@ "dotenv": "^16.4.5", "express": "^4.19.1", "http-status-codes": "^2.3.0", + "jsonwebtoken": "^9.0.2", "mongoose": "^8.2.3", "morgan": "^1.10.0", "passport": "^0.7.0", diff --git a/src/config.ts b/src/config.ts index 228dcc8..deb7dc2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -20,8 +20,11 @@ export const Config = { // REDIRECT_URI: "http://localhost:3000/auth/callback", AUTH_CALLBACK_URI_BASE: "http://localhost:3000/auth/callback/", // AUTH_CALLBACK_URI_BASE: "https://api.reflectionsprojections.org/auth/callback", + + JWT_SIGNING_SECRET: getEnv("JWT_SIGNING_SECRET"), + JWT_EXPIRATION_TIME: "1 day", }; export const DeviceRedirects: Record = { - web: `https://www.reflectionsprojections.org/`, + web: "https://www.google.com/", }; diff --git a/src/services/auth/auth-router.ts b/src/services/auth/auth-router.ts index 148ebfa..6a33379 100644 --- a/src/services/auth/auth-router.ts +++ b/src/services/auth/auth-router.ts @@ -1,9 +1,10 @@ import { Router } from "express"; import passport from "passport"; -import { DeviceRedirects } from "../../config"; +import { Config, DeviceRedirects } from "../../config"; import { StatusCodes } from "http-status-codes"; -import { Strategy as GoogleStrategy } from "passport-google-oauth20"; -import { createGoogleStrategy } from "./auth-utils"; +import { Strategy as GoogleStrategy, Profile } from "passport-google-oauth20"; +import { createGoogleStrategy, getJwtPayloadFromDatabase } from "./auth-utils"; +import jsonwebtoken from "jsonwebtoken"; const authStrategies: Record = {}; @@ -38,9 +39,23 @@ authRouter.get( passport.authenticate(req.params.DEVICE, { session: false, })(req, res, next), - function (req, res) { - const redirectUri = `${DeviceRedirects[req.params.DEVICE]}`; - return res.redirect(redirectUri); + async function (req, res, next) { + // Authentication failed - redirect to login + if (req.user == undefined) { + return res.redirect(`/auth/login/${req.params.DEVICE}`) + } + const userData = req.user as Profile; + const userId = `user${userData.id}`; + + // Generate the JWT, and redirect to JWT initialization + try { + const jwtPayload = (await getJwtPayloadFromDatabase(userId)).toObject(); + const token = jsonwebtoken.sign(jwtPayload, Config.JWT_SIGNING_SECRET, { expiresIn: Config.JWT_EXPIRATION_TIME }); + const redirectUri = `${DeviceRedirects[req.params.DEVICE]}/token=${token}`; + return res.redirect(redirectUri); + } catch (error) { + next(error); + } } ); diff --git a/src/services/auth/auth-utils.ts b/src/services/auth/auth-utils.ts index 129940c..08e82ab 100644 --- a/src/services/auth/auth-utils.ts +++ b/src/services/auth/auth-utils.ts @@ -29,3 +29,13 @@ export function createGoogleStrategy(device: string) { } ); } + + +export async function getJwtPayloadFromDatabase(userId: string) { + const payload = await Database.ROLES.findOne({userId: userId}).select(["userId", "roles"]); + if (!payload) { + throw new Error("NoUserFound"); + } + + return payload; +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 7fad951..33f43b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -280,6 +280,13 @@ resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/jsonwebtoken@^9.0.6": + version "9.0.6" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz#d1af3544d99ad992fb6681bbe60676e06b032bd3" + integrity sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw== + dependencies: + "@types/node" "*" + "@types/mime@*": version "3.0.4" resolved "https://registry.npmjs.org/@types/mime/-/mime-3.0.4.tgz" @@ -690,6 +697,11 @@ bson@^6.2.0: resolved "https://registry.npmjs.org/bson/-/bson-6.5.0.tgz" integrity sha512-DXf1BTAS8vKyR90BO4x5v3rKVarmkdkzwOrnYDFdjAY694ILNDkmA3uRh1xXJEl+C1DAh8XCvAQ+Gh3kzubtpg== +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + builtin-modules@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz" @@ -916,6 +928,13 @@ dotenv@*, dotenv@^16.4.5: resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" @@ -1909,6 +1928,22 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" +jsonwebtoken@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1: version "3.3.5" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" @@ -1919,6 +1954,23 @@ json5@^1.0.2: object.assign "^4.1.4" object.values "^1.1.6" +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + kareem@2.5.1: version "2.5.1" resolved "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz" @@ -1951,11 +2003,46 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -2504,7 +2591,7 @@ safe-buffer@5.1.2: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1: +safe-buffer@5.2.1, safe-buffer@^5.0.1: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== From f1951fef57c96906969cc473dc467296be004579 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Thu, 11 Apr 2024 02:54:03 -0500 Subject: [PATCH 48/93] Added support for dev auth endpoint --- src/config.ts | 1 + src/services/auth/auth-router.ts | 6 +++++- src/services/auth/auth-utils.ts | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index deb7dc2..5d6d7ae 100644 --- a/src/config.ts +++ b/src/config.ts @@ -27,4 +27,5 @@ export const Config = { export const DeviceRedirects: Record = { web: "https://www.google.com/", + dev: "http://127.0.0.1:3000/auth/dev/" }; diff --git a/src/services/auth/auth-router.ts b/src/services/auth/auth-router.ts index 6a33379..92d376c 100644 --- a/src/services/auth/auth-router.ts +++ b/src/services/auth/auth-router.ts @@ -51,7 +51,7 @@ authRouter.get( try { const jwtPayload = (await getJwtPayloadFromDatabase(userId)).toObject(); const token = jsonwebtoken.sign(jwtPayload, Config.JWT_SIGNING_SECRET, { expiresIn: Config.JWT_EXPIRATION_TIME }); - const redirectUri = `${DeviceRedirects[req.params.DEVICE]}/token=${token}`; + const redirectUri = DeviceRedirects[req.params.DEVICE] + `token=${token}`; return res.redirect(redirectUri); } catch (error) { next(error); @@ -59,4 +59,8 @@ authRouter.get( } ); +authRouter.get("/dev/", (req, res) => { + return res.status(StatusCodes.OK).json({"Token": req.headers.authorization}); +}) + export default authRouter; diff --git a/src/services/auth/auth-utils.ts b/src/services/auth/auth-utils.ts index 08e82ab..d163571 100644 --- a/src/services/auth/auth-utils.ts +++ b/src/services/auth/auth-utils.ts @@ -9,7 +9,7 @@ export function createGoogleStrategy(device: string) { { clientID: Config.CLIENT_ID, clientSecret: Config.CLIENT_SECRET, - callbackURL: `${Config.AUTH_CALLBACK_URI_BASE}${device}`, + callbackURL: Config.AUTH_CALLBACK_URI_BASE + device, }, // Strategy -> insert user into database if they don't exist From 65ac4cc67b3a8bf5bb639664cf9ed65278e5ded6 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Thu, 11 Apr 2024 10:37:21 -0500 Subject: [PATCH 49/93] Initial role checking middleware --- src/config.ts | 3 +-- src/middleware/role-checker.ts | 13 +++++++++++++ src/services/auth/auth-router.ts | 4 ++-- 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 src/middleware/role-checker.ts diff --git a/src/config.ts b/src/config.ts index 5d6d7ae..2620159 100644 --- a/src/config.ts +++ b/src/config.ts @@ -17,9 +17,8 @@ export const Config = { CLIENT_ID: getEnv("OAUTH_GOOGLE_CLIENT_ID"), CLIENT_SECRET: getEnv("OAUTH_GOOGLE_CLIENT_SECRET"), - // REDIRECT_URI: "http://localhost:3000/auth/callback", AUTH_CALLBACK_URI_BASE: "http://localhost:3000/auth/callback/", - // AUTH_CALLBACK_URI_BASE: "https://api.reflectionsprojections.org/auth/callback", + // AUTH_CALLBACK_URI_BASE: "https://api.reflectionsprojections.org/auth/callback/", JWT_SIGNING_SECRET: getEnv("JWT_SIGNING_SECRET"), JWT_EXPIRATION_TIME: "1 day", diff --git a/src/middleware/role-checker.ts b/src/middleware/role-checker.ts new file mode 100644 index 0000000..6999070 --- /dev/null +++ b/src/middleware/role-checker.ts @@ -0,0 +1,13 @@ +import { NextFunction } from "express"; +import { Role } from "../services/auth/auth-schema"; +import {z} from "zod"; + +export default function RoleChecker(req: Request, res: Response, next: NextFunction) { + const jwt = req.headers.get("authorization"); + console.log(jwt); + + return function (requiredRoles: z.infer[], weakVerification: boolean = false) { + console.log("in here") + next() + } +} \ No newline at end of file diff --git a/src/services/auth/auth-router.ts b/src/services/auth/auth-router.ts index 92d376c..7b8bc9a 100644 --- a/src/services/auth/auth-router.ts +++ b/src/services/auth/auth-router.ts @@ -51,7 +51,7 @@ authRouter.get( try { const jwtPayload = (await getJwtPayloadFromDatabase(userId)).toObject(); const token = jsonwebtoken.sign(jwtPayload, Config.JWT_SIGNING_SECRET, { expiresIn: Config.JWT_EXPIRATION_TIME }); - const redirectUri = DeviceRedirects[req.params.DEVICE] + `token=${token}`; + const redirectUri = DeviceRedirects[req.params.DEVICE] + `?token=${token}`; return res.redirect(redirectUri); } catch (error) { next(error); @@ -60,7 +60,7 @@ authRouter.get( ); authRouter.get("/dev/", (req, res) => { - return res.status(StatusCodes.OK).json({"Token": req.headers.authorization}); + return res.status(StatusCodes.OK).json(req.query); }) export default authRouter; From 5888d71943f1043436ac6c96b9def95994f76231 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Thu, 11 Apr 2024 11:16:59 -0500 Subject: [PATCH 50/93] Added rolechecker support --- src/database.ts | 1 - src/middleware/role-checker.ts | 66 ++++++++++++++++++++++++++++---- src/services/auth/auth-models.ts | 8 ++++ src/services/auth/auth-schema.ts | 2 +- src/services/auth/auth-utils.ts | 4 +- 5 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 src/services/auth/auth-models.ts diff --git a/src/database.ts b/src/database.ts index 8f0cc67..ebe9031 100644 --- a/src/database.ts +++ b/src/database.ts @@ -37,7 +37,6 @@ function initializeModel( // Example usage export const Database = { ROLES: initializeModel("roles", RoleSchema, RoleValidator), - ROLES: initializeModel("roles", RoleSchema, RoleInfo), EVENTS: initializeModel("events", EventSchema, EventValidator), SUBSCRIPTION: initializeModel( "subscription", diff --git a/src/middleware/role-checker.ts b/src/middleware/role-checker.ts index 6999070..8bcd50b 100644 --- a/src/middleware/role-checker.ts +++ b/src/middleware/role-checker.ts @@ -1,13 +1,63 @@ -import { NextFunction } from "express"; -import { Role } from "../services/auth/auth-schema"; +import { NextFunction, Request, Response } from "express"; +import { JwtPayload, Role } from "../services/auth/auth-models"; import {z} from "zod"; +import jsonwebtoken from "jsonwebtoken"; +import { Config } from "../config"; +import { StatusCodes } from "http-status-codes"; -export default function RoleChecker(req: Request, res: Response, next: NextFunction) { - const jwt = req.headers.get("authorization"); - console.log(jwt); - return function (requiredRoles: z.infer[], weakVerification: boolean = false) { - console.log("in here") - next() +export default function RoleChecker (requiredRoles: z.infer[], weakVerification: boolean = false){ + return function (req: Request, res: Response, next: NextFunction) { + const jwt = req.headers.authorization; + + if (jwt == undefined) { + if (weakVerification) { + next(); + } + + return res.status(StatusCodes.BAD_REQUEST).json({error: "NoJWT"}) + } + + try { + console.log("in"); + const payloadData = jsonwebtoken.verify(jwt, Config.JWT_SIGNING_SECRET); + const payload = JwtPayload.parse(payloadData); + res.locals.payload = payload; + + const error = new Error("InvalidRoles"); + const userRoles = payload.roles; + + if (weakVerification) { + next(); + } + + if (requiredRoles.length == 0) { + next(); + } + + // Admins (staff) can access any endpoint + if (userRoles.includes(Role.Enum.ADMIN)) { + next(); + } + + // Corporate role can access corporate only endpoints + if (requiredRoles.includes(Role.Enum.CORPORATE)) { + if (userRoles.includes(Role.Enum.CORPORATE)) { + next(); + } + } + + // Need to be a user to access user endpoints (app users) + if (requiredRoles.includes(Role.Enum.USER)) { + if (userRoles.includes(Role.Enum.USER)) { + next(); + } + } + + throw error; + + } catch (error) { + next(error) + } } } \ No newline at end of file diff --git a/src/services/auth/auth-models.ts b/src/services/auth/auth-models.ts new file mode 100644 index 0000000..a34b6db --- /dev/null +++ b/src/services/auth/auth-models.ts @@ -0,0 +1,8 @@ +import { z } from "zod"; + +export const Role = z.enum(["USER", "ADMIN", "CORPORATE"]); + +export const JwtPayload = z.object({ + userId: z.string(), + roles: Role.array(), +}) \ No newline at end of file diff --git a/src/services/auth/auth-schema.ts b/src/services/auth/auth-schema.ts index 619cf7a..b688077 100644 --- a/src/services/auth/auth-schema.ts +++ b/src/services/auth/auth-schema.ts @@ -1,7 +1,7 @@ import { Schema } from "mongoose"; import { z } from "zod"; +import { Role } from "./auth-models"; -export const Role = z.enum(["USER", "ADMIN", "CORPORATE"]); export const RoleValidator = z.object({ userId: z.coerce.string().regex(/user[0-9]*/), diff --git a/src/services/auth/auth-utils.ts b/src/services/auth/auth-utils.ts index d163571..fbb4e11 100644 --- a/src/services/auth/auth-utils.ts +++ b/src/services/auth/auth-utils.ts @@ -1,7 +1,6 @@ // Create a function to generate GoogleStrategy instances import { Strategy as GoogleStrategy } from "passport-google-oauth20"; import { Config } from "../../config"; -import { Role } from "./auth-schema"; import { Database } from "../../database"; export function createGoogleStrategy(device: string) { @@ -17,11 +16,10 @@ export function createGoogleStrategy(device: string) { const userId = `user${profile.id}`; const name = profile.displayName; const email = profile._json.email; - const roles = [Role.Enum.USER]; Database.ROLES.findOneAndUpdate( { userId: userId }, - { userId, name, email, roles }, + { userId, name, email }, { upsert: true } ) .then(() => cb(null, profile)) From dc4b9c8665c1cc42dc5a089125266b1a3fe9ce7f Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Thu, 11 Apr 2024 11:17:54 -0500 Subject: [PATCH 51/93] Added linting --- src/config.ts | 2 +- src/middleware/role-checker.ts | 26 +++++++++++++++----------- src/services/auth/auth-models.ts | 4 ++-- src/services/auth/auth-router.ts | 19 +++++++++++++------ src/services/auth/auth-schema.ts | 1 - src/services/auth/auth-utils.ts | 10 ++++++---- 6 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/config.ts b/src/config.ts index 1239660..38aab55 100644 --- a/src/config.ts +++ b/src/config.ts @@ -28,5 +28,5 @@ export const Config = { export const DeviceRedirects: Record = { web: "https://www.google.com/", - dev: "http://127.0.0.1:3000/auth/dev/" + dev: "http://127.0.0.1:3000/auth/dev/", }; diff --git a/src/middleware/role-checker.ts b/src/middleware/role-checker.ts index 8bcd50b..6fc5cf8 100644 --- a/src/middleware/role-checker.ts +++ b/src/middleware/role-checker.ts @@ -1,12 +1,14 @@ import { NextFunction, Request, Response } from "express"; import { JwtPayload, Role } from "../services/auth/auth-models"; -import {z} from "zod"; +import { z } from "zod"; import jsonwebtoken from "jsonwebtoken"; import { Config } from "../config"; import { StatusCodes } from "http-status-codes"; - -export default function RoleChecker (requiredRoles: z.infer[], weakVerification: boolean = false){ +export default function RoleChecker( + requiredRoles: z.infer[], + weakVerification: boolean = false +) { return function (req: Request, res: Response, next: NextFunction) { const jwt = req.headers.authorization; @@ -15,12 +17,15 @@ export default function RoleChecker (requiredRoles: z.infer[], weak next(); } - return res.status(StatusCodes.BAD_REQUEST).json({error: "NoJWT"}) + return res.status(StatusCodes.BAD_REQUEST).json({ error: "NoJWT" }); } - + try { console.log("in"); - const payloadData = jsonwebtoken.verify(jwt, Config.JWT_SIGNING_SECRET); + const payloadData = jsonwebtoken.verify( + jwt, + Config.JWT_SIGNING_SECRET + ); const payload = JwtPayload.parse(payloadData); res.locals.payload = payload; @@ -30,7 +35,7 @@ export default function RoleChecker (requiredRoles: z.infer[], weak if (weakVerification) { next(); } - + if (requiredRoles.length == 0) { next(); } @@ -55,9 +60,8 @@ export default function RoleChecker (requiredRoles: z.infer[], weak } throw error; - } catch (error) { - next(error) + next(error); } - } -} \ No newline at end of file + }; +} diff --git a/src/services/auth/auth-models.ts b/src/services/auth/auth-models.ts index a34b6db..bda56ab 100644 --- a/src/services/auth/auth-models.ts +++ b/src/services/auth/auth-models.ts @@ -2,7 +2,7 @@ import { z } from "zod"; export const Role = z.enum(["USER", "ADMIN", "CORPORATE"]); -export const JwtPayload = z.object({ +export const JwtPayload = z.object({ userId: z.string(), roles: Role.array(), -}) \ No newline at end of file +}); diff --git a/src/services/auth/auth-router.ts b/src/services/auth/auth-router.ts index 7b8bc9a..8ab4301 100644 --- a/src/services/auth/auth-router.ts +++ b/src/services/auth/auth-router.ts @@ -42,16 +42,23 @@ authRouter.get( async function (req, res, next) { // Authentication failed - redirect to login if (req.user == undefined) { - return res.redirect(`/auth/login/${req.params.DEVICE}`) + return res.redirect(`/auth/login/${req.params.DEVICE}`); } const userData = req.user as Profile; const userId = `user${userData.id}`; - + // Generate the JWT, and redirect to JWT initialization try { - const jwtPayload = (await getJwtPayloadFromDatabase(userId)).toObject(); - const token = jsonwebtoken.sign(jwtPayload, Config.JWT_SIGNING_SECRET, { expiresIn: Config.JWT_EXPIRATION_TIME }); - const redirectUri = DeviceRedirects[req.params.DEVICE] + `?token=${token}`; + const jwtPayload = ( + await getJwtPayloadFromDatabase(userId) + ).toObject(); + const token = jsonwebtoken.sign( + jwtPayload, + Config.JWT_SIGNING_SECRET, + { expiresIn: Config.JWT_EXPIRATION_TIME } + ); + const redirectUri = + DeviceRedirects[req.params.DEVICE] + `?token=${token}`; return res.redirect(redirectUri); } catch (error) { next(error); @@ -61,6 +68,6 @@ authRouter.get( authRouter.get("/dev/", (req, res) => { return res.status(StatusCodes.OK).json(req.query); -}) +}); export default authRouter; diff --git a/src/services/auth/auth-schema.ts b/src/services/auth/auth-schema.ts index b688077..9434d11 100644 --- a/src/services/auth/auth-schema.ts +++ b/src/services/auth/auth-schema.ts @@ -2,7 +2,6 @@ import { Schema } from "mongoose"; import { z } from "zod"; import { Role } from "./auth-models"; - export const RoleValidator = z.object({ userId: z.coerce.string().regex(/user[0-9]*/), name: z.coerce.string(), diff --git a/src/services/auth/auth-utils.ts b/src/services/auth/auth-utils.ts index fbb4e11..b4a3c2e 100644 --- a/src/services/auth/auth-utils.ts +++ b/src/services/auth/auth-utils.ts @@ -28,12 +28,14 @@ export function createGoogleStrategy(device: string) { ); } - export async function getJwtPayloadFromDatabase(userId: string) { - const payload = await Database.ROLES.findOne({userId: userId}).select(["userId", "roles"]); + const payload = await Database.ROLES.findOne({ userId: userId }).select([ + "userId", + "roles", + ]); if (!payload) { throw new Error("NoUserFound"); } - + return payload; -} \ No newline at end of file +} From 7aab40db50a455a08606b5360ff8dea7447c09a6 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Thu, 11 Apr 2024 13:27:13 -0500 Subject: [PATCH 52/93] Fixed naming conventions --- src/app.ts | 1 - src/middleware/role-checker.ts | 6 +++--- src/services/auth/auth-models.ts | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/app.ts b/src/app.ts index bfd276b..397879a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -28,7 +28,6 @@ app.use("/event", eventRouter); app.use("/subscription", subscriptionRouter); app.get("/status", (_, res) => { - console.log(StatusCodes.OK); return res.status(StatusCodes.OK).send("API is alive!"); }); diff --git a/src/middleware/role-checker.ts b/src/middleware/role-checker.ts index 6fc5cf8..4c672a4 100644 --- a/src/middleware/role-checker.ts +++ b/src/middleware/role-checker.ts @@ -1,5 +1,5 @@ import { NextFunction, Request, Response } from "express"; -import { JwtPayload, Role } from "../services/auth/auth-models"; +import { JwtPayloadValidator, Role } from "../services/auth/auth-models"; import { z } from "zod"; import jsonwebtoken from "jsonwebtoken"; import { Config } from "../config"; @@ -21,12 +21,12 @@ export default function RoleChecker( } try { - console.log("in"); const payloadData = jsonwebtoken.verify( jwt, Config.JWT_SIGNING_SECRET ); - const payload = JwtPayload.parse(payloadData); + + const payload = JwtPayloadValidator.parse(payloadData); res.locals.payload = payload; const error = new Error("InvalidRoles"); diff --git a/src/services/auth/auth-models.ts b/src/services/auth/auth-models.ts index bda56ab..2dbed28 100644 --- a/src/services/auth/auth-models.ts +++ b/src/services/auth/auth-models.ts @@ -2,7 +2,7 @@ import { z } from "zod"; export const Role = z.enum(["USER", "ADMIN", "CORPORATE"]); -export const JwtPayload = z.object({ +export const JwtPayloadValidator = z.object({ userId: z.string(), roles: Role.array(), }); From 61b117f3dc88d6805aa5da91613e32dd818e1997 Mon Sep 17 00:00:00 2001 From: divinedab Date: Fri, 12 Apr 2024 16:52:52 -0500 Subject: [PATCH 53/93] =?UTF-8?q?=F0=9F=90=9B=20Redoing=20subscription=20s?= =?UTF-8?q?chema+endpoint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit added a SubscriptionSchemaValidator and modified SubscriptionValidator, added array to schemas --- src/database.ts | 8 ++++---- src/services/subscription/subscription-router.ts | 7 +++++-- src/services/subscription/subscription-schema.ts | 11 ++++++++--- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/database.ts b/src/database.ts index ebe9031..7e0a9e6 100644 --- a/src/database.ts +++ b/src/database.ts @@ -2,7 +2,7 @@ import mongoose, { Schema } from "mongoose"; import { RoleValidator, RoleSchema } from "./services/auth/auth-schema"; import { EventSchema, EventValidator } from "./services/events/events-schema"; import { - SubscriptionValidator, + SubscriptionSchemaValidator, SubscriptionSchema, } from "./services/subscription/subscription-schema"; @@ -38,9 +38,9 @@ function initializeModel( export const Database = { ROLES: initializeModel("roles", RoleSchema, RoleValidator), EVENTS: initializeModel("events", EventSchema, EventValidator), - SUBSCRIPTION: initializeModel( - "subscription", + SUBSCRIPTIONS: initializeModel( + "subscriptions", SubscriptionSchema, - SubscriptionValidator + SubscriptionSchemaValidator ), }; diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts index b503fbe..d7ce86d 100644 --- a/src/services/subscription/subscription-router.ts +++ b/src/services/subscription/subscription-router.ts @@ -8,10 +8,13 @@ const subscriptionRouter = Router(); // Create a new subscription subscriptionRouter.post("/", async (req, res, next) => { try { + // Validate the incoming user subscription const subscriptionData = SubscriptionValidator.parse(req.body); - await Database.SUBSCRIPTION.findOneAndUpdate( + + // Upsert the user info into the corresponding Subscription collection + await Database.SUBSCRIPTIONS.findOneAndUpdate( { mailingList: subscriptionData.mailingList }, - { $push: { subscriptions: subscriptionData.email } }, + { $push: { emailList: subscriptionData.email } }, { upsert: true, new: true } ); return res.status(StatusCodes.CREATED).json(subscriptionData); diff --git a/src/services/subscription/subscription-schema.ts b/src/services/subscription/subscription-schema.ts index 32579bf..d8fa056 100644 --- a/src/services/subscription/subscription-schema.ts +++ b/src/services/subscription/subscription-schema.ts @@ -2,16 +2,21 @@ import mongoose from "mongoose"; import { z } from "zod"; import { MailingListName } from "../../config"; -// Zod schema for subscription +// Zod schema for incoming user subscriptions const SubscriptionValidator = z.object({ email: z.string().email(), mailingList: MailingListName, }); +const SubscriptionSchemaValidator = z.object({ + mailingList: MailingListName, + emailList: z.array(z.string().email()) +}); + // Mongoose schema for subscription const SubscriptionSchema = new mongoose.Schema({ - email: { type: String, required: true }, mailingList: { type: String, required: true }, + emailList: [{ type: String, required: true }] }); -export { SubscriptionValidator, SubscriptionSchema }; +export { SubscriptionValidator, SubscriptionSchemaValidator, SubscriptionSchema }; From eec069da25187c354752918feb078280f3c20d88 Mon Sep 17 00:00:00 2001 From: divinedab Date: Fri, 12 Apr 2024 17:00:59 -0500 Subject: [PATCH 54/93] trying to fix linting issues --- src/services/subscription/subscription-schema.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/services/subscription/subscription-schema.ts b/src/services/subscription/subscription-schema.ts index d8fa056..6798b2b 100644 --- a/src/services/subscription/subscription-schema.ts +++ b/src/services/subscription/subscription-schema.ts @@ -10,13 +10,17 @@ const SubscriptionValidator = z.object({ const SubscriptionSchemaValidator = z.object({ mailingList: MailingListName, - emailList: z.array(z.string().email()) + emailList: z.array(z.string().email()), }); // Mongoose schema for subscription const SubscriptionSchema = new mongoose.Schema({ mailingList: { type: String, required: true }, - emailList: [{ type: String, required: true }] + emailList: [{ type: String, required: true }], }); -export { SubscriptionValidator, SubscriptionSchemaValidator, SubscriptionSchema }; +export { + SubscriptionValidator, + SubscriptionSchemaValidator, + SubscriptionSchema +}; From 999ecbd185e8a3ffd7c8800097dcc9e7449d1313 Mon Sep 17 00:00:00 2001 From: divinedab Date: Fri, 12 Apr 2024 17:02:52 -0500 Subject: [PATCH 55/93] more linting --- src/services/subscription/subscription-schema.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/subscription/subscription-schema.ts b/src/services/subscription/subscription-schema.ts index 6798b2b..a6c71c3 100644 --- a/src/services/subscription/subscription-schema.ts +++ b/src/services/subscription/subscription-schema.ts @@ -19,8 +19,8 @@ const SubscriptionSchema = new mongoose.Schema({ emailList: [{ type: String, required: true }], }); -export { +export { SubscriptionValidator, SubscriptionSchemaValidator, - SubscriptionSchema + SubscriptionSchema, }; From 20b5e2722491de21821559229691f8200fa5e463 Mon Sep 17 00:00:00 2001 From: divinedab Date: Fri, 12 Apr 2024 17:25:13 -0500 Subject: [PATCH 56/93] renaming subscription list variable --- src/services/subscription/subscription-router.ts | 2 +- src/services/subscription/subscription-schema.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts index d7ce86d..e8b7a5f 100644 --- a/src/services/subscription/subscription-router.ts +++ b/src/services/subscription/subscription-router.ts @@ -14,7 +14,7 @@ subscriptionRouter.post("/", async (req, res, next) => { // Upsert the user info into the corresponding Subscription collection await Database.SUBSCRIPTIONS.findOneAndUpdate( { mailingList: subscriptionData.mailingList }, - { $push: { emailList: subscriptionData.email } }, + { $push: { subscriptions: subscriptionData.email } }, { upsert: true, new: true } ); return res.status(StatusCodes.CREATED).json(subscriptionData); diff --git a/src/services/subscription/subscription-schema.ts b/src/services/subscription/subscription-schema.ts index a6c71c3..27192f1 100644 --- a/src/services/subscription/subscription-schema.ts +++ b/src/services/subscription/subscription-schema.ts @@ -10,13 +10,13 @@ const SubscriptionValidator = z.object({ const SubscriptionSchemaValidator = z.object({ mailingList: MailingListName, - emailList: z.array(z.string().email()), + subscriptions: z.array(z.string().email()), }); // Mongoose schema for subscription const SubscriptionSchema = new mongoose.Schema({ mailingList: { type: String, required: true }, - emailList: [{ type: String, required: true }], + subscriptions: [{ type: String, required: true }], }); export { From d69c3cc357318dcd7e0be321a64cb88f0d4e1a23 Mon Sep 17 00:00:00 2001 From: divinedab Date: Fri, 12 Apr 2024 17:26:34 -0500 Subject: [PATCH 57/93] adding one comment :') --- src/services/subscription/subscription-schema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/subscription/subscription-schema.ts b/src/services/subscription/subscription-schema.ts index 27192f1..63a2fcf 100644 --- a/src/services/subscription/subscription-schema.ts +++ b/src/services/subscription/subscription-schema.ts @@ -8,6 +8,7 @@ const SubscriptionValidator = z.object({ mailingList: MailingListName, }); +// Zod schema for validating subscription lists const SubscriptionSchemaValidator = z.object({ mailingList: MailingListName, subscriptions: z.array(z.string().email()), From 53f999ddd4b87cba9cef427bd8f67b51be615735 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sat, 13 Apr 2024 18:40:10 -0500 Subject: [PATCH 58/93] Update README.md Making change to trigger codedeploy --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e111b0..943f61c 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# rp-api +# Official API for Reflections | Projections From 0bcf3ea02392708320dfcaa8307cff783a9fc19a Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sat, 13 Apr 2024 19:07:24 -0500 Subject: [PATCH 59/93] Another change to update pipelines --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 943f61c..3ba46f3 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# Official API for Reflections | Projections +# Official API for Reflections | Projections 2024 From d07d282659d1f621760b1db3d95576432b7d0ac8 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 15:29:40 -0500 Subject: [PATCH 60/93] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ba46f3..819f9e1 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# Official API for Reflections | Projections 2024 +# API for Reflections | Projections 2024 From dacccf74dbf8108445a71a93a79463f4f4162719 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 15:32:19 -0500 Subject: [PATCH 61/93] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 819f9e1..2ed3622 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ # API for Reflections | Projections 2024 + +Contributors: From c57d0d5190edbd04b97128cb9fb0d0bd73f472d9 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 15:49:17 -0500 Subject: [PATCH 62/93] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 2ed3622..f750803 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ # API for Reflections | Projections 2024 Contributors: +- Aydan Pirani +- Divya Koya +- Riya Patel +- Jacob Chang +- Alex Yang From d28edc6d0962d88c26b3db0505f665f0df34dae4 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 16:01:46 -0500 Subject: [PATCH 63/93] Update build.sh --- scripts/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build.sh b/scripts/build.sh index 95a91f4..1533d0b 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,3 +1,3 @@ #!/bin/bash cd /home/ubuntu/rp-api -tsc \ No newline at end of file +sudo tsc From 9fd5e5bb385bd40c6d57278cff4c8ab66fc24727 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 16:01:54 -0500 Subject: [PATCH 64/93] Update install_dependencies.sh --- scripts/install_dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index c51f6f2..2f6b228 100644 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -1,3 +1,3 @@ #!/bin/bash cd /home/ubuntu/rp-api -yarn \ No newline at end of file +sudo yarn From 30dfdb29422dde61b8005cbf09090ec1486b4d59 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 16:02:02 -0500 Subject: [PATCH 65/93] Update reload_server.sh --- scripts/reload_server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/reload_server.sh b/scripts/reload_server.sh index bb152c1..44b2694 100644 --- a/scripts/reload_server.sh +++ b/scripts/reload_server.sh @@ -1,3 +1,3 @@ #!/bin/bash cd /home/ubuntu/rp-api -pm2 reload RP_API +sudo pm2 reload RP_API From 1ba901f0d50101c556a7953a646f96228b5db2f9 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 16:06:33 -0500 Subject: [PATCH 66/93] Update build.sh --- scripts/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build.sh b/scripts/build.sh index 1533d0b..1d8b9e3 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,3 +1,3 @@ #!/bin/bash cd /home/ubuntu/rp-api -sudo tsc +yarn build From d3d6712ff826a1ee67a376bf239f880ebae5ae28 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 17:09:35 -0500 Subject: [PATCH 67/93] Ensure that emails are unique --- src/services/subscription/subscription-router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts index e8b7a5f..55d6c69 100644 --- a/src/services/subscription/subscription-router.ts +++ b/src/services/subscription/subscription-router.ts @@ -14,7 +14,7 @@ subscriptionRouter.post("/", async (req, res, next) => { // Upsert the user info into the corresponding Subscription collection await Database.SUBSCRIPTIONS.findOneAndUpdate( { mailingList: subscriptionData.mailingList }, - { $push: { subscriptions: subscriptionData.email } }, + { addToSet: { subscriptions: subscriptionData.email } }, { upsert: true, new: true } ); return res.status(StatusCodes.CREATED).json(subscriptionData); From df43776b5e0e9a127b98dd4187dfc61ca32a6c63 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 17:37:31 -0500 Subject: [PATCH 68/93] add $ --- src/services/subscription/subscription-router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts index 55d6c69..e83e69c 100644 --- a/src/services/subscription/subscription-router.ts +++ b/src/services/subscription/subscription-router.ts @@ -14,7 +14,7 @@ subscriptionRouter.post("/", async (req, res, next) => { // Upsert the user info into the corresponding Subscription collection await Database.SUBSCRIPTIONS.findOneAndUpdate( { mailingList: subscriptionData.mailingList }, - { addToSet: { subscriptions: subscriptionData.email } }, + { $addToSet: { subscriptions: subscriptionData.email } }, { upsert: true, new: true } ); return res.status(StatusCodes.CREATED).json(subscriptionData); From 70a62e5668746fdaeff302bb782481f803da2a87 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 17:44:17 -0500 Subject: [PATCH 69/93] Fixed CORS potentially? --- package.json | 2 ++ src/middleware/cors-middleware.ts | 26 +++++++++++++++++++ .../subscription/subscription-router.ts | 3 ++- yarn.lock | 19 ++++++++++++-- 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 src/middleware/cors-middleware.ts diff --git a/package.json b/package.json index aad14dd..c09db22 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,9 @@ }, "dependencies": { "@paralleldrive/cuid2": "^2.2.2", + "@types/cors": "^2.8.17", "body-parser": "^1.20.2", + "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.1", "http-status-codes": "^2.3.0", diff --git a/src/middleware/cors-middleware.ts b/src/middleware/cors-middleware.ts new file mode 100644 index 0000000..bc9242a --- /dev/null +++ b/src/middleware/cors-middleware.ts @@ -0,0 +1,26 @@ +import cors from "cors"; + +// Allow CORS for Netlify deploy previews +const allowedOrigins = ["https://reflectionsprojections.org"]; + +// Function to check if the origin matches the deploy preview format +function isNetlifyDeployPreview(origin: string) { + const regex = /^https:\/\/deploy-preview-\d+--rp2024\.netlify\.app\/$/; + return regex.test(origin); +} + +const corsMiddleware = cors({ + origin: function (origin, callback) { + if ( + !origin || + allowedOrigins.includes(origin) || + isNetlifyDeployPreview(origin) + ) { + callback(null, true); + } else { + callback(new Error("Not allowed by CORS")); + } + }, +}); + +export default corsMiddleware; diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts index e83e69c..50555bf 100644 --- a/src/services/subscription/subscription-router.ts +++ b/src/services/subscription/subscription-router.ts @@ -2,11 +2,12 @@ import { Router } from "express"; import { StatusCodes } from "http-status-codes"; import { SubscriptionValidator } from "./subscription-schema"; import { Database } from "../../database"; +import corsMiddleware from "../../middleware/cors-middleware"; const subscriptionRouter = Router(); // Create a new subscription -subscriptionRouter.post("/", async (req, res, next) => { +subscriptionRouter.post("/", corsMiddleware, async (req, res, next) => { try { // Validate the incoming user subscription const subscriptionData = SubscriptionValidator.parse(req.body); diff --git a/yarn.lock b/yarn.lock index 33f43b2..8a6dd15 100644 --- a/yarn.lock +++ b/yarn.lock @@ -238,6 +238,13 @@ dependencies: "@types/node" "*" +"@types/cors@^2.8.17": + version "2.8.17" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" + integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== + dependencies: + "@types/node" "*" + "@types/dotenv@^8.2.0": version "8.2.0" resolved "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz" @@ -807,6 +814,14 @@ core-js-pure@^3.30.2: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.36.1.tgz#1461c89e76116528b54eba20a0aff30164087a94" integrity sha512-NXCvHvSVYSrewP0L5OhltzXeWFJLo2AL2TYnj6iLV3Bw8mM62wAQMNgUCRI6EBu6hVVpbCxmOPlxh1Ikw2PfUA== +cors@^2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" @@ -2237,7 +2252,7 @@ oauth@0.10.x: resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.10.0.tgz#3551c4c9b95c53ea437e1e21e46b649482339c58" integrity sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q== -object-assign@^4.1.1: +object-assign@^4, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -2996,7 +3011,7 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== -vary@~1.1.2: +vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== From 207642abb3db6e76033b6742261c6ec9d6cf7cd1 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 17:58:13 -0500 Subject: [PATCH 70/93] clean up regex --- src/middleware/cors-middleware.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/middleware/cors-middleware.ts b/src/middleware/cors-middleware.ts index bc9242a..a902a69 100644 --- a/src/middleware/cors-middleware.ts +++ b/src/middleware/cors-middleware.ts @@ -2,10 +2,9 @@ import cors from "cors"; // Allow CORS for Netlify deploy previews const allowedOrigins = ["https://reflectionsprojections.org"]; - // Function to check if the origin matches the deploy preview format function isNetlifyDeployPreview(origin: string) { - const regex = /^https:\/\/deploy-preview-\d+--rp2024\.netlify\.app\/$/; + const regex = new RegExp("deploy-preview-[0-9]*(--rp2024\.netlify\.app)(.*)") return regex.test(origin); } From df0af0ec2dc1b7b81652e9372cf02df548c8fdf5 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 17:59:34 -0500 Subject: [PATCH 71/93] Added linting --- src/middleware/cors-middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middleware/cors-middleware.ts b/src/middleware/cors-middleware.ts index a902a69..72f3d01 100644 --- a/src/middleware/cors-middleware.ts +++ b/src/middleware/cors-middleware.ts @@ -4,7 +4,7 @@ import cors from "cors"; const allowedOrigins = ["https://reflectionsprojections.org"]; // Function to check if the origin matches the deploy preview format function isNetlifyDeployPreview(origin: string) { - const regex = new RegExp("deploy-preview-[0-9]*(--rp2024\.netlify\.app)(.*)") + const regex = new RegExp("deploy-preview-[0-9]*(--rp2024.netlify.app)(.*)"); return regex.test(origin); } From 4cb44a099cc3c3274622c382713f06a113c2aff3 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 18:02:38 -0500 Subject: [PATCH 72/93] Allowing everything for cors --- src/middleware/cors-middleware.ts | 44 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/middleware/cors-middleware.ts b/src/middleware/cors-middleware.ts index 72f3d01..be5e39f 100644 --- a/src/middleware/cors-middleware.ts +++ b/src/middleware/cors-middleware.ts @@ -1,25 +1,25 @@ import cors from "cors"; -// Allow CORS for Netlify deploy previews -const allowedOrigins = ["https://reflectionsprojections.org"]; -// Function to check if the origin matches the deploy preview format -function isNetlifyDeployPreview(origin: string) { - const regex = new RegExp("deploy-preview-[0-9]*(--rp2024.netlify.app)(.*)"); - return regex.test(origin); -} +// // Allow CORS for Netlify deploy previews +// const allowedOrigins = ["https://reflectionsprojections.org"]; +// // Function to check if the origin matches the deploy preview format +// function isNetlifyDeployPreview(origin: string) { +// const regex = new RegExp("deploy-preview-[0-9]*(--rp2024.netlify.app)(.*)"); +// return regex.test(origin); +// } +// +// const corsMiddleware = cors({ +// origin: function (origin, callback) { +// if ( +// !origin || +// allowedOrigins.includes(origin) || +// isNetlifyDeployPreview(origin) +// ) { +// callback(null, true); +// } else { +// callback(new Error("Not allowed by CORS")); +// } +// }, +// }); -const corsMiddleware = cors({ - origin: function (origin, callback) { - if ( - !origin || - allowedOrigins.includes(origin) || - isNetlifyDeployPreview(origin) - ) { - callback(null, true); - } else { - callback(new Error("Not allowed by CORS")); - } - }, -}); - -export default corsMiddleware; +export default cors(); From bf82da84699a651eb86484f6ee1d88fd54020cf7 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 18:05:46 -0500 Subject: [PATCH 73/93] more cors changes --- src/middleware/cors-middleware.ts | 4 ++-- src/services/subscription/subscription-router.ts | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/middleware/cors-middleware.ts b/src/middleware/cors-middleware.ts index be5e39f..599548f 100644 --- a/src/middleware/cors-middleware.ts +++ b/src/middleware/cors-middleware.ts @@ -1,4 +1,4 @@ -import cors from "cors"; +// import cors from "cors"; // // Allow CORS for Netlify deploy previews // const allowedOrigins = ["https://reflectionsprojections.org"]; @@ -22,4 +22,4 @@ import cors from "cors"; // }, // }); -export default cors(); +// export default cors(); diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts index 50555bf..93523ef 100644 --- a/src/services/subscription/subscription-router.ts +++ b/src/services/subscription/subscription-router.ts @@ -2,12 +2,13 @@ import { Router } from "express"; import { StatusCodes } from "http-status-codes"; import { SubscriptionValidator } from "./subscription-schema"; import { Database } from "../../database"; -import corsMiddleware from "../../middleware/cors-middleware"; +// import corsMiddleware from "../../middleware/cors-middleware"; +import cors from "cors"; const subscriptionRouter = Router(); // Create a new subscription -subscriptionRouter.post("/", corsMiddleware, async (req, res, next) => { +subscriptionRouter.post("/", cors(), async (req, res, next) => { try { // Validate the incoming user subscription const subscriptionData = SubscriptionValidator.parse(req.body); From ae64510d9d594ad1d7a1477b9bee011ade38ae11 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 14 Apr 2024 18:16:34 -0500 Subject: [PATCH 74/93] Update app.ts --- src/app.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app.ts b/src/app.ts index 397879a..7f9f4b5 100644 --- a/src/app.ts +++ b/src/app.ts @@ -3,6 +3,7 @@ import { StatusCodes } from "http-status-codes"; import { Config } from "./config"; import { connectToDatabase } from "./utilities"; +import cors from "cors"; import morgan from "morgan"; import bodyParser from "body-parser"; import errorHandler from "./middleware/error-handler"; @@ -17,6 +18,8 @@ const app = express(); // (we can remove this later) app.disable("etag"); +app.use(cors()); + // To display the logs every time app.use("/", morgan("dev")); From b0199d69342749626ebae2f826c172a9febc111d Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+DatProJack@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:48:00 -0500 Subject: [PATCH 75/93] github workflows --- .github/workflows/build.yml | 14 ++++---------- .github/workflows/lint.yml | 8 +------- .github/workflows/prettier.yml | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/prettier.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d837ecb..fd14671 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,16 +1,10 @@ -name: Prettier on Push and PR +name: Build on: push: - branches: - - "main" - - "dev**" - pull_request: - branches: - - "main" jobs: - prettier: + build: runs-on: ubuntu-latest steps: @@ -20,5 +14,5 @@ jobs: node-version: "18.x" - name: Install dependencies run: yarn - - name: Run Prettier - run: npx prettier --write . + - name: Build + run: yarn build diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ab6f447..c477b00 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,13 +1,7 @@ -name: Lint on Push and PR +name: Lint on: push: - branches: - - 'main' - - 'dev**' - pull_request: - branches: - - 'main' jobs: lint: diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml new file mode 100644 index 0000000..150599e --- /dev/null +++ b/.github/workflows/prettier.yml @@ -0,0 +1,18 @@ +name: Prettier + +on: + push: + +jobs: + prettier: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "18.x" + - name: Install dependencies + run: yarn + - name: Run Prettier + run: npx prettier --write . From 8f05bbecccc44bce9b5bd4b39b359dc7b1bcd917 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Mon, 15 Apr 2024 23:00:16 -0500 Subject: [PATCH 76/93] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f750803..781821c 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,4 @@ Contributors: - Riya Patel - Jacob Chang - Alex Yang +- Shreenija Daggavolu From f3e1c7aea935c27dd2d20f1f95bb7644c8fa55ef Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Mon, 1 Apr 2024 18:08:54 -0500 Subject: [PATCH 77/93] starting attendee api routes --- src/app.ts | 44 +++++++++++++++++++++++ src/services/attendees/attendee-schema.ts | 20 +++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/services/attendees/attendee-schema.ts diff --git a/src/app.ts b/src/app.ts index 7f9f4b5..232ecad 100644 --- a/src/app.ts +++ b/src/app.ts @@ -12,6 +12,9 @@ import authRouter from "./services/auth/auth-router"; import eventRouter from "./services/events/events-router"; import subscriptionRouter from "./services/subscription/subscription-router"; +import { CreateAttendeeSchema } from "./services/attendees/attendee-schema"; +import { AttendeeModel } from "./services/attendees/attendee-schema"; + const app = express(); // to prevent server-side caching/returning status code 200 @@ -30,6 +33,47 @@ app.use("/auth", authRouter); app.use("/event", eventRouter); app.use("/subscription", subscriptionRouter); +// Create a new attendee +app.post("/attendees", async (req, res) => { + try { + const { name, email } = CreateAttendeeSchema.parse(req.body); + console.log("Name:", name); + console.log("Email:", email); + + // Save attendee to the database + const attendee = new AttendeeModel({ name, email }); + await attendee.save(); + + res.status(201).send("Attendee created successfully."); + } catch (error) { + console.error("Error:", error); + res.status(400).send("Error creating attendee."); + } +}); + +// Check if a user email exists +app.get("/attendees/:email", async (req, res) => { + try { + const { email } = req.params; + + // Check if the user exists in the database + const userExists = await AttendeeModel.exists({ email }); + + if (!userExists) { + return res + .status(StatusCodes.NOT_FOUND) + .send("User with that email does not exist."); + } + + return res.status(StatusCodes.OK).send("User exists."); + } catch (error) { + console.error("Error:", error); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); + } +}); + app.get("/status", (_, res) => { return res.status(StatusCodes.OK).send("API is alive!"); }); diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts new file mode 100644 index 0000000..8e936bc --- /dev/null +++ b/src/services/attendees/attendee-schema.ts @@ -0,0 +1,20 @@ +import mongoose from "mongoose"; +import { z } from "zod"; + + +// Zod schema for attendee +const CreateAttendeeSchema = z.object({ + name: z.string(), + email: z.string().email(), +}); + + +// Mongoose schema for attendee +const AttendeeSchema = new mongoose.Schema({ + name: { type: String, required: true }, + email: { type: String, required: true, unique: true }, +}); + + +export const AttendeeModel = mongoose.model("Attendee", AttendeeSchema); +export { CreateAttendeeSchema }; \ No newline at end of file From 2ec7f39883bfba243116c426a5800baceecf29de Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Sun, 7 Apr 2024 12:17:19 -0500 Subject: [PATCH 78/93] continuing attendee schema and event schema --- src/app.ts | 48 +------------ src/services/attendees/attendee-router.ts | 49 +++++++++++++ src/services/attendees/attendee-schema.ts | 43 ++++++++++-- src/services/events/event-router.ts | 86 +++++++++++++++++++++++ src/services/events/event-schema.ts | 50 +++++++++++++ 5 files changed, 226 insertions(+), 50 deletions(-) create mode 100644 src/services/attendees/attendee-router.ts create mode 100644 src/services/events/event-router.ts create mode 100644 src/services/events/event-schema.ts diff --git a/src/app.ts b/src/app.ts index 232ecad..2c66856 100644 --- a/src/app.ts +++ b/src/app.ts @@ -9,11 +9,10 @@ import bodyParser from "body-parser"; import errorHandler from "./middleware/error-handler"; import authRouter from "./services/auth/auth-router"; -import eventRouter from "./services/events/events-router"; import subscriptionRouter from "./services/subscription/subscription-router"; -import { CreateAttendeeSchema } from "./services/attendees/attendee-schema"; -import { AttendeeModel } from "./services/attendees/attendee-schema"; +import attendeeRouter from "./services/attendees/attendee-router"; +import eventRouter from "./services/events/event-router"; const app = express(); @@ -30,49 +29,8 @@ app.use("/", bodyParser.json()); // API routes app.use("/auth", authRouter); +app.use("/attendee", attendeeRouter); app.use("/event", eventRouter); -app.use("/subscription", subscriptionRouter); - -// Create a new attendee -app.post("/attendees", async (req, res) => { - try { - const { name, email } = CreateAttendeeSchema.parse(req.body); - console.log("Name:", name); - console.log("Email:", email); - - // Save attendee to the database - const attendee = new AttendeeModel({ name, email }); - await attendee.save(); - - res.status(201).send("Attendee created successfully."); - } catch (error) { - console.error("Error:", error); - res.status(400).send("Error creating attendee."); - } -}); - -// Check if a user email exists -app.get("/attendees/:email", async (req, res) => { - try { - const { email } = req.params; - - // Check if the user exists in the database - const userExists = await AttendeeModel.exists({ email }); - - if (!userExists) { - return res - .status(StatusCodes.NOT_FOUND) - .send("User with that email does not exist."); - } - - return res.status(StatusCodes.OK).send("User exists."); - } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); - } -}); app.get("/status", (_, res) => { return res.status(StatusCodes.OK).send("API is alive!"); diff --git a/src/services/attendees/attendee-router.ts b/src/services/attendees/attendee-router.ts new file mode 100644 index 0000000..6c27a72 --- /dev/null +++ b/src/services/attendees/attendee-router.ts @@ -0,0 +1,49 @@ +import { Router } from "express"; +import { StatusCodes } from "http-status-codes"; +import { AttendeeValidator } from "./attendee-schema"; +import { AttendeeModel } from "./attendee-schema"; + +const attendeeRouter = Router(); + +// Create a new attendee +attendeeRouter.post("/", async (req, res) => { + try { + const { name, email } = AttendeeValidator.parse(req.body); + console.log("Name:", name); + console.log("Email:", email); + + // Save attendee to the database + const attendee = new AttendeeModel({ name, email }); + await attendee.save(); + + res.status(201).send("Attendee created successfully."); + } catch (error) { + console.error("Error:", error); + res.status(400).send("Error creating attendee."); + } +}); + +// Check if a user email exists +attendeeRouter.get("/:email", async (req, res) => { + try { + const { email } = req.params; + + // Check if the user exists in the database + const userExists = await AttendeeModel.exists({ email }); + + if (!userExists) { + return res + .status(StatusCodes.NOT_FOUND) + .send("User with that email does not exist."); + } + + return res.status(StatusCodes.OK).send("User exists."); + } catch (error) { + console.error("Error:", error); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); + } +}); + +export default attendeeRouter; diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index 8e936bc..c82a490 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -1,20 +1,53 @@ import mongoose from "mongoose"; import { z } from "zod"; - // Zod schema for attendee -const CreateAttendeeSchema = z.object({ +const AttendeeValidator = z.object({ name: z.string(), email: z.string().email(), + studentInfo: z.object({ + university: z.string().nonempty(), + graduation: z.string().nullable().optional(), + major: z.string().nullable().optional(), + }), + events: z.array(z.string()), + dietary_restrictions: z.string(), + age: z.number().nullable().optional(), + gender: z.string().nullable().optional(), + race: z.array(z.string()).nullable().optional(), + ethnicity: z.string().nullable().optional(), + first_gen: z.string().nullable().optional(), + hear_about_rp: z.array(z.string()).nullable().optional(), + portfolio: z.string().nullable().optional(), + job_interest: z.array(z.string()).nullable().optional(), + interest_mech_puzzle: z.array(z.string()).nullable().optional(), + priority_expiry: z.date().nullable().optional(), + has_resume: z.boolean().optional(), }); - // Mongoose schema for attendee const AttendeeSchema = new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true, unique: true }, + studentInfo: { + university: { type: String, required: true }, + graduation: { type: String, default: null }, + major: { type: String, default: null }, + }, + events: [{ type: mongoose.Schema.Types.ObjectId, ref: "Event" }], + dietary_restrictions: { type: String, required: true }, + age: { type: Number, default: null }, + gender: { type: String, default: null }, + race: [{ type: String }], + ethnicity: { type: String, default: null }, + first_gen: { type: String, default: null }, + hear_about_rp: [{ type: String }], + portfolio: { type: String, default: null }, + job_interest: [{ type: String }], + interest_mech_puzzle: [{ type: String }], + priority_expiry: { type: Date, default: null }, + has_resume: { type: Boolean, default: false }, }); - export const AttendeeModel = mongoose.model("Attendee", AttendeeSchema); -export { CreateAttendeeSchema }; \ No newline at end of file +export { AttendeeValidator }; diff --git a/src/services/events/event-router.ts b/src/services/events/event-router.ts new file mode 100644 index 0000000..360b1b3 --- /dev/null +++ b/src/services/events/event-router.ts @@ -0,0 +1,86 @@ +import { Router } from "express"; +import { StatusCodes } from "http-status-codes"; +import { EventValidator } from "./event-schema"; +import { EventModel } from "./event-schema"; + +const eventRouter = Router(); + +// Create a new event +eventRouter.post("/", async (req, res) => { + try { + const eventData = EventValidator.parse(req.body); + const event = new EventModel(eventData); + await event.save(); + res.status(StatusCodes.CREATED).json(event); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.BAD_REQUEST).send("Error creating event."); + } +}); + +// Get all events +eventRouter.get("/", async (req, res) => { + try { + const events = await EventModel.find(); + res.status(StatusCodes.OK).json(events); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( + "Internal server error." + ); + } +}); + +// Get event by ID +eventRouter.get("/:id", async (req, res) => { + try { + const event = await EventModel.findById(req.params.id); + if (!event) { + return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + } + res.status(StatusCodes.OK).json(event); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( + "Internal server error." + ); + } +}); + +// Update event +eventRouter.patch("/:id", async (req, res) => { + try { + const event = await EventModel.findByIdAndUpdate( + req.params.id, + req.body, + { new: true } + ); + if (!event) { + return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + } + res.status(StatusCodes.OK).json(event); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( + "Internal server error." + ); + } +}); + +// Delete event +eventRouter.delete("/:id", async (req, res) => { + try { + const event = await EventModel.findByIdAndDelete(req.params.id); + if (!event) { + return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + } + res.status(StatusCodes.NO_CONTENT).send(); + } catch (error) { + console.error("Error:", error); + res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( + "Internal server error." + ); + } +}); + +export default eventRouter; diff --git a/src/services/events/event-schema.ts b/src/services/events/event-schema.ts new file mode 100644 index 0000000..db29a3d --- /dev/null +++ b/src/services/events/event-schema.ts @@ -0,0 +1,50 @@ +import mongoose from "mongoose"; +import { z } from "zod"; + +// Zod schema for event +const EventValidator = z.object({ + name: z.string(), + description: z.string(), + start_time: z.date(), + end_time: z.date(), + attendees: z.array(z.string()), + location: z.array( + z.object({ + description: z.string(), + tags: z.array(z.string()), + latitude: z.number(), + longitude: z.number(), + }) + ), + virtual: z.boolean(), + upgrade: z.boolean().default(false), + downgrade: z.boolean().default(false), + imageUrl: z.string().nullable().optional(), + visible: z.boolean().default(false), +}); + +// Mongoose schema for location +const LocationSchema = new mongoose.Schema({ + description: { type: String, required: true }, + tags: [{ type: String }], + latitude: { type: Number, required: true }, + longitude: { type: Number, required: true }, +}); + +// Mongoose schema for event +const EventSchema = new mongoose.Schema({ + name: { type: String, required: true }, + description: { type: String, required: true }, + start_time: { type: Date, required: true }, + end_time: { type: Date, required: true }, + attendees: [{ type: mongoose.Schema.Types.ObjectId, ref: "Attendee" }], + location: [LocationSchema], + virtual: { type: Boolean, required: true }, + upgrade: { type: Boolean, default: false }, + downgrade: { type: Boolean, default: false }, + imageUrl: { type: String, default: null }, + visible: { type: Boolean, default: false }, +}); + +export const EventModel = mongoose.model("Event", EventSchema); +export { EventValidator }; From 425bcd6f189537fdda3f233332b3862a0a437297 Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 17:57:42 -0500 Subject: [PATCH 79/93] request changes --- src/app.ts | 2 +- src/database.ts | 5 +++ src/services/attendees/attendee-router.ts | 24 ++++++----- src/services/attendees/attendee-schema.ts | 3 +- src/services/events/event-router.ts | 52 ++++++++++++----------- src/services/events/event-schema.ts | 3 +- 6 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/app.ts b/src/app.ts index 2c66856..3ca3745 100644 --- a/src/app.ts +++ b/src/app.ts @@ -28,8 +28,8 @@ app.use("/", morgan("dev")); app.use("/", bodyParser.json()); // API routes -app.use("/auth", authRouter); app.use("/attendee", attendeeRouter); +app.use("/auth", authRouter); app.use("/event", eventRouter); app.get("/status", (_, res) => { diff --git a/src/database.ts b/src/database.ts index 7e0a9e6..bf1a1e6 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,4 +1,8 @@ import mongoose, { Schema } from "mongoose"; +import { + AttendeeSchema, + AttendeeValidator, +} from "./services/attendees/attendee-schema"; import { RoleValidator, RoleSchema } from "./services/auth/auth-schema"; import { EventSchema, EventValidator } from "./services/events/events-schema"; import { @@ -43,4 +47,5 @@ export const Database = { SubscriptionSchema, SubscriptionSchemaValidator ), + ATTENDEES: initializeModel("attendees", AttendeeSchema, AttendeeValidator), }; diff --git a/src/services/attendees/attendee-router.ts b/src/services/attendees/attendee-router.ts index 6c27a72..a5ebfac 100644 --- a/src/services/attendees/attendee-router.ts +++ b/src/services/attendees/attendee-router.ts @@ -1,25 +1,23 @@ import { Router } from "express"; import { StatusCodes } from "http-status-codes"; import { AttendeeValidator } from "./attendee-schema"; -import { AttendeeModel } from "./attendee-schema"; +import { Database } from "../../database"; const attendeeRouter = Router(); // Create a new attendee attendeeRouter.post("/", async (req, res) => { try { - const { name, email } = AttendeeValidator.parse(req.body); - console.log("Name:", name); - console.log("Email:", email); - - // Save attendee to the database - const attendee = new AttendeeModel({ name, email }); + const attendeeData = AttendeeValidator.parse(req.body); + const attendee = new Database.ATTENDEES(attendeeData); await attendee.save(); - res.status(201).send("Attendee created successfully."); + return res.status(StatusCodes.CREATED).json(attendeeData); } catch (error) { console.error("Error:", error); - res.status(400).send("Error creating attendee."); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Error creating attendee."); } }); @@ -29,7 +27,7 @@ attendeeRouter.get("/:email", async (req, res) => { const { email } = req.params; // Check if the user exists in the database - const userExists = await AttendeeModel.exists({ email }); + const userExists = await Database.ATTENDEES.exists({ email }); if (!userExists) { return res @@ -37,7 +35,11 @@ attendeeRouter.get("/:email", async (req, res) => { .send("User with that email does not exist."); } - return res.status(StatusCodes.OK).send("User exists."); + const user = await Database.ATTENDEES.findOne({ + email, + }); + + return res.status(StatusCodes.OK).json(user); } catch (error) { console.error("Error:", error); return res diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index c82a490..279a125 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -49,5 +49,4 @@ const AttendeeSchema = new mongoose.Schema({ has_resume: { type: Boolean, default: false }, }); -export const AttendeeModel = mongoose.model("Attendee", AttendeeSchema); -export { AttendeeValidator }; +export { AttendeeSchema, AttendeeValidator }; diff --git a/src/services/events/event-router.ts b/src/services/events/event-router.ts index 360b1b3..f365ea1 100644 --- a/src/services/events/event-router.ts +++ b/src/services/events/event-router.ts @@ -1,7 +1,7 @@ import { Router } from "express"; import { StatusCodes } from "http-status-codes"; import { EventValidator } from "./event-schema"; -import { EventModel } from "./event-schema"; +import { Database } from "../../database"; const eventRouter = Router(); @@ -9,77 +9,81 @@ const eventRouter = Router(); eventRouter.post("/", async (req, res) => { try { const eventData = EventValidator.parse(req.body); - const event = new EventModel(eventData); + const event = new Database.EVENTS(eventData); await event.save(); - res.status(StatusCodes.CREATED).json(event); + return res.status(StatusCodes.CREATED).json(event); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.BAD_REQUEST).send("Error creating event."); + return res + .status(StatusCodes.BAD_REQUEST) + .send("Error creating event."); } }); // Get all events eventRouter.get("/", async (req, res) => { try { - const events = await EventModel.find(); - res.status(StatusCodes.OK).json(events); + const events = await Database.EVENTS.find(); + return res.status(StatusCodes.OK).json(events); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( - "Internal server error." - ); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); } }); // Get event by ID eventRouter.get("/:id", async (req, res) => { try { - const event = await EventModel.findById(req.params.id); + const event = await Database.EVENTS.findById(req.params.id); if (!event) { return res.status(StatusCodes.NOT_FOUND).send("Event not found."); } - res.status(StatusCodes.OK).json(event); + return res.status(StatusCodes.OK).json(event); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( - "Internal server error." - ); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); } }); // Update event eventRouter.patch("/:id", async (req, res) => { try { - const event = await EventModel.findByIdAndUpdate( + const event = await Database.EVENTS.findByIdAndUpdate( req.params.id, req.body, { new: true } ); + if (!event) { return res.status(StatusCodes.NOT_FOUND).send("Event not found."); } - res.status(StatusCodes.OK).json(event); + + return res.status(StatusCodes.OK).json(event); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( - "Internal server error." - ); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); } }); // Delete event eventRouter.delete("/:id", async (req, res) => { try { - const event = await EventModel.findByIdAndDelete(req.params.id); + const event = await Database.EVENTS.findByIdAndDelete(req.params.id); if (!event) { return res.status(StatusCodes.NOT_FOUND).send("Event not found."); } - res.status(StatusCodes.NO_CONTENT).send(); + return res.status(StatusCodes.NO_CONTENT).send(); } catch (error) { console.error("Error:", error); - res.status(StatusCodes.INTERNAL_SERVER_ERROR).send( - "Internal server error." - ); + return res + .status(StatusCodes.INTERNAL_SERVER_ERROR) + .send("Internal server error."); } }); diff --git a/src/services/events/event-schema.ts b/src/services/events/event-schema.ts index db29a3d..768be72 100644 --- a/src/services/events/event-schema.ts +++ b/src/services/events/event-schema.ts @@ -46,5 +46,4 @@ const EventSchema = new mongoose.Schema({ visible: { type: Boolean, default: false }, }); -export const EventModel = mongoose.model("Event", EventSchema); -export { EventValidator }; +export { EventSchema, EventValidator, LocationSchema }; From 5df67e01f33b6553dc3949602e79e9d11b4233ec Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 18:14:33 -0500 Subject: [PATCH 80/93] error messages --- src/services/attendees/attendee-router.ts | 18 ++------ src/services/events/event-router.ts | 56 ++++++++++------------- 2 files changed, 29 insertions(+), 45 deletions(-) diff --git a/src/services/attendees/attendee-router.ts b/src/services/attendees/attendee-router.ts index a5ebfac..8006361 100644 --- a/src/services/attendees/attendee-router.ts +++ b/src/services/attendees/attendee-router.ts @@ -6,7 +6,7 @@ import { Database } from "../../database"; const attendeeRouter = Router(); // Create a new attendee -attendeeRouter.post("/", async (req, res) => { +attendeeRouter.post("/", async (req, res, next) => { try { const attendeeData = AttendeeValidator.parse(req.body); const attendee = new Database.ATTENDEES(attendeeData); @@ -14,15 +14,12 @@ attendeeRouter.post("/", async (req, res) => { return res.status(StatusCodes.CREATED).json(attendeeData); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Error creating attendee."); + next(error); } }); // Check if a user email exists -attendeeRouter.get("/:email", async (req, res) => { +attendeeRouter.get("/:email", async (req, res, next) => { try { const { email } = req.params; @@ -30,9 +27,7 @@ attendeeRouter.get("/:email", async (req, res) => { const userExists = await Database.ATTENDEES.exists({ email }); if (!userExists) { - return res - .status(StatusCodes.NOT_FOUND) - .send("User with that email does not exist."); + return { error: "DoesNotExist" }; } const user = await Database.ATTENDEES.findOne({ @@ -41,10 +36,7 @@ attendeeRouter.get("/:email", async (req, res) => { return res.status(StatusCodes.OK).json(user); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); diff --git a/src/services/events/event-router.ts b/src/services/events/event-router.ts index f365ea1..f7e154a 100644 --- a/src/services/events/event-router.ts +++ b/src/services/events/event-router.ts @@ -6,84 +6,76 @@ import { Database } from "../../database"; const eventRouter = Router(); // Create a new event -eventRouter.post("/", async (req, res) => { +eventRouter.post("/", async (req, res, next) => { try { const eventData = EventValidator.parse(req.body); const event = new Database.EVENTS(eventData); await event.save(); return res.status(StatusCodes.CREATED).json(event); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.BAD_REQUEST) - .send("Error creating event."); + next(error); } }); // Get all events -eventRouter.get("/", async (req, res) => { +eventRouter.get("/", async (req, res, next) => { try { const events = await Database.EVENTS.find(); return res.status(StatusCodes.OK).json(events); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); // Get event by ID -eventRouter.get("/:id", async (req, res) => { +eventRouter.get("/:id", async (req, res, next) => { try { - const event = await Database.EVENTS.findById(req.params.id); + const event = await Database.EVENTS.findOneAndUpdate( + { _id: req.params.id }, + { new: true } + ); + if (!event) { - return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + return { error: "DoesNotExist" }; } + return res.status(StatusCodes.OK).json(event); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); // Update event -eventRouter.patch("/:id", async (req, res) => { +eventRouter.patch("/:id", async (req, res, next) => { try { - const event = await Database.EVENTS.findByIdAndUpdate( - req.params.id, + const event = await Database.EVENTS.findOneAndUpdate( + { _id: req.params.id }, req.body, { new: true } ); if (!event) { - return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + return { error: "DoesNotExist" }; } return res.status(StatusCodes.OK).json(event); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); // Delete event -eventRouter.delete("/:id", async (req, res) => { +eventRouter.delete("/:id", async (req, res, next) => { try { const event = await Database.EVENTS.findByIdAndDelete(req.params.id); + if (!event) { - return res.status(StatusCodes.NOT_FOUND).send("Event not found."); + return { error: "DoesNotExist" }; } - return res.status(StatusCodes.NO_CONTENT).send(); + + return res.status(StatusCodes.OK).json(event); } catch (error) { - console.error("Error:", error); - return res - .status(StatusCodes.INTERNAL_SERVER_ERROR) - .send("Internal server error."); + next(error); } }); From 201007f6dc35a61d10fb21e379b5168f1d3b772b Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 18:17:35 -0500 Subject: [PATCH 81/93] event points --- src/services/events/event-schema.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/services/events/event-schema.ts b/src/services/events/event-schema.ts index 768be72..73890cd 100644 --- a/src/services/events/event-schema.ts +++ b/src/services/events/event-schema.ts @@ -17,8 +17,7 @@ const EventValidator = z.object({ }) ), virtual: z.boolean(), - upgrade: z.boolean().default(false), - downgrade: z.boolean().default(false), + points: z.number().min(0).default(0), imageUrl: z.string().nullable().optional(), visible: z.boolean().default(false), }); @@ -40,8 +39,7 @@ const EventSchema = new mongoose.Schema({ attendees: [{ type: mongoose.Schema.Types.ObjectId, ref: "Attendee" }], location: [LocationSchema], virtual: { type: Boolean, required: true }, - upgrade: { type: Boolean, default: false }, - downgrade: { type: Boolean, default: false }, + points: { type: Number, default: 0 }, imageUrl: { type: String, default: null }, visible: { type: Boolean, default: false }, }); From 849126624d3334ccceb3b1b44733d8dcc1f70891 Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 18:32:52 -0500 Subject: [PATCH 82/93] registration schema --- src/app.ts | 2 ++ src/database.ts | 9 ++++++++ src/services/attendees/attendee-schema.ts | 2 ++ .../registration/registration-router.ts | 10 +++++++++ .../registration/registration-schema.ts | 22 +++++++++++++++++++ 5 files changed, 45 insertions(+) create mode 100644 src/services/registration/registration-router.ts create mode 100644 src/services/registration/registration-schema.ts diff --git a/src/app.ts b/src/app.ts index 3ca3745..e413531 100644 --- a/src/app.ts +++ b/src/app.ts @@ -13,6 +13,7 @@ import subscriptionRouter from "./services/subscription/subscription-router"; import attendeeRouter from "./services/attendees/attendee-router"; import eventRouter from "./services/events/event-router"; +import registrationRouter from "./services/registration/registration-router"; const app = express(); @@ -31,6 +32,7 @@ app.use("/", bodyParser.json()); app.use("/attendee", attendeeRouter); app.use("/auth", authRouter); app.use("/event", eventRouter); +app.use("/registration", registrationRouter); app.get("/status", (_, res) => { return res.status(StatusCodes.OK).send("API is alive!"); diff --git a/src/database.ts b/src/database.ts index bf1a1e6..ba30eab 100644 --- a/src/database.ts +++ b/src/database.ts @@ -9,6 +9,10 @@ import { SubscriptionSchemaValidator, SubscriptionSchema, } from "./services/subscription/subscription-schema"; +import { + RegistrationSchema, + RegistrationValidator, +} from "./services/registration/registration-schema"; mongoose.set("toObject", { versionKey: false }); @@ -48,4 +52,9 @@ export const Database = { SubscriptionSchemaValidator ), ATTENDEES: initializeModel("attendees", AttendeeSchema, AttendeeValidator), + REGISTRATION: initializeModel( + "registration", + RegistrationSchema, + RegistrationValidator + ), }; diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index 279a125..79baebe 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -23,6 +23,7 @@ const AttendeeValidator = z.object({ interest_mech_puzzle: z.array(z.string()).nullable().optional(), priority_expiry: z.date().nullable().optional(), has_resume: z.boolean().optional(), + points: z.number().min(0).default(0), // }); // Mongoose schema for attendee @@ -47,6 +48,7 @@ const AttendeeSchema = new mongoose.Schema({ interest_mech_puzzle: [{ type: String }], priority_expiry: { type: Date, default: null }, has_resume: { type: Boolean, default: false }, + points: { type: Number, default: 0 }, }); export { AttendeeSchema, AttendeeValidator }; diff --git a/src/services/registration/registration-router.ts b/src/services/registration/registration-router.ts new file mode 100644 index 0000000..18d0210 --- /dev/null +++ b/src/services/registration/registration-router.ts @@ -0,0 +1,10 @@ +import { Router } from "express"; +import { StatusCodes } from "http-status-codes"; +import { RegistrationValidator } from "./registration-schema"; +import { Database } from "../../database"; + +const registrationRouter = Router(); + +// TODO: registration routes + +export default registrationRouter; diff --git a/src/services/registration/registration-schema.ts b/src/services/registration/registration-schema.ts new file mode 100644 index 0000000..2a35c14 --- /dev/null +++ b/src/services/registration/registration-schema.ts @@ -0,0 +1,22 @@ +import mongoose from "mongoose"; +import { z } from "zod"; + +// Zod schema for registration +const RegistrationValidator = z.object({ + name: z.string(), + email: z.string().email(), + events: z.array(z.string()), + dietary_restrictions: z.string(), + points: z.number().min(0).default(0), +}); + +// Mongoose schema for registration +const RegistrationSchema = new mongoose.Schema({ + 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 }, + points: { type: Number, default: 0 }, +}); + +export { RegistrationSchema, RegistrationValidator }; From cb2a33958d46cbcf1108da0b8b9d49852e8b06f4 Mon Sep 17 00:00:00 2001 From: Jacob Chang Date: Tue, 9 Apr 2024 19:04:24 -0500 Subject: [PATCH 83/93] subscription basic --- .github/workflows/lint.yml | 24 +++++++++---------- .github/workflows/prettier.yml | 36 ++++++++++++++-------------- README.md | 13 +++++----- appspec.yml | 44 +++++++++++++++++----------------- src/app.ts | 6 ++--- src/database.ts | 8 +++---- 6 files changed, 66 insertions(+), 65 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c477b00..992d3fd 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,18 +1,18 @@ name: Lint on: - push: + push: jobs: lint: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '18.x' - - name: Install dependencies - run: yarn - - name: Run ESLint - run: npx eslint . \ No newline at end of file + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "18.x" + - name: Install dependencies + run: yarn + - name: Run ESLint + run: npx eslint . diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml index 150599e..f4c3651 100644 --- a/.github/workflows/prettier.yml +++ b/.github/workflows/prettier.yml @@ -1,18 +1,18 @@ -name: Prettier - -on: - push: - -jobs: - prettier: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: "18.x" - - name: Install dependencies - run: yarn - - name: Run Prettier - run: npx prettier --write . +name: Prettier + +on: + push: + +jobs: + prettier: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "18.x" + - name: Install dependencies + run: yarn + - name: Run Prettier + run: npx prettier --write . diff --git a/README.md b/README.md index 781821c..cb79c58 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ # API for Reflections | Projections 2024 Contributors: -- Aydan Pirani -- Divya Koya -- Riya Patel -- Jacob Chang -- Alex Yang -- Shreenija Daggavolu + +- Aydan Pirani +- Divya Koya +- Riya Patel +- Jacob Chang +- Alex Yang +- Shreenija Daggavolu diff --git a/appspec.yml b/appspec.yml index 2e74e8d..7e68363 100644 --- a/appspec.yml +++ b/appspec.yml @@ -1,22 +1,22 @@ -version: 0.0 -os: linux -files: - - source: / - destination: /home/ubuntu/rp-api -file_exists_behavior: OVERWRITE -hooks: - BeforeInstall: - - location: scripts/install_dependencies.sh - timeout: 300 - runas: root - AfterInstall: - - location: scripts/build.sh - timeout: 300 - runas: root - ApplicationStart: - - location: scripts/install_dependencies.sh - timeout: 300 - runas: root - - location: scripts/reload_server.sh - timeout: 300 - runas: root \ No newline at end of file +version: 0.0 +os: linux +files: + - source: / + destination: /home/ubuntu/rp-api +file_exists_behavior: OVERWRITE +hooks: + BeforeInstall: + - location: scripts/install_dependencies.sh + timeout: 300 + runas: root + AfterInstall: + - location: scripts/build.sh + timeout: 300 + runas: root + ApplicationStart: + - location: scripts/install_dependencies.sh + timeout: 300 + runas: root + - location: scripts/reload_server.sh + timeout: 300 + runas: root diff --git a/src/app.ts b/src/app.ts index e413531..ea6d818 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,12 +8,11 @@ import morgan from "morgan"; import bodyParser from "body-parser"; import errorHandler from "./middleware/error-handler"; -import authRouter from "./services/auth/auth-router"; -import subscriptionRouter from "./services/subscription/subscription-router"; - import attendeeRouter from "./services/attendees/attendee-router"; +import authRouter from "./services/auth/auth-router"; import eventRouter from "./services/events/event-router"; import registrationRouter from "./services/registration/registration-router"; +import subscriptionRouter from "./services/subscription/subscription-router"; const app = express(); @@ -33,6 +32,7 @@ app.use("/attendee", attendeeRouter); app.use("/auth", authRouter); app.use("/event", eventRouter); app.use("/registration", registrationRouter); +app.use("/subscription", subscriptionRouter); app.get("/status", (_, res) => { return res.status(StatusCodes.OK).send("API is alive!"); diff --git a/src/database.ts b/src/database.ts index ba30eab..b1e4efa 100644 --- a/src/database.ts +++ b/src/database.ts @@ -5,14 +5,14 @@ import { } from "./services/attendees/attendee-schema"; import { RoleValidator, RoleSchema } from "./services/auth/auth-schema"; import { EventSchema, EventValidator } from "./services/events/events-schema"; -import { - SubscriptionSchemaValidator, - SubscriptionSchema, -} from "./services/subscription/subscription-schema"; import { RegistrationSchema, RegistrationValidator, } from "./services/registration/registration-schema"; +import { + SubscriptionSchemaValidator, + SubscriptionSchema, +} from "./services/subscription/subscription-schema"; mongoose.set("toObject", { versionKey: false }); From 9b451b8de74c108265c4eb51286b519329f211b8 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sat, 20 Apr 2024 12:31:13 -0500 Subject: [PATCH 84/93] Fixed build errors --- src/services/registration/registration-router.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/registration/registration-router.ts b/src/services/registration/registration-router.ts index 18d0210..8b18e65 100644 --- a/src/services/registration/registration-router.ts +++ b/src/services/registration/registration-router.ts @@ -1,7 +1,7 @@ import { Router } from "express"; -import { StatusCodes } from "http-status-codes"; -import { RegistrationValidator } from "./registration-schema"; -import { Database } from "../../database"; +// import { StatusCodes } from "http-status-codes"; +// import { RegistrationValidator } from "./registration-schema"; +// import { Database } from "../../database"; const registrationRouter = Router(); From 4558a8a8cdadaae78ef81b257601b870330d9c89 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sat, 20 Apr 2024 13:00:35 -0500 Subject: [PATCH 85/93] Fixed schemas --- src/services/attendees/attendee-schema.ts | 34 ++--------------- .../registration/registration-schema.ts | 38 ++++++++++++++++--- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index 79baebe..358795d 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -3,51 +3,23 @@ import { z } from "zod"; // Zod schema for attendee const AttendeeValidator = z.object({ + userId: z.string(), name: z.string(), email: z.string().email(), - studentInfo: z.object({ - university: z.string().nonempty(), - graduation: z.string().nullable().optional(), - major: z.string().nullable().optional(), - }), events: z.array(z.string()), dietary_restrictions: z.string(), - age: z.number().nullable().optional(), - gender: z.string().nullable().optional(), - race: z.array(z.string()).nullable().optional(), - ethnicity: z.string().nullable().optional(), - first_gen: z.string().nullable().optional(), - hear_about_rp: z.array(z.string()).nullable().optional(), - portfolio: z.string().nullable().optional(), - job_interest: z.array(z.string()).nullable().optional(), - interest_mech_puzzle: z.array(z.string()).nullable().optional(), priority_expiry: z.date().nullable().optional(), - has_resume: z.boolean().optional(), - points: z.number().min(0).default(0), // + points: z.number().min(0).default(0), }); // Mongoose schema for attendee const AttendeeSchema = new mongoose.Schema({ + userId: { type: String, required: true, unique: true }, name: { type: String, required: true }, email: { type: String, required: true, unique: true }, - studentInfo: { - university: { type: String, required: true }, - graduation: { type: String, default: null }, - major: { type: String, default: null }, - }, events: [{ type: mongoose.Schema.Types.ObjectId, ref: "Event" }], dietary_restrictions: { type: String, required: true }, - age: { type: Number, default: null }, - gender: { type: String, default: null }, - race: [{ type: String }], - ethnicity: { type: String, default: null }, - first_gen: { type: String, default: null }, - hear_about_rp: [{ type: String }], - portfolio: { type: String, default: null }, - job_interest: [{ type: String }], - interest_mech_puzzle: [{ type: String }], priority_expiry: { type: Date, default: null }, - has_resume: { type: Boolean, default: false }, points: { type: Number, default: 0 }, }); diff --git a/src/services/registration/registration-schema.ts b/src/services/registration/registration-schema.ts index 2a35c14..ede0edc 100644 --- a/src/services/registration/registration-schema.ts +++ b/src/services/registration/registration-schema.ts @@ -1,22 +1,50 @@ import mongoose from "mongoose"; -import { z } from "zod"; +import { boolean, z } from "zod"; // Zod schema for registration const RegistrationValidator = z.object({ + userId: z.string(), name: z.string(), email: z.string().email(), - events: z.array(z.string()), + studentInfo: z.object({ + university: z.string().nonempty(), + graduation: z.string().nullable().optional(), + major: z.string().nullable().optional(), + }), dietary_restrictions: z.string(), - points: z.number().min(0).default(0), + age: z.number().nullable().optional(), + gender: z.string().nullable().optional(), + race: z.array(z.string()).nullable().optional(), + ethnicity: z.array(z.string()).nullable().optional(), + first_gen: z.string().nullable().optional(), + hear_about_rp: z.array(z.string()).nullable().optional(), + portfolio: z.string().nullable().optional(), + job_interest: z.array(z.string()).nullable().optional(), + interest_mech_puzzle: z.array(z.string()).nullable().optional(), + has_resume: z.boolean() }); // Mongoose schema for registration const RegistrationSchema = 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" }], + studentInfo: { + university: { type: String, required: true }, + graduation: { type: String, default: null }, + major: { type: String, default: null }, + }, dietary_restrictions: { type: String, required: true }, - points: { type: Number, default: 0 }, + age: { type: Number, default: null }, + gender: { type: String, default: null }, + race: [{ type: String }], + ethnicity: [{ type: String }], + first_gen: { type: String, default: null }, + hear_about_rp: [{ type: String }], + portfolio: { type: String, default: null }, + job_interest: [{ type: String }], + interest_mech_puzzle: [{ type: String }], + has_resume: { type: Boolean, default: false }, }); export { RegistrationSchema, RegistrationValidator }; From 53d2c643c36cd3e2beb2901bc3d6d3cca77284ce Mon Sep 17 00:00:00 2001 From: divinedab Date: Sat, 20 Apr 2024 13:19:31 -0500 Subject: [PATCH 86/93] fixing linting issues --- src/services/registration/registration-schema.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/registration/registration-schema.ts b/src/services/registration/registration-schema.ts index ede0edc..1d0345e 100644 --- a/src/services/registration/registration-schema.ts +++ b/src/services/registration/registration-schema.ts @@ -1,5 +1,5 @@ import mongoose from "mongoose"; -import { boolean, z } from "zod"; +import { z } from "zod"; // Zod schema for registration const RegistrationValidator = z.object({ @@ -21,7 +21,7 @@ const RegistrationValidator = z.object({ portfolio: z.string().nullable().optional(), job_interest: z.array(z.string()).nullable().optional(), interest_mech_puzzle: z.array(z.string()).nullable().optional(), - has_resume: z.boolean() + has_resume: z.boolean(), }); // Mongoose schema for registration @@ -43,7 +43,7 @@ const RegistrationSchema = new mongoose.Schema({ hear_about_rp: [{ type: String }], portfolio: { type: String, default: null }, job_interest: [{ type: String }], - interest_mech_puzzle: [{ type: String }], + interest_mech_puzzle: [{ type: String }], has_resume: { type: Boolean, default: false }, }); From ef1dbe678ab53a34295961e18302bb52376e0ba6 Mon Sep 17 00:00:00 2001 From: divinedab Date: Sat, 20 Apr 2024 13:22:04 -0500 Subject: [PATCH 87/93] one last linting error --- src/services/registration/registration-schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/registration/registration-schema.ts b/src/services/registration/registration-schema.ts index 1d0345e..ab19968 100644 --- a/src/services/registration/registration-schema.ts +++ b/src/services/registration/registration-schema.ts @@ -26,7 +26,7 @@ const RegistrationValidator = z.object({ // Mongoose schema for registration const RegistrationSchema = new mongoose.Schema({ - userId: {type: String, required: true, unique: true }, + userId: { type: String, required: true, unique: true }, name: { type: String, required: true }, email: { type: String, required: true, unique: true }, studentInfo: { From 206bf05d075e3dcb05ad4a0706917b070a424f38 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 21 Apr 2024 17:59:05 -0500 Subject: [PATCH 88/93] Update config.ts --- src/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index 38aab55..be93c88 100644 --- a/src/config.ts +++ b/src/config.ts @@ -19,8 +19,8 @@ export const Config = { CLIENT_ID: getEnv("OAUTH_GOOGLE_CLIENT_ID"), CLIENT_SECRET: getEnv("OAUTH_GOOGLE_CLIENT_SECRET"), - AUTH_CALLBACK_URI_BASE: "http://localhost:3000/auth/callback/", - // AUTH_CALLBACK_URI_BASE: "https://api.reflectionsprojections.org/auth/callback/", + // AUTH_CALLBACK_URI_BASE: "http://localhost:3000/auth/callback/", + AUTH_CALLBACK_URI_BASE: "https://api.reflectionsprojections.org/auth/callback/", JWT_SIGNING_SECRET: getEnv("JWT_SIGNING_SECRET"), JWT_EXPIRATION_TIME: "1 day", From 62dc3db4005eb514854a00c62a60968777df07af Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 21 Apr 2024 18:02:02 -0500 Subject: [PATCH 89/93] Update config.ts --- src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index be93c88..072bc29 100644 --- a/src/config.ts +++ b/src/config.ts @@ -28,5 +28,5 @@ export const Config = { export const DeviceRedirects: Record = { web: "https://www.google.com/", - dev: "http://127.0.0.1:3000/auth/dev/", + dev: "https://api.reflectionsprojections.org/auth/dev/", }; From a52f1e18c00c54c0d8bbc8a99ffe2636a3df83ab Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 21 Apr 2024 18:04:34 -0500 Subject: [PATCH 90/93] Fix prettify --- src/config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 072bc29..0c84952 100644 --- a/src/config.ts +++ b/src/config.ts @@ -20,7 +20,8 @@ export const Config = { CLIENT_SECRET: getEnv("OAUTH_GOOGLE_CLIENT_SECRET"), // AUTH_CALLBACK_URI_BASE: "http://localhost:3000/auth/callback/", - AUTH_CALLBACK_URI_BASE: "https://api.reflectionsprojections.org/auth/callback/", + AUTH_CALLBACK_URI_BASE: + "https://api.reflectionsprojections.org/auth/callback/", JWT_SIGNING_SECRET: getEnv("JWT_SIGNING_SECRET"), JWT_EXPIRATION_TIME: "1 day", From e308cfae92d5cdcf18a20f4e9b9a3b39441b658a Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+aletya@users.noreply.github.com> Date: Sun, 21 Apr 2024 18:08:41 -0500 Subject: [PATCH 91/93] Update build.yml --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd14671..eaf0932 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,6 +12,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "18.x" + cache: 'yarn' - name: Install dependencies run: yarn - name: Build From 30e6fd32265a7d40a7647a9dedde13fb67bd013d Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+aletya@users.noreply.github.com> Date: Sun, 21 Apr 2024 18:08:49 -0500 Subject: [PATCH 92/93] Update lint.yml --- .github/workflows/lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 992d3fd..040636d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,6 +12,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "18.x" + cache: 'yarn' - name: Install dependencies run: yarn - name: Run ESLint From b87208fcb4a4913eef8c891d1a1ba016e95b2a2b Mon Sep 17 00:00:00 2001 From: Alex Yang <32620988+aletya@users.noreply.github.com> Date: Sun, 21 Apr 2024 18:08:56 -0500 Subject: [PATCH 93/93] Update prettier.yml --- .github/workflows/prettier.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml index f4c3651..701d6da 100644 --- a/.github/workflows/prettier.yml +++ b/.github/workflows/prettier.yml @@ -12,6 +12,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "18.x" + cache: 'yarn' - name: Install dependencies run: yarn - name: Run Prettier