From e33fa00fa382064fe1a1498725e319804b05ae17 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Sat, 7 Sep 2024 15:13:13 +0100 Subject: [PATCH] Updated the groups and users --- src/pages/api/grading/index.ts | 4 +- src/pages/api/make_user.ts | 7 ++- src/utils/groups.be.ts | 101 +++++++++++++-------------------- src/utils/users.be.ts | 97 +++++++++---------------------- 4 files changed, 72 insertions(+), 137 deletions(-) diff --git a/src/pages/api/grading/index.ts b/src/pages/api/grading/index.ts index bc829e00..8b84f55a 100644 --- a/src/pages/api/grading/index.ts +++ b/src/pages/api/grading/index.ts @@ -15,7 +15,7 @@ import {Grading} from "@/interfaces"; import {getGroupsForUser} from "@/utils/groups.be"; import {uniq} from "lodash"; import {getUser} from "@/utils/users.be"; -import { getGradingSystem } from "@/utils/grading.be"; +import {getGradingSystem} from "@/utils/grading.be"; const db = getFirestore(app); @@ -56,7 +56,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) { const participants = uniq(groups.flatMap((x) => x.participants)); const participantUsers = await Promise.all(participants.map(getUser)); - const corporateUsers = participantUsers.filter((x) => x.type === "corporate") as CorporateUser[]; + const corporateUsers = participantUsers.filter((x) => x?.type === "corporate") as CorporateUser[]; await Promise.all(corporateUsers.map(async (g) => await setDoc(doc(db, "grading", g.id), body))); } diff --git a/src/pages/api/make_user.ts b/src/pages/api/make_user.ts index a1956f74..025864d2 100644 --- a/src/pages/api/make_user.ts +++ b/src/pages/api/make_user.ts @@ -9,7 +9,7 @@ import {createUserWithEmailAndPassword, getAuth} from "firebase/auth"; import ShortUniqueId from "short-unique-id"; import {getUserCorporate, getUserGroups} from "@/utils/groups.be"; import {uniq} from "lodash"; -import {getUser} from "@/utils/users.be"; +import {getSpecificUsers, getUser} from "@/utils/users.be"; const DEFAULT_DESIRED_LEVELS = { reading: 9, @@ -32,9 +32,10 @@ export default withIronSessionApiRoute(handler, sessionOptions); const getUsersOfType = async (admin: string, type: Type) => { const groups = await getUserGroups(admin); - const users = await Promise.all(uniq(groups.flatMap((x) => x.participants)).map(getUser)); + const participants = groups.flatMap((x) => x.participants); + const users = await getSpecificUsers(participants); - return users.filter((x) => x.type === type).map((x) => x.id); + return users.filter((x) => x?.type === type).map((x) => x?.id); }; async function handler(req: NextApiRequest, res: NextApiResponse) { diff --git a/src/utils/groups.be.ts b/src/utils/groups.be.ts index 269eded7..9d649897 100644 --- a/src/utils/groups.be.ts +++ b/src/utils/groups.be.ts @@ -1,75 +1,73 @@ import {app} from "@/firebase"; -import {CorporateUser, Group, MasterCorporateUser, StudentUser, TeacherUser} from "@/interfaces/user"; +import {CorporateUser, Group, MasterCorporateUser, StudentUser, TeacherUser, User} from "@/interfaces/user"; +import client from "@/lib/mongodb"; import {collection, doc, getDoc, getDocs, getFirestore, query, setDoc, where} from "firebase/firestore"; import moment from "moment"; import {getUser} from "./users.be"; import {getSpecificUsers} from "./users.be"; -const db = getFirestore(app); + +const db = client.db(process.env.MONGODB_DB); export const updateExpiryDateOnGroup = async (participantID: string, corporateID: string) => { - const corporateRef = await getDoc(doc(db, "users", corporateID)); - const participantRef = await getDoc(doc(db, "users", participantID)); - - if (!corporateRef.exists() || !participantRef.exists()) return; - - const corporate = { - ...corporateRef.data(), - id: corporateRef.id, - } as CorporateUser; - const participant = {...participantRef.data(), id: participantRef.id} as StudentUser | TeacherUser; + const corporate = await db.collection("users").findOne({id: corporateID}); + const participant = await db.collection("users").findOne({id: participantID}); + if (!corporate || !participant) return; if (corporate.type !== "corporate" || (participant.type !== "student" && participant.type !== "teacher")) return; - if (!corporate.subscriptionExpirationDate || !participant.subscriptionExpirationDate) { - return await setDoc(doc(db, "users", participant.id), {subscriptionExpirationDate: null}, {merge: true}); - } + if (!corporate.subscriptionExpirationDate || !participant.subscriptionExpirationDate) + return await db.collection("users").updateOne({id: participant.id}, {$set: {subscriptionExpirationDate: null}}); const corporateDate = moment(corporate.subscriptionExpirationDate); const participantDate = moment(participant.subscriptionExpirationDate); if (corporateDate.isAfter(participantDate)) - return await setDoc(doc(db, "users", participant.id), {subscriptionExpirationDate: corporateDate.toISOString()}, {merge: true}); + return await db.collection("users").updateOne({id: participant.id}, {$set: {subscriptionExpirationDate: corporateDate.toISOString()}}); return; }; export const getUserCorporate = async (id: string) => { const user = await getUser(id); + if (!user) return undefined; + if (["admin", "developer"].includes(user.type)) return undefined; if (user.type === "mastercorporate") return user; const groups = await getParticipantGroups(id); const admins = await Promise.all(groups.map((x) => x.admin).map(getUser)); - const corporates = admins.filter((x) => (user.type === "corporate" ? x.type === "mastercorporate" : x.type === "corporate")); + const corporates = admins + .filter((x) => (user.type === "corporate" ? x?.type === "mastercorporate" : x?.type === "corporate")) + .filter((x) => !!x) as User[]; if (corporates.length === 0) return undefined; return corporates.shift() as CorporateUser | MasterCorporateUser; }; export const getGroups = async () => { - const groupDocs = await getDocs(collection(db, "groups")); - return groupDocs.docs.map((x) => ({...x.data(), id: x.id})) as Group[]; + return await db.collection("groups").find({}).toArray(); }; export const getParticipantGroups = async (id: string) => { - const snapshot = await getDocs(query(collection(db, "groups"), where("participants", "array-contains", id))); - - const groups = snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })) as Group[]; - - return groups; + return await db.collection("groups").find({participants: id}).toArray(); }; export const getUserGroups = async (id: string): Promise => { - const groupDocs = await getDocs(query(collection(db, "groups"), where("admin", "==", id))); - return groupDocs.docs.map((x) => ({...x.data(), id})) as Group[]; + return await db.collection("groups").find({admin: id}).toArray(); +}; + +export const getUsersGroups = async (ids: string[]) => { + return await db + .collection("groups") + .find({admin: {$in: ids}}) + .toArray(); }; export const getAllAssignersByCorporate = async (corporateID: string): Promise => { const groups = await getUserGroups(corporateID); - const groupUsers = (await Promise.all(groups.map(async (g) => await Promise.all(g.participants.map(getUser))))).flat(); + const groupUsers = (await Promise.all(groups.map(async (g) => await Promise.all(g.participants.map(getUser))))) + .flat() + .filter((x) => !!x) as User[]; const teacherPromises = await Promise.all( groupUsers.map(async (u) => u.type === "teacher" ? u.id : u.type === "corporate" ? [...(await getAllAssignersByCorporate(u.id)), u.id] : undefined, @@ -80,42 +78,19 @@ export const getAllAssignersByCorporate = async (corporateID: string): Promise { - try { - const queryConstraints = [ - ...(admin ? [where("admin", "==", admin)] : []), - ...(participant ? [where("participants", "array-contains", participant)] : []), - ]; - const snapshot = await getDocs(queryConstraints.length > 0 ? query(collection(db, "groups"), ...queryConstraints) : collection(db, "groups")); - const groups = snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })) as Group[]; + if (admin && participant) return await db.collection("groups").find({admin, participant}).toArray(); - return groups; - } catch (e) { - console.error(e); - return []; - } + if (admin) return await getUserGroups(admin); + if (participant) return await getParticipantGroups(participant); + + return await getGroups(); }; export const getStudentGroupsForUsersWithoutAdmin = async (admin: string, participants: string[]) => { - try { - const queryConstraints = [ - ...(admin ? [where("admin", "!=", admin)] : []), - ...(participants ? [where("participants", "array-contains-any", participants)] : []), - where("name", "==", "Students"), - ]; - const snapshot = await getDocs(queryConstraints.length > 0 ? query(collection(db, "groups"), ...queryConstraints) : collection(db, "groups")); - const groups = snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })) as Group[]; - - return groups; - } catch (e) { - console.error(e); - return []; - } + return await db + .collection("groups") + .find({...(admin ? {admin: {$ne: admin}} : {}), ...(participants ? {participants} : {})}) + .toArray(); }; export const getCorporateNameForStudent = async (studentID: string) => { @@ -123,7 +98,7 @@ export const getCorporateNameForStudent = async (studentID: string) => { if (groups.length === 0) return ""; const adminUserIds = [...new Set(groups.map((g) => g.admin))]; - const adminUsersData = await getSpecificUsers(adminUserIds); + const adminUsersData = (await getSpecificUsers(adminUserIds)).filter((x) => !!x) as User[]; if (adminUsersData.length === 0) return ""; const admins = adminUsersData.filter((x) => x.type === "corporate"); diff --git a/src/utils/users.be.ts b/src/utils/users.be.ts index ee28955f..ea701a52 100644 --- a/src/utils/users.be.ts +++ b/src/utils/users.be.ts @@ -18,67 +18,46 @@ import { where, } from "firebase/firestore"; import {CorporateUser, Group, Type, User} from "@/interfaces/user"; -import {getGroupsForUser} from "./groups.be"; +import {getGroupsForUser, getParticipantGroups, getUserGroups, getUsersGroups} from "./groups.be"; import {last, uniq, uniqBy} from "lodash"; import {getUserCodes} from "./codes.be"; import moment from "moment"; -const db = getFirestore(app); +import client from "@/lib/mongodb"; + +const db = client.db(process.env.MONGODB_DB); export async function getUsers() { - const snapshot = await getDocs(collection(db, "users")); - - return snapshot.docs.map((doc) => ({ - ...doc.data(), - id: doc.id, - registrationDate: moment(doc.data().registrationDate).toISOString(), - })) as unknown as User[]; + return await db.collection("users").find({}).toArray(); } -export async function getUser(id: string) { - const userDoc = await getDoc(doc(db, "users", id)); - - return {...userDoc.data(), id, registrationDate: moment(userDoc.data()?.registrationDate).toISOString()} as unknown as User; +export async function getUser(id: string): Promise { + const user = await db.collection("users").findOne({id}); + return !!user ? user : undefined; } export async function getSpecificUsers(ids: string[]) { if (ids.length === 0) return []; - const snapshot = await getDocs(query(collection(db, "users"), where("id", "in", ids))); - - const groups = snapshot.docs.map((doc) => ({ - ...doc.data(), - id: doc.id, - registrationDate: moment(doc.data().registrationDate).toISOString(), - })) as unknown as User[]; - - return groups; + return await db + .collection("users") + .find({id: {$in: ids}}) + .toArray(); } export async function getLinkedUsers(userID?: string, userType?: Type, type?: Type, firstID?: string, lastID?: string, size?: number) { - const q = [ - ...(!!type ? [where("type", "==", type)] : []), - orderBy("registrationDate"), - ...(!!firstID && !lastID ? [endBefore(firstID)] : []), - ...(!!lastID && !firstID ? [startAfter(lastID)] : []), - ...(!!size ? [limit(size)] : []), - ]; - - const totalQ = [...(!!type ? [where("type", "==", type)] : []), orderBy(documentId())]; + const filters = { + ...(!!type ? {type} : {}), + }; if (!userID || userType === "admin" || userType === "developer") { - const snapshot = await getDocs(query(collection(db, "users"), ...q)); - const users = snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })) as User[]; - - const total = await getCountFromServer(query(collection(db, "users"), ...totalQ)); - return {users, total: total.data().count}; + const users = await db.collection("users").find(filters).toArray(); + const total = await db.collection("users").countDocuments(filters); + return {users, total}; } - const adminGroups = await getGroupsForUser(userID); - const groups = await Promise.all(adminGroups.flatMap((x) => x.participants).map(async (x) => await getGroupsForUser(x))); - const belongingGroups = await getGroupsForUser(undefined, userID); + const adminGroups = await getUserGroups(userID); + const groups = await getUsersGroups(adminGroups.flatMap((x) => x.participants)); + const belongingGroups = await getParticipantGroups(userID); const participants = uniq([ ...adminGroups.flatMap((x) => x.participants), @@ -89,33 +68,13 @@ export async function getLinkedUsers(userID?: string, userType?: Type, type?: Ty // тип [FirebaseError: Invalid Query. A non-empty array is required for 'in' filters.] { if (participants.length === 0) return {users: [], total: 0}; - if (participants.length < 30) { - const snapshot = await getDocs(query(collection(db, "users"), ...[where(documentId(), "in", participants), ...q])); - const users = snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })) as User[]; + const users = await db + .collection("users") + .find({...filters, id: {$in: participants}}) + .toArray(); + const total = await db.collection("users").countDocuments({...filters, id: {$in: participants}}); - const total = await getCountFromServer(query(collection(db, "users"), ...[where(documentId(), "in", participants), ...totalQ])); - - return { - users, - total: total.data().count, - }; - } - - const snapshot = await getDocs(query(collection(db, "users"), ...q)); - const users = snapshot.docs.map((doc) => ({ - id: doc.id, - ...doc.data(), - })) as User[]; - - const participantUsers = users.filter((x) => participants.includes(x.id)); - - return { - users: participantUsers, - total: participantUsers.length, - }; + return {users, total}; } export async function getUserBalance(user: User) { @@ -128,7 +87,7 @@ export async function getUserBalance(user: User) { if (user.type === "corporate") return participants.length + codes.filter((x) => !participants.includes(x.userId || "")).length; const participantUsers = await Promise.all(participants.map(getUser)); - const corporateUsers = participantUsers.filter((x) => x.type === "corporate") as CorporateUser[]; + const corporateUsers = participantUsers.filter((x) => x?.type === "corporate") as CorporateUser[]; return ( corporateUsers.reduce((acc, curr) => acc + curr.corporateInformation?.companyInformation?.userAmount || 0, 0) +