Skip to content

Commit

Permalink
add: one-time script to filter unfinished tasks from archived users. (#…
Browse files Browse the repository at this point in the history
…2040)

* add: one-time script to filter unfinished tasks from archived users.

* fix: remove verified status as done

---------

Co-authored-by: Amit Prakash <[email protected]>
  • Loading branch information
MehulKChaudhari and iamitprakash authored May 16, 2024
1 parent 23c956e commit 28bce3d
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 45 deletions.
4 changes: 1 addition & 3 deletions controllers/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -491,9 +491,7 @@ const updateStatus = async (req, res) => {

const orphanTasks = async (req, res) => {
try {
const { lastOrphanTasksFilterationTimestamp = 0 } = req.body;

const updatedTasksData = await tasks.updateOrphanTasksStatus(lastOrphanTasksFilterationTimestamp);
const updatedTasksData = await tasks.updateOrphanTasksStatus();

return res.status(200).json({ message: "Orphan tasks filtered successfully", updatedTasksData });
} catch (error) {
Expand Down
24 changes: 10 additions & 14 deletions models/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -648,33 +648,29 @@ const updateTaskStatus = async () => {
}
};

const updateOrphanTasksStatus = async (lastOrphanTasksFilterationTimestamp) => {
const lastTimestamp = Number(lastOrphanTasksFilterationTimestamp);
const updateOrphanTasksStatus = async () => {
try {
const users = [];
const currentTimeStamp = Date.now();

const usersQuerySnapshot = await userModel
.where("roles.in_discord", "==", false)
.where("updated_at", ">=", lastTimestamp)
.where("updated_at", "<=", currentTimeStamp)
.get();
const batch = firestore.batch();
const usersQuerySnapshot = await userModel.where("roles.in_discord", "==", false).get();

usersQuerySnapshot.forEach((user) => users.push({ ...user.data(), id: user.id }));

let orphanTasksUpdatedCount = 0;

for (const user of users) {
const tasksQuerySnapshot = await tasksModel
.where("assigneeId", "==", user.id)
.where("status", "not-in", [COMPLETED, BACKLOG])
.where("assignee", "==", user.id)
.where("status", "not-in", [BACKLOG, COMPLETED, DONE])
.get();
tasksQuerySnapshot.forEach(async (taskDoc) => {
tasksQuerySnapshot.forEach((taskDoc) => {
orphanTasksUpdatedCount++;
await tasksModel.doc(taskDoc.id).update({ status: BACKLOG });
const taskRef = tasksModel.doc(taskDoc.id);
batch.update(taskRef, { status: BACKLOG, updated_at: Date.now() });
});
}

await batch.commit();
return { orphanTasksUpdatedCount };
} catch (error) {
logger.error("Error marking tasks as backlog:", error);
Expand All @@ -691,7 +687,7 @@ const markUnDoneTasksOfArchivedUsersBacklog = async (users) => {
.where("assignee", "==", user.id)
.where("status", "not-in", [COMPLETED, DONE, BACKLOG])
.get();
tasksQuerySnapshot.forEach(async (taskDoc) => {
tasksQuerySnapshot.forEach((taskDoc) => {
orphanTasksUpdatedCount++;
const taskRef = tasksModel.doc(taskDoc.id);
batch.update(taskRef, { status: BACKLOG, updated_at: Date.now() });
Expand Down
3 changes: 1 addition & 2 deletions routes/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const {
updateSelfTask,
getTasksValidator,
getUsersValidator,
filterOrphanTasksValidator,
} = require("../middlewares/validators/tasks");
const authorizeRoles = require("../middlewares/authorizeRoles");
const { authorizeAndAuthenticate } = require("../middlewares/authorizeUsersAndService");
Expand Down Expand Up @@ -68,6 +67,6 @@ router.patch("/assign/self", authenticate, invalidateCache({ invalidationKeys: [
router.get("/users/discord", verifyCronJob, getUsersValidator, tasks.getUsersHandler);

router.post("/migration", authenticate, authorizeRoles([SUPERUSER]), tasks.updateStatus);
router.post("/orphanTasks", verifyCronJob, filterOrphanTasksValidator, tasks.orphanTasks);
router.post("/orphanTasks", authenticate, authorizeRoles([SUPERUSER]), tasks.orphanTasks);

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
authorization
, but is not rate-limited.
This route handler performs
authorization
, but is not rate-limited.
This route handler performs
authorization
, but is not rate-limited.

module.exports = router;
46 changes: 20 additions & 26 deletions test/integration/tasks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1573,66 +1573,60 @@ describe("Tasks", function () {
});

describe("POST /tasks/orphanTasks", function () {
let jwtToken;

beforeEach(async function () {
const superUserId = await addUser(superUser);
superUserJwt = authService.generateAuthToken({ userId: superUserId });
const user1 = userData[6];
user1.roles.in_discord = false;
user1.updated_at = 1712053284000;
const user2 = userData[18];
user2.updated_at = 1712064084000;
user2.roles.in_discord = false;
const [{ id: userId }, { id: userId2 }] = await Promise.all([userDBModel.add(user1), userDBModel.add(user2)]);

const task1 = {
assigneeId: userId,
assignee: userId,
status: "ACTIVE",
};
const task2 = {
assigneeId: userId2,
assignee: userId2,
status: "COMPLETED",
};
const task3 = {
assigneeId: userId2,
assignee: userId2,
status: "IN_PROGRESS",
};
await Promise.all([tasksModel.add(task1), tasksModel.add(task2), tasksModel.add(task3)]);

jwtToken = generateCronJobToken({ name: CRON_JOB_HANDLER });
const task4 = {
assignee: userId,
status: "DONE",
};
await Promise.all([tasksModel.add(task1), tasksModel.add(task2), tasksModel.add(task3), tasksModel.add(task4)]);
});

afterEach(async function () {
await cleanDb();
});
it("Should update status of orphan tasks to BACKLOG", async function () {
const res = await chai.request(app).post("/tasks/orphanTasks").set("Authorization", `Bearer ${jwtToken}`).send({
lastOrphanTasksFilterationTimestamp: 1712040715000,
});

it("Should update status of orphan tasks to BACKLOG", async function () {
const res = await chai.request(app).post("/tasks/orphanTasks").set("cookie", `${cookieName}=${superUserJwt}`);
expect(res).to.have.status(200);
expect(res.body).to.deep.equal({
message: "Orphan tasks filtered successfully",
updatedTasksData: {
orphanTasksUpdatedCount: 2,
},
});
}).timeout(10000);
});

it("Should return 400 if not cron worker", async function () {
it("Should return 400 if not super user", async function () {
const nonSuperUserId = await addUser(appOwner);
const nonSuperUserJwt = authService.generateAuthToken({ userId: nonSuperUserId });
const res = await chai
.request(app)
.post("/tasks/orphanTasks")
.set("Authorization", `Bearer ${nonSuperUserJwt}`)
.send({
lastOrphanTasksFilterationTimestamp: 1712040715000,
});
const res = await chai.request(app).post("/tasks/orphanTasks").set("Authorization", `Bearer ${nonSuperUserJwt}`);

expect(res).to.have.status(400);
expect(res).to.have.status(401);
expect(res.body).to.deep.equal({
statusCode: 400,
error: "Bad Request",
message: "Unauthorized Cron Worker",
statusCode: 401,
error: "Unauthorized",
message: "You are not authorized for this action.",
});
});
});
Expand Down

0 comments on commit 28bce3d

Please sign in to comment.