diff --git a/src/services/attendees/attendee-schema.ts b/src/services/attendees/attendee-schema.ts index 443572f..3ef305d 100644 --- a/src/services/attendees/attendee-schema.ts +++ b/src/services/attendees/attendee-schema.ts @@ -11,6 +11,7 @@ const AttendeeValidator = z.object({ allergies: z.string().array(), hasCheckedIn: z.boolean().default(false), points: z.number().min(0).default(0), + foodWave: z.number().int().min(0).default(0), hasPriority: z.object({ dayOne: z.boolean(), dayTwo: z.boolean(), @@ -30,6 +31,7 @@ const AttendeeSchema = new mongoose.Schema({ allergies: { type: [String], required: true }, hasCheckedIn: { type: Boolean, default: false }, points: { type: Number, default: 0 }, + foodWave: { type: Number, default: 0 }, hasPriority: { type: new mongoose.Schema( { diff --git a/src/services/auth/auth-router.ts b/src/services/auth/auth-router.ts index 5fc59c8..5f84a83 100644 --- a/src/services/auth/auth-router.ts +++ b/src/services/auth/auth-router.ts @@ -5,6 +5,11 @@ import { StatusCodes } from "http-status-codes"; import { Strategy as GoogleStrategy, Profile } from "passport-google-oauth20"; import { createGoogleStrategy, getJwtPayloadFromDatabase } from "./auth-utils"; import jsonwebtoken from "jsonwebtoken"; +import { Database } from "../../database"; +import RoleChecker from "../../middleware/role-checker"; +import { Role } from "../auth/auth-models"; +import { AuthRoleChangeRequest } from "./auth-schema"; +import { z } from "zod"; const authStrategies: Record = {}; @@ -14,6 +19,71 @@ for (const key in DeviceRedirects) { const authRouter = Router(); +// Remove role from userId by email address (admin only endpoint) +authRouter.delete( + "/", + RoleChecker([Role.Enum.ADMIN]), + async (req, res, next) => { + try { + // Validate request body using Zod schema + const { email, role } = AuthRoleChangeRequest.parse(req.body); + + // Use findOneAndUpdate to remove the role + const user = await Database.ROLES.findOneAndUpdate( + { email: email }, + { $pull: { roles: role } }, + { new: true } + ); + + if (!user) { + return res.status(StatusCodes.NOT_FOUND).json({ + error: "UserNotFound", + }); + } + + return res.status(StatusCodes.OK).json(user); + } catch (error) { + if (error instanceof z.ZodError) { + return res.status(StatusCodes.BAD_REQUEST).json({ + error: "BadRole", + details: error.errors, + }); + } + + next(error); + } + } +); + +// Add role to userId by email address (admin only endpoint) +authRouter.put("/", RoleChecker([Role.Enum.ADMIN]), async (req, res, next) => { + try { + const { email, role } = AuthRoleChangeRequest.parse(req.body); + + const user = await Database.ROLES.findOneAndUpdate( + { email: email }, + { $addToSet: { roles: role } }, + { new: true, upsert: true } + ); + + if (!user) { + return res.status(StatusCodes.NOT_FOUND).json({ + error: "UserNotFound", + }); + } + + return res.status(StatusCodes.OK).json(user); + } catch (error) { + if (error instanceof z.ZodError) { + return res.status(StatusCodes.BAD_REQUEST).json({ + error: "BadRole", + }); + } + + next(error); + } +}); + authRouter.get("/login/:DEVICE/", (req, res) => { const device = req.params.DEVICE; @@ -69,4 +139,27 @@ authRouter.get("/dev/", (req, res) => { return res.status(StatusCodes.OK).json(req.query); }); +// Get a list of people by role (staff only endpoint) +authRouter.get( + "/:ROLE", + RoleChecker([Role.Enum.STAFF]), + async (req, res, next) => { + try { + // Validate the role using Zod schema + const role = Role.parse(req.params.ROLE); + + const usersWithRole = await Database.ROLES.find({ roles: role }); + return res.status(StatusCodes.OK).json(usersWithRole); + } catch (error) { + if (error instanceof z.ZodError) { + return res.status(StatusCodes.BAD_REQUEST).json({ + error: "BadRole", + }); + } + + next(error); + } + } +); + export default authRouter; diff --git a/src/services/auth/auth-schema.ts b/src/services/auth/auth-schema.ts index 9434d11..cd363d8 100644 --- a/src/services/auth/auth-schema.ts +++ b/src/services/auth/auth-schema.ts @@ -9,6 +9,11 @@ export const RoleValidator = z.object({ roles: z.array(Role), }); +export const AuthRoleChangeRequest = z.object({ + email: z.string().email(), + role: z.string(), +}); + export const RoleSchema = new Schema( { userId: {