diff --git a/src/controllers/taskController.js b/src/controllers/taskController.js index 42e4860a0..b6768ca2b 100644 --- a/src/controllers/taskController.js +++ b/src/controllers/taskController.js @@ -13,7 +13,24 @@ const followUp = require('../models/followUp'); const logger = require('../startup/logger'); const taskController = function (Task) { - const getTasks = (req, res) => { + const canSeeTaskExtensionCount = async (requestor) => + (await hasPermission(requestor, 'seeNumberOfTimesTimeAdded')) || + (await hasPermission(requestor, 'viewTaskExtensionCount')); + + const removeTaskExtensionCounts = (value) => { + if (Array.isArray(value)) { + value.forEach(removeTaskExtensionCounts); + return value; + } + if (value && typeof value === 'object') { + if (Object.prototype.hasOwnProperty.call(value, 'deadlineCount')) { + delete value.deadlineCount; + } + Object.values(value).forEach(removeTaskExtensionCounts); + } + return value; + }; + const getTasks = async (req, res) => { const { level } = req.params; let query = { @@ -32,19 +49,25 @@ const taskController = function (Task) { }; } - Task.find(query) - .populate('createdBy', 'firstName lastName email') // <-- added - .lean() - .then((results) => { - const withCreator = results.map((t) => ({ - ...t, - creatorName: t.createdBy - ? [t.createdBy.firstName, t.createdBy.lastName].filter(Boolean).join(' ').trim() - : undefined, - })); - return res.status(200).send(withCreator); - }) - .catch((error) => res.status(404).send(error)); + try { + const results = await Task.find(query) + .populate('createdBy', 'firstName lastName email') + .lean(); + + const withCreator = results.map((t) => ({ + ...t, + creatorName: t.createdBy + ? [t.createdBy.firstName, t.createdBy.lastName].filter(Boolean).join(' ').trim() + : undefined, + })); + + const canSeeCount = await canSeeTaskExtensionCount(req.body.requestor); + return res + .status(200) + .send(canSeeCount ? withCreator : removeTaskExtensionCounts(withCreator)); + } catch (error) { + return res.status(404).send(error); + } }; const getWBSId = (req, res) => { @@ -1071,6 +1094,9 @@ const taskController = function (Task) { resource.name = resourceNames[index] !== ' ' ? resourceNames[index] : resource.name; }); + const canSeeCount = await canSeeTaskExtensionCount(req.body.requestor); + if (!canSeeCount) removeTaskExtensionCounts(task); + return res.status(200).send(task); } catch (error) { return res.status(500).send({ error: 'Internal Server Error', details: error.message }); @@ -1267,12 +1293,16 @@ const taskController = function (Task) { if (teamsData && teamsData.length > 0) { await attachCreatorNames(teamsData); - return res.status(200).send(teamsData); + const canSeeCount = await canSeeTaskExtensionCount(req.body.requestor); + return res.status(200).send(canSeeCount ? teamsData : removeTaskExtensionCounts(teamsData)); } const singleUserData = await taskHelper.getTasksForSingleUser(userId).exec(); await attachCreatorNames(singleUserData); - return res.status(200).send(singleUserData); + const canSeeCount = await canSeeTaskExtensionCount(req.body.requestor); + return res + .status(200) + .send(canSeeCount ? singleUserData : removeTaskExtensionCounts(singleUserData)); } catch (error) { console.log(error); return res.status(400).send({ error }); diff --git a/src/controllers/taskController.spec.js b/src/controllers/taskController.spec.js index 87f12be53..bf93c4254 100644 --- a/src/controllers/taskController.spec.js +++ b/src/controllers/taskController.spec.js @@ -145,6 +145,22 @@ describe('Unit Tests for taskController.js', () => { expect(taskFindSpy).toHaveBeenCalled(); expect(taskFindSpy).toHaveBeenCalledTimes(1); }); + + test('Hides deadlineCount when the user lacks task extension count permission', async () => { + const { getTasks } = makeSut(); + const mockData = [{ _id: '1', taskName: 'A', deadlineCount: 5, createdBy: null }]; + const chain = makeFindChain({ data: mockData }); + jest.spyOn(Task, 'find').mockReturnValueOnce(chain); + hasPermission.mockResolvedValue(false); + + const response = await getTasks(mockReq, mockRes); + await flushPromises(); + + const expected = mockData.map((t) => ({ ...t, creatorName: undefined })); + delete expected[0].deadlineCount; + assertResMock(200, expected, response, mockRes); + expect(chain.populate).toHaveBeenCalled(); + }); }); describe('getWBSId function', () => { diff --git a/src/test/createTestPermissions.js b/src/test/createTestPermissions.js index 15c47eea7..a2342f7fe 100644 --- a/src/test/createTestPermissions.js +++ b/src/test/createTestPermissions.js @@ -30,6 +30,7 @@ const permissionsRoles = [ 'swapTask', 'deleteTask', 'viewTaskExtensionCount', // to view task extension count + 'seeNumberOfTimesTimeAdded', 'updateNum', // Teams 'postTeam', @@ -189,6 +190,7 @@ const permissionsRoles = [ 'importTask', 'postTask', 'viewTaskExtensionCount', // to view task extension count + 'seeNumberOfTimesTimeAdded', 'updateNum', 'updateTask', 'swapTask', diff --git a/src/utilities/createInitialPermissions.js b/src/utilities/createInitialPermissions.js index ab29f185d..c3b2409db 100644 --- a/src/utilities/createInitialPermissions.js +++ b/src/utilities/createInitialPermissions.js @@ -32,6 +32,7 @@ const permissionsRoles = [ 'swapTask', 'deleteTask', 'viewTaskExtensionCount', // to view task extension count + 'seeNumberOfTimesTimeAdded', 'updateNum', // Teams 'postTeam', @@ -225,6 +226,7 @@ const permissionsRoles = [ 'importTask', 'postTask', 'viewTaskExtensionCount', // to view task extension count + 'seeNumberOfTimesTimeAdded', 'updateNum', 'updateTask', 'swapTask',