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

Metadata + user ID fix #42

Merged
merged 1 commit into from
Mar 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ module.exports = {
V5_RESOURCES_API_URL: process.env.V5_RESOURCES_API_URL || 'http://localhost:4000/v5/resources',
V5_TERMS_API_URL: process.env.V5_TERMS_API_URL || 'http://localhost:4000/v5/terms',
V5_RESOURCE_ROLES_API_URL: process.env.V5_RESOURCE_ROLES_API_URL || 'http://localhost:4000/v5/resource-roles',
MEMBER_API_URL: process.env.MEMBER_API_URL || 'https://api.topcoder-dev.com/v5/members',

V5_CHALLENGE_TYPE_API_URL: process.env.V5_CHALLENGE_TYPE_API_URL || 'http://localhost:4000/v5/challenge-types',
V4_CHALLENGE_TYPE_API_URL: process.env.V4_CHALLENGE_TYPE_API_URL || 'http://localhost:4000/v4/challenge-types',
Expand Down
31 changes: 30 additions & 1 deletion src/common/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,34 @@ async function forceV4ESFeeder (legacyId) {
await request.put(`${config.V4_ES_FEEDER_API_URL}`).send(body).set({ Authorization: `Bearer ${token}` })
}

/**
* Get the member ID by handle
* @param {String} handle the handle
*/
async function getMemberIdByHandle (handle) {
const m2mToken = await getM2MToken()
let memberId
try {
const res = await getRequest(`${config.MEMBER_API_URL}/${handle}`, m2mToken)
if (_.get(res, 'body.userId')) {
memberId = res.body.userId
}
// handle return from v3 API, handle and memberHandle are the same under case-insensitive condition
handle = _.get(res, 'body.handle')
} catch (error) {
// re-throw all error except 404 Not-Founded, BadRequestError should be thrown if 404 occurs
if (error.status !== 404) {
throw error
}
}

if (_.isUndefined(memberId)) {
throw new Error(`User with handle: ${handle} doesn't exist`)
}

return memberId
}

module.exports = {
getInformixConnection,
getKafkaOptions,
Expand All @@ -171,5 +199,6 @@ module.exports = {
putRequest,
postRequest,
postBusEvent,
forceV4ESFeeder
forceV4ESFeeder,
getMemberIdByHandle
}
82 changes: 76 additions & 6 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* constants
*/
const metadataExtractor = require('./utils/metadataExtractor')

const prizeSetTypes = {
ChallengePrizes: 'placement',
Expand Down Expand Up @@ -57,12 +58,81 @@ const prizeTypesIds = {
}

const supportedMetadata = {
allowStockArt: 52,
drPoints: 30,
submissionViewable: 53,
submissionLimit: 51,
codeRepo: 85,
environment: 84
32: {
method: metadataExtractor.extractBillingProject,
defaultValue: null,
description: 'Billing Project'
},
30: {
method: metadataExtractor.extractDrPoints,
defaultValue: 0,
description: 'DR points'
},
35: {
method: metadataExtractor.extractSpecReviewCost,
defaultValue: null,
description: 'Spec review cost'
},
41: {
method: metadataExtractor.extractApprovalRequired,
defaultValue: true,
description: 'Approval Required'
},
44: {
method: metadataExtractor.extractPostMortemRequired,
defaultValue: true,
description: 'Post-Mortem Required'
},
48: {
method: metadataExtractor.extractTrackLateDeliverablesRequired,
defaultValue: true,
description: 'Track Late Deliverables'
},
51: {
method: metadataExtractor.extractSubmissionLimit,
defaultValue: null,
description: 'Maximum submissions'
},
52: {
method: metadataExtractor.extractAllowStockArtRequired,
defaultValue: false,
description: 'Allow Stock Art'
},
53: {
method: metadataExtractor.extractSubmissionViewable,
defaultValue: false,
description: 'Viewable Submissions Flag'
},
59: {
method: metadataExtractor.extractReviewFeedback,
defaultValue: true,
description: 'Review Feedback Flag'
},
84: {
method: metadataExtractor.extractEnvironment,
defaultValue: null,
description: 'Environment'
},
85: {
method: metadataExtractor.extractCodeRepo,
defaultValue: null,
description: 'Code repo'
},
88: {
method: metadataExtractor.extractEstimateEffortHours,
defaultValue: 0,
description: 'Effort Hours Estimate'
},
89: {
method: metadataExtractor.extractEstimateEffortOffshore,
defaultValue: 0,
description: 'Estimate Effort Days offshore'
},
90: {
method: metadataExtractor.extractEstimateEffortOnsite,
defaultValue: 0,
description: 'Estimate Effort Days Onsite'
}
}

module.exports = {
Expand Down
66 changes: 29 additions & 37 deletions src/services/ProcessorService.js
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,8 @@ async function processCreate (message) {
}

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

const saveDraftContestDTO = await parsePayload(message.payload, m2mToken)
logger.debug('Parsed Payload', saveDraftContestDTO)
Expand All @@ -514,7 +516,7 @@ async function processCreate (message) {
await helper.forceV4ESFeeder(newChallenge.body.result.content.id)
await associateChallengeGroups(saveDraftContestDTO.groupsToBeAdded, saveDraftContestDTO.groupsToBeDeleted, newChallenge.body.result.content.id)
// await associateChallengeTerms(saveDraftContestDTO.termsToBeAdded, saveDraftContestDTO.termsToBeRemoved, newChallenge.body.result.content.id)
await setCopilotPayment(challengeUuid, newChallenge.body.result.content.id, _.get(message, 'payload.prizeSets'), _.get(message, 'payload.createdBy'), _.get(message, 'payload.updatedBy'), m2mToken)
await setCopilotPayment(challengeUuid, newChallenge.body.result.content.id, _.get(message, 'payload.prizeSets'), createdByUserId, updatedByUserId, m2mToken)
await helper.patchRequest(`${config.V5_CHALLENGE_API_URL}/${challengeUuid}`, {
legacy: {
...message.payload.legacy,
Expand All @@ -528,7 +530,7 @@ async function processCreate (message) {
}, m2mToken)
// Repost all challenge resource on Kafka so they will get created on legacy by the legacy-challenge-resource-processor
await rePostResourcesOnKafka(challengeUuid, m2mToken)
await timelineService.enableTimelineNotifications(newChallenge.body.result.content.id, _.get(message, 'payload.createdBy'))
await timelineService.enableTimelineNotifications(newChallenge.body.result.content.id, createdByUserId)
logger.debug('End of processCreate')
return newChallenge.body.result.content.id
} catch (e) {
Expand Down Expand Up @@ -603,6 +605,9 @@ async function processUpdate (message) {
}
const m2mToken = await helper.getM2MToken()

const createdByUserId = await helper.getMemberIdByHandle(_.get(message, 'payload.createdBy'))
const updatedByUserId = await helper.getMemberIdByHandle(_.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'))

let challenge
try {
// ensure challenge existed
Expand Down Expand Up @@ -640,41 +645,28 @@ async function processUpdate (message) {
logger.debug(JSON.stringify(saveDraftContestDTO, null, 2))
// logger.debug('Parsed Payload', saveDraftContestDTO)
try {
try {
if (challenge) {
await helper.putRequest(`${config.V4_CHALLENGE_API_URL}/${legacyId}`, { param: _.omit(saveDraftContestDTO, ['groupsToBeAdded', 'groupsToBeDeleted']) }, m2mToken)
}
} catch (e) {
logger.warn('Failed to update the challenge via the V4 API')
logger.error(e)
}

// Update metadata in IFX
if (message.payload.metadata && message.payload.metadata.length > 0) {
for (const metadataKey of _.keys(constants.supportedMetadata)) {
const entry = _.find(message.payload.metadata, meta => meta.name === metadataKey)
if (entry) {
if (metadataKey === 'submissionLimit') {
// data here is JSON stringified
try {
const parsedEntryValue = JSON.parse(entry.value)
if (parsedEntryValue.limit) {
entry.value = parsedEntryValue.count
} else {
entry.value = null
}
} catch (e) {
entry.value = null
}
}
try {
await metadataService.createOrUpdateMetadata(legacyId, constants.supportedMetadata[metadataKey], entry.value, _.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'))
} catch (e) {
logger.warn(`Failed to set ${metadataKey} (${constants.supportedMetadata[metadataKey]})`)
}
// extract metadata from challenge and insert into IFX
let metaValue
for (const metadataKey of _.keys(constants.supportedMetadata)) {
try {
metaValue = constants.supportedMetadata[metadataKey].method(message.payload, constants.supportedMetadata[metadataKey].defaultValue)
if (metaValue !== null && metaValue !== '') {
logger.info(`Setting ${constants.supportedMetadata[metadataKey].description} to ${metaValue}`)
await metadataService.createOrUpdateMetadata(legacyId, metadataKey, metaValue, updatedByUserId)
}
} catch (e) {
logger.warn(`Failed to set ${constants.supportedMetadata[metadataKey].description} to ${metaValue}`)
}
}
// try {
// if (challenge) {
// await helper.putRequest(`${config.V4_CHALLENGE_API_URL}/${legacyId}`, { param: _.omit(saveDraftContestDTO, ['groupsToBeAdded', 'groupsToBeDeleted']) }, m2mToken)
// }
// } catch (e) {
// logger.warn('Failed to update the challenge via the V4 API')
// logger.error(e)
// }

if (message.payload.status && challenge) {
// logger.info(`The status has changed from ${challenge.currentStatus} to ${message.payload.status}`)
if (message.payload.status === constants.challengeStatuses.Active && challenge.currentStatus !== constants.challengeStatuses.Active) {
Expand Down Expand Up @@ -703,10 +695,10 @@ async function processUpdate (message) {
} else {
logger.info('Will skip syncing phases as the challenge is a task...')
}
await updateMemberPayments(message.payload.legacyId, message.payload.prizeSets, _.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'))
await updateMemberPayments(message.payload.legacyId, message.payload.prizeSets, updatedByUserId)
await associateChallengeGroups(saveDraftContestDTO.groupsToBeAdded, saveDraftContestDTO.groupsToBeDeleted, legacyId)
await associateChallengeTerms(message.payload.terms, legacyId, _.get(message, 'payload.createdBy'), _.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'))
await setCopilotPayment(message.payload.id, legacyId, _.get(message, 'payload.prizeSets'), _.get(message, 'payload.createdBy'), _.get(message, 'payload.updatedBy') || _.get(message, 'payload.createdBy'), m2mToken)
await associateChallengeTerms(message.payload.terms, legacyId, createdByUserId, updatedByUserId)
await setCopilotPayment(message.payload.id, legacyId, _.get(message, 'payload.prizeSets'), createdByUserId, updatedByUserId, m2mToken)

try {
await helper.forceV4ESFeeder(legacyId)
Expand Down
Loading