Skip to content

Commit 6e8da42

Browse files
authored
Merge branch 'development' into populateProjectsJupyterNotebook
2 parents def66a2 + 9307f59 commit 6e8da42

File tree

15 files changed

+788
-342
lines changed

15 files changed

+788
-342
lines changed

backend/controllers/project.controller.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { Project } = require('../models');
1+
const { Project, User } = require('../models');
22

33
const ProjectController = {};
44

@@ -66,4 +66,40 @@ ProjectController.destroy = async function (req, res) {
6666
}
6767
};
6868

69+
ProjectController.updateManagedByUsers = async function (req, res) {
70+
const { ProjectId } = req.params;
71+
const { action, userId } = req.body; // action - 'add' or 'remove'
72+
73+
try {
74+
// Update project's managedByUsers and the user's managedProjects
75+
const project = await Project.findById(ProjectId);
76+
let managedByUsers = project.managedByUsers || [];
77+
78+
const user = await User.findById(userId);
79+
let managedProjects = user.managedProjects || [];
80+
81+
if (action === 'add') {
82+
managedByUsers = [...new Set([...managedByUsers, userId])];
83+
managedProjects = [...new Set([...managedProjects, ProjectId])];
84+
} else {
85+
// remove case
86+
managedByUsers = managedByUsers.filter((id) => id !== userId);
87+
managedProjects = managedProjects.filter((id) => id !== ProjectId);
88+
}
89+
90+
// Update project's managedByUsers
91+
project.managedByUsers = managedByUsers;
92+
await project.save({ validateBeforeSave: false });
93+
94+
// Update user's managedProjects
95+
user.managedProjects = managedProjects;
96+
await user.save({ validateBeforeSave: false });
97+
98+
return res.status(200).send({ project, user });
99+
} catch (err) {
100+
console.log(err);
101+
return res.sendStatus(400);
102+
}
103+
};
104+
69105
module.exports = ProjectController;

backend/controllers/user.controller.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,4 +266,47 @@ UserController.logout = async function (req, res) {
266266
return res.clearCookie('token').status(200).send('Successfully logged out.');
267267
};
268268

269+
// Update user's managedProjects
270+
UserController.updateManagedProjects = async function (req, res) {
271+
const { headers } = req;
272+
const { UserId } = req.params;
273+
const { action, projectId } = req.body; // action - 'add' or 'remove'
274+
// console.log('action:', action, 'projectId:', projectId);
275+
276+
if (headers['x-customrequired-header'] !== expectedHeader) {
277+
return res.sendStatus(403);
278+
}
279+
280+
try {
281+
// Update user's managedProjects and the project's managedByUsers
282+
const user = await User.findById(UserId);
283+
let managedProjects = user.managedProjects || [];
284+
285+
const project = await Project.findById(projectId);
286+
let managedByUsers = project.managedByUsers || [];
287+
288+
if (action === 'add') {
289+
managedProjects = [...managedProjects, projectId];
290+
managedByUsers = [...managedByUsers, UserId];
291+
} else {
292+
// remove case
293+
managedProjects = managedProjects.filter((id) => id !== projectId);
294+
managedByUsers = managedByUsers.filter((id) => id !== UserId);
295+
}
296+
297+
// Update user's managedProjects
298+
user.managedProjects = managedProjects;
299+
await user.save({ validateBeforeSave: false });
300+
301+
// Update project's managedByUsers
302+
project.managedByUsers = managedByUsers;
303+
await project.save({ validateBeforeSave: false });
304+
305+
return res.status(200).send({ user, project });
306+
} catch (err) {
307+
console.log(err);
308+
return res.sendStatus(400);
309+
}
310+
};
311+
269312
module.exports = UserController;

backend/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
"start": "node server.js",
1212
"dev": "nodemon server.js",
1313
"client": "npm run start --prefix client",
14-
"heroku-postbuild": "cd client && npm install && npm run build"
14+
"heroku-postbuild": "cd client && npm install && npm run build",
15+
"clone-or-sync-projects": "node ./scripts/cloneOrSyncCollections.js",
16+
"clear-dev-collections": "node ./scripts/clearDevCollections.js"
1517
},
1618
"author": "sarL3y",
1719
"license": "ISC",

backend/routers/projects.router.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ router.get('/:ProjectId', ProjectController.project_by_id);
1616

1717
router.put('/:ProjectId', AuthUtil.verifyCookie, ProjectController.update);
1818

19-
router.patch('/:ProjectId', AuthUtil.verifyCookie, ProjectController.update);
19+
// Update project's managedByUsers in db
20+
router.patch('/:ProjectId', AuthUtil.verifyCookie, ProjectController.updateManagedByUsers);
2021

2122
module.exports = router;

backend/routers/projects.router.test.js

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ describe('Unit testing for Projects router', () => {
158158

159159
// Tests
160160
expect(ProjectController.create).toHaveBeenCalledWith(
161-
expect.objectContaining({ body: newProject }), // Check if newProject in body is parsed
161+
expect.objectContaining({ body: newProject }), // Check if newProject in body is parsed
162162
expect.anything(), // Mock response
163163
expect.anything(), // Mock next
164164
);
@@ -234,7 +234,7 @@ describe('Unit testing for Projects router', () => {
234234
});
235235

236236
const updatedProject = {
237-
id: '1',
237+
id: 'projectId1',
238238
name: 'updated project1',
239239
description: 'updated testing',
240240
githubIdentifier: 'gitHubTest3',
@@ -251,7 +251,7 @@ describe('Unit testing for Projects router', () => {
251251
lookingDescription: 'n/a',
252252
recruitingCategories: ['n/a'],
253253
partners: ['n/a'],
254-
managedByUsers: ['n/a'],
254+
managedByUsers: ['userId1'],
255255
};
256256

257257
const ProjectId = updatedProject.id;
@@ -274,7 +274,7 @@ describe('Unit testing for Projects router', () => {
274274

275275
// Tests
276276
expect(ProjectController.update).toHaveBeenCalledWith(
277-
expect.objectContaining({ params: { ProjectId }}), // Check if ProjectId is parsed from params
277+
expect.objectContaining({ params: { ProjectId } }), // Check if ProjectId is parsed from params
278278
expect.anything(), // Mock response
279279
expect.anything(), // Mock next
280280
);
@@ -284,5 +284,85 @@ describe('Unit testing for Projects router', () => {
284284
// Marks completion of tests
285285
done();
286286
});
287+
288+
const updatedUser = {
289+
id: 'userId1',
290+
name: 'Updated User',
291+
email: 'mockuser@example.com',
292+
managedProjects: ['projectId1'],
293+
};
294+
295+
const userId = updatedUser.id;
296+
297+
it("should add to the project's managedByUsers and the user's managedProjects fields with PATCH /api/projects/:ProjectId", async (done) => {
298+
// Mock ProjectController.updateManagedByUsers method when this route is called
299+
ProjectController.updateManagedByUsers.mockImplementationOnce((req, res) => {
300+
res.status(200).send({ project: updatedProject, user: updatedUser });
301+
});
302+
303+
// Mock PUT API call
304+
const response = await request
305+
.patch(`/api/projects/${ProjectId}`)
306+
.send({ action: 'add', userId });
307+
308+
// Middlware assertions
309+
expect(mockVerifyCookie).toHaveBeenCalledWith(
310+
expect.any(Object),
311+
expect.any(Object),
312+
expect.any(Function),
313+
);
314+
315+
// Tests
316+
expect(ProjectController.updateManagedByUsers).toHaveBeenCalledWith(
317+
expect.objectContaining({
318+
params: { ProjectId },
319+
body: { action: 'add', userId },
320+
}), // Check if ProjectId is parsed from params
321+
expect.anything(), // Mock response
322+
expect.anything(), // Mock next
323+
);
324+
expect(response.status).toBe(200);
325+
expect(response.body).toEqual({ project: updatedProject, user: updatedUser });
326+
327+
// Marks completion of tests
328+
done();
329+
});
330+
331+
it("should remove user from the project's managedByUsers and remove project from the user's managedProjects fields with PATCH /api/projects/:ProjectId", async (done) => {
332+
updatedProject.managedByUsers = [];
333+
updatedUser.managedProjects = [];
334+
335+
// Mock ProjectController.updateManagedByUsers method when this route is called
336+
ProjectController.updateManagedByUsers.mockImplementationOnce((req, res) => {
337+
res.status(200).send({ project: updatedProject, user: updatedUser });
338+
});
339+
340+
// Mock PUT API call
341+
const response = await request
342+
.patch(`/api/projects/${ProjectId}`)
343+
.send({ action: 'remove', userId });
344+
345+
// Middlware assertions
346+
expect(mockVerifyCookie).toHaveBeenCalledWith(
347+
expect.any(Object),
348+
expect.any(Object),
349+
expect.any(Function),
350+
);
351+
352+
// Tests
353+
expect(ProjectController.updateManagedByUsers).toHaveBeenCalledWith(
354+
expect.objectContaining({
355+
params: { ProjectId },
356+
body: { action: 'remove', userId },
357+
}), // Check if ProjectId is parsed from params
358+
expect.anything(), // Mock response
359+
expect.anything(), // Mock next
360+
);
361+
expect(response.status).toBe(200);
362+
expect(response.body).toEqual({ project: updatedProject, user: updatedUser });
363+
364+
// Marks completion of tests
365+
done();
366+
});
287367
});
288368
});

backend/routers/users.router.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ router.get('/:UserId', UserController.user_by_id);
1616

1717
router.patch('/:UserId', UserController.update);
1818

19+
// Update user projects in db
20+
router.patch('/:UserId/managedProjects', UserController.updateManagedProjects);
21+
1922
router.delete('/:UserId', UserController.delete);
2023

2124
module.exports = router;

0 commit comments

Comments
 (0)