Skip to content

Commit 88107de

Browse files
Merge branch 'develop' into feat/issue1314
2 parents 786e7be + 9d8dc64 commit 88107de

16 files changed

+343
-27
lines changed

controllers/discordactions.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const admin = require("firebase-admin");
33
const config = require("config");
44
const jwt = require("jsonwebtoken");
55
const discordRolesModel = require("../models/discordactions");
6+
const { retrieveUsers } = require("../services/dataAccessLayer");
67

78
/**
89
* Creates a role
@@ -66,9 +67,25 @@ const createGroupRole = async (req, res) => {
6667
const getAllGroupRoles = async (req, res) => {
6768
try {
6869
const { groups } = await discordRolesModel.getAllGroupRoles();
70+
const groupsWithMemberCount = await discordRolesModel.getNumberOfMemberForGroups(groups);
71+
const groupCreatorIds = groupsWithMemberCount.reduce((ids, group) => {
72+
ids.add(group.createdBy);
73+
return ids;
74+
}, new Set());
75+
const groupCreatorsDetails = await retrieveUsers({ userIds: Array.from(groupCreatorIds) });
76+
const groupsWithUserDetails = groupsWithMemberCount.map((group) => {
77+
const groupCreator = groupCreatorsDetails[group.createdBy];
78+
return {
79+
...group,
80+
firstName: groupCreator.first_name,
81+
lastName: groupCreator.last_name,
82+
image: groupCreator.picture?.url,
83+
};
84+
});
85+
6986
return res.json({
7087
message: "Roles fetched successfully!",
71-
groups,
88+
groups: groupsWithUserDetails,
7289
});
7390
} catch (err) {
7491
logger.error(`Error while getting roles: ${err}`);

controllers/issues.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const getIssues = async (req, res) => {
2525
const taskData = await tasks.fetchTaskByIssueId(issue.id);
2626
if (taskData) {
2727
issue.taskExists = true;
28+
issue.taskId = taskData.id;
2829
}
2930

3031
return issue;

models/discordactions.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,41 @@ const updateDiscordImageForVerification = async (userDiscordId) => {
114114
}
115115
};
116116

117+
const getNumberOfMemberForGroups = async (groups = []) => {
118+
try {
119+
if (!groups.length) {
120+
return [];
121+
}
122+
const roleIds = groups.map((group) => group.roleid);
123+
124+
const snapshots = await memberRoleModel.where("roleid", "in", roleIds).get();
125+
const roleCount = {};
126+
127+
snapshots.forEach((doc) => {
128+
const roleToMemberMapping = doc.data();
129+
130+
if (roleCount[roleToMemberMapping.roleid]) {
131+
roleCount[roleToMemberMapping.roleid] += 1;
132+
} else {
133+
roleCount[roleToMemberMapping.roleid] = 1;
134+
}
135+
});
136+
137+
return groups.map((group) => ({
138+
...group,
139+
memberCount: roleCount[group.roleid] || 0,
140+
}));
141+
} catch (err) {
142+
logger.error("Error while counting members for each group", err);
143+
throw err;
144+
}
145+
};
146+
117147
module.exports = {
118148
createNewRole,
119149
getAllGroupRoles,
120150
addGroupRoleToMember,
121151
isGroupRoleExists,
122152
updateDiscordImageForVerification,
153+
getNumberOfMemberForGroups,
123154
};

models/userStatus.js

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const {
1111
checkIfUserHasLiveTasks,
1212
generateErrorResponse,
1313
generateNewStatus,
14+
getNextDayTimeStamp,
1415
} = require("../utils/userStatus");
1516
const { TASK_STATUS } = require("../constants/tasks");
1617
const userStatusModel = firestore.collection("usersStatus");
@@ -371,7 +372,7 @@ const batchUpdateUsersStatus = async (users) => {
371372
const statusToUpdate = {
372373
state,
373374
message: "",
374-
from: currentTimeStamp,
375+
from: new Date().setUTCHours(0, 0, 0, 0),
375376
until: "",
376377
updatedAt: currentTimeStamp,
377378
};
@@ -391,8 +392,7 @@ const batchUpdateUsersStatus = async (users) => {
391392
if (currentState === state) {
392393
currentState === userState.ACTIVE ? summary.activeUsersUnaltered++ : summary.idleUsersUnaltered++;
393394
continue;
394-
}
395-
if (currentState === userState.ONBOARDING) {
395+
} else if (currentState === userState.ONBOARDING) {
396396
const docRef = userStatusModel.doc(id);
397397
if (state === userState.ACTIVE) {
398398
const updatedStatusData = {
@@ -403,20 +403,35 @@ const batchUpdateUsersStatus = async (users) => {
403403
} else {
404404
summary.onboardingUsersUnaltered++;
405405
}
406-
} else {
406+
} else if (currentState === userState.OOO) {
407+
const docRef = userStatusModel.doc(id);
407408
state === userState.ACTIVE ? summary.activeUsersAltered++ : summary.idleUsersAltered++;
409+
410+
const currentDate = new Date();
411+
const untilDate = new Date(until);
412+
413+
const timeDifferenceMilliseconds = currentDate.setUTCHours(0, 0, 0, 0) - untilDate.setUTCHours(0, 0, 0, 0);
414+
const timeDifferenceDays = Math.floor(timeDifferenceMilliseconds / (24 * 60 * 60 * 1000));
415+
416+
if (timeDifferenceDays >= 1) {
417+
batch.update(docRef, {
418+
currentStatus: statusToUpdate,
419+
});
420+
} else {
421+
const getNextDayAfterUntil = getNextDayTimeStamp(until);
422+
batch.update(docRef, {
423+
futureStatus: {
424+
...statusToUpdate,
425+
from: getNextDayAfterUntil,
426+
},
427+
});
428+
}
429+
} else {
408430
const docRef = userStatusModel.doc(id);
409-
const updatedStatusData =
410-
currentState === userState.OOO
411-
? {
412-
futureStatus: {
413-
...statusToUpdate,
414-
from: until,
415-
},
416-
}
417-
: {
418-
currentStatus: statusToUpdate,
419-
};
431+
state === userState.ACTIVE ? summary.activeUsersAltered++ : summary.idleUsersAltered++;
432+
const updatedStatusData = {
433+
currentStatus: statusToUpdate,
434+
};
420435
batch.update(docRef, updatedStatusData);
421436
}
422437
}

models/users.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,31 @@ const fetchUsersWithToken = async () => {
584584
return users;
585585
} catch (err) {
586586
logger.error(`Error while fetching all users with tokens field: ${err}`);
587+
return [];
588+
}
589+
};
590+
/**
591+
*
592+
* @param {[string]} userIds Array id's of user
593+
* @returns Object containing the details of the users whose userId was provided.
594+
*/
595+
const fetchUserByIds = async (userIds = []) => {
596+
if (userIds.length === 0) {
597+
return {};
598+
}
599+
try {
600+
const users = {};
601+
const usersRefs = userIds.map((docId) => userModel.doc(docId));
602+
const documents = await firestore.getAll(...usersRefs);
603+
documents.forEach((snapshot) => {
604+
if (snapshot.exists) {
605+
users[snapshot.id] = snapshot.data();
606+
}
607+
});
608+
609+
return users;
610+
} catch (err) {
611+
logger.error("Error retrieving user data", err);
587612
throw err;
588613
}
589614
};
@@ -666,4 +691,5 @@ module.exports = {
666691
fetchUsersWithToken,
667692
removeGitHubToken,
668693
getUsersByRole,
694+
fetchUserByIds,
669695
};

services/dataAccessLayer.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const retrieveUsers = async ({
1010
userdata,
1111
level = ACCESS_LEVEL.PUBLIC,
1212
role = null,
13+
userIds = [],
1314
}) => {
1415
if (id || username) {
1516
let result;
@@ -29,6 +30,12 @@ const retrieveUsers = async ({
2930
result.push(user);
3031
});
3132
return result;
33+
} else if (userIds.length > 0) {
34+
const userDetails = await userQuery.fetchUserByIds(userIds);
35+
Object.keys(userDetails).forEach((userId) => {
36+
removeSensitiveInfo(userDetails[userId]);
37+
});
38+
return userDetails;
3239
} else if (query) {
3340
const { allUsers, nextId, prevId } = await userQuery.fetchPaginatedUsers(query);
3441
const users = [];

test/fixtures/discordactions/discordactions.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const groupData = [
2-
{ id: "1", name: "Group 1" },
3-
{ id: "2", name: "Group 2" },
4-
{ id: "3", name: "Group 3" },
2+
{ rolename: "Group 1", roleid: 1 },
3+
{ rolename: "Group 2", roleid: 2 },
4+
{ rolename: "Group 3", roleid: 3 },
55
];
66

77
const roleData = {

test/integration/discord.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ const authService = require("../../services/authService");
88
const userData = require("../fixtures/user/user")();
99
const { requestRoleData } = require("../fixtures/discordactions/discordactions");
1010

11+
const firestore = require("../../utils/firestore");
12+
const discordRoleModel = firestore.collection("discord-roles");
13+
const userModel = firestore.collection("users");
14+
15+
const { addGroupRoleToMember } = require("../../models/discordactions");
16+
17+
const { groupData } = require("../fixtures/discordactions/discordactions");
18+
1119
const cookieName = config.get("userToken.cookieName");
1220

1321
let userId;
@@ -59,6 +67,29 @@ describe("test discord actions", function () {
5967
const user = { ...userData[4], discordId: "123456789" };
6068
userId = await addUser(user);
6169
jwt = authService.generateAuthToken({ userId });
70+
71+
let allIds = [];
72+
73+
const addUsersPromises = userData.map((user) => userModel.add({ ...user }));
74+
const responses = await Promise.all(addUsersPromises);
75+
allIds = responses.map((response) => response.id);
76+
77+
const addRolesPromises = [
78+
discordRoleModel.add({ roleid: groupData[0].roleid, rolename: groupData[0].rolename, createdBy: allIds[1] }),
79+
discordRoleModel.add({ roleid: groupData[1].roleid, rolename: groupData[1].rolename, createdBy: allIds[0] }),
80+
];
81+
await Promise.all(addRolesPromises);
82+
83+
const addGroupRolesPromises = [
84+
addGroupRoleToMember({ roleid: groupData[0].roleid, userid: allIds[0] }),
85+
addGroupRoleToMember({ roleid: groupData[0].roleid, userid: allIds[1] }),
86+
addGroupRoleToMember({ roleid: groupData[0].roleid, userid: allIds[1] }),
87+
addGroupRoleToMember({ roleid: groupData[1].roleid, userid: allIds[0] }),
88+
];
89+
await Promise.all(addGroupRolesPromises);
90+
});
91+
afterEach(async function () {
92+
await cleanDb();
6293
});
6394

6495
it("returns 200 for active users get method", function (done) {

test/integration/discordactions.test.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ const cookieName = config.get("userToken.cookieName");
1616
const firestore = require("../../utils/firestore");
1717
const { userPhotoVerificationData } = require("../fixtures/user/photo-verification");
1818
const photoVerificationModel = firestore.collection("photo-verification");
19+
const discordRoleModel = firestore.collection("discord-roles");
20+
const userModel = firestore.collection("users");
21+
22+
const { groupData } = require("../fixtures/discordactions/discordactions");
23+
const { addGroupRoleToMember } = require("../../models/discordactions");
1924
chai.use(chaiHttp);
2025

2126
describe("Discord actions", function () {
@@ -85,4 +90,54 @@ describe("Discord actions", function () {
8590
});
8691
});
8792
});
93+
94+
describe("GET /discord-actions/groups", function () {
95+
before(async function () {
96+
let allIds = [];
97+
98+
const addUsersPromises = userData.map((user) => userModel.add({ ...user }));
99+
const responses = await Promise.all(addUsersPromises);
100+
allIds = responses.map((response) => response.id);
101+
102+
const addRolesPromises = [
103+
discordRoleModel.add({ roleid: groupData[0].roleid, rolename: groupData[0].rolename, createdBy: allIds[1] }),
104+
discordRoleModel.add({ roleid: groupData[1].roleid, rolename: groupData[1].rolename, createdBy: allIds[0] }),
105+
];
106+
await Promise.all(addRolesPromises);
107+
108+
const addGroupRolesPromises = [
109+
addGroupRoleToMember({ roleid: groupData[0].roleid, userid: allIds[0] }),
110+
addGroupRoleToMember({ roleid: groupData[0].roleid, userid: allIds[1] }),
111+
addGroupRoleToMember({ roleid: groupData[0].roleid, userid: allIds[1] }),
112+
addGroupRoleToMember({ roleid: groupData[1].roleid, userid: allIds[0] }),
113+
];
114+
await Promise.all(addGroupRolesPromises);
115+
});
116+
117+
after(async function () {
118+
await cleanDb();
119+
});
120+
121+
it("should successfully return all groups detail", function (done) {
122+
chai
123+
.request(app)
124+
.get(`/discord-actions/groups`)
125+
.set("cookie", `${cookieName}=${superUserAuthToken}`)
126+
.end((err, res) => {
127+
if (err) {
128+
return done(err);
129+
}
130+
131+
expect(res).to.have.status(200);
132+
expect(res.body).to.be.an("object");
133+
// Verify presence of specific properties in each group
134+
const expectedProps = ["roleid", "rolename", "memberCount", "firstName", "lastName", "image"];
135+
res.body.groups.forEach((group) => {
136+
expect(group).to.include.all.keys(expectedProps);
137+
});
138+
expect(res.body.message).to.equal("Roles fetched successfully!");
139+
return done();
140+
});
141+
});
142+
});
88143
});

0 commit comments

Comments
 (0)