Skip to content

Commit

Permalink
Merge branch 'develop' into feat-debug
Browse files Browse the repository at this point in the history
  • Loading branch information
vinit717 authored Aug 30, 2024
2 parents fdaabe5 + 6c33d2a commit d5fc0cc
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 138 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- [About the Project](#about-the-project)
- [Running the Project](#running-the-project)
- [Prerequisites](#prerequisites)
- [API Documentation](#api-documentation)
- [API Documentation](https://github.com/Real-Dev-Squad/website-api-contracts/)
- [CONTRIBUTING](CONTRIBUTING.md)

## About the Project
Expand Down
11 changes: 0 additions & 11 deletions controllers/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,6 @@ const { API_RESPONSE_MESSAGES } = require("../constants/application");
const { getUserApplicationObject } = require("../utils/application");
const admin = require("firebase-admin");

const batchUpdateApplications = async (req: CustomRequest, res: CustomResponse): Promise<any> => {
try {
const updateStats = await ApplicationModel.batchUpdateApplications();
return res.json(updateStats);
} catch (err) {
logger.error(`Error in batch updating application: ${err}`);
return res.boom.badImplementation(INTERNAL_SERVER_ERROR);
}
};

const getAllOrUserApplication = async (req: CustomRequest, res: CustomResponse): Promise<any> => {
try {
const { userId, status, next, size } = req.query;
Expand Down Expand Up @@ -154,5 +144,4 @@ module.exports = {
addApplication,
updateApplication,
getApplicationById,
batchUpdateApplications,
};
2 changes: 1 addition & 1 deletion controllers/external-accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const linkExternalAccount = async (req, res) => {

await addOrUpdate(
{
roles: { ...roles, in_discord: true },
roles: { ...roles, in_discord: true, archived: false },
discordId: attributes.discordId,
discordJoinedAt: attributes.discordJoinedAt,
},
Expand Down
2 changes: 1 addition & 1 deletion controllers/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ const updateSelf = async (req, res) => {
}
}

if (userRoles.in_discord) {
if (userRoles.in_discord && !user.incompleteUserDetails) {
const membersInDiscord = await getDiscordMembers();
const discordMember = membersInDiscord.find((member) => member.user.id === discordId);
if (discordMember) {
Expand Down
65 changes: 55 additions & 10 deletions middlewares/checkCanGenerateDiscordLink.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,73 @@
import { NextFunction } from "express";
import { CustomRequest, CustomResponse } from "../types/global";
const ApplicationModel = require("../models/applications");

const checkCanGenerateDiscordLink = async (req: CustomRequest, res: CustomResponse, next: NextFunction) => {
const { discordId, roles, id: userId, profileStatus } = req.userData;
const { id: userId, roles } = req.userData;
const isSuperUser = roles.super_user;
const userIdInQuery = req.query.userId;
const currentTime = Date.now();
const cutoffTime = 1725147849000; // Todo will remove this Hotfix time for 31 August 2024

if (isSuperUser) {
return next();
}

if (userIdInQuery && userIdInQuery !== userId && !isSuperUser) {
return res.boom.forbidden("User should be super user to generate link for other users");
}

if (!isSuperUser && discordId) {
return res.boom.forbidden("Only users who have never joined discord can generate invite link");
if (currentTime >= cutoffTime) {
return res.boom.forbidden("Discord invite link generation is not allowed after the cutoff time.");
}

if (roles.archived) {
return res.boom.forbidden("Archived users cannot generate invite");
}
try {
const applications = await ApplicationModel.getUserApplications(userId);

if (!applications || applications.length === 0) {
return res.boom.forbidden("No applications found.");
}

if (!isSuperUser && !roles.maven && !roles.designer && !roles.product_manager && profileStatus !== "VERIFIED") {
return res.boom.forbidden("Only selected roles can generate discord link directly");
}
const approvedApplication = applications.find((application: { status: string; }) => application.status === 'accepted');

if (!approvedApplication) {
return res.boom.forbidden("Only users with an approved application can generate a Discord invite link.");
}

return next();
return next();
} catch (error) {
return res.boom.badImplementation("An error occurred while checking user applications.");
}
};

export default checkCanGenerateDiscordLink;

// <------ We have to revisit this later ------->
// <--- https://github.com/Real-Dev-Squad/website-backend/issues/2078 --->


// const checkCanGenerateDiscordLink = async (req: CustomRequest, res: CustomResponse, next: NextFunction) => {
// const { discordId, roles, id: userId, profileStatus } = req.userData;
// const isSuperUser = roles.super_user;
// const userIdInQuery = req.query.userId;

// if (userIdInQuery && userIdInQuery !== userId && !isSuperUser) {
// return res.boom.forbidden("User should be super user to generate link for other users");
// }

// if (!isSuperUser && discordId) {
// return res.boom.forbidden("Only users who have never joined discord can generate invite link");
// }

// if (roles.archived) {
// return res.boom.forbidden("Archived users cannot generate invite");
// }

// if (!isSuperUser && !roles.maven && !roles.designer && !roles.product_manager && profileStatus !== "VERIFIED") {
// return res.boom.forbidden("Only selected roles can generate discord link directly");
// }

// return next();
// };

module.exports = checkCanGenerateDiscordLink;
53 changes: 1 addition & 52 deletions models/applications.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,6 @@
import { application } from "../types/application";
const firestore = require("../utils/firestore");
const ApplicationsModel = firestore.collection("applicants");
const { DOCUMENT_WRITE_SIZE: FIRESTORE_BATCH_OPERATIONS_LIMIT } = require("../constants/constants");
import { chunks } from "../utils/array";

const batchUpdateApplications = async () => {
try {
const operationStats = {
failedApplicationUpdateIds: [],
totalFailedApplicationUpdates: 0,
totalApplicationUpdates: 0,
};

const updatedApplications = [];
const applications = await ApplicationsModel.get();

if (applications.empty) {
return operationStats;
}

operationStats.totalApplicationUpdates = applications.size;

applications.forEach((application) => {
const taskData = application.data();
taskData.createdAt = null;
updatedApplications.push({ id: application.id, data: taskData });
});

const multipleApplicationUpdateBatch = [];
const chunkedApplication = chunks(updatedApplications, FIRESTORE_BATCH_OPERATIONS_LIMIT);

chunkedApplication.forEach(async (applications) => {
const batch = firestore.batch();
applications.forEach(({ id, data }) => {
batch.update(ApplicationsModel.doc(id), data);
});
try {
await batch.commit();
multipleApplicationUpdateBatch.push(batch);
} catch (error) {
operationStats.totalFailedApplicationUpdates += applications.length;
applications.forEach(({ id }) => operationStats.failedApplicationUpdateIds.push(id));
}
});

await Promise.allSettled(multipleApplicationUpdateBatch);
return operationStats;
} catch (err) {
logger.log("Error in batch update", err);
throw err;
}
};

const getAllApplications = async (limit: number, lastDocId?: string) => {
try {
Expand Down Expand Up @@ -114,7 +64,7 @@ const getApplicationsBasedOnStatus = async (status: string, limit: number, lastD
lastDoc = await ApplicationsModel.doc(lastDocId).get();
}

dbQuery = dbQuery.orderBy("createdAt", "desc");
dbQuery = dbQuery.orderBy("createdAt", "desc");

if (lastDoc) {
dbQuery = dbQuery.startAfter(lastDoc);
Expand Down Expand Up @@ -182,5 +132,4 @@ module.exports = {
updateApplication,
getApplicationsBasedOnStatus,
getApplicationById,
batchUpdateApplications,
};
6 changes: 3 additions & 3 deletions models/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,9 @@ const fetchPaginatedUsers = async (query) => {

let compositeQuery = [dbQuery];
if (isDevMode) {
const usernameQuery = userModel.where("roles.archived", "==", false).orderBy("username");
const firstNameQuery = userModel.where("roles.archived", "==", false).orderBy("first_name");
const lastNameQuery = userModel.where("roles.archived", "==", false).orderBy("last_name");
const usernameQuery = userModel.where("roles.archived", "==", false).orderBy("username_lowercase");
const firstNameQuery = userModel.where("roles.archived", "==", false).orderBy("first_name_lowercase");
const lastNameQuery = userModel.where("roles.archived", "==", false).orderBy("last_name_lowercase");
compositeQuery = [usernameQuery, firstNameQuery, lastNameQuery];
}

Expand Down
1 change: 0 additions & 1 deletion routes/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,5 @@ router.patch(
applicationValidator.validateApplicationUpdateData,
applications.updateApplication
);
router.patch("/batch/update", authenticate, authorizeRoles([SUPERUSER]), applications.batchUpdateApplications);

module.exports = router;
39 changes: 0 additions & 39 deletions test/integration/application.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,43 +400,4 @@ describe("Application", function () {
});
});
});

describe("PATCH /application/batch/update", function () {
it("should return 401 if the user is not super user", function (done) {
chai
.request(app)
.patch(`/applications/batch/update`)
.set("cookie", `${cookieName}=${jwt}`)
.end((err, res) => {
if (err) {
return done(err);
}

expect(res).to.have.status(401);
expect(res.body.message).to.be.equal("You are not authorized for this action.");
return done();
});
});

it("should return updated stats after updating all the application", function (done) {
chai
.request(app)
.patch(`/applications/batch/update`)
.set("cookie", `${cookieName}=${superUserJwt}`)
.end((err, res) => {
if (err) {
return done(err);
}

expect(res).to.have.status(200);
expect(res.body).to.be.a("object");
expect(res.body).to.be.deep.equal({
failedApplicationUpdateIds: [],
totalFailedApplicationUpdates: 0,
totalApplicationUpdates: 6,
});
return done();
});
});
});
});
Loading

0 comments on commit d5fc0cc

Please sign in to comment.