Skip to content
This repository was archived by the owner on Jan 23, 2025. It is now read-only.

Commit 8338c59

Browse files
authored
Merge pull request #42 from topcoder-platform/hotfix/metadata
Metadata + user ID fix
2 parents 555f903 + d661f95 commit 8338c59

File tree

5 files changed

+336
-44
lines changed

5 files changed

+336
-44
lines changed

config/default.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ module.exports = {
5151
V5_RESOURCES_API_URL: process.env.V5_RESOURCES_API_URL || 'http://localhost:4000/v5/resources',
5252
V5_TERMS_API_URL: process.env.V5_TERMS_API_URL || 'http://localhost:4000/v5/terms',
5353
V5_RESOURCE_ROLES_API_URL: process.env.V5_RESOURCE_ROLES_API_URL || 'http://localhost:4000/v5/resource-roles',
54+
MEMBER_API_URL: process.env.MEMBER_API_URL || 'https://api.topcoder-dev.com/v5/members',
5455

5556
V5_CHALLENGE_TYPE_API_URL: process.env.V5_CHALLENGE_TYPE_API_URL || 'http://localhost:4000/v5/challenge-types',
5657
V4_CHALLENGE_TYPE_API_URL: process.env.V4_CHALLENGE_TYPE_API_URL || 'http://localhost:4000/v4/challenge-types',

src/common/helper.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,34 @@ async function forceV4ESFeeder (legacyId) {
162162
await request.put(`${config.V4_ES_FEEDER_API_URL}`).send(body).set({ Authorization: `Bearer ${token}` })
163163
}
164164

165+
/**
166+
* Get the member ID by handle
167+
* @param {String} handle the handle
168+
*/
169+
async function getMemberIdByHandle (handle) {
170+
const m2mToken = await getM2MToken()
171+
let memberId
172+
try {
173+
const res = await getRequest(`${config.MEMBER_API_URL}/${handle}`, m2mToken)
174+
if (_.get(res, 'body.userId')) {
175+
memberId = res.body.userId
176+
}
177+
// handle return from v3 API, handle and memberHandle are the same under case-insensitive condition
178+
handle = _.get(res, 'body.handle')
179+
} catch (error) {
180+
// re-throw all error except 404 Not-Founded, BadRequestError should be thrown if 404 occurs
181+
if (error.status !== 404) {
182+
throw error
183+
}
184+
}
185+
186+
if (_.isUndefined(memberId)) {
187+
throw new Error(`User with handle: ${handle} doesn't exist`)
188+
}
189+
190+
return memberId
191+
}
192+
165193
module.exports = {
166194
getInformixConnection,
167195
getKafkaOptions,
@@ -171,5 +199,6 @@ module.exports = {
171199
putRequest,
172200
postRequest,
173201
postBusEvent,
174-
forceV4ESFeeder
202+
forceV4ESFeeder,
203+
getMemberIdByHandle
175204
}

src/constants.js

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
* constants
33
*/
4+
const metadataExtractor = require('./utils/metadataExtractor')
45

56
const prizeSetTypes = {
67
ChallengePrizes: 'placement',
@@ -57,12 +58,81 @@ const prizeTypesIds = {
5758
}
5859

5960
const supportedMetadata = {
60-
allowStockArt: 52,
61-
drPoints: 30,
62-
submissionViewable: 53,
63-
submissionLimit: 51,
64-
codeRepo: 85,
65-
environment: 84
61+
32: {
62+
method: metadataExtractor.extractBillingProject,
63+
defaultValue: null,
64+
description: 'Billing Project'
65+
},
66+
30: {
67+
method: metadataExtractor.extractDrPoints,
68+
defaultValue: 0,
69+
description: 'DR points'
70+
},
71+
35: {
72+
method: metadataExtractor.extractSpecReviewCost,
73+
defaultValue: null,
74+
description: 'Spec review cost'
75+
},
76+
41: {
77+
method: metadataExtractor.extractApprovalRequired,
78+
defaultValue: true,
79+
description: 'Approval Required'
80+
},
81+
44: {
82+
method: metadataExtractor.extractPostMortemRequired,
83+
defaultValue: true,
84+
description: 'Post-Mortem Required'
85+
},
86+
48: {
87+
method: metadataExtractor.extractTrackLateDeliverablesRequired,
88+
defaultValue: true,
89+
description: 'Track Late Deliverables'
90+
},
91+
51: {
92+
method: metadataExtractor.extractSubmissionLimit,
93+
defaultValue: null,
94+
description: 'Maximum submissions'
95+
},
96+
52: {
97+
method: metadataExtractor.extractAllowStockArtRequired,
98+
defaultValue: false,
99+
description: 'Allow Stock Art'
100+
},
101+
53: {
102+
method: metadataExtractor.extractSubmissionViewable,
103+
defaultValue: false,
104+
description: 'Viewable Submissions Flag'
105+
},
106+
59: {
107+
method: metadataExtractor.extractReviewFeedback,
108+
defaultValue: true,
109+
description: 'Review Feedback Flag'
110+
},
111+
84: {
112+
method: metadataExtractor.extractEnvironment,
113+
defaultValue: null,
114+
description: 'Environment'
115+
},
116+
85: {
117+
method: metadataExtractor.extractCodeRepo,
118+
defaultValue: null,
119+
description: 'Code repo'
120+
},
121+
88: {
122+
method: metadataExtractor.extractEstimateEffortHours,
123+
defaultValue: 0,
124+
description: 'Effort Hours Estimate'
125+
},
126+
89: {
127+
method: metadataExtractor.extractEstimateEffortOffshore,
128+
defaultValue: 0,
129+
description: 'Estimate Effort Days offshore'
130+
},
131+
90: {
132+
method: metadataExtractor.extractEstimateEffortOnsite,
133+
defaultValue: 0,
134+
description: 'Estimate Effort Days Onsite'
135+
}
66136
}
67137

68138
module.exports = {

src/services/ProcessorService.js

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,8 @@ async function processCreate (message) {
496496
}
497497

498498
const m2mToken = await helper.getM2MToken()
499+
const createdByUserId = await helper.getMemberIdByHandle(_.get(message, 'payload.createdBy'))
500+
const updatedByUserId = await helper.getMemberIdByHandle(_.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'))
499501

500502
const saveDraftContestDTO = await parsePayload(message.payload, m2mToken)
501503
logger.debug('Parsed Payload', saveDraftContestDTO)
@@ -514,7 +516,7 @@ async function processCreate (message) {
514516
await helper.forceV4ESFeeder(newChallenge.body.result.content.id)
515517
await associateChallengeGroups(saveDraftContestDTO.groupsToBeAdded, saveDraftContestDTO.groupsToBeDeleted, newChallenge.body.result.content.id)
516518
// await associateChallengeTerms(saveDraftContestDTO.termsToBeAdded, saveDraftContestDTO.termsToBeRemoved, newChallenge.body.result.content.id)
517-
await setCopilotPayment(challengeUuid, newChallenge.body.result.content.id, _.get(message, 'payload.prizeSets'), _.get(message, 'payload.createdBy'), _.get(message, 'payload.updatedBy'), m2mToken)
519+
await setCopilotPayment(challengeUuid, newChallenge.body.result.content.id, _.get(message, 'payload.prizeSets'), createdByUserId, updatedByUserId, m2mToken)
518520
await helper.patchRequest(`${config.V5_CHALLENGE_API_URL}/${challengeUuid}`, {
519521
legacy: {
520522
...message.payload.legacy,
@@ -528,7 +530,7 @@ async function processCreate (message) {
528530
}, m2mToken)
529531
// Repost all challenge resource on Kafka so they will get created on legacy by the legacy-challenge-resource-processor
530532
await rePostResourcesOnKafka(challengeUuid, m2mToken)
531-
await timelineService.enableTimelineNotifications(newChallenge.body.result.content.id, _.get(message, 'payload.createdBy'))
533+
await timelineService.enableTimelineNotifications(newChallenge.body.result.content.id, createdByUserId)
532534
logger.debug('End of processCreate')
533535
return newChallenge.body.result.content.id
534536
} catch (e) {
@@ -603,6 +605,9 @@ async function processUpdate (message) {
603605
}
604606
const m2mToken = await helper.getM2MToken()
605607

608+
const createdByUserId = await helper.getMemberIdByHandle(_.get(message, 'payload.createdBy'))
609+
const updatedByUserId = await helper.getMemberIdByHandle(_.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'))
610+
606611
let challenge
607612
try {
608613
// ensure challenge existed
@@ -640,41 +645,28 @@ async function processUpdate (message) {
640645
logger.debug(JSON.stringify(saveDraftContestDTO, null, 2))
641646
// logger.debug('Parsed Payload', saveDraftContestDTO)
642647
try {
643-
try {
644-
if (challenge) {
645-
await helper.putRequest(`${config.V4_CHALLENGE_API_URL}/${legacyId}`, { param: _.omit(saveDraftContestDTO, ['groupsToBeAdded', 'groupsToBeDeleted']) }, m2mToken)
646-
}
647-
} catch (e) {
648-
logger.warn('Failed to update the challenge via the V4 API')
649-
logger.error(e)
650-
}
651-
652-
// Update metadata in IFX
653-
if (message.payload.metadata && message.payload.metadata.length > 0) {
654-
for (const metadataKey of _.keys(constants.supportedMetadata)) {
655-
const entry = _.find(message.payload.metadata, meta => meta.name === metadataKey)
656-
if (entry) {
657-
if (metadataKey === 'submissionLimit') {
658-
// data here is JSON stringified
659-
try {
660-
const parsedEntryValue = JSON.parse(entry.value)
661-
if (parsedEntryValue.limit) {
662-
entry.value = parsedEntryValue.count
663-
} else {
664-
entry.value = null
665-
}
666-
} catch (e) {
667-
entry.value = null
668-
}
669-
}
670-
try {
671-
await metadataService.createOrUpdateMetadata(legacyId, constants.supportedMetadata[metadataKey], entry.value, _.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'))
672-
} catch (e) {
673-
logger.warn(`Failed to set ${metadataKey} (${constants.supportedMetadata[metadataKey]})`)
674-
}
648+
// extract metadata from challenge and insert into IFX
649+
let metaValue
650+
for (const metadataKey of _.keys(constants.supportedMetadata)) {
651+
try {
652+
metaValue = constants.supportedMetadata[metadataKey].method(message.payload, constants.supportedMetadata[metadataKey].defaultValue)
653+
if (metaValue !== null && metaValue !== '') {
654+
logger.info(`Setting ${constants.supportedMetadata[metadataKey].description} to ${metaValue}`)
655+
await metadataService.createOrUpdateMetadata(legacyId, metadataKey, metaValue, updatedByUserId)
675656
}
657+
} catch (e) {
658+
logger.warn(`Failed to set ${constants.supportedMetadata[metadataKey].description} to ${metaValue}`)
676659
}
677660
}
661+
// try {
662+
// if (challenge) {
663+
// await helper.putRequest(`${config.V4_CHALLENGE_API_URL}/${legacyId}`, { param: _.omit(saveDraftContestDTO, ['groupsToBeAdded', 'groupsToBeDeleted']) }, m2mToken)
664+
// }
665+
// } catch (e) {
666+
// logger.warn('Failed to update the challenge via the V4 API')
667+
// logger.error(e)
668+
// }
669+
678670
if (message.payload.status && challenge) {
679671
// logger.info(`The status has changed from ${challenge.currentStatus} to ${message.payload.status}`)
680672
if (message.payload.status === constants.challengeStatuses.Active && challenge.currentStatus !== constants.challengeStatuses.Active) {
@@ -703,10 +695,10 @@ async function processUpdate (message) {
703695
} else {
704696
logger.info('Will skip syncing phases as the challenge is a task...')
705697
}
706-
await updateMemberPayments(message.payload.legacyId, message.payload.prizeSets, _.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'))
698+
await updateMemberPayments(message.payload.legacyId, message.payload.prizeSets, updatedByUserId)
707699
await associateChallengeGroups(saveDraftContestDTO.groupsToBeAdded, saveDraftContestDTO.groupsToBeDeleted, legacyId)
708-
await associateChallengeTerms(message.payload.terms, legacyId, _.get(message, 'payload.createdBy'), _.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'))
709-
await setCopilotPayment(message.payload.id, legacyId, _.get(message, 'payload.prizeSets'), _.get(message, 'payload.createdBy'), _.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'), m2mToken)
700+
await associateChallengeTerms(message.payload.terms, legacyId, createdByUserId, updatedByUserId)
701+
await setCopilotPayment(message.payload.id, legacyId, _.get(message, 'payload.prizeSets'), createdByUserId, updatedByUserId, m2mToken)
710702

711703
try {
712704
await helper.forceV4ESFeeder(legacyId)

0 commit comments

Comments
 (0)