From 90f9c266da06627d2a7bde257b3a3bf31ab03c84 Mon Sep 17 00:00:00 2001 From: xxcxy Date: Wed, 2 Dec 2020 01:32:47 +0800 Subject: [PATCH] Import groups for a new user --- README.md | 7 +++++++ config/default.js | 9 +++++++++ package.json | 2 ++ src/common/helper.js | 33 ++++++++++++++++++++++++++++++++ src/services/ProcessorService.js | 6 ++++++ 5 files changed, 57 insertions(+) diff --git a/README.md b/README.md index 6491314..049d748 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,13 @@ The following parameters can be set in config files or in env variables: - ELASTICCLOUD_ID: The elastic cloud id, if your elasticsearch instance is hosted on elastic cloud. DO NOT provide a value for ES_HOST if you are using this - ELASTICCLOUD_USERNAME: The elastic cloud username for basic authentication. Provide this only if your elasticsearch instance is hosted on elastic cloud - ELASTICCLOUD_PASSWORD: The elastic cloud password for basic authentication. Provide this only if your elasticsearch instance is hosted on elastic cloud +- AUTH0_URL: The auth0 url, Default is 'https://topcoder-dev.auth0.com/oauth/token' +- AUTH0_AUDIENCE: The auth0 audience for accessing ubahn api(s), Default is 'https://m2m.topcoder-dev.com/' +- AUTH0_CLIENT_ID: The auth0 client id +- AUTH0_CLIENT_SECRET: The auth0 client secret +- AUTH0_PROXY_SERVER_URL: The auth0 proxy server url +- TOKEN_CACHE_TIME: The token cache time +- TOPCODER_GROUP_API: The topcoder groups api, Default is 'https://api.topcoder-dev.com/v5/groups' There is a `/health` endpoint that checks for the health of the app. This sets up an expressjs server and listens on the environment variable `PORT`. It's not part of the configuration file and needs to be passed as an environment variable diff --git a/config/default.js b/config/default.js index 82564c6..3e698d7 100644 --- a/config/default.js +++ b/config/default.js @@ -14,6 +14,15 @@ module.exports = { // Kafka group id KAFKA_GROUP_ID: process.env.KAFKA_GROUP_ID || 'ubahn-processor-es', + TOPCODER_GROUP_API: process.env.TOPCODER_GROUP_API || 'https://api.topcoder-dev.com/v5/groups', + + AUTH0_URL: process.env.AUTH0_URL || 'https://topcoder-dev.auth0.com/oauth/token', // Auth0 credentials + AUTH0_AUDIENCE: process.env.AUTH0_AUDIENCE || 'https://m2m.topcoder-dev.com/', + TOKEN_CACHE_TIME: process.env.TOKEN_CACHE_TIME, + AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID, + AUTH0_CLIENT_SECRET: process.env.AUTH0_CLIENT_SECRET, + AUTH0_PROXY_SERVER_URL: process.env.AUTH0_PROXY_SERVER_URL, + UBAHN_CREATE_TOPIC: process.env.UBAHN_CREATE_TOPIC || 'u-bahn.action.create', UBAHN_UPDATE_TOPIC: process.env.UBAHN_UPDATE_TOPIC || 'u-bahn.action.update', UBAHN_DELETE_TOPIC: process.env.UBAHN_DELETE_TOPIC || 'u-bahn.action.delete', diff --git a/package.json b/package.json index b4a6d6b..4aabcf7 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,8 @@ "get-parameter-names": "^0.3.0", "lodash": "^4.17.19", "no-kafka": "^3.4.3", + "axios": "^0.19.2", + "tc-core-library-js": "appirio-tech/tc-core-library-js.git#v2.6", "topcoder-healthcheck-dropin": "^1.0.3", "winston": "^3.2.1" }, diff --git a/src/common/helper.js b/src/common/helper.js index e09fe77..188e762 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -8,6 +8,10 @@ const elasticsearch = require('@elastic/elasticsearch') const _ = require('lodash') const Joi = require('@hapi/joi') const { Mutex } = require('async-mutex') +const axios = require('axios') +const logger = require('./logger') +const m2mAuth = require('tc-core-library-js').auth.m2m +const topcoderM2M = m2mAuth(_.pick(config, ['AUTH0_URL', 'AUTH0_AUDIENCE', 'TOKEN_CACHE_TIME', 'AUTH0_PROXY_SERVER_URL'])) AWS.config.region = config.ES.AWS_REGION @@ -18,6 +22,34 @@ let transactionId const esClientMutex = new Mutex() const mutexReleaseMap = {} +/* Function to get M2M token + * (Topcoder APIs only) + * @returns {Promise} + */ +async function getTopcoderM2Mtoken () { + return topcoderM2M.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) +} + +/** + * Returns the user in Topcoder identified by the email + * @param {String} email The user email + */ +async function getUserGroup (memberId) { + const url = config.TOPCODER_GROUP_API + const token = await getTopcoderM2Mtoken() + const params = { memberId, membershipType: 'user', page: 1 } + + logger.debug(`request GET ${url} with params: ${JSON.stringify(params)}`) + let groups = [] + let groupRes = await axios.get(url, { headers: { Authorization: `Bearer ${token}` }, params }) + while (groupRes.data.length > 0) { + groups = _.concat(groups, _.map(groupRes.data, g => _.pick(g, 'id', 'name'))) + params.page = params.page + 1 + groupRes = await axios.get(url, { headers: { Authorization: `Bearer ${token}` }, params }) + } + return groups +} + /** * Get Kafka options * @return {Object} the Kafka options @@ -201,6 +233,7 @@ module.exports = { getESClient, validProperties, getUser, + getUserGroup, updateUser, getOrg, updateOrg, diff --git a/src/services/ProcessorService.js b/src/services/ProcessorService.js index c27046a..d5a5f21 100644 --- a/src/services/ProcessorService.js +++ b/src/services/ProcessorService.js @@ -49,6 +49,12 @@ async function processCreate (message, transactionId) { user[userResource.propertyName] = [] } + // import groups for a new user + if (resource === 'externalprofile' && message.payload.externalId) { + const userGroups = await helper.getUserGroup(message.payload.externalId) + user[config.get('ES.USER_GROUP_PROPERTY_NAME')] = _.unionBy(user[config.get('ES.USER_GROUP_PROPERTY_NAME')], userGroups, 'id') + } + // check the resource does not exist if (_.some(user[userResource.propertyName], [userResource.relateKey, relateId])) { logger.error(`Can't create existed ${resource} with the ${userResource.relateKey}: ${relateId}, userId: ${message.payload.userId}`)