ENCOA-283 or ENCOA-282, I don't know someone deleted the issue

This commit is contained in:
Carlos-Mesquita
2024-12-22 21:19:27 +00:00
parent 98a1636d0c
commit 860f1295e5
6 changed files with 314 additions and 56 deletions

View File

@@ -25,6 +25,10 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
case 'getIds':
res.status(200).json(await getIds(req.body));
break;
case 'deletePriorEntitiesGroups':
await deletePriorEntitiesGroups(req.body);
res.status(200).json({ ok: true });
break;
default:
res.status(400).json({ error: 'Invalid operation!' })
}
@@ -34,23 +38,47 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}
async function crossRefOwnership(body: any): Promise<string[]> {
const { userId, classrooms } = body;
const { userId, classrooms, entity } = body;
// First find which classrooms from input exist
const existingClassrooms = await db.collection('groups')
.find({ name: { $in: classrooms } })
.find({
name: { $in: classrooms },
admin: { $ne: userId }
})
.project({ name: 1, admin: 1, _id: 0 })
.toArray();
// From those existing classrooms, return the ones where user is NOT the admin
return existingClassrooms
.filter(classroom => classroom.admin !== userId)
.map(classroom => classroom.name);
if (existingClassrooms.length === 0) {
return [];
}
const adminUsers = await db.collection('users')
.find({
id: { $in: existingClassrooms.map(classroom => classroom.admin) }
})
.project({ id: 1, entities: 1, _id: 0 })
.toArray();
const adminEntitiesMap = new Map(
adminUsers.map(admin => [
admin.id,
admin.entities?.map((e: any) => e.id) || []
])
);
return Array.from(new Set(
existingClassrooms
.filter(classroom => {
const adminEntities = adminEntitiesMap.get(classroom.admin) || [];
return adminEntities.includes(entity);
})
.map(classroom => classroom.name)
));
}
async function getIds(body: any): Promise<Record<string, string>> {
const { names, userEmails } = body;
const existingGroups: any[] = await db.collection('groups')
.find({ name: { $in: names } })
.project({ name: 1, id: 1, _id: 0 })
@@ -72,3 +100,31 @@ async function getIds(body: any): Promise<Record<string, string>> {
}, {} as Record<string, string>)
};
}
async function deletePriorEntitiesGroups(body: any) {
const { ids, entity } = body;
if (!Array.isArray(ids) || ids.length === 0 || !entity) {
return;
}
const users = await db.collection('users')
.find({ id: { $in: ids } })
.project({ id: 1, entities: 1, _id: 0 })
.toArray();
// if the user doesn't have the target entity mark them for all groups deletion
const toDeleteUserIds = users
.filter(user => !user.entities?.some((e: any) => e.id === entity))
.map(user => user.id);
if (toDeleteUserIds.length === 0) {
return;
}
db.collection('groups').updateMany(
{ participants: { $in: toDeleteUserIds } },
{ $pull: { participants: { $in: toDeleteUserIds } } } as any
);
}

View File

@@ -29,7 +29,14 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json(await entityCheck(req.body));
break;
case 'crossRefClassrooms':
res.status(200).json(await crossRefClassrooms(req.body.sets));
res.status(200).json(await crossRefClassrooms(req.body));
break;
case 'getIds':
res.status(200).json(await getIds(req.body.emails));
break;
case 'assignToEntity':
await assignToEntity(req.body);
res.status(200).json({"ok": true});
break;
default:
res.status(400).json({ error: 'Invalid operation!' })
@@ -68,9 +75,12 @@ async function dontExist(emails: string[]): Promise<string[]> {
}
async function entityCheck(body: Record<string, any>): Promise<string[]> {
async function entityCheck(body: Record<string, any>): Promise<Array<{
email: string;
names?: string[];
}>> {
const { entities, emails } = body;
const pipeline = [
// Match users with the provided emails
{
@@ -99,20 +109,65 @@ async function entityCheck(body: Record<string, any>): Promise<string[]> {
]
}
},
// Project only the email field
// Unwind the entities array (if it exists)
{
$unwind: {
path: "$entities",
preserveNullAndEmptyArrays: true
}
},
// Lookup entity details from entities collection
{
$lookup: {
from: 'entities',
localField: 'entities.id',
foreignField: 'id',
as: 'entityDetails'
}
},
// Unwind the entityDetails array
{
$unwind: {
path: "$entityDetails",
preserveNullAndEmptyArrays: true
}
},
// Group by email to collect all entity names in an array
{
$group: {
_id: "$email",
email: { $first: "$email" },
name: {
$push: {
$cond: [
{ $ifNull: ["$entityDetails.label", false] },
"$entityDetails.label",
"$$REMOVE"
]
}
}
}
},
// Final projection to clean up
{
$project: {
_id: 0,
email: 1
email: 1,
name: 1
}
}
];
const results = await db.collection('users').aggregate(pipeline).toArray();
return results.map((result: any) => result.email);
return results.map(result => ({
email: result.email as string,
names: result.name as string[] | undefined
}));
}
async function crossRefClassrooms(sets: { email: string, classroom: string }[]) {
async function crossRefClassrooms(body: any) {
const { sets, entity } = body as { sets: { email: string, classroom: string }[], entity: string };
const pipeline = [
// Match users with the provided emails
{
@@ -132,7 +187,6 @@ async function crossRefClassrooms(sets: { email: string, classroom: string }[])
$and: [
{ $in: ['$$userId', '$participants'] },
{
// Match the classroom that corresponds to this user's email
$let: {
vars: {
matchingSet: {
@@ -153,6 +207,38 @@ async function crossRefClassrooms(sets: { email: string, classroom: string }[])
]
}
}
},
// Lookup admin's entities
{
$lookup: {
from: 'users',
let: { adminId: '$admin' },
pipeline: [
{
$match: {
$expr: { $eq: ['$id', '$$adminId'] }
}
}
],
as: 'adminInfo'
}
},
// Filter where admin has the target entity
{
$match: {
$expr: {
$in: [
entity,
{
$map: {
input: { $arrayElemAt: ['$adminInfo.entities', 0] },
as: 'entityObj',
in: '$$entityObj.id'
}
}
]
}
}
}
],
as: 'matchingGroups'
@@ -172,7 +258,54 @@ async function crossRefClassrooms(sets: { email: string, classroom: string }[])
}
}
];
const results = await db.collection('users').aggregate(pipeline).toArray();
return results.map((result: any) => result.email);
}
async function getIds(emails: string[]): Promise<Array<{ email: string; id: string }>> {
const users = await db.collection('users')
.find({ email: { $in: emails } })
.project({ email: 1, id: 1, _id: 0 })
.toArray();
return users.map(user => ({
email: user.email,
id: user.id
}));
}
async function assignToEntity(body: any) {
const { ids, entity } = body;
if (!Array.isArray(ids) || ids.length === 0 || !entity) {
return;
}
const users = await db.collection('users')
.find({ id: { $in: ids } })
.project({ id: 1, entities: 1 })
.toArray();
const toUpdateUsers = users.filter((u) => u.entities[0].id !== entity);
if (toUpdateUsers.length > 0) {
const writes = users.map(user => ({
updateOne: {
filter: { id: user.id },
update: {
$set: {
entities: [{
id: entity,
role: user.entities?.[0]?.role
}]
}
}
}
}));
db.collection('users').bulkWrite(writes);
}
}