Skip to content

Commit df6d055

Browse files
author
vikasrohit
authored
Merge pull request #340 from topcoder-platform/challenge/30095006
Challenge/30095006
2 parents a5a78ef + 1e40ba0 commit df6d055

File tree

4 files changed

+74
-6
lines changed

4 files changed

+74
-6
lines changed

src/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,5 @@ export const INVITE_STATUS = {
182182
REQUEST_APPROVED: 'request_approved',
183183
CANCELED: 'canceled',
184184
};
185+
186+
export const MAX_PARALLEL_REQUEST_QTY = 5;

src/routes/projectMemberInvites/create.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { middleware as tcMiddleware } from 'tc-core-library-js';
88
import models from '../../models';
99
import util from '../../util';
1010
import { PROJECT_MEMBER_ROLE, PROJECT_MEMBER_MANAGER_ROLES,
11-
MANAGER_ROLES, INVITE_STATUS, EVENT, BUS_API_EVENT, USER_ROLE } from '../../constants';
11+
MANAGER_ROLES, INVITE_STATUS, EVENT, BUS_API_EVENT, USER_ROLE, MAX_PARALLEL_REQUEST_QTY } from '../../constants';
1212
import { createEvent } from '../../services/busApi';
1313

1414

@@ -80,7 +80,7 @@ const buildCreateInvitePromises = (req, invite, invites, data, failed) => {
8080
if (invite.emails) {
8181
// if for some emails there are already existent users, we will invite them by userId,
8282
// to avoid sending them registration email
83-
return util.lookupUserEmails(req, invite.emails)
83+
return util.lookupMultipleUserEmails(req, invite.emails, MAX_PARALLEL_REQUEST_QTY)
8484
.then((existentUsers) => {
8585
// existent user we will invite by userId and email
8686
const existentUsersWithNumberId = existentUsers.map((user) => {

src/routes/projectMemberInvites/create.spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ describe('Project Member Invite create', () => {
147147
server.services.pubsub.publish.restore();
148148
sinon.stub(server.services.pubsub, 'init', () => {});
149149
sinon.stub(server.services.pubsub, 'publish', () => {});
150-
// by default mock lookupUserEmails return nothing so all the cases are not broken
150+
// by default mock lookupMultipleUserEmails return nothing so all the cases are not broken
151151
sandbox.stub(util, 'getUserRoles', () => Promise.resolve([]));
152-
sandbox.stub(util, 'lookupUserEmails', () => Promise.resolve([]));
152+
sandbox.stub(util, 'lookupMultipleUserEmails', () => Promise.resolve([]));
153153
sandbox.stub(util, 'getMemberDetailsByUserIds', () => Promise.resolve([{
154154
userId: 40051333,
155155
firstName: 'Admin',
@@ -366,8 +366,8 @@ describe('Project Member Invite create', () => {
366366
}),
367367
});
368368
sandbox.stub(util, 'getHttpClient', () => mockHttpClient);
369-
util.lookupUserEmails.restore();
370-
sandbox.stub(util, 'lookupUserEmails', () => Promise.resolve([{
369+
util.lookupMultipleUserEmails.restore();
370+
sandbox.stub(util, 'lookupMultipleUserEmails', () => Promise.resolve([{
371371
id: '12345',
372372
email: 'hello@world.com',
373373
}]));

src/util.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,72 @@ _.assignIn(util, {
463463
});
464464
},
465465

466+
/**
467+
* Lookup user handles from multiple emails
468+
* @param {Object} req request
469+
* @param {Array} userEmails user emails
470+
* @param {Number} maximumRequests limit number of request on one batch
471+
* @param {Boolean} isPattern flag to indicate that pattern matching is required or not
472+
* @return {Promise} promise
473+
*/
474+
lookupMultipleUserEmails(req, userEmails, maximumRequests, isPattern = false) {
475+
req.log.debug(`identityServiceEndpoint: ${config.get('identityServiceEndpoint')}`);
476+
477+
const httpClient = util.getHttpClient({ id: req.id, log: req.log });
478+
// request generator function
479+
const generateRequest = ({ token, email }) => {
480+
let filter = `email=${email}`;
481+
if (isPattern) {
482+
filter += '&like=true';
483+
}
484+
return httpClient.get(`${config.get('identityServiceEndpoint')}users`, {
485+
headers: {
486+
Authorization: `Bearer ${token}`,
487+
Accept: 'application/json',
488+
'Content-Type': 'application/json',
489+
},
490+
params: {
491+
fields: 'handle,id,email',
492+
filter,
493+
},
494+
// set longer timeout as default 3000 could be not enough for identity service response
495+
timeout: 15000,
496+
}).catch(() => {
497+
// in case of any error happens during getting user by email
498+
// we treat such users as not found and don't return error
499+
// as per discussion in issue #334
500+
});
501+
};
502+
// send batch of requests, one batch at one time
503+
const sendBatch = (options) => {
504+
const token = options.token;
505+
const emails = options.emails;
506+
const users = options.users || [];
507+
const batch = options.batch || 0;
508+
const start = batch * maximumRequests;
509+
const end = (batch + 1) * maximumRequests;
510+
const requests = emails.slice(start, end).map(userEmail =>
511+
generateRequest({ token, email: userEmail }));
512+
return Promise.all(requests)
513+
.then((responses) => {
514+
const data = responses.reduce((contents, response) => {
515+
const content = _.get(response, 'data.result.content', []);
516+
return _.concat(contents, content);
517+
}, users);
518+
req.log.debug(`UserHandle response batch-${batch}`, data);
519+
if (end < emails.length) {
520+
return sendBatch({ token, users: data, emails, batch: batch + 1 });
521+
}
522+
return data;
523+
});
524+
};
525+
return util.getM2MToken()
526+
.then((m2mToken) => {
527+
req.log.debug(`Bearer ${m2mToken}`);
528+
return sendBatch({ token: m2mToken, emails: userEmails });
529+
});
530+
},
531+
466532
/**
467533
* Filter only members of topcoder team
468534
* @param {Array} members project members

0 commit comments

Comments
 (0)