import type {NextApiRequest, NextApiResponse} from "next"; import {app} from "@/firebase"; import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import {v4} from "uuid"; import {CorporateUser, Group, Type, User} from "@/interfaces/user"; import {createUserWithEmailAndPassword, getAuth} from "firebase/auth"; import ShortUniqueId from "short-unique-id"; import {getGroup, getGroups, getUserCorporate, getUserGroups, getUserNamedGroup} from "@/utils/groups.be"; import {uniq} from "lodash"; import {getSpecificUsers, getUser} from "@/utils/users.be"; import client from "@/lib/mongodb"; const DEFAULT_DESIRED_LEVELS = { reading: 9, listening: 9, writing: 9, speaking: 9, }; const DEFAULT_LEVELS = { reading: 0, listening: 0, writing: 0, speaking: 0, }; const auth = getAuth(app); const db = client.db(process.env.MONGODB_DB); export default withIronSessionApiRoute(handler, sessionOptions); const getUsersOfType = async (admin: string, type: Type) => { const groups = await getUserGroups(admin); const participants = groups.flatMap((x) => x.participants); const users = await getSpecificUsers(participants); return users.filter((x) => x?.type === type).map((x) => x?.id); }; async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "POST") return post(req, res); return res.status(404).json({ok: false}); } async function post(req: NextApiRequest, res: NextApiResponse) { const maker = req.session.user; if (!maker) { return res.status(401).json({ok: false, reason: "You must be logged in to make user!"}); } const corporateCorporate = await getUserCorporate(maker.id); const {email, passport_id, password, type, groupID, expiryDate, corporate} = req.body as { email: string; password?: string; passport_id: string; type: string; groupID?: string; corporate?: string; expiryDate: null | Date; }; // cleaning data delete req.body.passport_id; delete req.body.groupID; delete req.body.expiryDate; delete req.body.password; delete req.body.corporate; await createUserWithEmailAndPassword(auth, email.toLowerCase(), !!password ? password : passport_id) .then(async (userCredentials) => { const userId = userCredentials.user.uid; const profilePicture = !corporateCorporate ? "/defaultAvatar.png" : corporateCorporate.profilePicture; const user = { ...req.body, bio: "", id: userId, type: type, focus: "academic", status: "active", desiredLevels: DEFAULT_DESIRED_LEVELS, profilePicture, levels: DEFAULT_LEVELS, isFirstLogin: false, isVerified: true, registrationDate: new Date(), subscriptionExpirationDate: expiryDate || null, ...((maker.type === "corporate" || maker.type === "mastercorporate") && type === "corporate" ? { corporateInformation: { companyInformation: { name: maker.corporateInformation?.companyInformation?.name || "N/A", userAmount: 0, }, }, } : {}), }; const uid = new ShortUniqueId(); const code = uid.randomUUID(6); await db.collection("users").insertOne(user); await db.collection("codes").insertOne({ code, creator: maker.id, expiryDate, type, creationDate: new Date(), userId, email: email.toLowerCase(), name: req.body.name, ...(!!passport_id ? {passport_id} : {}), }); if (type === "corporate") { const students = maker.type === "corporate" ? await getUsersOfType(maker.id, "student") : []; const teachers = maker.type === "corporate" ? await getUsersOfType(maker.id, "teacher") : []; const defaultTeachersGroup: Group = { admin: userId, id: v4(), name: "Teachers", participants: teachers, disableEditing: true, }; const defaultStudentsGroup: Group = { admin: userId, id: v4(), name: "Students", participants: students, disableEditing: true, }; await db.collection("groups").insertMany([defaultStudentsGroup, defaultTeachersGroup]); } if (!!corporate) { const corporateUser = await db.collection("users").findOne({email: corporate.trim().toLowerCase()}); if (!!corporateUser) { await db.collection("codes").updateOne({code}, {$set: {creator: corporateUser.id}}); const typeGroup = await db .collection("groups") .findOne({creator: corporateUser.id, name: type === "student" ? "Students" : "Teachers"}); if (!!typeGroup) { if (!typeGroup.participants.includes(userId)) { await db.collection("groups").updateOne({id: typeGroup.id}, {$set: {participants: [...typeGroup.participants, userId]}}); } } else { const defaultGroup: Group = { admin: corporateUser.id, id: v4(), name: type === "student" ? "Students" : "Teachers", participants: [userId], disableEditing: true, }; await db.collection("groups").insertOne(defaultGroup); } } } if (maker.type === "corporate") { await db.collection("codes").updateOne({code}, {$set: {creator: maker.id}}); const typeGroup = await getUserNamedGroup(maker.id, type === "student" ? "Students" : "Teachers"); if (!!typeGroup) { if (!typeGroup.participants.includes(userId)) { await db.collection("groups").updateOne({id: typeGroup.id}, {$set: {participants: [...typeGroup.participants, userId]}}); } } else { const defaultGroup: Group = { admin: maker.id, id: v4(), name: type === "student" ? "Students" : "Teachers", participants: [userId], disableEditing: true, }; await db.collection("groups").insertOne(defaultGroup); } } if (!!corporateCorporate && corporateCorporate.type === "mastercorporate" && type === "corporate") { const corporateGroup = await getUserNamedGroup(corporateCorporate.id, "Corporate"); if (!!corporateGroup) { if (!corporateGroup.participants.includes(userId)) { await db .collection("groups") .updateOne({id: corporateGroup.id}, {$set: {participants: [...corporateGroup.participants, userId]}}); } } else { const defaultGroup: Group = { admin: corporateCorporate.id, id: v4(), name: "Corporate", participants: [userId], disableEditing: true, }; await db.collection("groups").insertOne(defaultGroup); } } if (!!groupID) { const group = await getGroup(groupID); if (!!group) await db.collection("groups").updateOne({id: group.id}, {$set: {participants: [...group.participants, userId]}}); } console.log(`Returning - ${email}`); return res.status(200).json({ok: true}); }) .catch((error) => { if (error.code.includes("email-already-in-use")) return res.status(403).json({error, message: "E-mail is already in the platform."}); console.log(`Failing - ${email}`); console.log(error); return res.status(401).json({error}); }); }