Skip to content

Commit 824ecf1

Browse files
vinayak-trivedisatyam73prakashchoudhary07
authored
added endpoint for generating and getting discord invite for user (#1553)
* added enpoint for generating and getting discord invite for user * changes in middleware and controller method * changed discordNewComersChannelId constant * tests for endpoint for getting discord link generated for user * tests for post API * fix for failing tests * fix for failing unit test * types issue fixed * model tests * did suggested changes * invite get model test changes * removed the model test getInvite * test description string change * Update test/integration/discordactions.test.js Co-authored-by: Satyam Bajpai <[email protected]> * fix for failing tests * fix for failing unit test * made suggested changes * updated one model test and added one model test for getInvite model --------- Co-authored-by: Satyam Bajpai <[email protected]> Co-authored-by: Prakash Choudhary <[email protected]>
1 parent 579404c commit 824ecf1

File tree

11 files changed

+403
-3
lines changed

11 files changed

+403
-3
lines changed

config/development.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module.exports = {
1010
port: port,
1111
enableFileLogs: false,
1212
enableConsoleLogs: true,
13+
discordNewComersChannelId: "709080951824842783",
1314

1415
services: {
1516
rdsApi: {

config/test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = {
1111
enableConsoleLogs: true,
1212
discordUnverifiedRoleId: "1234567890",
1313
discordDeveloperRoleId: "9876543210",
14+
discordNewComersChannelId: "709080951824842783",
1415
discordMavenRoleId: "1212121212",
1516
githubOauth: {
1617
clientId: "clientId",

controllers/discordactions.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,75 @@ const setRoleToUsersWith31DaysPlusOnboarding = async (req, res) => {
403403
}
404404
};
405405

406+
const generateInviteForUser = async (req, res) => {
407+
try {
408+
const { userId } = req.query;
409+
const userIdForInvite = userId || req.userData.id;
410+
411+
const modelResponse = await discordRolesModel.getUserDiscordInvite(userIdForInvite);
412+
413+
if (!modelResponse.notFound) {
414+
return res.status(409).json({
415+
message: "User invite is already present!",
416+
});
417+
}
418+
419+
const channelId = config.get("discordNewComersChannelId");
420+
const authToken = jwt.sign({}, config.get("rdsServerlessBot.rdsServerLessPrivateKey"), {
421+
algorithm: "RS256",
422+
expiresIn: config.get("rdsServerlessBot.ttl"),
423+
});
424+
425+
const inviteOptions = {
426+
channelId: channelId,
427+
};
428+
const response = await fetch(`${DISCORD_BASE_URL}/invite`, {
429+
method: "POST",
430+
body: JSON.stringify(inviteOptions),
431+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${authToken}` },
432+
});
433+
const discordInviteResponse = await response.json();
434+
435+
const inviteCode = discordInviteResponse.data.code;
436+
const inviteLink = `discord.gg/${inviteCode}`;
437+
438+
await discordRolesModel.addInviteToInviteModel({ userId: userIdForInvite, inviteLink });
439+
440+
return res.status(201).json({
441+
message: "invite generated successfully",
442+
inviteLink,
443+
});
444+
} catch (err) {
445+
logger.error(`Error in generating invite for user: ${err}`);
446+
return res.boom.badImplementation(INTERNAL_SERVER_ERROR);
447+
}
448+
};
449+
450+
const getUserDiscordInvite = async (req, res) => {
451+
try {
452+
const { userId } = req.query;
453+
const isSuperUser = req.userData.roles.super_user;
454+
455+
if (userId && !isSuperUser) return res.boom.forbidden("User should be super user to get link for other users");
456+
457+
const userIdForInvite = userId || req.userData.id;
458+
459+
const invite = await discordRolesModel.getUserDiscordInvite(userIdForInvite);
460+
461+
if (invite.notFound) {
462+
return res.boom.notFound("User invite doesn't exist");
463+
}
464+
465+
return res.json({
466+
message: "Invite returned successfully",
467+
inviteLink: invite?.inviteLink,
468+
});
469+
} catch (err) {
470+
logger.error(`Error in fetching user invite: ${err}`);
471+
return res.boom.badImplementation(INTERNAL_SERVER_ERROR);
472+
}
473+
};
474+
406475
module.exports = {
407476
getGroupsRoleId,
408477
createGroupRole,
@@ -416,4 +485,6 @@ module.exports = {
416485
updateUsersNicknameStatus,
417486
syncDiscordGroupRolesInFirestore,
418487
setRoleToUsersWith31DaysPlusOnboarding,
488+
getUserDiscordInvite,
489+
generateInviteForUser,
419490
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { NextFunction } from "express";
2+
import { CustomRequest, CustomResponse } from "../types/global";
3+
4+
const checkCanGenerateDiscordLink = async (req: CustomRequest, res: CustomResponse, next: NextFunction) => {
5+
const { discordId, roles, id: userId, profileStatus } = req.userData;
6+
const isSuperUser = roles.super_user;
7+
const userIdInQuery = req.query.userId;
8+
9+
if (userIdInQuery && userIdInQuery !== userId && !isSuperUser) {
10+
return res.boom.forbidden("User should be super user to generate link for other users");
11+
}
12+
13+
if (discordId) {
14+
return res.boom.forbidden("Only users who have never joined discord can generate invite link");
15+
}
16+
17+
if (roles.archived) {
18+
return res.boom.forbidden("Archived users cannot generate invite");
19+
}
20+
21+
if (!roles.maven && !roles.designer && !roles.product_manager && profileStatus !== "VERIFIED") {
22+
return res.boom.forbidden("Only selected roles can generate discord link directly");
23+
}
24+
25+
return next();
26+
};
27+
28+
module.exports = checkCanGenerateDiscordLink;

models/discordactions.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const { generateDiscordProfileImageUrl } = require("../utils/discord-actions");
22
const firestore = require("../utils/firestore");
33
const discordRoleModel = firestore.collection("discord-roles");
44
const memberRoleModel = firestore.collection("member-group-roles");
5+
const discordInvitesModel = firestore.collection("discord-invites");
56
const admin = require("firebase-admin");
67
const { findSubscribedGroupIds } = require("../utils/helper");
78
const { retrieveUsers } = require("../services/dataAccessLayer");
@@ -830,6 +831,31 @@ const updateUsersWith31DaysPlusOnboarding = async () => {
830831
}
831832
};
832833

834+
const addInviteToInviteModel = async (inviteObject) => {
835+
try {
836+
const invite = await discordInvitesModel.add(inviteObject);
837+
return invite.id;
838+
} catch (err) {
839+
logger.error("Error in adding invite", err);
840+
throw err;
841+
}
842+
};
843+
844+
const getUserDiscordInvite = async (userId) => {
845+
try {
846+
const invite = await discordInvitesModel.where("userId", "==", userId).get();
847+
const [inviteDoc] = invite.docs;
848+
if (inviteDoc) {
849+
return { id: inviteDoc.id, ...inviteDoc.data(), notFound: false };
850+
} else {
851+
return { notFound: true };
852+
}
853+
} catch (err) {
854+
logger.log("error in getting user invite", err);
855+
throw err;
856+
}
857+
};
858+
833859
module.exports = {
834860
createNewRole,
835861
removeMemberGroup,
@@ -847,4 +873,6 @@ module.exports = {
847873
updateUsersNicknameStatus,
848874
updateIdle7dUsersOnDiscord,
849875
updateUsersWith31DaysPlusOnboarding,
876+
getUserDiscordInvite,
877+
addInviteToInviteModel,
850878
};

routes/discordactions.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ const {
88
deleteRole,
99
updateDiscordImageForVerification,
1010
setRoleIdleToIdleUsers,
11+
getUserDiscordInvite,
12+
generateInviteForUser,
1113
setRoleIdle7DToIdleUsers,
1214
updateDiscordNicknames,
1315
updateUsersNicknameStatus,
@@ -20,6 +22,7 @@ const {
2022
validateUpdateUsersNicknameStatusBody,
2123
} = require("../middlewares/validators/discordactions");
2224
const checkIsVerifiedDiscord = require("../middlewares/verifydiscord");
25+
const checkCanGenerateDiscordLink = require("../middlewares/checkCanGenerateDiscordLink");
2326
const { SUPERUSER } = require("../constants/roles");
2427
const authorizeRoles = require("../middlewares/authorizeRoles");
2528
const { verifyCronJob } = require("../middlewares/authorizeBot");
@@ -29,6 +32,8 @@ const router = express.Router();
2932
router.post("/groups", authenticate, checkIsVerifiedDiscord, validateGroupRoleBody, createGroupRole);
3033
router.get("/groups", authenticate, checkIsVerifiedDiscord, getAllGroupRoles);
3134
router.post("/roles", authenticate, checkIsVerifiedDiscord, validateMemberRoleBody, addGroupRoleToMember);
35+
router.get("/invite", authenticate, getUserDiscordInvite);
36+
router.post("/invite", authenticate, checkCanGenerateDiscordLink, generateInviteForUser);
3237
router.delete("/roles", authenticate, checkIsVerifiedDiscord, deleteRole);
3338
router.get("/roles", authenticate, checkIsVerifiedDiscord, getGroupsRoleId);
3439
router.patch(

test/fixtures/user/user.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ module.exports = () => {
217217
archived: false,
218218
member: true,
219219
in_discord: true,
220+
designer: true,
220221
},
221222
twitter_id: "RitvikJamwal4u",
222223
linkedin_id: "ritvik-jamwal4u",
@@ -239,6 +240,7 @@ module.exports = () => {
239240
member: true,
240241
archived: false,
241242
in_discord: true,
243+
product_manager: true,
242244
},
243245
picture: {
244246
publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar",
@@ -261,6 +263,7 @@ module.exports = () => {
261263
},
262264
roles: {
263265
member: true,
266+
maven: true,
264267
},
265268
picture: {
266269
publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar",
@@ -411,5 +414,31 @@ module.exports = () => {
411414
updated_at: Date.now(),
412415
created_at: Date.now(),
413416
},
417+
{
418+
username: "Vinayak",
419+
first_name: "Vinayak",
420+
last_name: "Trivedi",
421+
yoe: 2,
422+
img: "./img.png",
423+
linkedin_id: "_",
424+
github_id: "xfasrfsd",
425+
github_display_name: "vinayak-trivedi",
426+
discordJoinedAt: "2023-04-06T01:47:34.488000+00:00",
427+
phone: "1234567890",
428+
429+
status: "active",
430+
tokens: {
431+
githubAccessToken: "githubAccessToken",
432+
},
433+
roles: {
434+
restricted: false,
435+
app_owner: true,
436+
archived: true,
437+
},
438+
picture: {
439+
publicId: "profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar",
440+
url: "https://res.cloudinary.com/realdevsquad/image/upload/v1667685133/profile/mtS4DhUvNYsKqI7oCWVB/aenklfhtjldc5ytei3ar.jpg",
441+
},
442+
},
414443
];
415444
};

0 commit comments

Comments
 (0)