// Next.js API route support: https://nextjs.org/docs/api-routes/introduction import type {NextApiRequest, NextApiResponse} from "next"; import {app} from "@/firebase"; import {getFirestore, getDoc, doc, deleteDoc, setDoc, getDocs, collection, where, query} from "firebase/firestore"; import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import {Ticket} from "@/interfaces/ticket"; import {Invite} from "@/interfaces/invite"; import {CorporateUser, Group, User} from "@/interfaces/user"; import {v4} from "uuid"; import {sendEmail} from "@/email"; import {updateExpiryDateOnGroup} from "@/utils/groups.be"; const db = getFirestore(app); export default withIronSessionApiRoute(handler, sessionOptions); async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "GET") return await get(req, res); res.status(404).json(undefined); } async function addToInviterGroup(user: User, invitedBy: User) { const invitedByGroupsRef = await getDocs(query(collection(db, "groups"), where("admin", "==", invitedBy.id))); const invitedByGroups = invitedByGroupsRef.docs.map((g) => ({ ...g.data(), id: g.id, })) as Group[]; const typeGroupName = user.type === "student" ? "Students" : user.type === "teacher" ? "Teachers" : undefined; if (typeGroupName) { const typeGroup: Group = invitedByGroups.find((g) => g.name === typeGroupName) || { id: v4(), admin: invitedBy.id, name: typeGroupName, participants: [], disableEditing: true, }; await setDoc( doc(db, "groups", typeGroup.id), { ...typeGroup, participants: [...typeGroup.participants.filter((x) => x !== user.id), user.id], }, {merge: true}, ); } const invitationsGroup: Group = invitedByGroups.find((g) => g.name === "Invited") || { id: v4(), admin: invitedBy.id, name: "Invited", participants: [], disableEditing: true, }; await setDoc( doc(db, "groups", invitationsGroup.id), { ...invitationsGroup, participants: [...invitationsGroup.participants.filter((x) => x !== user.id), user.id], }, { merge: true, }, ); } async function deleteFromPreviousCorporateGroups(user: User, invitedBy: User) { const corporatesRef = await getDocs(query(collection(db, "users"), where("type", "==", "corporate"))); const corporates = (corporatesRef.docs.map((x) => ({...x.data(), id: x.id})) as CorporateUser[]).filter((x) => x.id !== invitedBy.id); const userGroupsRef = await getDocs(query(collection(db, "groups"), where("participants", "array-contains", user.id))); const userGroups = userGroupsRef.docs.map((x) => ({...x.data(), id: x.id})) as Group[]; const corporateGroups = userGroups.filter((x) => corporates.map((c) => c.id).includes(x.admin)); await Promise.all( corporateGroups.map(async (group) => { await setDoc(doc(db, "groups", group.id), {participants: group.participants.filter((x) => x !== user.id)}, {merge: true}); }), ); } async function get(req: NextApiRequest, res: NextApiResponse) { if (!req.session.user) { res.status(401).json({ok: false}); return; } const {id} = req.query as {id: string}; const snapshot = await getDoc(doc(db, "invites", id)); if (snapshot.exists()) { const invite = {...snapshot.data(), id: snapshot.id} as Invite; if (invite.to !== req.session.user.id) return res.status(403).json({ok: false}); await deleteDoc(snapshot.ref); const invitedByRef = await getDoc(doc(db, "users", invite.from)); if (!invitedByRef.exists()) return res.status(404).json({ok: false}); await updateExpiryDateOnGroup(invite.to, invite.from); const invitedBy = {...invitedByRef.data(), id: invitedByRef.id} as User; if (invitedBy.type === "corporate") await deleteFromPreviousCorporateGroups(req.session.user, invitedBy); await addToInviterGroup(req.session.user, invitedBy); try { await sendEmail( "respondedInvite", { corporateName: invitedBy.name, name: req.session.user.name, decision: "accept", environment: process.env.ENVIRONMENT, }, [invitedBy.email], `${req.session.user.name} has accepted your invite!`, ); } catch (e) { console.log(e); } res.status(200).json({ok: true}); } else { res.status(404).json(undefined); } }