Skip to content

Commit aa53f73

Browse files
authored
Merge pull request #1 from imcaizheng/winner_submission
Populate member details
2 parents e2c233f + cfc2c41 commit aa53f73

File tree

6 files changed

+90
-4
lines changed

6 files changed

+90
-4
lines changed

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ The following parameters can be set in config files or in env variables:
2525
- UPDATE_DATA_TOPIC: update data Kafka topic, default value is 'project.action.update'
2626
- DELETE_DATA_TOPIC: delete data Kafka topic, default value is 'project.action.delete'
2727
- KAFKA_MESSAGE_ORIGINATOR: Kafka topic originator, default value is 'project-api'
28+
- MEMBER_SERVICE_ENDPOINT: used to get member details
29+
- AUTH0_URL: AUTH0 URL, used to get M2M token
30+
- AUTH0_PROXY_SERVER_URL: AUTH0 proxy server URL, used to get M2M token
31+
- AUTH0_AUDIENCE: AUTH0 audience, used to get M2M token
32+
- TOKEN_CACHE_TIME: AUTH0 token cache time, used to get M2M token
33+
- AUTH0_CLIENT_ID: AUTH0 client id, used to get M2M token
34+
- AUTH0_CLIENT_SECRET: AUTH0 client secret, used to get M2M token
2835
- esConfig: config object for Elasticsearch
2936

3037
Refer to `esConfig` variable in `config/default.js` for ES related configuration.
@@ -69,12 +76,20 @@ Config for tests are at `config/test.js`, it overrides some default config.
6976
- In the `docker-es` folder, run `docker-compose up`
7077

7178
## Local deployment
72-
7379
- Install dependencies `npm i`
7480
- Run code lint check `npm run lint`, running `npm run lint:fix` can fix some lint errors if any
7581
- Initialize Elasticsearch, create configured Elasticsearch index if not present: `npm run sync:es`
7682
- Start processor app `npm start`
7783

84+
Note that you need to set AUTH0 related environment variables belows before you can start the processor.
85+
86+
- AUTH0_URL
87+
- AUTH0_AUDIENCE
88+
- TOKEN_CACHE_TIME
89+
- AUTH0_CLIENT_ID
90+
- AUTH0_CLIENT_SECRET
91+
- AUTH0_PROXY_SERVER_URL
92+
7893
## Local Deployment with Docker
7994

8095
To run the Challenge ES Processor using docker, follow the below steps
@@ -254,4 +269,4 @@ info: {
254269
- Then in the app console, you will see error messages
255270

256271
- To test the health check API, run `export PORT=5000`, start the processor, then browse `http://localhost:5000/health` in a browser,
257-
and you will see result `{"checksRun":1}`
272+
and you will see result `{"checksRun":1}`

config/default.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ module.exports = {
1717
DELETE_DATA_TOPIC: process.env.DELETE_DATA_TOPIC || 'project.action.delete',
1818
KAFKA_MESSAGE_ORIGINATOR: process.env.KAFKA_MESSAGE_ORIGINATOR || 'project-api',
1919

20+
MEMBER_SERVICE_ENDPOINT: process.env.MEMBER_SERVICE_ENDPOINT || 'https://api.topcoder-dev.com/v3/members',
21+
22+
AUTH0_URL: process.env.AUTH0_URL,
23+
AUTH0_PROXY_SERVER_URL: process.env.AUTH0_PROXY_SERVER_URL,
24+
AUTH0_AUDIENCE: process.env.AUTH0_AUDIENCE,
25+
TOKEN_CACHE_TIME: process.env.TOKEN_CACHE_TIME,
26+
AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID,
27+
AUTH0_CLIENT_SECRET: process.env.AUTH0_CLIENT_SECRET,
28+
2029
esConfig: {
2130
HOST: process.env.ES_HOST || 'localhost:9200',
2231
AWS_REGION: process.env.AWS_REGION || 'us-east-1', // AWS Region to be used if we use AWS ES

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
"joi": "^14.3.1",
3131
"lodash": "^4.17.11",
3232
"no-kafka": "^3.4.3",
33+
"tc-core-library-js": "github:appirio-tech/tc-core-library-js#v2.6",
3334
"topcoder-healthcheck-dropin": "^1.0.3",
35+
"urlencode": "^1.1.0",
3436
"winston": "^3.2.1"
3537
},
3638
"standard": {

src/common/helper.js

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,31 @@
55
const AWS = require('aws-sdk')
66
const config = require('config')
77
const elasticsearch = require('elasticsearch')
8+
const _ = require('lodash')
9+
const tcCoreLibAuth = require('tc-core-library-js')
10+
const urlencode = require('urlencode')
811

912
const logger = require('./logger')
1013

1114
AWS.config.region = config.get('esConfig.AWS_REGION')
1215
// ES Client mapping
1316
const esClients = {}
1417

18+
const m2mAuth = tcCoreLibAuth.auth.m2m
19+
const util = tcCoreLibAuth.util(config)
20+
let m2m = null
21+
22+
/**
23+
* Get machine to machine token.
24+
* @returns {Promise} promise which resolves to the m2m token
25+
*/
26+
async function getM2MToken () {
27+
if (_.isNull(m2m)) {
28+
m2m = m2mAuth(_.pick(config, ['AUTH0_URL', 'AUTH0_AUDIENCE', 'TOKEN_CACHE_TIME', 'AUTH0_PROXY_SERVER_URL']))
29+
}
30+
return m2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET)
31+
}
32+
1533
/**
1634
* Get ES Client
1735
* @return {Object} Elastic Host Client Instance
@@ -126,9 +144,35 @@ async function updateMetadadaESPromise (updateDocHandler) {
126144
})
127145
}
128146

147+
/**
148+
* Retrieve member details from userIds
149+
*
150+
* @param {Array} userIds the list of userIds
151+
* @returns {Promise} the member details
152+
*/
153+
async function getMemberDetailsByUserIds (userIds) {
154+
try {
155+
const token = await getM2MToken()
156+
const httpClient = util.getHttpClient({ id: `projectMemberService_${userIds.join('_')}`, log: logger })
157+
return httpClient.get(`${config.MEMBER_SERVICE_ENDPOINT}/_search`, {
158+
params: {
159+
query: `${_.map(userIds, id => `userId:${id}`).join(urlencode(' OR ', 'utf8'))}`,
160+
fields: 'userId,handle,firstName,lastName,email'
161+
},
162+
headers: {
163+
'Content-Type': 'application/json',
164+
Authorization: `Bearer ${token}`
165+
}
166+
}).then(res => _.get(res, 'data.result.content', null))
167+
} catch (err) {
168+
return Promise.reject(err)
169+
}
170+
}
171+
129172
module.exports = {
130173
getESClient,
131174
updateProjectESPromise,
132175
updateTimelineESPromise,
133-
updateMetadadaESPromise
176+
updateMetadadaESPromise,
177+
getMemberDetailsByUserIds
134178
}

src/services/ProcessorServiceProjectMember.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,15 @@ async function create (message) {
5353
async function updateDocPromise (doc) {
5454
const members = _.isArray(doc._source.members) ? doc._source.members : []
5555
const existingMemberIndex = _.findIndex(members, p => p.id === message.id)// if member does not exists already
56+
console.log(message)
5657
if (existingMemberIndex === -1) {
57-
members.push(message)
58+
if (!message.userId) {
59+
members.push(message)
60+
return
61+
}
62+
const memberDetails = await helper.getMemberDetailsByUserIds([message.userId])
63+
const messageWithDetails = _.merge(message, _.pick(memberDetails[0], 'handle', 'firstName', 'lastName', 'email'))
64+
members.push(messageWithDetails)
5865
} else { // if member already exists, ideally we should never land here, but code handles the buggy indexing
5966
// replaces the old inconsistent index where previously member was not removed from the index but deleted
6067
// from the database

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const Joi = require('joi')
1111
const ProcessorService = require('../../src/services/ProcessorService')
1212
const testHelper = require('../common/testHelper')
1313
const logger = require('../../src/common/logger')
14+
const helper = require('../../src/common/helper')
1415

1516
const {
1617
projectId,
@@ -799,13 +800,21 @@ xdescribe('TC Phase Product Topic Tests', () => {
799800
})
800801

801802
describe('TC Project Member Topic Tests', () => {
803+
let getMemberDetailsByUserIds
804+
802805
before(async () => {
803806
// runs before all tests in this block
804807
await ProcessorService.create(projectCreatedMessage)
808+
getMemberDetailsByUserIds = helper.getMemberDetailsByUserIds
809+
helper.getMemberDetailsByUserIds = async (userIds) => {
810+
return [] // return empty details
811+
}
805812
})
806813
after(async () => {
807814
// runs after all tests in this block
808815
await ProcessorService.deleteMessage(projectDeletedMessage)
816+
// restore the method
817+
helper.getMemberDetailsByUserIds = getMemberDetailsByUserIds
809818
})
810819

811820
it('create project member message', async () => {

0 commit comments

Comments
 (0)