Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 15 additions & 49 deletions backend/controllers/user.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ UserController.admin_list = async function (req, res) {
}
};

UserController.projectManager_list = async function (req, res) {
// Get list of Users with accessLevel 'admin' or 'superadmin' and also managed projects with GET
UserController.projectLead_list = async function (req, res) {
const { headers } = req;

if (headers['x-customrequired-header'] !== expectedHeader) {
Expand All @@ -51,68 +52,33 @@ UserController.projectManager_list = async function (req, res) {

try {
const projectManagers = await User.find({
managedProjects: { $exists: true, $type: 'array', $not: { $size: 0 } },
});

// Filter out managers with empty arrays early
const validProjectManagers = projectManagers.filter(
(manager) => manager.managedProjects && manager.managedProjects.length > 0,
);

if (validProjectManagers.length === 0) {
return res.status(200).send([]);
}

// Collect all unique project IDs to fetch in one query
const allProjectIds = new Set();
validProjectManagers.forEach((manager) => {
manager.managedProjects.forEach((projectId) => {
// Filter out invalid project IDs (non-string or obviously invalid values)
if (typeof projectId === 'string' && projectId !== 'false' && projectId.length > 0) {
allProjectIds.add(projectId);
}
});
});

// Fetch all projects in a single query
const projects = await Project.find({ _id: { $in: Array.from(allProjectIds) } });

// Create a map for O(1) lookup
const projectMap = new Map();
projects.forEach((project) => {
projectMap.set(project._id.toString(), project.name);
$and: [
{ accessLevel: { $in: ['admin', 'superadmin'] } },
{ managedProjects: { $exists: true, $type: 'array', $ne: [] } },
],
});

const updatedProjectManagers = [];

for (const projectManager of validProjectManagers) {
for (const projectManager of projectManagers) {
const projectManagerObj = projectManager.toObject();
projectManagerObj.isProjectMember = true;
projectManagerObj.isProjectLead = true;
const projectNames = [];

for (const projectId of projectManagerObj.managedProjects) {
// using try-catch block because old user data had invalid strings (aka 'false') for ProjectIds
try {
const projectName = projectMap.get(projectId.toString());
if (projectName) {
projectNames.push(projectName);
} else {
console.warn('Project detail is null, cannot access name');
}
} catch (error) {
console.warn('Failed to fetch project details for ID:', projectId, error);
const projectDetail = await Project.findById(projectId);
if (projectDetail && projectDetail.name) {
projectNames.push(projectDetail.name);
} else {
console.warn('Project detail is null, cannot access name');
}
}
projectManagerObj.managedProjectNames = projectNames;

if (projectNames.length) {
projectManagerObj.managedProjectNames = projectNames;
updatedProjectManagers.push(projectManagerObj);
}
updatedProjectManagers.push(projectManagerObj);
}

return res.status(200).send(updatedProjectManagers);
} catch (err) {
console.log('Projectlead error', err);
return res.sendStatus(400);
}
};
Expand Down
2 changes: 1 addition & 1 deletion backend/models/project.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Idea for the future: programmingLanguages, numberGithubContributions (pull these
*/

const projectSchema = mongoose.Schema({
name: { type: String, trim: true, required: true },
name: { type: String, trim: true },
description: { type: String, trim: true },
githubIdentifier: { type: String, trim: true },
projectStatus: { type: String }, // Active, Completed, or Paused
Expand Down
25 changes: 10 additions & 15 deletions backend/models/user.model.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const mongoose = require('mongoose');
const mongoose = require("mongoose");
// const bcrypt = require('bcrypt-nodejs');

mongoose.Promise = global.Promise;
Expand All @@ -9,10 +9,10 @@ const userSchema = mongoose.Schema({
lastName: { type: String },
},
email: { type: String, unique: true },
accessLevel: {
type: String,
enum: ['user', 'admin', 'superadmin'], // restricts values to "user", "admin" and "superadmin"
default: 'user',
accessLevel: {
type: String,
enum: ["user", "admin", "superadmin"], // restricts values to "user", "admin" and "superadmin"
default: "user"
},
createdDate: { type: Date, default: Date.now },
currentRole: { type: String }, // will remove but need to update check-in form
Expand All @@ -27,7 +27,7 @@ const userSchema = mongoose.Schema({
projects: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Project',
ref: "Project",
},
],
githubHandle: { type: String }, // handle not including @, not the URL
Expand All @@ -37,15 +37,10 @@ const userSchema = mongoose.Schema({
isHflaGithubMember: { type: Boolean }, // pull from API once github handle in place?
githubPublic2FA: { type: Boolean }, // does the user have 2FA enabled on their github and membership set to public?
availability: { type: String }, // availability to meet outside of hacknight times; string for now, more structured in future
managedProjects: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Project',
},
], // Which projects managed by user.
managedProjects: [{ type: String}], // Which projects managed by user.
//currentProject: { type: String } // no longer need this as we can get it from Project Team Member table
// password: { type: String, required: true }
isActive: { type: Boolean, default: true },
isActive: { type: Boolean, default: true }
});

userSchema.methods.serialize = function () {
Expand Down Expand Up @@ -76,10 +71,10 @@ userSchema.methods.serialize = function () {
githubPublic2FA: this.githubPublic2FA,
availability: this.availability,
managedProjects: this.managedProjects,
isActive: this.isActive,
isActive: this.isActive
};
};

const User = mongoose.model('User', userSchema);
const User = mongoose.model("User", userSchema);

module.exports = { User };
2 changes: 1 addition & 1 deletion backend/routers/users.router.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ router.get('/', UserController.user_list);

router.get('/admins', UserController.admin_list);

router.get('/projectManagers', UserController.projectManager_list);
router.get('/projectManagers', UserController.projectLead_list);

router.post('/', UserController.create);

Expand Down
Loading
Loading