179 lines
4.5 KiB
TypeScript
179 lines
4.5 KiB
TypeScript
|
|
import { sessionOptions } from '@/lib/session';
|
|
import { withIronSessionApiRoute } from 'iron-session/next';
|
|
import type { NextApiRequest, NextApiResponse } from 'next'
|
|
import client from "@/lib/mongodb";
|
|
|
|
const db = client.db(process.env.MONGODB_DB);
|
|
|
|
export default withIronSessionApiRoute(handler, sessionOptions);
|
|
|
|
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
const { op } = req.query
|
|
|
|
if (req.method === 'GET') {
|
|
switch (op) {
|
|
default:
|
|
res.status(400).json({ error: 'Invalid operation!' })
|
|
}
|
|
}
|
|
else if (req.method === 'POST') {
|
|
switch (op) {
|
|
case 'crossRefEmails':
|
|
res.status(200).json(await crossRefEmails(req.body.emails));
|
|
break;
|
|
case 'dontExist':
|
|
res.status(200).json(await dontExist(req.body.emails))
|
|
break;
|
|
case 'entityCheck':
|
|
res.status(200).json(await entityCheck(req.body));
|
|
break;
|
|
case 'crossRefClassrooms':
|
|
res.status(200).json(await crossRefClassrooms(req.body.sets));
|
|
break;
|
|
default:
|
|
res.status(400).json({ error: 'Invalid operation!' })
|
|
}
|
|
} else {
|
|
res.status(400).end(`Method ${req.method} Not Allowed`)
|
|
}
|
|
}
|
|
|
|
async function crossRefEmails(emails: string[]) {
|
|
return await db.collection("users").aggregate([
|
|
{
|
|
$match: {
|
|
email: { $in: emails }
|
|
}
|
|
},
|
|
{
|
|
$project: {
|
|
_id: 0,
|
|
email: 1
|
|
}
|
|
}
|
|
]).toArray();
|
|
}
|
|
|
|
async function dontExist(emails: string[]): Promise<string[]> {
|
|
const existingUsers = await db.collection('users')
|
|
.find(
|
|
{ email: { $in: emails } },
|
|
{ projection: { _id: 0, email: 1 } }
|
|
)
|
|
.toArray();
|
|
|
|
const existingEmails = new Set(existingUsers.map(u => u.email));
|
|
return emails.filter(email => !existingEmails.has(email));
|
|
}
|
|
|
|
|
|
async function entityCheck(body: Record<string, any>): Promise<string[]> {
|
|
const { entities, emails } = body;
|
|
|
|
const pipeline = [
|
|
// Match users with the provided emails
|
|
{
|
|
$match: {
|
|
email: { $in: emails }
|
|
}
|
|
},
|
|
// Match users who don't have any of the entities
|
|
{
|
|
$match: {
|
|
$or: [
|
|
// Either they have no entities array
|
|
{ entities: { $exists: false } },
|
|
// Or their entities array is empty
|
|
{ entities: { $size: 0 } },
|
|
// Or none of their entities match the provided IDs
|
|
{
|
|
entities: {
|
|
$not: {
|
|
$elemMatch: {
|
|
id: { $in: entities.map((e: any) => e.id) }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
// Project only the email field
|
|
{
|
|
$project: {
|
|
_id: 0,
|
|
email: 1
|
|
}
|
|
}
|
|
];
|
|
|
|
const results = await db.collection('users').aggregate(pipeline).toArray();
|
|
return results.map((result: any) => result.email);
|
|
}
|
|
|
|
async function crossRefClassrooms(sets: { email: string, classroom: string }[]) {
|
|
const pipeline = [
|
|
// Match users with the provided emails
|
|
{
|
|
$match: {
|
|
email: { $in: sets.map(set => set.email) }
|
|
}
|
|
},
|
|
// Lookup groups that contain the user's ID in participants
|
|
{
|
|
$lookup: {
|
|
from: 'groups',
|
|
let: { userId: '$id', userEmail: '$email' },
|
|
pipeline: [
|
|
{
|
|
$match: {
|
|
$expr: {
|
|
$and: [
|
|
{ $in: ['$$userId', '$participants'] },
|
|
{
|
|
// Match the classroom that corresponds to this user's email
|
|
$let: {
|
|
vars: {
|
|
matchingSet: {
|
|
$arrayElemAt: [
|
|
{
|
|
$filter: {
|
|
input: sets,
|
|
cond: { $eq: ['$$this.email', '$$userEmail'] }
|
|
}
|
|
},
|
|
0
|
|
]
|
|
}
|
|
},
|
|
in: { $eq: ['$name', '$$matchingSet.classroom'] }
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
],
|
|
as: 'matchingGroups'
|
|
}
|
|
},
|
|
// Only keep users who have matching groups
|
|
{
|
|
$match: {
|
|
matchingGroups: { $ne: [] }
|
|
}
|
|
},
|
|
// Project only the email
|
|
{
|
|
$project: {
|
|
_id: 0,
|
|
email: 1
|
|
}
|
|
}
|
|
];
|
|
|
|
const results = await db.collection('users').aggregate(pipeline).toArray();
|
|
return results.map((result: any) => result.email);
|
|
}
|