Skip to content

Commit 541e1f1

Browse files
Ajeyakrishna-kyesyashprakashchoudhary07
authored
Modifies api to reject task requests (#1696)
* feat : adds function to reject task requests * feat : adds tests and minor changes in validation * chore : rename and add jsdoc for models function * chore : update comment * refactor: rename variables * Update models/taskRequests.js Co-authored-by: Yash Raj <[email protected]> * chore: rename variable * fix: remove stubs in integration tests --------- Co-authored-by: Yash Raj <[email protected]> Co-authored-by: Prakash Choudhary <[email protected]>
1 parent 6318b9a commit 541e1f1

File tree

7 files changed

+480
-38
lines changed

7 files changed

+480
-38
lines changed

constants/taskRequests.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ const TASK_REQUEST_STATUS = {
44
PENDING: "PENDING",
55
DENIED: "DENIED",
66
};
7+
8+
const TASK_REQUEST_ACTIONS = {
9+
APPROVE: "approve",
10+
REJECT: "reject",
11+
};
712
const TASK_REQUEST_ERROR_MESSAGE = {
813
INVALID_PREV: "Invalid 'prev' value",
914
INVALID_NEXT: "Invalid 'next' value",
@@ -44,5 +49,6 @@ module.exports = {
4449
TASK_REQUEST_SORT_KEYS,
4550
TASK_REQUEST_ERROR_MESSAGE,
4651
TASK_REQUEST_SORT_VALUES,
47-
MIGRATION_TYPE
48-
};
52+
MIGRATION_TYPE,
53+
TASK_REQUEST_ACTIONS,
54+
};

controllers/tasksRequests.js

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const { INTERNAL_SERVER_ERROR, SOMETHING_WENT_WRONG } = require("../constants/errorMessages");
2-
const { TASK_REQUEST_TYPE, MIGRATION_TYPE } = require("../constants/taskRequests");
2+
const { TASK_REQUEST_TYPE, MIGRATION_TYPE, TASK_REQUEST_ACTIONS } = require("../constants/taskRequests");
33
const { addLog } = require("../models/logs");
44
const taskRequestsModel = require("../models/taskRequests");
55
const tasksModel = require("../models/tasks.js");
@@ -97,7 +97,7 @@ const addTaskRequests = async (req, res) => {
9797
break;
9898
}
9999
}
100-
const newTaskRequest = await taskRequestsModel.createRequest(taskRequestData, req.userData.username);
100+
const newTaskRequest = await taskRequestsModel.createRequest(taskRequestData, req.userData.id);
101101

102102
if (newTaskRequest.isCreationRequestApproved) {
103103
return res.boom.conflict("Task exists for the given issue.");
@@ -111,9 +111,9 @@ const addTaskRequests = async (req, res) => {
111111
meta: {
112112
taskRequestId: newTaskRequest.id,
113113
action: "create",
114-
createdBy: req.userData.username,
114+
createdBy: req.userData.id,
115115
createdAt: Date.now(),
116-
lastModifiedBy: req.userData.username,
116+
lastModifiedBy: req.userData.id,
117117
lastModifiedAt: Date.now(),
118118
},
119119
body: newTaskRequest.taskRequest,
@@ -169,45 +169,62 @@ const addOrUpdate = async (req, res) => {
169169
}
170170
};
171171

172-
const approveTaskRequest = async (req, res) => {
172+
const updateTaskRequests = async (req, res) => {
173173
try {
174174
const { taskRequestId, user } = req.body;
175175
if (!taskRequestId) {
176176
return res.boom.badRequest("taskRequestId not provided");
177177
}
178178

179-
const response = await taskRequestsModel.approveTaskRequest(taskRequestId, user);
179+
const { action = TASK_REQUEST_ACTIONS.APPROVE } = req.query;
180180

181-
if (response.taskRequestNotFound) {
181+
let updateTaskRequestResponse = {};
182+
switch (action) {
183+
case TASK_REQUEST_ACTIONS.APPROVE: {
184+
updateTaskRequestResponse = await taskRequestsModel.approveTaskRequest(taskRequestId, user, req.userData.id);
185+
break;
186+
}
187+
case TASK_REQUEST_ACTIONS.REJECT: {
188+
updateTaskRequestResponse = await taskRequestsModel.rejectTaskRequest(taskRequestId, req.userData.id);
189+
break;
190+
}
191+
default: {
192+
return res.boom.badRequest("Unknown action");
193+
}
194+
}
195+
196+
if (updateTaskRequestResponse.taskRequestNotFound) {
182197
return res.boom.badRequest("Task request not found.");
183198
}
184-
if (response.isUserInvalid) {
199+
if (updateTaskRequestResponse.isUserInvalid) {
185200
return res.boom.badRequest("User request not available.");
186201
}
187-
if (response.isTaskRequestInvalid) {
202+
if (updateTaskRequestResponse.isTaskRequestInvalid) {
188203
return res.boom.badRequest("Task request was previously approved or rejected.");
189204
}
190205

191-
await updateUserStatusOnTaskUpdate(user.username);
206+
if (action && action === TASK_REQUEST_ACTIONS.APPROVE) {
207+
await updateUserStatusOnTaskUpdate(user.username);
208+
}
192209

193210
const taskRequestLog = {
194211
type: "taskRequests",
195212
meta: {
196213
taskRequestId: taskRequestId,
197214
action: "update",
198-
subAction: "approve",
199-
createdBy: req.userData.username,
215+
subAction: action,
216+
createdBy: req.userData.id,
200217
createdAt: Date.now(),
201-
lastModifiedBy: req.userData.username,
218+
lastModifiedBy: req.userData.id,
202219
lastModifiedAt: Date.now(),
203220
},
204-
body: response.taskRequest,
221+
body: updateTaskRequestResponse.taskRequest,
205222
};
206223
await addLog(taskRequestLog.type, taskRequestLog.meta, taskRequestLog.body);
207224

208225
return res.status(200).json({
209-
message: `Task successfully assigned to user ${response.approvedTo}`,
210-
taskRequest: response.taskRequest,
226+
message: `Task updated successfully.`,
227+
taskRequest: updateTaskRequestResponse?.taskRequest,
211228
});
212229
} catch (err) {
213230
logger.error("Error while approving task request", err);
@@ -239,7 +256,7 @@ const migrateTaskRequests = async (req, res) => {
239256
}
240257
};
241258
module.exports = {
242-
approveTaskRequest,
259+
updateTaskRequests,
243260
addOrUpdate,
244261
fetchTaskRequests,
245262
fetchTaskRequestById,

middlewares/taskRequests.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
const { SOMETHING_WENT_WRONG } = require("../constants/errorMessages");
22
const dataAccess = require("../services/dataAccessLayer");
3+
const { TASK_REQUEST_ACTIONS } = require("../constants/taskRequests");
34
/**
45
* Validates user id for task request
56
*
67
* @param userId { string }: user id of the user
78
*/
89
async function validateUser(req, res, next) {
910
try {
11+
const { action } = req.query;
12+
if (action === TASK_REQUEST_ACTIONS.REJECT) {
13+
return next();
14+
}
1015
const { userId } = req.body;
1116

1217
if (!userId) {

models/taskRequests.js

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,28 @@ const fetchTaskRequestById = async (taskRequestId) => {
187187
};
188188
};
189189

190-
const createRequest = async (data, authenticatedUsername) => {
190+
/**
191+
* Creates a task request with user details.
192+
*
193+
* @param {Object} data - The data for creating the task request.
194+
* @param {string} data.userId - The ID of the user to whom the task request is being created.
195+
* @param {string} data.proposedDeadline - The proposed deadline for the task.
196+
* @param {string} data.proposedStartDate - The proposed start date for the task.
197+
* @param {string} data.description - The description of the task request.
198+
* @param {string} data.taskTitle - The title of the task.
199+
* @param {string} data.taskId - The ID of the task (optional).
200+
* @param {string} data.externalIssueUrl - The external issue URL (optional).
201+
* @param {string} data.requestType - The type of the task request (CREATION | ASSIGNMENT).
202+
* @param {string} authorUserId - The ID of the authenticated user creating the request.
203+
* @returns {Promise<{
204+
* isCreationRequestApproved: boolean | undefined,
205+
* alreadyRequesting: boolean | undefined,
206+
* id: string,
207+
* isCreate: boolean,
208+
* taskRequest: Object,
209+
* }>}
210+
*/
211+
const createRequest = async (data, authorUserId) => {
191212
try {
192213
const queryFieldPath = data.requestType === TASK_REQUEST_TYPE.CREATION ? "externalIssueUrl" : "taskId";
193214
const queryValue = data.requestType === TASK_REQUEST_TYPE.CREATION ? data.externalIssueUrl : data.taskId;
@@ -233,7 +254,7 @@ const createRequest = async (data, authenticatedUsername) => {
233254
const updatedTaskRequest = {
234255
requestors: updatedRequestors,
235256
users: updatedUsers,
236-
lastModifiedBy: authenticatedUsername,
257+
lastModifiedBy: authorUserId,
237258
lastModifiedAt: Date.now(),
238259
};
239260
await taskRequestsCollection.doc(taskRequestRef.id).update(updatedTaskRequest);
@@ -254,9 +275,9 @@ const createRequest = async (data, authenticatedUsername) => {
254275
externalIssueUrl: data.externalIssueUrl,
255276
requestType: data.requestType,
256277
users: [userRequest],
257-
createdBy: authenticatedUsername,
278+
createdBy: authorUserId,
258279
createdAt: Date.now(),
259-
lastModifiedBy: authenticatedUsername,
280+
lastModifiedBy: authorUserId,
260281
lastModifiedAt: Date.now(),
261282
};
262283
if (!newTaskRequest.externalIssueUrl) delete newTaskRequest.externalIssueUrl;
@@ -321,13 +342,20 @@ const addOrUpdate = async (taskId, userId) => {
321342
};
322343

323344
/**
324-
* Approves task request to user
345+
* Approve task request for a user.
325346
*
326-
* @param taskRequestId { string }: id of task request
327-
* @param userId { Object }: user whose being approved
328-
* @return {Promise<{approvedTo: string, taskRequest: Object}>}
347+
* @param {string} taskRequestId - The ID of the task request.
348+
* @param {Object} user - The user to whom the task request is being approved.
349+
* @param {string} authorUserId - The ID of the authenticated user performing the approval.
350+
* @returns {Promise<{
351+
* approvedTo: string,
352+
* taskRequest: Object,
353+
* taskRequestNotFound: boolean | undefined
354+
* isUserInvalid: boolean | undefined
355+
* isTaskRequestInvalid: boolean | undefined
356+
* }>}
329357
*/
330-
const approveTaskRequest = async (taskRequestId, user) => {
358+
const approveTaskRequest = async (taskRequestId, user, authorUserId) => {
331359
try {
332360
return await firestore.runTransaction(async (transaction) => {
333361
const taskRequestDocRef = taskRequestsCollection.doc(taskRequestId);
@@ -364,6 +392,8 @@ const approveTaskRequest = async (taskRequestId, user) => {
364392
users: taskRequestData.users,
365393
approvedTo: user.id,
366394
status: TASK_REQUEST_STATUS.APPROVED,
395+
lastModifiedBy: authorUserId,
396+
lastModifiedAt: Date.now(),
367397
};
368398
// End of TODO
369399
const updateTaskRequestPromise = transaction.update(taskRequestDocRef, updatedTaskRequest);
@@ -397,6 +427,8 @@ const approveTaskRequest = async (taskRequestId, user) => {
397427
const updatedTaskRequest = {
398428
approvedTo: user.id,
399429
status: TASK_REQUEST_STATUS.APPROVED,
430+
lastModifiedBy: authorUserId,
431+
lastModifiedAt: Date.now(),
400432
};
401433
let userRequestData;
402434
if (taskRequestData.users) {
@@ -435,6 +467,38 @@ const approveTaskRequest = async (taskRequestId, user) => {
435467
}
436468
};
437469

470+
/**
471+
* Rejects a task request.
472+
*
473+
* @param {string} taskRequestId - The ID of the task request.
474+
* @param {string} authorUserId - The ID of the authenticated or logged in user performing the rejection.
475+
* @returns {Promise<{taskRequest: Object
476+
* taskRequestNotFound: boolean | undefined
477+
* isTaskRequestInvalid: boolean | undefined
478+
* }>}
479+
*/
480+
const rejectTaskRequest = async (taskRequestId, authorUserId) => {
481+
const taskRequestDoc = taskRequestsCollection.doc(taskRequestId);
482+
const taskRequestData = (await taskRequestDoc.get()).data();
483+
if (!taskRequestData) {
484+
return { taskRequestNotFound: true };
485+
}
486+
487+
if (
488+
taskRequestData.status === TASK_REQUEST_STATUS.APPROVED ||
489+
taskRequestData.status === TASK_REQUEST_STATUS.DENIED
490+
) {
491+
return { isTaskRequestInvalid: true };
492+
}
493+
const updatedTaskRequest = {
494+
status: TASK_REQUEST_STATUS.DENIED,
495+
lastModifiedBy: authorUserId,
496+
lastModifiedAt: Date.now(),
497+
};
498+
await taskRequestDoc.update(updatedTaskRequest);
499+
return { taskRequest: { ...taskRequestData, ...updatedTaskRequest } };
500+
};
501+
438502
const addNewFields = async () => {
439503
const taskRequestsSnapshots = (await taskRequestsCollection.get()).docs;
440504

@@ -506,4 +570,5 @@ module.exports = {
506570
fetchPaginatedTaskRequests,
507571
addNewFields,
508572
removeOldField,
573+
rejectTaskRequest,
509574
};

routes/taskRequests.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ const validators = require("../middlewares/validators/task-requests");
1010
router.get("/", authenticate, taskRequests.fetchTaskRequests);
1111
router.get("/:id", authenticate, taskRequests.fetchTaskRequestById);
1212
router.post("/addOrUpdate", authenticate, validateUser, taskRequests.addOrUpdate);
13-
router.patch("/approve", authenticate, authorizeRoles([SUPERUSER]), validateUser, taskRequests.approveTaskRequest);
13+
router.patch("/approve", authenticate, authorizeRoles([SUPERUSER]), validateUser, taskRequests.updateTaskRequests);
14+
router.patch("/", authenticate, authorizeRoles([SUPERUSER]), validateUser, taskRequests.updateTaskRequests);
1415
router.post("/", authenticate, validators.postTaskRequests, taskRequests.addTaskRequests);
1516
router.post("/migrations", authenticate, authorizeRoles([SUPERUSER]), taskRequests.migrateTaskRequests);
1617

0 commit comments

Comments
 (0)