From 78fc74f669596a05f3d4c92ab398a495dbec57a8 Mon Sep 17 00:00:00 2001 From: Rakib Ansary Date: Mon, 12 Sep 2022 18:53:38 +0600 Subject: [PATCH 1/3] fix: task.memberId getting reset * keep winners.userId in sync with task.memberId for pureV5Tasks --- .circleci/config.yml | 4 +-- src/common/helper.js | 2 +- src/routes.js | 2 +- src/services/ChallengeService.js | 47 +++++++++++++++++++++++++------- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b49f0029..5ae70314 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -70,9 +70,7 @@ workflows: branches: only: - develop - - fix/challenge-timelines-edit-routes - - test/performance-profile - - July2022Updates + - fix/task-memberId-reset # Production builds are exectuted only on tagged commits to the # master branch. diff --git a/src/common/helper.js b/src/common/helper.js index c349ecfb..0db4a781 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -889,7 +889,7 @@ async function listChallengesByMember (memberId) { // get search is paginated, we need to get all pages' data let page = 1 while (true) { - let result = {}; + let result = {} try { result = await axios.get(`${config.RESOURCES_API_URL}/${memberId}/challenges`, { headers: { Authorization: `Bearer ${token}` }, diff --git a/src/routes.js b/src/routes.js index 3c778369..b02f79fe 100644 --- a/src/routes.js +++ b/src/routes.js @@ -70,7 +70,7 @@ module.exports = { '/challenges/:challengeId/statistics': { get: { controller: 'ChallengeController', - method: 'getChallengeStatistics', + method: 'getChallengeStatistics' } }, '/challenges/:challengeId/notifications': { diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index ed15a9a7..d3353fe7 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -274,7 +274,7 @@ async function searchChallenges (currentUser, criteria) { { wildcard: { name: `*${criteria.search}*` } }, { wildcard: { name: `${criteria.search}*` } }, { wildcard: { name: `*${criteria.search}` } }, - { match_phrase: { tags: criteria.search } }, + { match_phrase: { tags: criteria.search } } ] } }) } else { @@ -1649,6 +1649,39 @@ async function update (currentUser, challengeId, data, isFull) { await validateWinners(data.winners, challengeId) } + // Only m2m tokens are allowed to modify the `task.*` information on a challenge + if (!_.isUndefined(_.get(data, 'task')) && !currentUser.isMachine) { + if (!_.isUndefined(_.get(challenge, 'task'))) { + logger.info(`User ${currentUser.handle || currentUser.sub} is not allowed to modify the task information on challenge ${challengeId}`) + data.task = challenge.task + logger.info(`Task information on challenge ${challengeId} is reset to ${JSON.stringify(challenge.task)}. Original data: ${JSON.stringify(data.task)}`) + } else { + delete data.task + } + } + + // task.memberId goes out of sync due to another processor setting "task.memberId" but subsequent immediate update to the task + // will not have the memberId set. So we need to set it using winners to ensure it is always in sync. The proper fix is to correct + // the sync issue in the processor. However this is quick fix that works since winner.userId is task.memberId. + if (_.get(challenge, 'legacy.pureV5Task') && !_.isUndefined(data.winners)) { + const winnerMemberId = _.get(data.winners, '[0].userId') + logger.info(`Setting task.memberId to ${winnerMemberId} for challenge ${challengeId}`) + + if (winnerMemberId != null && data.task.memberId !== winnerMemberId) { + logger.info(`Task ${challengeId} has a winner ${winnerMemberId}`) + data.task = { + isTask: true, + isAssigned: true, + memberId: winnerMemberId + } + logger.warn(`task.memberId mismatched with winner memberId. task.memberId is updated to ${winnerMemberId}`) + } else { + logger.info(`task ${challengeId} has no winner set yet.`) + } + } else { + logger.info(`${challengeId} is not a pureV5 challenge or has no winners set yet.`) + } + data.updated = moment().utc() data.updatedBy = currentUser.handle || currentUser.sub const updateDetails = {} @@ -1709,6 +1742,9 @@ async function update (currentUser, challengeId, data, isFull) { op = '$PUT' } else if (_.isUndefined(challenge[key]) || challenge[key] !== value) { op = '$PUT' + } else if (_.get(challenge, 'legacy.pureV5Task') && key === 'task') { + // always update task for pureV5 challenges + op = '$PUT' } if (op) { @@ -1848,15 +1884,6 @@ async function update (currentUser, challengeId, data, isFull) { const { track, type } = await validateChallengeData(_.pick(challenge, ['trackId', 'typeId'])) - // Only m2m tokens are allowed to modify the `task.*` information on a challenge - if (!_.isUndefined(_.get(data, 'task')) && !currentUser.isMachine) { - if (!_.isUndefined(_.get(challenge, 'task'))) { - data.task = challenge.task - } else { - delete data.task - } - } - if (_.get(type, 'isTask')) { if (!_.isEmpty(_.get(data, 'task.memberId'))) { const challengeResources = await helper.getChallengeResources(challengeId) From 3fec2c0568af6507f260e90f72099f9848b82f36 Mon Sep 17 00:00:00 2001 From: Rakib Ansary Date: Mon, 12 Sep 2022 19:21:10 +0600 Subject: [PATCH 2/3] fix: null check --- src/services/ChallengeService.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index d3353fe7..b2ed2acb 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -1665,9 +1665,9 @@ async function update (currentUser, challengeId, data, isFull) { // the sync issue in the processor. However this is quick fix that works since winner.userId is task.memberId. if (_.get(challenge, 'legacy.pureV5Task') && !_.isUndefined(data.winners)) { const winnerMemberId = _.get(data.winners, '[0].userId') - logger.info(`Setting task.memberId to ${winnerMemberId} for challenge ${challengeId}`) + logger.info(`Setting task.memberId to ${winnerMemberId} for challenge ${challengeId}. Task ${_.get(challenge, 'task')}`) - if (winnerMemberId != null && data.task.memberId !== winnerMemberId) { + if (winnerMemberId != null && _.get(data, 'task.memberId') !== winnerMemberId) { logger.info(`Task ${challengeId} has a winner ${winnerMemberId}`) data.task = { isTask: true, From e610d8225f89cffe138daee932707840602b40d7 Mon Sep 17 00:00:00 2001 From: Rakib Ansary Date: Mon, 12 Sep 2022 19:23:40 +0600 Subject: [PATCH 3/3] chore: logs --- src/services/ChallengeService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index b2ed2acb..ee691b2c 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -1665,7 +1665,7 @@ async function update (currentUser, challengeId, data, isFull) { // the sync issue in the processor. However this is quick fix that works since winner.userId is task.memberId. if (_.get(challenge, 'legacy.pureV5Task') && !_.isUndefined(data.winners)) { const winnerMemberId = _.get(data.winners, '[0].userId') - logger.info(`Setting task.memberId to ${winnerMemberId} for challenge ${challengeId}. Task ${_.get(challenge, 'task')}`) + logger.info(`Setting task.memberId to ${winnerMemberId} for challenge ${challengeId}. Task ${_.get(data, 'task')} - ${_.get(challenge, 'task')}`) if (winnerMemberId != null && _.get(data, 'task.memberId') !== winnerMemberId) { logger.info(`Task ${challengeId} has a winner ${winnerMemberId}`)