Skip to content

Commit 8135d1a

Browse files
author
vikasrohit
authored
Merge pull request #33 from topcoder-platform/hotfix/remove-invite-on-member-create
[HOTFIX] [PROD] Remove not removed invite for added member
2 parents 2fd5533 + 764ef45 commit 8135d1a

File tree

5 files changed

+68
-15
lines changed

5 files changed

+68
-15
lines changed

src/common/helper.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,26 @@ async function getMemberDetailsByUserIds (userIds) {
165165
}
166166
}
167167

168+
/**
169+
* Reusable method to generate a function which would remove invite from the project ES document.
170+
*
171+
* @param {Object} message invite update or delete message
172+
*/
173+
const removeInvitePromise = message => async (doc) => {
174+
// now merge the updated changes and re-index the document
175+
const invites = _.isArray(doc._source.invites) ? doc._source.invites : []
176+
const removedInvites = _.remove(invites, { id: message.id })
177+
if (!removedInvites.length) {
178+
throw new Error(`Invite with id "${message.id}" is not found and not removed.`)
179+
}
180+
return _.assign(doc._source, { invites })
181+
}
182+
168183
module.exports = {
169184
getESClient,
170185
updateProjectESPromise,
171186
updateTimelineESPromise,
172187
updateMetadadaESPromise,
173-
getMemberDetailsByUserIds
188+
getMemberDetailsByUserIds,
189+
removeInvitePromise
174190
}

src/services/ProcessorServiceProjectMember.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,35 @@ async function create (message) {
7878
// from the database
7979
members.splice(existingMemberIndex, 1, member)
8080
}
81+
82+
// sometimes we have issue that when member accepts invitation the invitation is somehow
83+
// is not removed from the ES, so here we are making sure that invite is removed when we are adding member
84+
try { // make sure that this logic never cause an error in member adding process
85+
const invites = _.filter(doc._source.invites, (invite) => (
86+
invite.email === member.email || invite.userId === member.userId
87+
))
88+
89+
if (invites.length > 0) {
90+
logger.warn(`There are ${invites.length} invite(s) are not yet removed` +
91+
` for member.id: ${member.id} member.userId: ${member.userId}.`)
92+
93+
for (let i = 0; i < invites.length; i++) {
94+
const invite = invites[i]
95+
logger.debug(`Removing invite.id: ${invite.id} for member.id: ${member.id} member.userId: ${member.userId}.`)
96+
try {
97+
const message = { id: invite.id }
98+
const updateDocHandler = helper.removeInvitePromise(message)
99+
await updateDocHandler(doc)
100+
logger.debug(`Successfully removed invite.id: ${invite.id}.`)
101+
} catch (err) {
102+
logger.error(`Failed removing invite.id: ${invite.id}. ${err}`)
103+
}
104+
}
105+
}
106+
} catch (err) {
107+
logger.error(`Error during removing existent invites for added member: ${err}`)
108+
}
109+
81110
return _.assign(doc._source, { members })
82111
}
83112

src/services/ProcessorServiceProjectMemberInvite.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,24 +53,13 @@ create.schema = {
5353
message: createSchema()
5454
}
5555

56-
// handle ES Update or Delete on invites
57-
const updateInvitesPromise = message => async (doc) => {
58-
// now merge the updated changes and re-index the document
59-
const invites = _.isArray(doc._source.invites) ? doc._source.invites : []
60-
const removedInvites = _.remove(invites, invite => message.id === invite.id)
61-
if (!removedInvites.length) {
62-
throw new Error(`Invite with id "${message.id}" is not found and not removed.`)
63-
}
64-
return _.assign(doc._source, { invites })
65-
}
66-
6756
/**
6857
* Update message in Elasticsearch.
6958
* @param {Object} message the challenge updated message
7059
* @return {Promise} promise result
7160
*/
7261
async function update (message) {
73-
await helper.updateProjectESPromise(message.projectId, updateInvitesPromise(message))
62+
await helper.updateProjectESPromise(message.projectId, helper.removeInvitePromise(message))
7463
logger.debug(`Member invite updated successfully in elasticsearch index, (memberInviteId: ${message.id})`)
7564
}
7665

@@ -84,7 +73,7 @@ update.schema = {
8473
* @return {Promise} promise result
8574
*/
8675
async function deleteMessage (message) {
87-
await helper.updateProjectESPromise(message.projectId, updateInvitesPromise(message))
76+
await helper.updateProjectESPromise(message.projectId, helper.removeInvitePromise(message))
8877
logger.debug(`Member invite deleted successfully in elasticsearch index, (memberInviteId: ${message.id})`)
8978
}
9079

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"topic":"project.action.create","originator":"project-api","timestamp":"2019-06-21T04:45:18.165Z","mime-type":"application/json","payload":{"resource":"project.member","createdAt":"2019-06-21T04:45:18.036Z","updatedAt":"2019-06-21T04:45:18.038Z","isPrimary":false,"id":1,"projectId":1,"role":"manager","userId":40051334,"createdBy":40051334,"updatedBy":40051334,"deletedAt":null,"deletedBy":null}}
1+
{"topic":"project.action.create","originator":"project-api","timestamp":"2019-06-21T04:45:18.165Z","mime-type":"application/json","payload":{"resource":"project.member","createdAt":"2019-06-21T04:45:18.036Z","updatedAt":"2019-06-21T04:45:18.038Z","isPrimary":false,"id":1,"projectId":1,"role":"manager","userId":40051331,"createdBy":40051334,"updatedBy":40051334,"deletedAt":null,"deletedBy":null}}

test/e2e/processor.project.index.test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,25 @@ describe('TC Project Member Topic Tests', () => {
832832
_.keys(_.omit(projectMemberCreatedMessage.payload, ['resource'])))
833833
})
834834

835+
it('create project member message - already exists - remove not removed invite', async () => {
836+
// let's say we still have invite
837+
await ProcessorService.create(projectMemberInviteCreatedMessage)
838+
let data = await testHelper.getProjectESData(projectId)
839+
// make sure that invite is there
840+
testHelper.expectObj(_.find(data.invites, { id: projectMemberInviteId }), projectMemberInviteCreatedMessage.payload,
841+
_.keys(_.omit(projectMemberInviteCreatedMessage.payload, ['resource'])))
842+
843+
// and we are adding a member (but invite is still there as we created above)
844+
await ProcessorService.create(projectMemberCreatedMessage)
845+
data = await testHelper.getProjectESData(projectId)
846+
847+
// check that member has been added
848+
testHelper.expectObj(_.find(data.members, { id: projectMemberId }), projectMemberCreatedMessage.payload,
849+
_.keys(_.omit(projectMemberCreatedMessage.payload, ['resource'])))
850+
// and at the same time the invite for the member has been removed
851+
expect(_.find(data.invites, { id: projectMemberInviteId })).to.be.an('undefined')
852+
})
853+
835854
it('update project member message', async () => {
836855
await ProcessorService.update(projectMemberUpdatedMessage)
837856
const data = await testHelper.getProjectESData(projectId)

0 commit comments

Comments
 (0)