Skip to content

Commit 4a2c6ed

Browse files
add unverified role to db and remove on /verify
1 parent c0b5305 commit 4a2c6ed

File tree

6 files changed

+192
-18
lines changed

6 files changed

+192
-18
lines changed

constants/logs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export const logType = {
1010
TASKS_MISSED_UPDATES_ERRORS: "TASKS_MISSED_UPDATES_ERRORS",
1111
DISCORD_INVITES: "DISCORD_INVITES",
1212
EXTERNAL_SERVICE: "EXTERNAL_SERVICE",
13+
ADD_UNVERIFIED_ROLE: "ADD_UNVERIFIED_ROLE",
14+
REMOVE_UNVERIFIED_ROLE: "REMOVE_UNVERIFIED_ROLE",
1315
EXTENSION_REQUESTS: "extensionRequests",
1416
TASK: "task",
1517
TASK_REQUESTS: "taskRequests",

controllers/external-accounts.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const { getDiscordMembers } = require("../services/discordService");
44
const { addOrUpdate, getUsersByRole, updateUsersInBatch } = require("../models/users");
55
const { retrieveDiscordUsers, fetchUsersForKeyValues } = require("../services/dataAccessLayer");
66
const { EXTERNAL_ACCOUNTS_POST_ACTIONS } = require("../constants/external-accounts");
7-
const discordServices = require("../services/discordService");
7+
const removeDiscordRoleUtils = require("../utils/removeDiscordRoleFromUser");
88
const config = require("config");
99
const logger = require("../utils/logger");
1010
const { markUnDoneTasksOfArchivedUsersBacklog } = require("../models/tasks");
@@ -71,14 +71,20 @@ const linkExternalAccount = async (req, res) => {
7171
userId
7272
);
7373

74-
try {
75-
const unverifiedRoleId = config.get("discordUnverifiedRoleId");
76-
await discordServices.removeRoleFromUser(unverifiedRoleId, attributes.discordId, req.userData);
77-
} catch (error) {
78-
logger.error(`Error getting external account data: ${error}`);
79-
return res.boom.internal("Role Deletion failed. Please contact admin.", {
80-
message: "Role Deletion failed. Please contact admin.",
81-
});
74+
const unverifiedRoleId = config.get("discordUnverifiedRoleId");
75+
const unverifiedRoleRemovalResponse = await removeDiscordRoleUtils.removeDiscordRoleFromUser(
76+
req.userData,
77+
attributes.discordId,
78+
unverifiedRoleId
79+
);
80+
81+
if (!unverifiedRoleRemovalResponse.success) {
82+
return res.boom.internal(
83+
`User details updated but ${unverifiedRoleRemovalResponse.message}. Please contact admin`,
84+
{
85+
message: `User details updated but ${unverifiedRoleRemovalResponse.message}. Please contact admin`,
86+
}
87+
);
8288
}
8389

8490
return res.status(204).json({ message: "Your discord profile has been linked successfully" });

controllers/users.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const chaincodeQuery = require("../models/chaincodes");
22
const userQuery = require("../models/users");
33
const profileDiffsQuery = require("../models/profileDiffs");
4+
const admin = require("firebase-admin");
45
const logsQuery = require("../models/logs");
56
const imageService = require("../services/imageService");
67
const { profileDiffStatus } = require("../constants/profileDiff");
@@ -30,6 +31,8 @@ const { addLog } = require("../models/logs");
3031
const { getUserStatus } = require("../models/userStatus");
3132
const config = require("config");
3233
const { generateUniqueUsername } = require("../services/users");
34+
const { addGroupRoleToMember } = require("../models/discordactions");
35+
3336
const discordDeveloperRoleId = config.get("discordDeveloperRoleId");
3437

3538
const verifyUser = async (req, res) => {
@@ -595,7 +598,6 @@ const markUnverified = async (req, res) => {
595598
const unverifiedRoleId = config.get("discordUnverifiedRoleId");
596599
const usersToApplyUnverifiedRole = [];
597600
const addRolePromises = [];
598-
const discordDeveloperRoleId = config.get("discordDeveloperRoleId");
599601

600602
allRdsLoggedInUsers.forEach((user) => {
601603
rdsUserMap[user.discordId] = true;
@@ -612,7 +614,19 @@ const markUnverified = async (req, res) => {
612614
});
613615

614616
usersToApplyUnverifiedRole.forEach((id) => {
615-
addRolePromises.push(addRoleToUser(id, unverifiedRoleId));
617+
addRolePromises.push(
618+
addRoleToUser(id, unverifiedRoleId),
619+
addGroupRoleToMember({
620+
roleid: unverifiedRoleId,
621+
userid: id,
622+
date: admin.firestore.Timestamp.fromDate(new Date()),
623+
}),
624+
addLog(
625+
logType.ADD_UNVERIFIED_ROLE,
626+
{ roleid: unverifiedRoleId, userid: id },
627+
{ message: "Unverified role added successfully" }
628+
)
629+
);
616630
});
617631

618632
await Promise.all(addRolePromises);

test/integration/external-accounts.test.js

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ const externalAccountsModel = require("../../models/external-accounts");
1212
const { usersFromRds, getDiscordMembers } = require("../fixtures/discordResponse/discord-response");
1313
const Sinon = require("sinon");
1414
const { INTERNAL_SERVER_ERROR } = require("../../constants/errorMessages");
15+
const removeDiscordRoleUtils = require("../../utils/removeDiscordRoleFromUser");
1516
const firestore = require("../../utils/firestore");
1617
const userData = require("../fixtures/user/user")();
1718
const userModel = firestore.collection("users");
1819
const tasksModel = firestore.collection("tasks");
19-
const discordServices = require("../../services/discordService");
2020
const { EXTERNAL_ACCOUNTS_POST_ACTIONS } = require("../../constants/external-accounts");
2121
chai.use(chaiHttp);
2222
const cookieName = config.get("userToken.cookieName");
@@ -538,7 +538,10 @@ describe("External Accounts", function () {
538538
expect(getUserResponseBeforeUpdate.body).to.not.have.property("discordId");
539539
expect(getUserResponseBeforeUpdate.body).to.not.have.property("discordJoinedAt");
540540

541-
const removeRoleFromUserStub = Sinon.stub(discordServices, "removeRoleFromUser").resolves();
541+
const removeDiscordRoleStub = Sinon.stub(removeDiscordRoleUtils, "removeDiscordRoleFromUser").resolves({
542+
success: true,
543+
message: "Role deleted successfully",
544+
});
542545

543546
const response = await chai
544547
.request(app)
@@ -557,26 +560,59 @@ describe("External Accounts", function () {
557560
expect(updatedUserDetails.body).to.have.property("discordId");
558561
expect(updatedUserDetails.body).to.have.property("discordJoinedAt");
559562

560-
removeRoleFromUserStub.restore();
563+
removeDiscordRoleStub.restore();
564+
});
565+
566+
it("Should return 500 when removeDiscordRole fails because role doesn't exist", async function () {
567+
await externalAccountsModel.addExternalAccountData(externalAccountData[2]);
568+
569+
const removeDiscordRoleStub = Sinon.stub(removeDiscordRoleUtils, "removeDiscordRoleFromUser").resolves({
570+
success: false,
571+
message: "Role doesn't exist",
572+
});
573+
574+
const response = await chai
575+
.request(app)
576+
.patch(`/external-accounts/link/${externalAccountData[2].token}`)
577+
.query({ action: EXTERNAL_ACCOUNTS_POST_ACTIONS.DISCORD_USERS_SYNC })
578+
.set("Cookie", `${cookieName}=${newUserJWT}`);
579+
580+
const unverifiedRoleRemovalResponse = await removeDiscordRoleStub();
581+
582+
expect(response).to.have.status(500);
583+
expect(response.body).to.be.an("object");
584+
expect(response.body).to.have.property("message");
585+
expect(response.body.message).to.equal(
586+
`User details updated but ${unverifiedRoleRemovalResponse.message}. Please contact admin`
587+
);
588+
589+
removeDiscordRoleStub.restore();
561590
});
562591

563-
it("Should return 500 when unverified role deletion failed", async function () {
592+
it("Should return 500 when removeDiscordRole fails because role deletion failed", async function () {
564593
await externalAccountsModel.addExternalAccountData(externalAccountData[2]);
565594

566-
const removeRoleFromUserStub = Sinon.stub(discordServices, "removeRoleFromUser").rejects();
595+
const removeDiscordRoleStub = Sinon.stub(removeDiscordRoleUtils, "removeDiscordRoleFromUser").resolves({
596+
success: false,
597+
message: "Role deletion failed",
598+
});
567599

568600
const response = await chai
569601
.request(app)
570602
.patch(`/external-accounts/link/${externalAccountData[2].token}`)
571603
.query({ action: EXTERNAL_ACCOUNTS_POST_ACTIONS.DISCORD_USERS_SYNC })
572604
.set("Cookie", `${cookieName}=${newUserJWT}`);
573605

606+
const unverifiedRoleRemovalResponse = await removeDiscordRoleStub();
607+
574608
expect(response).to.have.status(500);
575609
expect(response.body).to.be.an("object");
576610
expect(response.body).to.have.property("message");
577-
expect(response.body.message).to.equal(`Role Deletion failed. Please contact admin.`);
611+
expect(response.body.message).to.equal(
612+
`User details updated but ${unverifiedRoleRemovalResponse.message}. Please contact admin`
613+
);
578614

579-
removeRoleFromUserStub.restore();
615+
removeDiscordRoleStub.restore();
580616
});
581617
});
582618
});
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
const chai = require("chai");
2+
const Sinon = require("sinon");
3+
const { expect } = chai;
4+
const { removeDiscordRoleFromUser } = require("../../../utils/removeDiscordRoleFromUser");
5+
const addUser = require("../../utils/addUser");
6+
const cleanDb = require("../../utils/cleanDb");
7+
const firestore = require("../../../utils/firestore");
8+
const discordRolesModel = firestore.collection("discord-roles");
9+
const memberRoleModel = firestore.collection("member-group-roles");
10+
const userData = require("../../fixtures/user/user")();
11+
const { groupData, memberGroupData } = require("../../fixtures/discordactions/discordactions");
12+
13+
describe("removeDiscordRoleFromUser", function () {
14+
let userId;
15+
let discordId;
16+
let roleid;
17+
let fetchStub;
18+
19+
beforeEach(async function () {
20+
userData[0].roles = { archived: false, in_discord: true };
21+
userId = await addUser(userData[0]);
22+
discordId = userData[0].discordId;
23+
userData[0] = { ...userData[0], id: userId };
24+
25+
const addRolePromises = memberGroupData.map(async (data) => {
26+
await memberRoleModel.add(data);
27+
});
28+
const discordRolesModelPromise = [discordRolesModel.add(groupData[0]), discordRolesModel.add(groupData[1])];
29+
await Promise.all(discordRolesModelPromise);
30+
roleid = groupData[0].roleid;
31+
await memberRoleModel.add({ roleid, userid: discordId });
32+
await Promise.all(addRolePromises);
33+
34+
fetchStub = Sinon.stub(global, "fetch");
35+
});
36+
37+
afterEach(async function () {
38+
await cleanDb();
39+
fetchStub.restore();
40+
});
41+
42+
it("should remove discord role successfully", async function () {
43+
fetchStub.returns(
44+
Promise.resolve({ json: () => Promise.resolve({ success: true, message: "Role deleted successfully" }) })
45+
);
46+
47+
const isDiscordRoleRemoved = await removeDiscordRoleFromUser(userData[0], discordId, roleid);
48+
49+
expect(isDiscordRoleRemoved.success).to.be.equal(true);
50+
expect(isDiscordRoleRemoved.message).to.be.equal("Role deleted successfully");
51+
});
52+
53+
it("should throw an error if role doesn't exist in database when attempting to remove", async function () {
54+
roleid = "randomRoleId";
55+
56+
try {
57+
await removeDiscordRoleFromUser(userData[0], discordId, roleid);
58+
} catch (error) {
59+
expect(error.message).to.equal("Role doesn't exist");
60+
}
61+
});
62+
63+
it("should throw an error if role deletion failed", async function () {
64+
fetchStub.rejects(new Error("Role deletion failed"));
65+
66+
try {
67+
await removeDiscordRoleFromUser(userData[0], discordId, roleid);
68+
} catch (error) {
69+
expect(error.message).to.equal("Role deletion failed");
70+
}
71+
});
72+
});

utils/removeDiscordRoleFromUser.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const discordRolesModel = require("../models/discordactions");
2+
const discordServices = require("../services/discordService");
3+
const { logType } = require("../constants/logs");
4+
const { addLog } = require("../models/logs");
5+
6+
/**
7+
* Removes a Discord role from a user using Discord Id.
8+
*
9+
* @param {Object} userData - User data.
10+
* @param {string} discordId - User's Discord ID.
11+
* @param {string} roleid - Discord Role ID.
12+
*
13+
* @returns {Promise<Object>} - Result with success status and message.
14+
*/
15+
export const removeDiscordRoleFromUser = async (userData, discordId, roleid) => {
16+
try {
17+
const role = await discordRolesModel.isGroupRoleExists({ roleid });
18+
19+
if (!role.roleExists) {
20+
throw new Error("Role doesn't exist");
21+
}
22+
23+
const roleData = role.existingRoles.docs[0].data();
24+
25+
await discordServices.removeRoleFromUser(roleData.roleid, discordId, userData);
26+
27+
const { wasSuccess } = await discordRolesModel.removeMemberGroup(roleData.roleid, discordId);
28+
if (!wasSuccess) {
29+
throw new Error("Role deletion failed");
30+
}
31+
32+
await addLog(
33+
logType.REMOVE_UNVERIFIED_ROLE,
34+
{ roleid, userid: discordId },
35+
{ message: "Unverified role removed successfully" }
36+
);
37+
38+
return { success: true, message: "Role deleted successfully" };
39+
} catch (error) {
40+
logger.error(`Error removing role ${roleid} for user ${discordId}: ${error.message}`);
41+
42+
return { success: false, message: error.message };
43+
}
44+
};

0 commit comments

Comments
 (0)