diff --git a/connect/config.js b/connect/config.js index 5f939c8..407761b 100644 --- a/connect/config.js +++ b/connect/config.js @@ -8,15 +8,6 @@ module.exports = { TC_API_V4_BASE_URL: process.env.TC_API_V4_BASE_URL || 'https://api.topcoder-dev.com/v4', MESSAGE_API_BASE_URL: process.env.MESSAGE_API_BASE_URL || 'https://api.topcoder-dev.com/v5', - // Probably temporary variables for TopCoder role ids for 'Connect Manager', 'Connect Copilot' and 'administrator' - // These are values for development backend. For production backend they may be different. - // These variables are currently being used to retrieve above role members using API V3 `/roles` endpoint. - // As soon as this endpoint is replaced with more suitable one, these variables has to be removed if no need anymore. - CONNECT_MANAGER_ROLE_ID: 8, - CONNECT_COPILOT_MANAGER_ROLE_ID: 113, - CONNECT_ACCOUNT_MANAGER_ROLE_ID: 114, - CONNECT_COPILOT_ROLE_ID: 4, - ADMINISTRATOR_ROLE_ID: 1, // id of the BOT user which creates post with various events in discussions TCWEBSERVICE_ID: process.env.TCWEBSERVICE_ID || '22838965', CODERBOT_USER_ID: process.env.CODERBOT_USER_ID || 'CoderBot', diff --git a/connect/connectNotificationServer.js b/connect/connectNotificationServer.js index 5777ab9..d581e09 100644 --- a/connect/connectNotificationServer.js +++ b/connect/connectNotificationServer.js @@ -11,7 +11,6 @@ const _ = require('lodash'); const service = require('./service'); const { BUS_API_EVENT } = require('./constants'); const EVENTS = require('./events-config').EVENTS; -const TOPCODER_ROLE_RULES = require('./events-config').TOPCODER_ROLE_RULES; const PROJECT_ROLE_RULES = require('./events-config').PROJECT_ROLE_RULES; const PROJECT_ROLE_OWNER = require('./events-config').PROJECT_ROLE_OWNER; const emailNotificationServiceHandler = require('./notificationServices/email').handler; @@ -30,7 +29,7 @@ const getTopCoderMembersNotifications = (eventConfig) => { } const getRoleMembersPromises = eventConfig.topcoderRoles.map(topcoderRole => ( - service.getRoleMembers(TOPCODER_ROLE_RULES[topcoderRole].id) + service.getRoleMembers(topcoderRole) )); return Promise.all(getRoleMembersPromises).then((membersPerRole) => { @@ -351,8 +350,10 @@ const handler = (topic, message, logger, callback) => { )).then((notifications) => { allNotifications = _.filter(notifications, notification => notification.userId !== `${message.initiatorUserId}`); - if (eventConfig.includeUsers && message[eventConfig.includeUsers] && message[eventConfig.includeUsers].length > 0) { - allNotifications = _.filter(allNotifications, notification => message[eventConfig.includeUsers].includes(notification.userId)); + if (eventConfig.includeUsers && message[eventConfig.includeUsers] && + message[eventConfig.includeUsers].length > 0) { + allNotifications = _.filter(allNotifications, + notification => message[eventConfig.includeUsers].includes(notification.userId)); } logger.debug('filtered notifications: ', allNotifications); // now let's retrieve some additional data diff --git a/connect/events-config.js b/connect/events-config.js index 028518f..f32c511 100644 --- a/connect/events-config.js +++ b/connect/events-config.js @@ -1,7 +1,6 @@ /** * Configuration of connect events */ -const config = require('./config'); const { BUS_API_EVENT } = require('./constants'); // project member role names @@ -27,15 +26,6 @@ const ROLE_CONNECT_COPILOT_MANAGER = 'Connect Copilot Manager'; const ROLE_CONNECT_ACCOUNT_MANAGER = 'Connect Account Manager'; const ROLE_ADMINISTRATOR = 'administrator'; -// TopCoder role rules -const TOPCODER_ROLE_RULES = { - [ROLE_CONNECT_COPILOT]: { id: config.CONNECT_COPILOT_ROLE_ID }, - [ROLE_CONNECT_MANAGER]: { id: config.CONNECT_MANAGER_ROLE_ID }, - [ROLE_CONNECT_COPILOT_MANAGER]: { id: config.CONNECT_COPILOT_MANAGER_ROLE_ID }, - [ROLE_CONNECT_ACCOUNT_MANAGER]: { id: config.CONNECT_ACCOUNT_MANAGER_ROLE_ID }, - [ROLE_ADMINISTRATOR]: { id: config.ADMINISTRATOR_ROLE_ID }, -}; - /** * Supported events configuration * @@ -313,7 +303,6 @@ const EVENT_BUNDLES = { module.exports = { PROJECT_ROLE_RULES, - TOPCODER_ROLE_RULES, EVENTS, EVENT_BUNDLES, diff --git a/connect/service.js b/connect/service.js index 850bb48..10a416c 100644 --- a/connect/service.js +++ b/connect/service.js @@ -6,6 +6,8 @@ const request = require('superagent'); const config = require('./config'); const _ = require('lodash'); +let rolesCache = null; + /** * Get project details * @@ -13,10 +15,10 @@ const _ = require('lodash'); * * @return {Promise} promise resolved to project details */ -const getProject = (projectId) => { - return M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) - .then((token) => { - return request +const getProject = (projectId) => ( + M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) + .then((token) => ( + request .get(`${config.TC_API_V4_BASE_URL}/projects/${projectId}`) .set('accept', 'application/json') .set('authorization', `Bearer ${token}`) @@ -32,24 +34,68 @@ const getProject = (projectId) => { `Failed to get project details of project id: ${projectId}.` + (errorDetails ? ' Server response: ' + errorDetails : '') ); - }); + }) + )) + .catch((err) => { + err.message = 'Error generating m2m token: ' + err.message; + throw err; }) +); + +/** + * Get role id + * + * @param {String} role role + * + * @return {Promise} promise resolved to role members ids list + */ +const getRoleId = (role) => { + if (rolesCache) { + const cachedRole = _.find(rolesCache, { roleName: role }); + if (cachedRole) { + return Promise.resolve(cachedRole.id); + } + } + return M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) + .then((token) => ( + request + .get(`${config.TC_API_V3_BASE_URL}/roles`) + .set('accept', 'application/json') + .set('authorization', `Bearer ${token}`) + .then((res) => { + if (!_.get(res, 'body.result.success')) { + throw new Error('Failed to get roles list'); + } + const roles = _.get(res, 'body.result.content'); + rolesCache = roles; + return _.find(roles, { roleName: role }).id; + }).catch((err) => { + const errorDetails = _.get(err, 'response.body.result.content.message'); + throw new Error( + `Failed to get role id for role ${role}.` + + (errorDetails ? ' Server response: ' + errorDetails : '') + ); + }) + )) .catch((err) => { err.message = 'Error generating m2m token: ' + err.message; throw err; }); }; + /** * Get role members * - * @param {String} roleId role id + * @param {String} role role * * @return {Promise} promise resolved to role members ids list */ -const getRoleMembers = (roleId) => { - return M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) - .then((token) => { - return request +const getRoleMembers = (role) => ( + M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) + .then((token) => ( + getRoleId(role) + .then(roleId => ( + request .get(`${config.TC_API_V3_BASE_URL}/roles/${roleId}?fields=subjects`) .set('accept', 'application/json') .set('authorization', `Bearer ${token}`) @@ -65,13 +111,14 @@ const getRoleMembers = (roleId) => { `Failed to get role membrs of role id: ${roleId}.` + (errorDetails ? ' Server response: ' + errorDetails : '') ); - }); - }) + }) + )) + )) .catch((err) => { err.message = 'Error generating m2m token: ' + err.message; throw err; - }); -}; + }) +); /** * Get users details by ids @@ -88,8 +135,9 @@ const getUsersById = (ids) => { throw err; }) .then((token) => { + const fields = 'fields=userId,email,handle,firstName,lastName,photoURL,status'; return request - .get(`${config.TC_API_V3_BASE_URL}/members/_search?fields=userId,email,handle,firstName,lastName,photoURL,status&query=${query}`) + .get(`${config.TC_API_V3_BASE_URL}/members/_search?${fields}&query=${query}`) .set('accept', 'application/json') .set('authorization', `Bearer ${token}`) .then((res) => { @@ -125,8 +173,9 @@ const getUsersByHandle = (handles) => { throw err; }) .then((token) => { + const fields = 'fields=userId,handle,firstName,lastName,photoURL'; return request - .get(`${config.TC_API_V3_BASE_URL}/members/_search?fields=userId,handle,firstName,lastName,photoURL&query=${query}`) + .get(`${config.TC_API_V3_BASE_URL}/members/_search?${fields}&query=${query}`) .set('accept', 'application/json') .set('authorization', `Bearer ${token}`) .then((res) => { @@ -154,10 +203,10 @@ const getUsersByHandle = (handles) => { * * @return {Promise} promise resolved to topic details */ -const getTopic = (topicId, logger) => { - return M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) - .then((token) => { - return request +const getTopic = (topicId, logger) => ( + M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET) + .then((token) => ( + request .get(`${config.MESSAGE_API_BASE_URL}/topics/${topicId}/read`) .set('accept', 'application/json') .set('authorization', `Bearer ${token}`) @@ -175,13 +224,13 @@ const getTopic = (topicId, logger) => { `Failed to get topic details of topic id: ${topicId}.` + (errorDetails ? ' Server response: ' + errorDetails : '') ); - }); - }) + }) + )) .catch((err) => { err.message = 'Error generating m2m token: ' + err.message; throw err; - }); -}; + }) +); module.exports = { getProject,