From 171231cd214c45159e5e45739c902e666e187ec2 Mon Sep 17 00:00:00 2001 From: Carlos Mesquita Date: Sat, 7 Sep 2024 15:41:09 +0100 Subject: [PATCH] Refactored codes --- src/pages/api/code/[id].ts | 21 ++++---- src/pages/api/code/index.ts | 98 ++++++++++++++++++------------------- 2 files changed, 57 insertions(+), 62 deletions(-) diff --git a/src/pages/api/code/[id].ts b/src/pages/api/code/[id].ts index 3f636c7a..19f6c5f9 100644 --- a/src/pages/api/code/[id].ts +++ b/src/pages/api/code/[id].ts @@ -1,12 +1,12 @@ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction import type {NextApiRequest, NextApiResponse} from "next"; -import {app} from "@/firebase"; -import {getFirestore, collection, getDocs, query, where, setDoc, doc, getDoc, deleteDoc} from "firebase/firestore"; +import client from "@/lib/mongodb"; +import { ObjectId } from 'mongodb'; import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import {uuidv4} from "@firebase/util"; -const db = getFirestore(app); +const db = client.db(process.env.MONGODB_DB); export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "GET") return GET(req, res); @@ -17,18 +17,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) async function GET(req: NextApiRequest, res: NextApiResponse) { const {id} = req.query; + const code = await db.collection("codes").findOne({ _id: new ObjectId(id as string) }); - const snapshot = await getDoc(doc(db, "codes", id as string)); - - res.status(200).json({...snapshot.data(), id: snapshot.id}); + res.status(200).json(code); } async function DELETE(req: NextApiRequest, res: NextApiResponse) { const {id} = req.query; + const code = await db.collection("codes").findOne({ _id: new ObjectId(id as string) }); - const snapshot = await getDoc(doc(db, "codes", id as string)); - if (!snapshot.exists()) return res.status(404).json; - - await deleteDoc(snapshot.ref); - res.status(200).json({...snapshot.data(), id: snapshot.id}); + if (!code) return res.status(404).json; + await db.collection("codes").deleteOne({ _id: new ObjectId(id as string) }); + + res.status(200).json(code); } diff --git a/src/pages/api/code/index.ts b/src/pages/api/code/index.ts index 2d829e64..24c518d7 100644 --- a/src/pages/api/code/index.ts +++ b/src/pages/api/code/index.ts @@ -1,15 +1,14 @@ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type {NextApiRequest, NextApiResponse} from "next"; -import {app} from "@/firebase"; -import {getFirestore, setDoc, doc, query, collection, where, getDocs, getDoc, deleteDoc} from "firebase/firestore"; -import {withIronSessionApiRoute} from "iron-session/next"; -import {sessionOptions} from "@/lib/session"; -import {Code, Group, Type} from "@/interfaces/user"; -import {PERMISSIONS} from "@/constants/userPermissions"; -import {uuidv4} from "@firebase/util"; -import {prepareMailer, prepareMailOptions} from "@/email"; +import type { NextApiRequest, NextApiResponse } from "next"; +import client from "@/lib/mongodb"; +import { ObjectId } from 'mongodb'; +import { withIronSessionApiRoute } from "iron-session/next"; +import { sessionOptions } from "@/lib/session"; +import { Code, Group, Type } from "@/interfaces/user"; +import { PERMISSIONS } from "@/constants/userPermissions"; +import { prepareMailer, prepareMailOptions } from "@/email"; -const db = getFirestore(app); +const db = client.db(process.env.MONGODB_DB); export default withIronSessionApiRoute(handler, sessionOptions); @@ -18,32 +17,31 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "POST") return post(req, res); if (req.method === "DELETE") return del(req, res); - return res.status(404).json({ok: false}); + return res.status(404).json({ ok: false }); } async function get(req: NextApiRequest, res: NextApiResponse) { if (!req.session.user) { - res.status(401).json({ok: false, reason: "You must be logged in to generate a code!"}); + res.status(401).json({ ok: false, reason: "You must be logged in to generate a code!" }); return; } - const {creator} = req.query as {creator?: string}; - const q = query(collection(db, "codes"), where("creator", "==", creator || "")); - const snapshot = await getDocs(creator ? q : collection(db, "codes")); + const { creator } = req.query as { creator?: string }; + const snapshot = await db.collection("codes").find(creator ? { creator: creator } : {}).toArray(); - res.status(200).json(snapshot.docs.map((doc) => doc.data())); + res.status(200).json(snapshot); } async function post(req: NextApiRequest, res: NextApiResponse) { if (!req.session.user) { - res.status(401).json({ok: false, reason: "You must be logged in to generate a code!"}); + res.status(401).json({ ok: false, reason: "You must be logged in to generate a code!" }); return; } - const {type, codes, infos, expiryDate} = req.body as { + const { type, codes, infos, expiryDate } = req.body as { type: Type; codes: string[]; - infos?: {email: string; name: string; passport_id?: string}[]; + infos?: { email: string; name: string; passport_id?: string }[]; expiryDate: null | Date; }; const permission = PERMISSIONS.generateCode[type]; @@ -56,19 +54,12 @@ async function post(req: NextApiRequest, res: NextApiResponse) { return; } - const codesGeneratedByUserSnapshot = await getDocs(query(collection(db, "codes"), where("creator", "==", req.session.user.id))); - const creatorGroupsSnapshot = await getDocs(query(collection(db, "groups"), where("admin", "==", req.session.user.id))); - - const creatorGroups = ( - creatorGroupsSnapshot.docs.map((x) => ({ - ...x.data(), - })) as Group[] - ).filter((x) => x.name === "Students" || x.name === "Teachers" || x.name === "Corporate"); + const userCodes = await db.collection("codes").find({ creator: req.session.user.id }).toArray() + const creatorGroupsSnapshot = await db.collection("groups").find({ admin: req.session.user.id }).toArray() + const creatorGroups = creatorGroupsSnapshot.filter((x) => x.name === "Students" || x.name === "Teachers" || x.name === "Corporate"); const usersInGroups = creatorGroups.flatMap((x) => x.participants); - const userCodes = codesGeneratedByUserSnapshot.docs.map((x) => ({ - ...x.data(), - })) as Code[]; + if (req.session.user.type === "corporate") { const totalCodes = userCodes.filter((x) => !x.userId || !usersInGroups.includes(x.userId)).length + usersInGroups.length + codes.length; @@ -77,16 +68,15 @@ async function post(req: NextApiRequest, res: NextApiResponse) { if (totalCodes > allowedCodes) { res.status(403).json({ ok: false, - reason: `You have or would have exceeded your amount of allowed codes, you currently are allowed to generate ${ - allowedCodes - codesGeneratedByUserSnapshot.docs.length - } codes.`, + reason: `You have or would have exceeded your amount of allowed codes, you currently are allowed to generate ${allowedCodes - userCodes.length + } codes.`, }); return; } } const codePromises = codes.map(async (code, index) => { - const codeRef = doc(db, "codes", code); + const codeRef = await db.collection("codes").findOne({ _id: new ObjectId(code) }); let codeInformation = { type, code, @@ -96,7 +86,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) { }; if (infos && infos.length > index) { - const {email, name, passport_id} = infos[index]; + const { email, name, passport_id } = infos[index]; const previousCode = userCodes.find((x) => x.email === email) as Code; const transport = prepareMailer(); @@ -114,16 +104,17 @@ async function post(req: NextApiRequest, res: NextApiResponse) { try { await transport.sendMail(mailOptions); - if (!previousCode) { - await setDoc( - codeRef, + if (!previousCode && codeRef) { + await db.collection("codes").updateOne( + { _id: new ObjectId(codeRef._id) }, { - ...codeInformation, - email: email.trim().toLowerCase(), - name: name.trim(), - ...(passport_id ? {passport_id: passport_id.trim()} : {}), - }, - {merge: true}, + $set: { + ...codeInformation, + email: email.trim().toLowerCase(), + name: name.trim(), + ...(passport_id ? { passport_id: passport_id.trim() } : {}), + } + } ); } @@ -132,29 +123,34 @@ async function post(req: NextApiRequest, res: NextApiResponse) { return false; } } else { - await setDoc(codeRef, codeInformation); + // upsert: true -> if it doesnt exist insert + await db.collection("codes").updateOne( + { _id: new ObjectId(code) }, + { $set: codeInformation }, + { upsert: true } + ); } }); Promise.all(codePromises).then((results) => { - res.status(200).json({ok: true, valid: results.filter((x) => x).length}); + res.status(200).json({ ok: true, valid: results.filter((x) => x).length }); }); } async function del(req: NextApiRequest, res: NextApiResponse) { if (!req.session.user) { - res.status(401).json({ok: false, reason: "You must be logged in to generate a code!"}); + res.status(401).json({ ok: false, reason: "You must be logged in to generate a code!" }); return; } const codes = req.query.code as string[]; for (const code of codes) { - const snapshot = await getDoc(doc(db, "codes", code as string)); - if (!snapshot.exists()) continue; + const snapshot = await db.collection("codes").findOne({ _id: new ObjectId(code as string) }); + if (!snapshot) continue; - await deleteDoc(snapshot.ref); + await db.collection("codes").deleteOne({ _id: snapshot._id }); } - res.status(200).json({codes}); + res.status(200).json({ codes }); }