11const jwt = require ( 'jsonwebtoken' ) ;
2+ const { ObjectId } = require ( 'mongodb' ) ;
23
34const EmailController = require ( './email.controller' ) ;
45const { CONFIG_AUTH } = require ( '../config' ) ;
@@ -21,6 +22,25 @@ UserController.user_list = async function (req, res) {
2122 try {
2223 const user = await User . find ( query ) ;
2324 return res . status ( 200 ) . send ( user ) ;
25+ } catch ( err ) {
26+ console . error ( err ) ;
27+ return res . sendStatus ( 400 ) ;
28+ }
29+ } ;
30+
31+ UserController . user_by_email = async function ( req , res ) {
32+ const { headers } = req ;
33+ const { email } = req . params ;
34+
35+ console . log ( 'email: ' , email ) ;
36+
37+ if ( headers [ 'x-customrequired-header' ] !== expectedHeader ) {
38+ return res . sendStatus ( 403 ) ;
39+ }
40+
41+ try {
42+ const user = await User . find ( { email } ) ;
43+ return res . status ( 200 ) . send ( user ) ;
2444 } catch ( err ) {
2545 console . log ( err ) ;
2646 return res . sendStatus ( 400 ) ;
@@ -39,7 +59,7 @@ UserController.admin_list = async function (req, res) {
3959 const admins = await User . find ( { accessLevel : { $in : [ 'admin' , 'superadmin' ] } } ) ;
4060 return res . status ( 200 ) . send ( admins ) ;
4161 } catch ( err ) {
42- console . log ( err ) ;
62+ console . error ( err ) ;
4363 return res . sendStatus ( 400 ) ;
4464 }
4565} ;
@@ -53,17 +73,24 @@ UserController.projectManager_list = async function (req, res) {
5373
5474 try {
5575 const projectManagers = await User . find ( {
56- $and : [
57- { accessLevel : { $in : [ 'admin' , 'superadmin' ] } } ,
58- { managedProjects : { $exists : true , $type : 'array' , $ne : [ ] } } ,
59- ] ,
76+ managedProjects : { $exists : true , $type : 'array' , $ne : [ ] } ,
6077 } ) ;
6178
6279 // Collect all unique project IDs
63- const allProjectIds = [ ...new Set ( projectManagers . flatMap ( ( pm ) => pm . managedProjects ) ) ] ;
80+ const allProjectIds = [
81+ ...new Set (
82+ projectManagers
83+ . flatMap ( ( pm ) => pm . managedProjects )
84+ . filter ( ( id ) => typeof id === 'string' && id . match ( / ^ [ a - f \d ] { 24 } $ / i) ) ,
85+ ) ,
86+ ] ;
6487
6588 // Fetch all projects in one query
66- const projects = await Project . find ( { _id : { $in : allProjectIds } } ) ;
89+ const projects = await Project . find (
90+ { _id : { $in : allProjectIds } } ,
91+ { _id : 1 , name : 1 } , // projection
92+ ) ;
93+
6794 const projectIdToName = { } ;
6895 for ( const project of projects ) {
6996 projectIdToName [ project . _id . toString ( ) ] = project . name ;
@@ -80,7 +107,8 @@ UserController.projectManager_list = async function (req, res) {
80107
81108 return res . status ( 200 ) . send ( updatedProjectManagers ) ;
82109 } catch ( err ) {
83- console . log ( err ) ;
110+ console . error ( err ) ;
111+ console . log ( 'Projectlead error' , err ) ;
84112 return res . sendStatus ( 400 ) ;
85113 }
86114} ;
@@ -96,11 +124,9 @@ UserController.user_by_id = async function (req, res) {
96124
97125 try {
98126 const user = await User . findById ( UserId ) ;
99- // TODO throw 404 if User.findById returns empty object
100- // and look downstream to see whether 404 would break anything
101127 return res . status ( 200 ) . send ( user ) ;
102128 } catch ( err ) {
103- console . log ( err ) ;
129+ console . error ( err ) ;
104130 return res . sendStatus ( 400 ) ;
105131 }
106132} ;
@@ -144,7 +170,7 @@ UserController.update = async function (req, res) {
144170 const user = await User . findOneAndUpdate ( { _id : UserId } , req . body , { new : true } ) ;
145171 return res . status ( 200 ) . send ( user ) ;
146172 } catch ( err ) {
147- console . log ( err ) ;
173+ console . error ( err ) ;
148174 return res . sendStatus ( 400 ) ;
149175 }
150176} ;
@@ -162,7 +188,7 @@ UserController.delete = async function (req, res) {
162188 const user = await User . findByIdAndDelete ( UserId ) ;
163189 return res . status ( 200 ) . send ( user ) ;
164190 } catch ( err ) {
165- console . log ( err ) ;
191+ console . error ( err ) ;
166192 return res . sendStatus ( 400 ) ;
167193 }
168194} ;
@@ -232,7 +258,6 @@ UserController.signin = function (req, res) {
232258} ;
233259
234260UserController . verifySignIn = async function ( req , res ) {
235-
236261 let token = req . headers [ 'x-access-token' ] || req . headers [ 'authorization' ] ;
237262 if ( token . startsWith ( 'Bearer ' ) ) {
238263 // Remove Bearer from string
@@ -245,7 +270,7 @@ UserController.verifySignIn = async function (req, res) {
245270 res . cookie ( 'token' , token , { httpOnly : true } ) ;
246271 return res . send ( user ) ;
247272 } catch ( err ) {
248- console . log ( err ) ;
273+ console . error ( err ) ;
249274 return res . status ( 403 ) ;
250275 }
251276} ;
@@ -259,4 +284,74 @@ UserController.logout = async function (req, res) {
259284 return res . clearCookie ( 'token' ) . status ( 200 ) . send ( 'Successfully logged out.' ) ;
260285} ;
261286
287+ // Update user's managedProjects
288+ UserController . updateManagedProjects = async function ( req , res ) {
289+ const { headers } = req ;
290+ const { UserId } = req . params ;
291+ const { action, projectId } = req . body ; // action - 'add' or 'remove'
292+ // console.log('action:', action, 'projectId:', projectId);
293+
294+ if ( headers [ 'x-customrequired-header' ] !== expectedHeader ) {
295+ return res . sendStatus ( 403 ) ;
296+ }
297+
298+ try {
299+ // Update user's managedProjects and the project's managedByUsers
300+ const user = await User . findById ( UserId ) ;
301+ let managedProjects = user . managedProjects || [ ] ;
302+
303+ const project = await Project . findById ( projectId ) ;
304+ let managedByUsers = project . managedByUsers || [ ] ;
305+
306+ if ( action === 'add' ) {
307+ managedProjects = [ ...managedProjects , projectId ] ;
308+ managedByUsers = [ ...managedByUsers , UserId ] ;
309+ } else {
310+ // remove case
311+ managedProjects = managedProjects . filter ( ( id ) => id !== projectId ) ;
312+ managedByUsers = managedByUsers . filter ( ( id ) => id !== UserId ) ;
313+ }
314+
315+ // Update user's managedProjects
316+ user . managedProjects = managedProjects ;
317+ await user . save ( { validateBeforeSave : false } ) ;
318+
319+ // Update project's managedByUsers
320+ project . managedByUsers = managedByUsers ;
321+ await project . save ( { validateBeforeSave : false } ) ;
322+
323+ return res . status ( 200 ) . send ( { user, project } ) ;
324+ } catch ( err ) {
325+ console . log ( err ) ;
326+ return res . sendStatus ( 400 ) ;
327+ }
328+ } ;
329+
330+ UserController . bulkUpdateManagedProjects = async function ( req , res ) {
331+ const { bulkOps } = req . body ;
332+
333+ // Convert string IDs to ObjectId in bulkOps
334+ bulkOps . forEach ( ( op ) => {
335+ if ( op ?. updateOne ?. filter . _id ) {
336+ op . updateOne . filter . _id = ObjectId ( op . updateOne . filter . _id ) ;
337+ }
338+ if ( op ?. updateOne ?. update ) {
339+ const update = op . updateOne . update ;
340+ if ( update ?. $addToSet ?. managedProjects ) {
341+ update . $addToSet . managedProjects = ObjectId ( update . $addToSet . managedProjects ) ;
342+ }
343+ if ( update ?. $pull ?. managedProjects ) {
344+ update . $pull . managedProjects = ObjectId ( update . $pull . managedProjects ) ;
345+ }
346+ }
347+ } ) ;
348+
349+ try {
350+ const result = await User . bulkWrite ( bulkOps ) ;
351+ res . status ( 200 ) . json ( result ) ;
352+ } catch ( err ) {
353+ res . status ( 500 ) . json ( { error : err . message } ) ;
354+ }
355+ } ;
356+
262357module . exports = UserController ;
0 commit comments