From b8816fcc336538a1d4983deac2969314765cc1d1 Mon Sep 17 00:00:00 2001 From: vinayak Date: Sun, 24 Sep 2023 10:59:55 +0530 Subject: [PATCH 01/18] added enpoint for generating and getting discord invite for user --- controllers/discordactions.js | 84 +++++++++++++++++++--- middlewares/checkCanGenerateDiscordLink.ts | 18 +++++ models/discordactions.js | 28 ++++++++ routes/discordactions.js | 5 ++ types/global.d.ts | 41 +++++++++++ 5 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 middlewares/checkCanGenerateDiscordLink.ts create mode 100644 types/global.d.ts diff --git a/controllers/discordactions.js b/controllers/discordactions.js index 39fd7a41d..f3ee98bff 100644 --- a/controllers/discordactions.js +++ b/controllers/discordactions.js @@ -2,7 +2,7 @@ const { INTERNAL_SERVER_ERROR } = require("../constants/errorMessages"); const admin = require("firebase-admin"); const config = require("config"); const jwt = require("jsonwebtoken"); -const discordRolesModel = require("../models/discordactions"); +const discordActionModel = require("../models/discordactions"); /** * Creates a role @@ -17,7 +17,7 @@ const createGroupRole = async (req, res) => { try { const rolename = `group-${req.body.rolename}`; - const { wasSuccess } = await discordRolesModel.isGroupRoleExists(rolename); + const { wasSuccess } = await discordActionModel.isGroupRoleExists(rolename); if (!wasSuccess) { return res.status(400).json({ @@ -46,7 +46,7 @@ const createGroupRole = async (req, res) => { groupRoleData.roleid = responseForCreatedRole.id; - const { id } = await discordRolesModel.createNewRole(groupRoleData); + const { id } = await discordActionModel.createNewRole(groupRoleData); return res.status(201).json({ message: "Role created successfully!", id, @@ -65,12 +65,12 @@ const createGroupRole = async (req, res) => { const getAllGroupRoles = async (req, res) => { try { - const { groups } = await discordRolesModel.getAllGroupRoles(); + const { groups } = await discordActionModel.getAllGroupRoles(); const dev = req.query.dev === "true"; if (dev) { // Placing the new changes under the feature flag. const discordId = req.userData?.discordId; - const groupsWithMembershipInfo = await discordRolesModel.enrichGroupDataWithMembershipInfo(discordId, groups); + const groupsWithMembershipInfo = await discordActionModel.enrichGroupDataWithMembershipInfo(discordId, groups); return res.json({ message: "Roles fetched successfully!", groups: groupsWithMembershipInfo, @@ -88,7 +88,7 @@ const getAllGroupRoles = async (req, res) => { /** * Gets all group-roles - * @param req {Object} - Express request object + * @param req {Object} - Epxpress request object * @param res {Object} - Express response object */ @@ -99,7 +99,7 @@ const addGroupRoleToMember = async (req, res) => { date: admin.firestore.Timestamp.fromDate(new Date()), }; - const { roleData, wasSuccess } = await discordRolesModel.addGroupRoleToMember(memberGroupRole); + const { roleData, wasSuccess } = await discordActionModel.addGroupRoleToMember(memberGroupRole); if (!wasSuccess) { return res.status(400).json({ @@ -140,7 +140,7 @@ const addGroupRoleToMember = async (req, res) => { const updateDiscordImageForVerification = async (req, res) => { try { const { id: userDiscordId } = req.params; - const discordAvatarUrl = await discordRolesModel.updateDiscordImageForVerification(userDiscordId); + const discordAvatarUrl = await discordActionModel.updateDiscordImageForVerification(userDiscordId); return res.json({ message: "Discord avatar URL updated successfully!", discordAvatarUrl, @@ -158,7 +158,7 @@ const updateDiscordImageForVerification = async (req, res) => { */ const setRoleIdleToIdleUsers = async (req, res) => { try { - const result = await discordRolesModel.updateIdleUsersOnDiscord(); + const result = await discordActionModel.updateIdleUsersOnDiscord(); return res.status(201).json({ message: "All Idle Users updated successfully.", ...result, @@ -169,10 +169,76 @@ const setRoleIdleToIdleUsers = async (req, res) => { } }; +const generateInviteForUser = async (req, res) => { + try { + const { userId } = req.query; + const userIdForInvite = userId || req.userData.id; + + const modelResponse = await discordActionModel.getUserDiscordInvite(userIdForInvite); + + if (!modelResponse.notFound) { + return res.status(409).json({ + message: "User invite is already present!", + }); + } + + const channelId = config.get("discordNewComersChannelId"); + const authToken = jwt.sign({}, config.get("rdsServerlessBot.rdsServerLessPrivateKey"), { + algorithm: "RS256", + expiresIn: config.get("rdsServerlessBot.ttl"), + }); + + const inviteOptions = { + channelId: channelId, + }; + const response = await fetch(`${DISCORD_BASE_URL}/invite`, { + method: "POST", + body: JSON.stringify(inviteOptions), + headers: { "Content-Type": "application/json", Authorization: `Bearer ${authToken}` }, + }).then((response) => response.json()); + + const inviteCode = response.data.code; + const inviteLink = `discord.gg/${inviteCode}`; + + await discordActionModel.addInviteToInviteModel({ userId: userIdForInvite, inviteLink }); + + return res.json({ + message: "invite generated successfully", + inviteLink, + }); + } catch (err) { + logger.error(`Error in generating invite for user: ${err}`); + return res.boom.badImplementation(INTERNAL_SERVER_ERROR); + } +}; + +const getUserDiscordInvite = async (req, res) => { + try { + const { userId } = req.query; + const userIdForInvite = userId || req.userData.id; + + const modelResponse = await discordActionModel.getUserDiscordInvite(userIdForInvite); + + if (modelResponse.notFound) { + return res.boom.notFound("User invite doesn't exist"); + } + + return res.json({ + message: "Invite returned successfully", + modelResponse, + }); + } catch (err) { + logger.error(`Error in fetching user invite: ${err}`); + return res.boom.badImplementation(INTERNAL_SERVER_ERROR); + } +}; + module.exports = { createGroupRole, getAllGroupRoles, addGroupRoleToMember, updateDiscordImageForVerification, setRoleIdleToIdleUsers, + getUserDiscordInvite, + generateInviteForUser, }; diff --git a/middlewares/checkCanGenerateDiscordLink.ts b/middlewares/checkCanGenerateDiscordLink.ts new file mode 100644 index 000000000..7976665da --- /dev/null +++ b/middlewares/checkCanGenerateDiscordLink.ts @@ -0,0 +1,18 @@ +import { NextFunction } from "express"; +import { CustomRequest, CustomResponse } from "../types/global"; + +const checkCanGenerateDiscordLink = async ( + req: CustomRequest, + res: CustomResponse, + next: NextFunction +) => { + const { discordId, roles, id: userId } = req.userData; + const isSuperUser = roles.super_user; + const userIdInQuery = req.query.userId; + if ((userIdInQuery && userIdInQuery !== userId && !isSuperUser) || discordId || roles.archived) { + return res.boom.forbidden("You are restricted from performing this action"); + } + return next(); +}; + +module.exports = checkCanGenerateDiscordLink; diff --git a/models/discordactions.js b/models/discordactions.js index 4f7c62177..c1e48a867 100644 --- a/models/discordactions.js +++ b/models/discordactions.js @@ -2,6 +2,7 @@ const { generateDiscordProfileImageUrl } = require("../utils/discord-actions"); const firestore = require("../utils/firestore"); const discordRoleModel = firestore.collection("discord-roles"); const memberRoleModel = firestore.collection("member-group-roles"); +const discordInvitesModel = firestore.collection("discord-invites"); const admin = require("firebase-admin"); const { findSubscribedGroupIds } = require("../utils/helper"); const { retrieveUsers } = require("../services/dataAccessLayer"); @@ -336,6 +337,31 @@ const updateIdleUsersOnDiscord = async () => { }; }; +const addInviteToInviteModel = async (inviteObject) => { + try { + const invite = await discordInvitesModel.add(inviteObject); + return invite.id; + } catch (err) { + logger.error("Error in adding invite", err); + throw err; + } +}; + +const getUserDiscordInvite = async (userId) => { + try { + const invite = await discordInvitesModel.where("userId", "==", userId).get(); + const [inviteDoc] = invite.docs; + if (inviteDoc) { + return { id: inviteDoc.id, ...inviteDoc.data() }; + } else { + return { notFound: true }; + } + } catch (err) { + logger.log("error in getting user invite", err); + throw err; + } +}; + module.exports = { createNewRole, getAllGroupRoles, @@ -345,4 +371,6 @@ module.exports = { enrichGroupDataWithMembershipInfo, fetchGroupToUserMapping, updateIdleUsersOnDiscord, + getUserDiscordInvite, + addInviteToInviteModel, }; diff --git a/routes/discordactions.js b/routes/discordactions.js index 6ae3b0eda..7930d24be 100644 --- a/routes/discordactions.js +++ b/routes/discordactions.js @@ -6,9 +6,12 @@ const { addGroupRoleToMember, updateDiscordImageForVerification, setRoleIdleToIdleUsers, + getUserDiscordInvite, + generateInviteForUser, } = require("../controllers/discordactions"); const { validateGroupRoleBody, validateMemberRoleBody } = require("../middlewares/validators/discordactions"); const checkIsVerifiedDiscord = require("../middlewares/verifydiscord"); +const checkCanGenerateDiscordLink = require("../middlewares/checkCanGenerateDiscordLink"); const { SUPERUSER } = require("../constants/roles"); const authorizeRoles = require("../middlewares/authorizeRoles"); @@ -17,6 +20,8 @@ const router = express.Router(); router.post("/groups", authenticate, checkIsVerifiedDiscord, validateGroupRoleBody, createGroupRole); router.get("/groups", authenticate, checkIsVerifiedDiscord, getAllGroupRoles); router.post("/roles", authenticate, checkIsVerifiedDiscord, validateMemberRoleBody, addGroupRoleToMember); +router.get("/invite", authenticate, getUserDiscordInvite); +router.post("/invite", authenticate, checkCanGenerateDiscordLink, generateInviteForUser); router.patch( "/avatar/verify/:id", authenticate, diff --git a/types/global.d.ts b/types/global.d.ts new file mode 100644 index 000000000..187cc4b70 --- /dev/null +++ b/types/global.d.ts @@ -0,0 +1,41 @@ +import { Request, Response, NextFunction } from "express"; +import { Boom } from "express-boom"; + +export type userData = { + message: string; + user: { + id: string; + profileURL: string; + discordJoinedAt: string; + roles: { + archived: boolean; + in_discord: boolean; + member: boolean; + }; + profileStatus: string; + created_at: number; + yoe: number; + github_created_at: number; + company: string; + twitter_id: string; + first_name: string; + incompleteUserDetails: boolean; + discordId: string; + last_name: string; + linkedin_id: string; + picture: { + url: string; + publicId: string; + }; + instagram_id: string; + github_display_name: string; + github_id: string; + designation: string; + status: string; + username: string; + updated_at: string; + }; +}; + +export type CustomResponse = Response & { boom: Boom }; +export type CustomRequest = Request & { userData }; From 799efb769a116fcdf21936c61b0207b79a57a32d Mon Sep 17 00:00:00 2001 From: vinayak Date: Tue, 26 Sep 2023 22:20:27 +0530 Subject: [PATCH 02/18] changes in middleware and controller method --- controllers/discordactions.js | 2 +- middlewares/checkCanGenerateDiscordLink.ts | 26 +++++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/controllers/discordactions.js b/controllers/discordactions.js index f3ee98bff..add74e9d9 100644 --- a/controllers/discordactions.js +++ b/controllers/discordactions.js @@ -225,7 +225,7 @@ const getUserDiscordInvite = async (req, res) => { return res.json({ message: "Invite returned successfully", - modelResponse, + inviteResponse: modelResponse, }); } catch (err) { logger.error(`Error in fetching user invite: ${err}`); diff --git a/middlewares/checkCanGenerateDiscordLink.ts b/middlewares/checkCanGenerateDiscordLink.ts index 7976665da..3bc985119 100644 --- a/middlewares/checkCanGenerateDiscordLink.ts +++ b/middlewares/checkCanGenerateDiscordLink.ts @@ -1,17 +1,27 @@ import { NextFunction } from "express"; import { CustomRequest, CustomResponse } from "../types/global"; -const checkCanGenerateDiscordLink = async ( - req: CustomRequest, - res: CustomResponse, - next: NextFunction -) => { - const { discordId, roles, id: userId } = req.userData; +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) || discordId || roles.archived) { - return res.boom.forbidden("You are restricted from performing this action"); + + if (userIdInQuery && userIdInQuery !== userId && !isSuperUser) { + return res.boom.forbidden("User should be super user to generate link for other users"); + } + + if (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 (!roles.maven && !roles.designer && profileStatus !== "VERIFIED") { + return res.boom.forbidden("Only mavens and designers can generate discord link directly, others need to have verified profile status"); } + return next(); }; From 2abbcedff8fa579dccd9d9cf2c76821c7d688dd4 Mon Sep 17 00:00:00 2001 From: vinayak Date: Tue, 3 Oct 2023 20:32:25 +0530 Subject: [PATCH 03/18] changed discordNewComersChannelId constant --- config/development.js | 1 + 1 file changed, 1 insertion(+) diff --git a/config/development.js b/config/development.js index 324cba609..a2ddaa2a7 100644 --- a/config/development.js +++ b/config/development.js @@ -10,6 +10,7 @@ module.exports = { port: port, enableFileLogs: false, enableConsoleLogs: true, + discordNewComersChannelId: "709080951824842783", services: { rdsApi: { From 59102970075cbb1ee9b55191c474361a2ff7ae9b Mon Sep 17 00:00:00 2001 From: vinayak Date: Sun, 8 Oct 2023 13:21:21 +0530 Subject: [PATCH 04/18] tests for endpoint for getting discord link generated for user --- controllers/discordactions.js | 4 ++ test/integration/discordactions.test.js | 55 ++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/controllers/discordactions.js b/controllers/discordactions.js index add74e9d9..4c53497a4 100644 --- a/controllers/discordactions.js +++ b/controllers/discordactions.js @@ -215,6 +215,10 @@ const generateInviteForUser = async (req, res) => { const getUserDiscordInvite = async (req, res) => { try { const { userId } = req.query; + const isSuperUser = req.userData.roles.super_user; + + if (userId && !isSuperUser) return res.boom.forbidden("User should be super user to get link for other users"); + const userIdForInvite = userId || req.userData.id; const modelResponse = await discordActionModel.getUserDiscordInvite(userIdForInvite); diff --git a/test/integration/discordactions.test.js b/test/integration/discordactions.test.js index dc8062710..d266d9f5b 100644 --- a/test/integration/discordactions.test.js +++ b/test/integration/discordactions.test.js @@ -20,12 +20,13 @@ const discordRoleModel = firestore.collection("discord-roles"); const userModel = firestore.collection("users"); const { groupData } = require("../fixtures/discordactions/discordactions"); -const { addGroupRoleToMember } = require("../../models/discordactions"); +const { addGroupRoleToMember, addInviteToInviteModel } = require("../../models/discordactions"); chai.use(chaiHttp); describe("Discord actions", function () { let superUserId; let superUserAuthToken; + let userAuthToken; let userId = ""; let discordId = ""; let fetchStub; @@ -34,6 +35,7 @@ describe("Discord actions", function () { userId = await addUser(); superUserId = await addUser(superUser); superUserAuthToken = authService.generateAuthToken({ userId: superUserId }); + userAuthToken = authService.generateAuthToken({ userId: userId }); discordId = "12345"; const docRefUser0 = photoVerificationModel.doc(); @@ -167,4 +169,55 @@ describe("Discord actions", function () { }); }); }); + + describe("GET /discord-actions/invite", function () { + it("should return the invite for the user if no userId is provided in the params and the invite exists", async function () { + const inviteId = await addInviteToInviteModel({ userId: superUserId, inviteLink: "discord.gg/apQYT7HB" }); + + const res = await chai + .request(app) + .get("/discord-actions/invite") + .set("cookie", `${cookieName}=${superUserAuthToken}`); + expect(res).to.have.status(200); + expect(res.body).to.be.a("object"); + expect(res.body).to.deep.equal({ + message: "Invite returned successfully", + inviteResponse: { + id: inviteId, + inviteLink: "discord.gg/apQYT7HB", + userId: superUserId, + }, + }); + }); + + it("Should return the invite for other user if the userId is provided in the query and the user is super user", async function () { + const inviteId = await addInviteToInviteModel({ userId: userId, inviteLink: "discord.gg/apQYT7HA" }); + const res = await chai + .request(app) + .get(`/discord-actions/invite?userId=${userId}`) + .set("cookie", `${cookieName}=${superUserAuthToken}`); + expect(res).to.have.status(200); + expect(res.body).to.be.a("object"); + expect(res.body).to.deep.equal({ + message: "Invite returned successfully", + inviteResponse: { + id: inviteId, + inviteLink: "discord.gg/apQYT7HA", + userId: userId, + }, + }); + }); + + it("should return 403 if the other user's id is provided and the user is not a super user", async function () { + const res = await chai + .request(app) + .get(`/discord-actions/invite?userId=${superUserId}`) + .set("cookie", `${cookieName}=${userAuthToken}`); + expect(res).to.have.status(403); + expect(res.body).to.be.a("object"); + expect(res.body.message).to.be.equal("User should be super user to get link for other users"); + }); + }); + + describe("POST /discord-actions/invite", function () {}); }); From 36dac7cd500ce6ce701cd6eb201767055cbd29c3 Mon Sep 17 00:00:00 2001 From: vinayak Date: Sun, 8 Oct 2023 16:06:47 +0530 Subject: [PATCH 05/18] tests for post API --- config/test.js | 1 + controllers/discordactions.js | 2 +- middlewares/checkCanGenerateDiscordLink.ts | 4 +- test/fixtures/user/user.js | 4 + test/integration/discordactions.test.js | 125 ++++++++++++++++++++- 5 files changed, 132 insertions(+), 4 deletions(-) diff --git a/config/test.js b/config/test.js index 98b272c30..e31237312 100644 --- a/config/test.js +++ b/config/test.js @@ -11,6 +11,7 @@ module.exports = { enableConsoleLogs: true, discordUnverifiedRoleId: "1234567890", discordDeveloperRoleId: "9876543210", + discordNewComersChannelId: "709080951824842783", githubOauth: { clientId: "clientId", clientSecret: "clientSecret", diff --git a/controllers/discordactions.js b/controllers/discordactions.js index 4c53497a4..b5ac0ec5f 100644 --- a/controllers/discordactions.js +++ b/controllers/discordactions.js @@ -202,7 +202,7 @@ const generateInviteForUser = async (req, res) => { await discordActionModel.addInviteToInviteModel({ userId: userIdForInvite, inviteLink }); - return res.json({ + return res.status(201).json({ message: "invite generated successfully", inviteLink, }); diff --git a/middlewares/checkCanGenerateDiscordLink.ts b/middlewares/checkCanGenerateDiscordLink.ts index 3bc985119..c4ba1916a 100644 --- a/middlewares/checkCanGenerateDiscordLink.ts +++ b/middlewares/checkCanGenerateDiscordLink.ts @@ -18,8 +18,8 @@ const checkCanGenerateDiscordLink = async (req: CustomRequest, res: CustomRespon return res.boom.forbidden("Archived users cannot generate invite"); } - if (!roles.maven && !roles.designer && profileStatus !== "VERIFIED") { - return res.boom.forbidden("Only mavens and designers can generate discord link directly, others need to have verified profile status"); + if (!roles.maven && !roles.designer && !roles.product_manager && profileStatus !== "VERIFIED") { + return res.boom.forbidden("Only mavens, product managers and designers can generate discord link directly, others need to have verified profile status"); } return next(); diff --git a/test/fixtures/user/user.js b/test/fixtures/user/user.js index eef8fb70b..60fbf5df2 100644 --- a/test/fixtures/user/user.js +++ b/test/fixtures/user/user.js @@ -97,6 +97,7 @@ module.exports = () => { roles: { restricted: false, app_owner: true, + archived: true, }, picture: { publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar", @@ -213,6 +214,7 @@ module.exports = () => { archived: false, member: true, in_discord: true, + designer: true, }, twitter_id: "RitvikJamwal4u", linkedin_id: "ritvik-jamwal4u", @@ -235,6 +237,7 @@ module.exports = () => { member: true, archived: false, in_discord: true, + product_manager: true, }, picture: { publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar", @@ -257,6 +260,7 @@ module.exports = () => { }, roles: { member: true, + maven: true, }, picture: { publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar", diff --git a/test/integration/discordactions.test.js b/test/integration/discordactions.test.js index d266d9f5b..1c28d4fa1 100644 --- a/test/integration/discordactions.test.js +++ b/test/integration/discordactions.test.js @@ -9,6 +9,11 @@ const cleanDb = require("../utils/cleanDb"); // Import fixtures const userData = require("../fixtures/user/user")(); const superUser = userData[4]; +const archievedUser = userData[3]; +const developerUserWithoutApprovedProfileStatus = userData[6]; +const designerUser = userData[8]; +const productManagerUser = userData[9]; +const mavenUser = userData[10]; const config = require("config"); const sinon = require("sinon"); @@ -25,8 +30,18 @@ chai.use(chaiHttp); describe("Discord actions", function () { let superUserId; + let archievedUserId; + let designerUserId; + let mavenUserId; + let productManagerUserId; + let developerUserWithoutApprovedProfileStatusId; let superUserAuthToken; let userAuthToken; + let developerUserWithoutApprovedProfileStatusToken; + let designerAuthToken; + let mavenAuthToken; + let productManagerAuthToken; + let archievedUserToken; let userId = ""; let discordId = ""; let fetchStub; @@ -219,5 +234,113 @@ describe("Discord actions", function () { }); }); - describe("POST /discord-actions/invite", function () {}); + describe("POST /discord-actions/invite", function () { + it("should return 403 if the userId in the query param is not equal to the user of the user and user is not a super user", async function () { + const res = await chai + .request(app) + .post(`/discord-actions/invite?userId=${superUserId}`) + .set("cookie", `${cookieName}=${userAuthToken}`); + expect(res).to.have.status(403); + expect(res.body).to.be.a("object"); + expect(res.body.message).to.be.equal("User should be super user to generate link for other users"); + }); + + it("should return 403 if the user has discord id in their user object, which means user is already in discord", async function () { + const res = await chai + .request(app) + .post(`/discord-actions/invite`) + .set("cookie", `${cookieName}=${userAuthToken}`); + expect(res).to.have.status(403); + expect(res.body).to.be.a("object"); + expect(res.body.message).to.be.equal("Only users who have never joined discord can generate invite link"); + }); + + it("should return 403 if user has role archieved", async function () { + archievedUserId = await addUser(archievedUser); + archievedUserToken = authService.generateAuthToken({ userId: archievedUserId }); + const res = await chai + .request(app) + .post(`/discord-actions/invite`) + .set("cookie", `${cookieName}=${archievedUserToken}`); + expect(res).to.have.status(403); + expect(res.body).to.be.a("object"); + expect(res.body.message).to.be.equal("Archived users cannot generate invite"); + }); + + it("should return 403 if the user doesn't have role designer, product_manager, or mavens", async function () { + developerUserWithoutApprovedProfileStatusId = await addUser(developerUserWithoutApprovedProfileStatus); + developerUserWithoutApprovedProfileStatusToken = authService.generateAuthToken({ + userId: developerUserWithoutApprovedProfileStatusId, + }); + const res = await chai + .request(app) + .post(`/discord-actions/invite`) + .set("cookie", `${cookieName}=${developerUserWithoutApprovedProfileStatusToken}`); + expect(res).to.have.status(403); + expect(res.body).to.be.a("object"); + expect(res.body.message).to.be.equal( + "Only mavens, product managers and designers can generate discord link directly, others need to have verified profile status" + ); + }); + + it("should generate discord link if user is a product mananger", async function () { + fetchStub.returns( + Promise.resolve({ + status: 201, + json: () => Promise.resolve({ data: { code: "xyz" } }), + }) + ); + + productManagerUserId = await addUser(productManagerUser); + productManagerAuthToken = authService.generateAuthToken({ userId: productManagerUserId }); + const res = await chai + .request(app) + .post(`/discord-actions/invite`) + .set("cookie", `${cookieName}=${productManagerAuthToken}`); + + expect(res).to.have.status(201); + expect(res.body.message).to.be.equal("invite generated successfully"); + expect(res.body.inviteLink).to.be.equal("discord.gg/xyz"); + }); + + it("should generate discord link if user is a designer", async function () { + fetchStub.returns( + Promise.resolve({ + status: 201, + json: () => Promise.resolve({ data: { code: "zlmfasd" } }), + }) + ); + + designerUserId = await addUser(designerUser); + designerAuthToken = authService.generateAuthToken({ userId: designerUserId }); + const res = await chai + .request(app) + .post(`/discord-actions/invite`) + .set("cookie", `${cookieName}=${designerAuthToken}`); + + expect(res).to.have.status(201); + expect(res.body.message).to.be.equal("invite generated successfully"); + expect(res.body.inviteLink).to.be.equal("discord.gg/zlmfasd"); + }); + + it("should generate discord link if user is a maven", async function () { + fetchStub.returns( + Promise.resolve({ + status: 201, + json: () => Promise.resolve({ data: { code: "asdfdsfsd" } }), + }) + ); + + mavenUserId = await addUser(mavenUser); + mavenAuthToken = authService.generateAuthToken({ userId: mavenUserId }); + const res = await chai + .request(app) + .post(`/discord-actions/invite`) + .set("cookie", `${cookieName}=${mavenAuthToken}`); + + expect(res).to.have.status(201); + expect(res.body.message).to.be.equal("invite generated successfully"); + expect(res.body.inviteLink).to.be.equal("discord.gg/asdfdsfsd"); + }); + }); }); From f5655a1fc1e9a2cd63c490f5a8e66e72c81f3aaf Mon Sep 17 00:00:00 2001 From: vinayak Date: Sun, 22 Oct 2023 13:03:54 +0530 Subject: [PATCH 06/18] fix for failing tests --- test/fixtures/user/user.js | 27 ++++++++++++++++++++++++- test/integration/discordactions.test.js | 2 +- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/test/fixtures/user/user.js b/test/fixtures/user/user.js index 1eb528967..8f41044d3 100644 --- a/test/fixtures/user/user.js +++ b/test/fixtures/user/user.js @@ -101,7 +101,6 @@ module.exports = () => { roles: { restricted: false, app_owner: true, - archived: true, }, picture: { publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar", @@ -403,5 +402,31 @@ module.exports = () => { updated_at: Date.now(), created_at: Date.now(), }, + { + username: "Vinayak", + first_name: "Vinayak", + last_name: "Trivedi", + yoe: 2, + img: "./img.png", + linkedin_id: "_", + github_id: "xfasrfsd", + github_display_name: "vinayak-trivedi", + discordJoinedAt: "2023-04-06T01:47:34.488000+00:00", + phone: "1234567890", + email: "abc@gmail.com", + status: "active", + tokens: { + githubAccessToken: "githubAccessToken", + }, + roles: { + restricted: false, + app_owner: true, + archived: true, + }, + picture: { + publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar", + url: "https://res.cloudinary.com/realdevsquad/image/upload/v1667685133/profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar.jpg", + }, + }, ]; }; diff --git a/test/integration/discordactions.test.js b/test/integration/discordactions.test.js index 218004052..1a0e4534d 100644 --- a/test/integration/discordactions.test.js +++ b/test/integration/discordactions.test.js @@ -10,7 +10,7 @@ const cleanDb = require("../utils/cleanDb"); const userData = require("../fixtures/user/user")(); const usersInDiscord = require("../fixtures/user/inDiscord"); const superUser = userData[4]; -const archievedUser = userData[3]; +const archievedUser = userData[18]; const developerUserWithoutApprovedProfileStatus = userData[6]; const designerUser = userData[8]; const productManagerUser = userData[9]; From 30f77812a7f2f2e0ef131ea7699ff214eb834645 Mon Sep 17 00:00:00 2001 From: vinayak Date: Sat, 28 Oct 2023 13:22:26 +0530 Subject: [PATCH 07/18] fix for failing unit test --- test/unit/services/users.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/services/users.test.js b/test/unit/services/users.test.js index f10ecab3c..021c9d826 100644 --- a/test/unit/services/users.test.js +++ b/test/unit/services/users.test.js @@ -53,7 +53,7 @@ describe("Users services", function () { expect(res).to.deep.equal({ message: "Successfully completed batch updates", - totalUsersArchived: 18, + totalUsersArchived: 19, totalOperationsFailed: 0, updatedUserDetails: userDetails, failedUserDetails: [], @@ -74,7 +74,7 @@ describe("Users services", function () { expect(res).to.deep.equal({ message: "Firebase batch operation failed", totalUsersArchived: 0, - totalOperationsFailed: 18, + totalOperationsFailed: 19, updatedUserDetails: [], failedUserDetails: userDetails, }); From c948307748145ebde33388749cdf44e95dbd465c Mon Sep 17 00:00:00 2001 From: vinayak Date: Sat, 28 Oct 2023 14:52:37 +0530 Subject: [PATCH 08/18] types issue fixed --- types/global.d.ts | 64 +++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/types/global.d.ts b/types/global.d.ts index 187cc4b70..89c28c86b 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -2,39 +2,39 @@ import { Request, Response, NextFunction } from "express"; import { Boom } from "express-boom"; export type userData = { - message: string; - user: { - id: string; - profileURL: string; - discordJoinedAt: string; - roles: { - archived: boolean; - in_discord: boolean; - member: boolean; - }; - profileStatus: string; - created_at: number; - yoe: number; - github_created_at: number; - company: string; - twitter_id: string; - first_name: string; - incompleteUserDetails: boolean; - discordId: string; - last_name: string; - linkedin_id: string; - picture: { - url: string; - publicId: string; - }; - instagram_id: string; - github_display_name: string; - github_id: string; - designation: string; - status: string; - username: string; - updated_at: string; + id: string; + profileURL: string; + discordJoinedAt: string; + roles: { + archived: boolean; + in_discord?: boolean; + member?: boolean; + maven?: boolean; + designer?: boolean; + product_manager: boolean; }; + profileStatus: string; + created_at: number; + yoe: number; + github_created_at: number; + company: string; + twitter_id: string; + first_name: string; + incompleteUserDetails: boolean; + discordId: string; + last_name: string; + linkedin_id: string; + picture: { + url: string; + publicId: string; + }; + instagram_id: string; + github_display_name: string; + github_id: string; + designation: string; + status: string; + username: string; + updated_at: number; }; export type CustomResponse = Response & { boom: Boom }; From 998f5597d328577c75cfbef25add9d11402e3121 Mon Sep 17 00:00:00 2001 From: vinayak Date: Sun, 29 Oct 2023 11:48:10 +0530 Subject: [PATCH 09/18] model tests --- test/unit/models/discordactions.test.js | 58 +++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/test/unit/models/discordactions.test.js b/test/unit/models/discordactions.test.js index 86e0837de..d0eafd998 100644 --- a/test/unit/models/discordactions.test.js +++ b/test/unit/models/discordactions.test.js @@ -7,6 +7,7 @@ const discordRoleModel = firestore.collection("discord-roles"); const memberRoleModel = firestore.collection("member-group-roles"); const userModel = firestore.collection("users"); const admin = require("firebase-admin"); +const discordInvitesModel = firestore.collection("discord-invites"); const { createNewRole, @@ -18,6 +19,8 @@ const { enrichGroupDataWithMembershipInfo, fetchGroupToUserMapping, updateUsersNicknameStatus, + addInviteToInviteModel, + getUserDiscordInvite, } = require("../../../models/discordactions"); const { groupData, roleData, existingRole, memberGroupData } = require("../../fixtures/discordactions/discordactions"); const cleanDb = require("../../utils/cleanDb"); @@ -567,4 +570,59 @@ describe("discordactions", function () { } }).timeout(10000); }); + + describe("addInviteToInviteModel", function () { + let addStub; + + beforeEach(function () { + addStub = sinon.stub(discordRoleModel, "add").resolves({ id: "invite-test-id" }); + }); + + afterEach(function () { + addStub.restore(); + }); + + it("should add invite in the invite model for user", async function () { + const inviteObject = { userId: "kfjkasdfl", inviteLink: "discord.gg/xyz" }; + const inviteId = await addInviteToInviteModel(inviteObject); + expect(inviteId).to.exist; + }); + + it("should throw an error if creating invite fails", async function () { + const inviteObject = { userId: "kfjkasdfl", inviteLink: "discord.gg/xyz" }; + addStub.rejects(new Error("Database error!")); + return await addInviteToInviteModel(inviteObject).catch((error) => { + expect(error).to.be.an.instanceOf(Error); + expect(error.message).to.equal("Database error!"); + }); + }); + }); + + describe("getUserDiscordInvite", function () { + let getStub; + + beforeEach(function () { + getStub = sinon.stub(discordInvitesModel, "where").resolves({ + get: sinon.stub().returns({ + docs: [ + { + id: "zyfdsf", + data: sinon.stub().returns({ + inviteLink: "discord.gg/tYU6Gm7e", + userId: "hKzs2IQGe4sLnAuSZ85i", + }), + }, + ], + }), + }); + }); + + afterEach(function () { + getStub.restore(); + }); + + it("should return the invite for the user", async function () { + const result = await getUserDiscordInvite("xyz"); + }); + }); }); From 1ea7df40246528de640608d73b3e4101ef211ade Mon Sep 17 00:00:00 2001 From: vinayak Date: Sun, 29 Oct 2023 11:53:53 +0530 Subject: [PATCH 10/18] did suggested changes --- controllers/discordactions.js | 2 +- middlewares/checkCanGenerateDiscordLink.ts | 2 +- models/discordactions.js | 2 +- test/integration/discordactions.test.js | 4 +--- types/global.d.ts | 6 +++--- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/controllers/discordactions.js b/controllers/discordactions.js index 4baa18d67..6ad49d81c 100644 --- a/controllers/discordactions.js +++ b/controllers/discordactions.js @@ -451,7 +451,7 @@ const getUserDiscordInvite = async (req, res) => { return res.json({ message: "Invite returned successfully", - inviteResponse: modelResponse, + inviteLink: modelResponse?.inviteLink, }); } catch (err) { logger.error(`Error in fetching user invite: ${err}`); diff --git a/middlewares/checkCanGenerateDiscordLink.ts b/middlewares/checkCanGenerateDiscordLink.ts index c4ba1916a..0578e695d 100644 --- a/middlewares/checkCanGenerateDiscordLink.ts +++ b/middlewares/checkCanGenerateDiscordLink.ts @@ -19,7 +19,7 @@ const checkCanGenerateDiscordLink = async (req: CustomRequest, res: CustomRespon } if (!roles.maven && !roles.designer && !roles.product_manager && profileStatus !== "VERIFIED") { - return res.boom.forbidden("Only mavens, product managers and designers can generate discord link directly, others need to have verified profile status"); + return res.boom.forbidden("Only selected roles can generate discord link directly"); } return next(); diff --git a/models/discordactions.js b/models/discordactions.js index a61773bc3..0cf0b1a41 100644 --- a/models/discordactions.js +++ b/models/discordactions.js @@ -833,7 +833,7 @@ const getUserDiscordInvite = async (userId) => { const invite = await discordInvitesModel.where("userId", "==", userId).get(); const [inviteDoc] = invite.docs; if (inviteDoc) { - return { id: inviteDoc.id, ...inviteDoc.data() }; + return { id: inviteDoc.id, ...inviteDoc.data(), notFound: false }; } else { return { notFound: true }; } diff --git a/test/integration/discordactions.test.js b/test/integration/discordactions.test.js index 1a0e4534d..89f133e41 100644 --- a/test/integration/discordactions.test.js +++ b/test/integration/discordactions.test.js @@ -662,9 +662,7 @@ describe("Discord actions", function () { .set("cookie", `${cookieName}=${developerUserWithoutApprovedProfileStatusToken}`); expect(res).to.have.status(403); expect(res.body).to.be.a("object"); - expect(res.body.message).to.be.equal( - "Only mavens, product managers and designers can generate discord link directly, others need to have verified profile status" - ); + expect(res.body.message).to.be.equal("Only selected roles can generate discord link directly"); }); it("should generate discord link if user is a product mananger", async function () { diff --git a/types/global.d.ts b/types/global.d.ts index 89c28c86b..a43f48c81 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -24,9 +24,9 @@ export type userData = { discordId: string; last_name: string; linkedin_id: string; - picture: { - url: string; - publicId: string; + picture?: { + url?: string; + publicId?: string; }; instagram_id: string; github_display_name: string; From 71446ad5e2c2123da97f50e224fafc878538ee4b Mon Sep 17 00:00:00 2001 From: vinayak Date: Sun, 29 Oct 2023 12:29:46 +0530 Subject: [PATCH 11/18] invite get model test changes --- test/unit/models/discordactions.test.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/test/unit/models/discordactions.test.js b/test/unit/models/discordactions.test.js index d0eafd998..645ea42bd 100644 --- a/test/unit/models/discordactions.test.js +++ b/test/unit/models/discordactions.test.js @@ -107,6 +107,7 @@ describe("discordactions", function () { it("should return true if role doesn't exist in the database", async function () { const result = await isGroupRoleExists("Test Role"); + console.log(result, 'result') expect(result.wasSuccess).to.equal(true); expect(getStub.calledOnceWith("rolename", "==", "Test Role")).to.equal(false); }); @@ -598,18 +599,18 @@ describe("discordactions", function () { }); }); - describe("getUserDiscordInvite", function () { + describe.only("getUserDiscordInvite", function () { let getStub; beforeEach(function () { - getStub = sinon.stub(discordInvitesModel, "where").resolves({ - get: sinon.stub().returns({ + getStub = sinon.stub(discordRoleModel, "where").returns({ + get: sinon.stub().resolves({ docs: [ { - id: "zyfdsf", + id: "xyzfdsf", data: sinon.stub().returns({ - inviteLink: "discord.gg/tYU6Gm7e", - userId: "hKzs2IQGe4sLnAuSZ85i", + userId: "xyz", + inviteLink: "discord.gg/fkjasdfjk", }), }, ], @@ -623,6 +624,10 @@ describe("discordactions", function () { it("should return the invite for the user", async function () { const result = await getUserDiscordInvite("xyz"); + expect(result.id).to.be.equal("xyzfdsf"); + expect(result.notFound).to.be.equal(false); + expect(result.userId).to.be.equals("xyz"); + expect(result.inviteLink).to.be.equal("discord.gg/fkjasdfjk"); }); }); }); From 1105698b3123fca2aa8a1160824311ce6f11b58c Mon Sep 17 00:00:00 2001 From: vinayak Date: Wed, 1 Nov 2023 21:23:27 +0530 Subject: [PATCH 12/18] removed the model test getInvite --- test/unit/models/discordactions.test.js | 38 ++----------------------- 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/test/unit/models/discordactions.test.js b/test/unit/models/discordactions.test.js index 645ea42bd..318744194 100644 --- a/test/unit/models/discordactions.test.js +++ b/test/unit/models/discordactions.test.js @@ -20,7 +20,6 @@ const { fetchGroupToUserMapping, updateUsersNicknameStatus, addInviteToInviteModel, - getUserDiscordInvite, } = require("../../../models/discordactions"); const { groupData, roleData, existingRole, memberGroupData } = require("../../fixtures/discordactions/discordactions"); const cleanDb = require("../../utils/cleanDb"); @@ -107,7 +106,6 @@ describe("discordactions", function () { it("should return true if role doesn't exist in the database", async function () { const result = await isGroupRoleExists("Test Role"); - console.log(result, 'result') expect(result.wasSuccess).to.equal(true); expect(getStub.calledOnceWith("rolename", "==", "Test Role")).to.equal(false); }); @@ -576,7 +574,7 @@ describe("discordactions", function () { let addStub; beforeEach(function () { - addStub = sinon.stub(discordRoleModel, "add").resolves({ id: "invite-test-id" }); + addStub = sinon.stub(discordInvitesModel, "add").resolves({ id: "invite-test-id" }); }); afterEach(function () { @@ -586,7 +584,7 @@ describe("discordactions", function () { it("should add invite in the invite model for user", async function () { const inviteObject = { userId: "kfjkasdfl", inviteLink: "discord.gg/xyz" }; const inviteId = await addInviteToInviteModel(inviteObject); - expect(inviteId).to.exist; + expect(inviteId).to.exist; // eslint-disable-line no-unused-expressions }); it("should throw an error if creating invite fails", async function () { @@ -598,36 +596,4 @@ describe("discordactions", function () { }); }); }); - - describe.only("getUserDiscordInvite", function () { - let getStub; - - beforeEach(function () { - getStub = sinon.stub(discordRoleModel, "where").returns({ - get: sinon.stub().resolves({ - docs: [ - { - id: "xyzfdsf", - data: sinon.stub().returns({ - userId: "xyz", - inviteLink: "discord.gg/fkjasdfjk", - }), - }, - ], - }), - }); - }); - - afterEach(function () { - getStub.restore(); - }); - - it("should return the invite for the user", async function () { - const result = await getUserDiscordInvite("xyz"); - expect(result.id).to.be.equal("xyzfdsf"); - expect(result.notFound).to.be.equal(false); - expect(result.userId).to.be.equals("xyz"); - expect(result.inviteLink).to.be.equal("discord.gg/fkjasdfjk"); - }); - }); }); From 99252d1b79eaa178199a9406543d4e8fd2a47dba Mon Sep 17 00:00:00 2001 From: vinayak Date: Wed, 1 Nov 2023 21:29:13 +0530 Subject: [PATCH 13/18] test description string change --- test/integration/discordactions.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/discordactions.test.js b/test/integration/discordactions.test.js index 89f133e41..9820c97c3 100644 --- a/test/integration/discordactions.test.js +++ b/test/integration/discordactions.test.js @@ -607,7 +607,7 @@ describe("Discord actions", function () { }); }); - it("should return 403 if the other user's id is provided and the user is not a super user", async function () { + it("should return 403 if the userId in the query param is not equal to the userId of the user and user is not a super user", async function () { const res = await chai .request(app) .get(`/discord-actions/invite?userId=${superUserId}`) From 2bfd652d82260267dae99068371b3a06673823e3 Mon Sep 17 00:00:00 2001 From: vinayak-trivedi <90315175+vinayak-trivedi@users.noreply.github.com> Date: Thu, 2 Nov 2023 19:35:28 +0530 Subject: [PATCH 14/18] Update test/integration/discordactions.test.js Co-authored-by: Satyam Bajpai --- test/integration/discordactions.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/discordactions.test.js b/test/integration/discordactions.test.js index 9820c97c3..fdf3c71a9 100644 --- a/test/integration/discordactions.test.js +++ b/test/integration/discordactions.test.js @@ -619,7 +619,7 @@ describe("Discord actions", function () { }); describe("POST /discord-actions/invite", function () { - it("should return 403 if the userId in the query param is not equal to the user of the user and user is not a super user", async function () { + it("should return 403 if the userId in the query param is not equal to the userId of the user and user is not a super user", async function () { const res = await chai .request(app) .post(`/discord-actions/invite?userId=${superUserId}`) From 09a9eca688f00b5468d8b93954e71bab78ba123d Mon Sep 17 00:00:00 2001 From: vinayak Date: Thu, 9 Nov 2023 21:22:11 +0530 Subject: [PATCH 15/18] fix for failing tests --- test/integration/discordactions.test.js | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/test/integration/discordactions.test.js b/test/integration/discordactions.test.js index df6120dd1..542fcc748 100644 --- a/test/integration/discordactions.test.js +++ b/test/integration/discordactions.test.js @@ -10,7 +10,7 @@ const cleanDb = require("../utils/cleanDb"); const userData = require("../fixtures/user/user")(); const usersInDiscord = require("../fixtures/user/inDiscord"); const superUser = userData[4]; -const archievedUser = userData[18]; +const archievedUser = userData[19]; const developerUserWithoutApprovedProfileStatus = userData[6]; const designerUser = userData[8]; const productManagerUser = userData[9]; @@ -549,7 +549,7 @@ describe("Discord actions", function () { describe("GET /discord-actions/invite", function () { it("should return the invite for the user if no userId is provided in the params and the invite exists", async function () { - const inviteId = await addInviteToInviteModel({ userId: superUserId, inviteLink: "discord.gg/apQYT7HB" }); + await addInviteToInviteModel({ userId: superUserId, inviteLink: "discord.gg/apQYT7HB" }); const res = await chai .request(app) @@ -559,16 +559,12 @@ describe("Discord actions", function () { expect(res.body).to.be.a("object"); expect(res.body).to.deep.equal({ message: "Invite returned successfully", - inviteResponse: { - id: inviteId, - inviteLink: "discord.gg/apQYT7HB", - userId: superUserId, - }, + inviteLink: "discord.gg/apQYT7HB", }); }); it("Should return the invite for other user if the userId is provided in the query and the user is super user", async function () { - const inviteId = await addInviteToInviteModel({ userId: userId, inviteLink: "discord.gg/apQYT7HA" }); + await addInviteToInviteModel({ userId: userId, inviteLink: "discord.gg/apQYT7HA" }); const res = await chai .request(app) .get(`/discord-actions/invite?userId=${userId}`) @@ -577,11 +573,7 @@ describe("Discord actions", function () { expect(res.body).to.be.a("object"); expect(res.body).to.deep.equal({ message: "Invite returned successfully", - inviteResponse: { - id: inviteId, - inviteLink: "discord.gg/apQYT7HA", - userId: userId, - }, + inviteLink: "discord.gg/apQYT7HA", }); }); From 1ae3bef74ddf1cbad309dbcb0c063fb0ace0ac09 Mon Sep 17 00:00:00 2001 From: vinayak Date: Thu, 9 Nov 2023 21:45:20 +0530 Subject: [PATCH 16/18] fix for failing unit test --- test/unit/services/users.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/services/users.test.js b/test/unit/services/users.test.js index 021c9d826..59384b0a7 100644 --- a/test/unit/services/users.test.js +++ b/test/unit/services/users.test.js @@ -53,7 +53,7 @@ describe("Users services", function () { expect(res).to.deep.equal({ message: "Successfully completed batch updates", - totalUsersArchived: 19, + totalUsersArchived: 20, totalOperationsFailed: 0, updatedUserDetails: userDetails, failedUserDetails: [], @@ -74,7 +74,7 @@ describe("Users services", function () { expect(res).to.deep.equal({ message: "Firebase batch operation failed", totalUsersArchived: 0, - totalOperationsFailed: 19, + totalOperationsFailed: 20, updatedUserDetails: [], failedUserDetails: userDetails, }); From 9f2870cbe839112ff1453b1293a02e9817af4dc3 Mon Sep 17 00:00:00 2001 From: vinayak Date: Sat, 18 Nov 2023 21:04:39 +0530 Subject: [PATCH 17/18] made suggested changes --- controllers/discordactions.js | 11 ++++++----- types/global.d.ts | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/controllers/discordactions.js b/controllers/discordactions.js index c08e3dbc5..f5b0d5568 100644 --- a/controllers/discordactions.js +++ b/controllers/discordactions.js @@ -409,9 +409,10 @@ const generateInviteForUser = async (req, res) => { method: "POST", body: JSON.stringify(inviteOptions), headers: { "Content-Type": "application/json", Authorization: `Bearer ${authToken}` }, - }).then((response) => response.json()); + }); + const discordInviteResponse = await response.json(); - const inviteCode = response.data.code; + const inviteCode = discordInviteResponse.data.code; const inviteLink = `discord.gg/${inviteCode}`; await discordRolesModel.addInviteToInviteModel({ userId: userIdForInvite, inviteLink }); @@ -435,15 +436,15 @@ const getUserDiscordInvite = async (req, res) => { const userIdForInvite = userId || req.userData.id; - const modelResponse = await discordRolesModel.getUserDiscordInvite(userIdForInvite); + const invite = await discordRolesModel.getUserDiscordInvite(userIdForInvite); - if (modelResponse.notFound) { + if (invite.notFound) { return res.boom.notFound("User invite doesn't exist"); } return res.json({ message: "Invite returned successfully", - inviteLink: modelResponse?.inviteLink, + inviteLink: invite?.inviteLink, }); } catch (err) { logger.error(`Error in fetching user invite: ${err}`); diff --git a/types/global.d.ts b/types/global.d.ts index a43f48c81..6333142f8 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -11,7 +11,7 @@ export type userData = { member?: boolean; maven?: boolean; designer?: boolean; - product_manager: boolean; + product_manager?: boolean; }; profileStatus: string; created_at: number; From 4431f07d47c94fa4804a92fc4d0e7d0508c2dec5 Mon Sep 17 00:00:00 2001 From: vinayak Date: Fri, 24 Nov 2023 06:46:49 +0530 Subject: [PATCH 18/18] updated one model test and added one model test for getInvite model --- test/unit/models/discordactions.test.js | 35 +++++++++++++------------ 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/test/unit/models/discordactions.test.js b/test/unit/models/discordactions.test.js index 318744194..be9389fc9 100644 --- a/test/unit/models/discordactions.test.js +++ b/test/unit/models/discordactions.test.js @@ -7,7 +7,6 @@ const discordRoleModel = firestore.collection("discord-roles"); const memberRoleModel = firestore.collection("member-group-roles"); const userModel = firestore.collection("users"); const admin = require("firebase-admin"); -const discordInvitesModel = firestore.collection("discord-invites"); const { createNewRole, @@ -20,6 +19,7 @@ const { fetchGroupToUserMapping, updateUsersNicknameStatus, addInviteToInviteModel, + getUserDiscordInvite, } = require("../../../models/discordactions"); const { groupData, roleData, existingRole, memberGroupData } = require("../../fixtures/discordactions/discordactions"); const cleanDb = require("../../utils/cleanDb"); @@ -571,29 +571,30 @@ describe("discordactions", function () { }); describe("addInviteToInviteModel", function () { - let addStub; - - beforeEach(function () { - addStub = sinon.stub(discordInvitesModel, "add").resolves({ id: "invite-test-id" }); - }); - - afterEach(function () { - addStub.restore(); - }); - it("should add invite in the invite model for user", async function () { const inviteObject = { userId: "kfjkasdfl", inviteLink: "discord.gg/xyz" }; const inviteId = await addInviteToInviteModel(inviteObject); expect(inviteId).to.exist; // eslint-disable-line no-unused-expressions }); + }); - it("should throw an error if creating invite fails", async function () { + describe("getUserDiscordInvite", function () { + before(async function () { const inviteObject = { userId: "kfjkasdfl", inviteLink: "discord.gg/xyz" }; - addStub.rejects(new Error("Database error!")); - return await addInviteToInviteModel(inviteObject).catch((error) => { - expect(error).to.be.an.instanceOf(Error); - expect(error.message).to.equal("Database error!"); - }); + await addInviteToInviteModel(inviteObject); + }); + + it("should return invite for the user when the userId of a user is passed at it exists in the db", async function () { + const invite = await getUserDiscordInvite("kfjkasdfl"); + expect(invite).to.have.property("id"); + expect(invite.notFound).to.be.equal(false); + expect(invite.userId).to.be.equal("kfjkasdfl"); + expect(invite.inviteLink).to.be.equal("discord.gg/xyz"); + }); + + it("should return notFound true, if the invite for user doesn't exist", async function () { + const invite = await getUserDiscordInvite("kfjkasdafdfdsfl"); + expect(invite.notFound).to.be.equal(true); }); }); });