Skip to content

Feature/roles cache #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 28, 2019
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
9 changes: 0 additions & 9 deletions connect/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
9 changes: 5 additions & 4 deletions connect/connectNotificationServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) => {
Expand Down Expand Up @@ -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
Expand Down
11 changes: 0 additions & 11 deletions connect/events-config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* Configuration of connect events
*/
const config = require('./config');
const { BUS_API_EVENT } = require('./constants');

// project member role names
Expand All @@ -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
*
Expand Down Expand Up @@ -313,7 +303,6 @@ const EVENT_BUNDLES = {

module.exports = {
PROJECT_ROLE_RULES,
TOPCODER_ROLE_RULES,
EVENTS,
EVENT_BUNDLES,

Expand Down
97 changes: 73 additions & 24 deletions connect/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ const request = require('superagent');
const config = require('./config');
const _ = require('lodash');

let rolesCache = null;

/**
* Get project details
*
* @param {String} projectId project id
*
* @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}`)
Expand All @@ -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}`)
Expand All @@ -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
Expand All @@ -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) => {
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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}`)
Expand All @@ -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,
Expand Down