diff --git a/backend/controllers/user.controller.js b/backend/controllers/user.controller.js index d6bad1e1d..2543b3ad2 100644 --- a/backend/controllers/user.controller.js +++ b/backend/controllers/user.controller.js @@ -22,7 +22,7 @@ UserController.user_list = async function (req, res) { const user = await User.find(query); return res.status(200).send(user); } catch (err) { - console.log(err); + console.error(err); return res.sendStatus(400); } }; @@ -39,7 +39,7 @@ UserController.admin_list = async function (req, res) { const admins = await User.find({ accessLevel: { $in: ['admin', 'superadmin'] } }); return res.status(200).send(admins); } catch (err) { - console.log(err); + console.error(err); return res.sendStatus(400); } }; @@ -53,17 +53,24 @@ UserController.projectManager_list = async function (req, res) { try { const projectManagers = await User.find({ - $and: [ - { accessLevel: { $in: ['admin', 'superadmin'] } }, - { managedProjects: { $exists: true, $type: 'array', $ne: [] } }, - ], + managedProjects: { $exists: true, $type: 'array', $ne: [] }, }); // Collect all unique project IDs - const allProjectIds = [...new Set(projectManagers.flatMap((pm) => pm.managedProjects))]; + const allProjectIds = [ + ...new Set( + projectManagers + .flatMap((pm) => pm.managedProjects) + .filter((id) => typeof id === 'string' && id.match(/^[a-f\d]{24}$/i)), + ), + ]; // Fetch all projects in one query - const projects = await Project.find({ _id: { $in: allProjectIds } }); + const projects = await Project.find( + { _id: { $in: allProjectIds } }, + { _id: 1, name: 1 }, // projection + ); + const projectIdToName = {}; for (const project of projects) { projectIdToName[project._id.toString()] = project.name; @@ -80,7 +87,8 @@ UserController.projectManager_list = async function (req, res) { return res.status(200).send(updatedProjectManagers); } catch (err) { - console.log(err); + console.error(err); + console.log('Projectlead error', err); return res.sendStatus(400); } }; @@ -100,7 +108,7 @@ UserController.user_by_id = async function (req, res) { // and look downstream to see whether 404 would break anything return res.status(200).send(user); } catch (err) { - console.log(err); + console.error(err); return res.sendStatus(400); } }; @@ -144,7 +152,7 @@ UserController.update = async function (req, res) { const user = await User.findOneAndUpdate({ _id: UserId }, req.body, { new: true }); return res.status(200).send(user); } catch (err) { - console.log(err); + console.error(err); return res.sendStatus(400); } }; @@ -162,7 +170,7 @@ UserController.delete = async function (req, res) { const user = await User.findByIdAndDelete(UserId); return res.status(200).send(user); } catch (err) { - console.log(err); + console.error(err); return res.sendStatus(400); } }; @@ -232,7 +240,6 @@ UserController.signin = function (req, res) { }; UserController.verifySignIn = async function (req, res) { - let token = req.headers['x-access-token'] || req.headers['authorization']; if (token.startsWith('Bearer ')) { // Remove Bearer from string @@ -245,7 +252,7 @@ UserController.verifySignIn = async function (req, res) { res.cookie('token', token, { httpOnly: true }); return res.send(user); } catch (err) { - console.log(err); + console.error(err); return res.status(403); } }; diff --git a/client/src/components/user-admin/UserPermissionSearch.jsx b/client/src/components/user-admin/UserPermissionSearch.jsx index f3cc5894e..96f1a950f 100644 --- a/client/src/components/user-admin/UserPermissionSearch.jsx +++ b/client/src/components/user-admin/UserPermissionSearch.jsx @@ -246,7 +246,7 @@ const UserPermissionSearch = ({ admins, projectLeads, setUserToEdit }) => { variant={isProjectLead ? 'contained' : 'secondary'} onClick={buttonSwap} > - Project Leads + Project Members diff --git a/client/src/pages/UserPermissionSearch.jsx b/client/src/pages/UserPermissionSearch.jsx index fd559ff31..a077aa33f 100644 --- a/client/src/pages/UserPermissionSearch.jsx +++ b/client/src/pages/UserPermissionSearch.jsx @@ -1,5 +1,15 @@ import React, { useState, useEffect } from 'react'; -import {Box, Button, ButtonGroup, Grid, TextField, Typography, List, ListItem, ListItemButton} from '@mui/material'; +import { + Box, + Button, + ButtonGroup, + Grid, + TextField, + Typography, + List, + ListItem, + ListItemButton, +} from '@mui/material'; import { useLocation } from 'react-router-dom'; import '../sass/UserAdmin.scss'; @@ -7,164 +17,170 @@ import '../sass/UserAdmin.scss'; const Buttonsx = { px: 2, py: 0.5, -} +}; const dummyData = [ { - "_id": 1, - "name": { - "firstName": "John", - "lastName": "Doe", + _id: 1, + name: { + firstName: 'John', + lastName: 'Doe', }, - "accessLevel": "admin", - "email": "johndoe@hackforla.org", - "projects": [] + accessLevel: 'admin', + email: 'johndoe@hackforla.org', + projects: [], }, { - "_id": 2, - "name": { - "firstName": "Vinny", - "lastName": "Harris", + _id: 2, + name: { + firstName: 'Vinny', + lastName: 'Harris', }, - "accessLevel": "admin", - "email": "vinnyharris@hackforla.org", - "projects": [] + accessLevel: 'admin', + email: 'vinnyharris@hackforla.org', + projects: [], }, { - "_id": 3, - "name": { - "firstName": "Gary", - "lastName": "Jones", + _id: 3, + name: { + firstName: 'Gary', + lastName: 'Jones', }, - "accessLevel": "admin", - "email": "garyjones@hackforla.org", - "projects": [] + accessLevel: 'admin', + email: 'garyjones@hackforla.org', + projects: [], }, { - "_id": 4, - "name": { - "firstName": "Jane", - "lastName": "Smith", + _id: 4, + name: { + firstName: 'Jane', + lastName: 'Smith', }, - "accessLevel": "projectLead", - "email": "janesmith@hackforla.org", - "projects": ["VRMS", "Mobile"] + accessLevel: 'projectLead', + email: 'janesmith@hackforla.org', + projects: ['VRMS', 'Mobile'], }, { - "_id": 5, - "name": { - "firstName": "Bonnie", - "lastName": "Wolfe", + _id: 5, + name: { + firstName: 'Bonnie', + lastName: 'Wolfe', }, - "accessLevel": "projectLead", - "email": "bonnie@hackforla.org", - "projects": ["Home Unite Us"] + accessLevel: 'projectLead', + email: 'bonnie@hackforla.org', + projects: ['Home Unite Us'], }, { - "_id": 6, - "name": { - "firstName": "Diana", - "lastName": "Loeb", + _id: 6, + name: { + firstName: 'Diana', + lastName: 'Loeb', }, - "accessLevel": "projectLead", - "email": "dianaloeb@hackforla.org", - "projects": ["HackforLA Mobile", "LA TDM Calculator"] + accessLevel: 'projectLead', + email: 'dianaloeb@hackforla.org', + projects: ['HackforLA Mobile', 'LA TDM Calculator'], }, { - "_id": 7, - "name": { - "firstName": "Zack", - "lastName": "Cruz", + _id: 7, + name: { + firstName: 'Zack', + lastName: 'Cruz', }, - "accessLevel": "projectLead", - "email": "dianaloeb@hackforla.org", - "projects": ["LA TDM Calculator", "VRMS backend"] + accessLevel: 'projectLead', + email: 'dianaloeb@hackforla.org', + projects: ['LA TDM Calculator', 'VRMS backend'], }, { - "_id": 8, - "name": { - "firstName": "Iris", - "lastName": "Sosa", + _id: 8, + name: { + firstName: 'Iris', + lastName: 'Sosa', }, - "accessLevel": "projectLead", - "email": "irissosa@hackforla.org", - "projects": ["Home Unite Us", "VRMS Support"] + accessLevel: 'projectLead', + email: 'irissosa@hackforla.org', + projects: ['Home Unite Us', 'VRMS Support'], }, ]; const DummyComponent = ({ data, type }) => { return ( - {data.map((user, index) => { - // Destructure user object - const { _id, name, email } = user; - return type === 'admin' ? - ( - - setUserToEdit(user)} - > - - - - {`${name.firstName.toUpperCase()} ${name.lastName.toUpperCase()} ( ${email.toUpperCase()} )`} - - - - - - ) : - - setUserToEdit(user)} - > - - - {name.firstName.toUpperCase() + " " + name.lastName.toUpperCase()} - - - {user.project} - - - - - }) - } - - ) -} - + {data.map((user, index) => { + // Destructure user object + const { _id, name, email } = user; + return type === 'admin' ? ( + + setUserToEdit(user)} + > + + + + {`${name.firstName.toUpperCase()} ${name.lastName.toUpperCase()} ( ${email.toUpperCase()} )`} + + + + + + ) : ( + + setUserToEdit(user)} + > + + + + {name.firstName.toUpperCase() + + ' ' + + name.lastName.toUpperCase()} + + + + + {user.project} + + + + + + ); + })} + + ); +}; const UserPermissionSearch = ({ users, setUserToEdit }) => { const [userType, setUserType] = useState('admin'); // Which results will display @@ -180,10 +196,9 @@ const UserPermissionSearch = ({ users, setUserToEdit }) => { } else { editURL = location.pathname + '/projects'; } - window.history.replaceState({}, "", editURL); + window.history.replaceState({}, '', editURL); }, [userType]); - // Swaps the buttons and displayed panels for the search results, by email or by name const buttonSwap = () => userType === 'projectLead' @@ -201,79 +216,91 @@ const UserPermissionSearch = ({ users, setUserToEdit }) => { filteredData = dummyData.filter((user) => user.accessLevel === userType); if (userType === 'admin') { // Default display for admins, sorted ASC based on first name - filteredData.sort((u1, u2) => u1.name?.firstName.localeCompare(u2.name?.firstName)) + filteredData.sort((u1, u2) => + u1.name?.firstName.localeCompare(u2.name?.firstName) + ); } else { // Default display of all PMs, sorted ASC based on project name, then first name let tempFilter = []; filteredData.forEach((user) => { user.projects.forEach((project) => { - tempFilter.push({ ...user, project }) - }) - }) - tempFilter.sort((u1, u2) => u1.project.localeCompare(u2.project) || u1.name?.firstName.localeCompare(u2.name?.firstName)) + tempFilter.push({ ...user, project }); + }); + }); + tempFilter.sort( + (u1, u2) => + u1.project.localeCompare(u2.project) || + u1.name?.firstName.localeCompare(u2.name?.firstName) + ); filteredData = [...tempFilter]; } } return ( - - - User Permission Search + + + + User Permission Search + - - - + + + - 0? '#F5F5F5': 'transparent', - my: 1.2, - borderRadius: 1, - flexGrow: 1, - width: 1/1, - }}> + 0 ? '#F5F5F5' : 'transparent', + my: 1.2, + borderRadius: 1, + flexGrow: 1, + width: 1 / 1, + }} + > {/*Component to render admins and PMs*/}