import { NextApiRequest, NextApiResponse } from "next"; import { createUserWithEmailAndPassword, getAuth } from "firebase/auth"; import { app } from "@/firebase"; import { sessionOptions } from "@/lib/session"; import { withIronSessionApiRoute } from "iron-session/next"; import { getFirestore, doc, setDoc, query, collection, where, getDocs, } from "firebase/firestore"; import { CorporateInformation, DemographicInformation, Type, } from "@/interfaces/user"; import { addUserToGroupOnCreation } from "@/utils/registration"; import moment from "moment"; const auth = getAuth(app); const db = getFirestore(app); export default withIronSessionApiRoute(register, sessionOptions); const DEFAULT_DESIRED_LEVELS = { reading: 9, listening: 9, writing: 9, speaking: 9, }; const DEFAULT_LEVELS = { reading: 0, listening: 0, writing: 0, speaking: 0, }; async function register(req: NextApiRequest, res: NextApiResponse) { const { type } = req.body as { type: "individual" | "corporate"; }; if (type === "individual") return registerIndividual(req, res); if (type === "corporate") return registerCorporate(req, res); } async function registerIndividual(req: NextApiRequest, res: NextApiResponse) { const { email, passport_id, password, code } = req.body as { email: string; passport_id?: string; password: string; code?: string; }; const codeQuery = query(collection(db, "codes"), where("code", "==", code)); const codeDocs = (await getDocs(codeQuery)).docs.filter( (x) => !Object.keys(x.data()).includes("userId"), ); if (code && code.length > 0 && codeDocs.length === 0) { res.status(400).json({ error: "Invalid Code!" }); return; } const codeData = codeDocs.length > 0 ? (codeDocs[0].data() as { code: string; type: Type; creator?: string; expiryDate: Date | null; }) : undefined; createUserWithEmailAndPassword(auth, email.toLowerCase(), password) .then(async (userCredentials) => { const userId = userCredentials.user.uid; delete req.body.password; const user = { ...req.body, email: email.toLowerCase(), desiredLevels: DEFAULT_DESIRED_LEVELS, levels: DEFAULT_LEVELS, bio: "", isFirstLogin: codeData ? codeData.type === "student" : true, focus: "academic", type: email.endsWith("@ecrop.dev") ? "developer" : codeData ? codeData.type : "student", subscriptionExpirationDate: codeData ? codeData.expiryDate : moment().subtract(1, "days").toISOString(), ...(passport_id ? { demographicInformation: { passport_id } } : {}), registrationDate: new Date().toISOString(), status: code ? "active" : "paymentDue", }; await setDoc(doc(db, "users", userId), user); if (codeDocs.length > 0 && codeData) { await setDoc(codeDocs[0].ref, { userId: userId }, { merge: true }); if (codeData.creator) await addUserToGroupOnCreation( userId, codeData.type, codeData.creator, ); } req.session.user = { ...user, id: userId }; await req.session.save(); res.status(200).json({ user: { ...user, id: userId } }); }) .catch((error) => { console.log(error); res.status(401).json({ error }); }); } async function registerCorporate(req: NextApiRequest, res: NextApiResponse) { const { email, password } = req.body as { email: string; password: string; corporateInformation: CorporateInformation; }; createUserWithEmailAndPassword(auth, email.toLowerCase(), password) .then(async (userCredentials) => { const userId = userCredentials.user.uid; delete req.body.password; const user = { ...req.body, email: email.toLowerCase(), desiredLevels: DEFAULT_DESIRED_LEVELS, levels: DEFAULT_LEVELS, bio: "", isFirstLogin: false, focus: "academic", type: "corporate", subscriptionExpirationDate: req.body.subscriptionExpirationDate || null, status: "paymentDue", registrationDate: new Date().toISOString(), }; await setDoc(doc(db, "users", userId), user); req.session.user = { ...user, id: userId }; await req.session.save(); res.status(200).json({ user: { ...user, id: userId } }); }) .catch((error) => { console.log(error); res.status(401).json({ error }); }); }