Skip to content

Commit e0d2a5d

Browse files
authored
Merge pull request #35 from topcoder-platform/plat-1143-OR-validation-issue
fixed the issue of OR validation, not create the resouce if the member is not part of all the associted folder; remove the resource on challenge update if not part of all associated groups
2 parents 9daea63 + 821c2d3 commit e0d2a5d

File tree

4 files changed

+105
-5
lines changed

4 files changed

+105
-5
lines changed

config/default.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module.exports = {
2323
KAFKA_CLIENT_CERT_KEY: process.env.KAFKA_CLIENT_CERT_KEY,
2424
// Topics
2525
CHALLENGE_CREATE_TOPIC: process.env.CHALLENGE_CREATE_TOPIC || 'challenge.notification.create',
26+
CHALLENGE_UPDATE_TOPIC: process.env.CHALLENGE_UPDATE_TOPIC || 'challenge.notification.update',
2627
PROJECT_MEMBER_ADDED_TOPIC: process.env.PROJECT_MEMBER_ADDED_TOPIC || 'connect.notification.project.member.joined',
2728
PROJECT_MEMBER_REMOVED_TOPIC: process.env.PROJECT_MEMBER_REMOVED_TOPIC || 'connect.notification.project.member.removed',
2829

@@ -37,5 +38,9 @@ module.exports = {
3738
RESOURCES_API: process.env.RESOURCES_API || 'http://localhost:4000/v5/resources',
3839
CHALLENGE_API: process.env.CHALLENGE_API || 'http://localhost:4000/v5/challenges',
3940

40-
IGNORED_ORIGINATORS: process.env.IGNORED_ORIGINATORS ? process.env.IGNORED_ORIGINATORS.split(',') : ['legacy-migration-script']
41+
IGNORED_ORIGINATORS: process.env.IGNORED_ORIGINATORS ? process.env.IGNORED_ORIGINATORS.split(',') : ['legacy-migration-script'],
42+
43+
GROUPS_TO_IGNORE: process.env.GROUPS_TO_IGNORE ? process.env.GROUPS_TO_IGNORE.split(',') : ['72a0b8a0-aa45-44f7-86c2-bf9de6321e5b'],
44+
GROUPS_API_URL: process.env.GROUPS_API_URL || 'http://localhost:4000/v5/groups',
45+
4146
}

src/app.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ const dataHandler = (messageSet, topic, partition) => Promise.each(messageSet, (
4040
} else {
4141
if (topic === config.CHALLENGE_CREATE_TOPIC) {
4242
await ProcessorService.handleChallengeCreate(messageJSON)
43+
} else if (topic === config.CHALLENGE_UPDATE_TOPIC) {
44+
await ProcessorService.handleChallengeUpdate(messageJSON)
4345
} else if (topic === config.PROJECT_MEMBER_ADDED_TOPIC) {
4446
await ProcessorService.handleMemberAdded(messageJSON)
4547
} else if (topic === config.PROJECT_MEMBER_REMOVED_TOPIC) {
@@ -71,6 +73,7 @@ consumer
7173
.init([{
7274
subscriptions: [
7375
config.CHALLENGE_CREATE_TOPIC,
76+
config.CHALLENGE_UPDATE_TOPIC,
7477
config.PROJECT_MEMBER_ADDED_TOPIC,
7578
config.PROJECT_MEMBER_REMOVED_TOPIC
7679
],

src/common/helper.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,48 @@ async function deleteResource (challengeId, memberHandle, roleId) {
188188
return res.body
189189
}
190190

191+
/**
192+
* Search members of the given group ids
193+
* @param {Array} members
194+
* @param {Array} groupIds
195+
* @return {Array} filtered members
196+
*/
197+
async function filterMemberForGroups(memberIds, groupIds) {
198+
for (const memberId of memberIds) {
199+
const res = await Promise.allSettled(groupIds.map(groupId => memberGroupsCall(groupId, memberId)));
200+
const memberGroups =_.compact(_.flattenDeep(_.map(res, 'value')))
201+
202+
if (memberGroups.length != groupIds.length) memberList.push(memberId)
203+
}
204+
}
205+
206+
/**
207+
* Return the memberId if member is part of the groups
208+
* @param {String} groupId
209+
* @param {String} memberId
210+
* @returns {String} memberId in case of member of group
211+
*/
212+
async function memberGroupsCall(groupId, memberId) {
213+
// M2M token is cached by 'tc-core-library-js' lib
214+
const token = await getM2MToken()
215+
216+
const url = `${config.GROUPS_API_URL}/${groupId}/members/${memberId}`
217+
const res = await superagent
218+
.get(url)
219+
.set('Authorization', `Bearer ${token}`)
220+
.timeout(config.REQUEST_TIMEOUT)
221+
222+
return memberId
223+
}
224+
225+
191226
module.exports = {
192227
getKafkaOptions,
193228
getProject,
194229
searchMembers,
195230
createResource,
196231
deleteResource,
197232
getProjectChallenges,
198-
getChallengeResources
233+
getChallengeResources,
234+
filterMemberForGroups
199235
}

src/services/ProcessorService.js

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,20 @@ async function handleChallengeCreate (message) {
2424
logger.info(`Found member ids [${memberIds.join(', ')}] of project id ${projectId}`)
2525

2626
// search members
27-
const members = await helper.searchMembers(memberIds)
27+
let members = await helper.searchMembers(memberIds)
28+
29+
// fetch all members of groups
30+
const groupIds = _.difference(message.payload.groups, config.GROUPS_TO_IGNORE)
31+
32+
// filter members who are NOT part of all the groups
33+
if (groupIds.length > 0 && members.length > 0) {
34+
const memberIds = members.map(m => m.id)
35+
const filteredMemberIds = await helper.filterMemberForGroups(memberIds, groupIds)
36+
37+
// remove the members who are not part of all the groups
38+
members = members.filter(m => !filteredMemberIds.includes(m.id))
39+
}
40+
2841
// create resource for each member
2942
for (const member of members) {
3043
const resource = await helper.createResource(challengeId, member.handle)
@@ -46,6 +59,49 @@ handleChallengeCreate.schema = {
4659
}).required()
4760
}
4861

62+
/**
63+
* Process Kafka message of challenge updated
64+
* @param {Object} message the challenge update message
65+
*/
66+
async function handleChallengeUpdate (message) {
67+
const challengeId = message.payload.id
68+
const projectId = message.payload.projectId
69+
logger.info(`Process message of challenge id ${challengeId} and project id ${projectId}`)
70+
71+
// get challenge resources (all observers for the challenge)
72+
let challengeResources = await helper.getChallengeResources(challengeId, config.RESOURCE_ROLE_ID)
73+
74+
// fetch all members of groups
75+
const groupIds = _.difference(message.payload.groups, config.GROUPS_TO_IGNORE)
76+
77+
// filter members who are NOT part of all the groups
78+
if (groupIds.length > 0 && challengeResources.length > 0) {
79+
const memberIds = challengeResources.map(cr => cr.memberId)
80+
const filteredMemberIds = await helper.filterMemberForGroups(memberIds, groupIds)
81+
82+
// filter the members who are not part of all the groups
83+
challengeResources = challengeResources.filter(member => filteredMemberIds.includes(member.memberId) )
84+
85+
// remove members from resources who are not part of all the groups
86+
await Promise.allSettled(challengeResources.map(member => helper.deleteResource(challengeId, member.memberHandle, config.RESOURCE_ROLE_ID)));
87+
}
88+
89+
logger.info(`Successfully processed message of challenge id ${challengeId} and project id ${projectId}`)
90+
}
91+
92+
handleChallengeUpdate.schema = {
93+
message: Joi.object().keys({
94+
topic: Joi.string().required(),
95+
originator: Joi.string().required(),
96+
timestamp: Joi.date().required(),
97+
'mime-type': Joi.string().required(),
98+
payload: Joi.object().keys({
99+
id: Joi.string().uuid().required(), // challenge id
100+
projectId: Joi.number().integer().positive().required()
101+
}).unknown(true).required()
102+
}).required()
103+
}
104+
49105
/**
50106
* Handle project member changes
51107
* @param {Number} projectId the project ID
@@ -61,8 +117,8 @@ async function handleProjectMemberChange (projectId, userId, isDeleted) {
61117
const [memberDetails] = await helper.searchMembers([userId])
62118
const { handle } = memberDetails
63119
for (const challenge of challenges) {
64-
const challenngeResources = await helper.getChallengeResources(challenge.id, config.MANAGER_RESOURCE_ROLE_ID)
65-
const existing = _.find(challenngeResources, r => _.toString(r.memberId) === _.toString(userId))
120+
const challengeResources = await helper.getChallengeResources(challenge.id, config.MANAGER_RESOURCE_ROLE_ID)
121+
const existing = _.find(challengeResources, r => _.toString(r.memberId) === _.toString(userId))
66122
if (isDeleted) {
67123
if (existing) {
68124
await helper.deleteResource(challenge.id, handle, config.MANAGER_RESOURCE_ROLE_ID)

0 commit comments

Comments
 (0)