From 2a079f5ea4bbbbf180d822ad2e844eaeae0b06c2 Mon Sep 17 00:00:00 2001 From: Cagdas U Date: Thu, 29 Apr 2021 23:48:51 +0300 Subject: [PATCH] fix(interview-scheduler): fix interview permissions & mail feature 1. Fixes the interview permissions as per [1]. 2. Updates email sending feature to get candidate's email automatically. [2] References: [1]: https://github.com/topcoder-platform/taas-app/issues/173 [2]: https://github.com/topcoder-platform/taas-app/issues/165 --- src/common/helper.js | 21 ++++++++++++++++++++- src/eventHandlers/InterviewEventHandler.js | 7 ++++--- src/services/InterviewService.js | 18 ++++++++++-------- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/common/helper.js b/src/common/helper.js index 8c51a750..42f96ca5 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -1350,6 +1350,24 @@ function extractWorkPeriods (start, end) { return periods } +/** + * Returns the email address of specified (via handle) user. + * + * @param {String} userHandle user handle + * @returns {String} email address of the user + */ +async function getUserEmailByHandle (userHandle) { + const token = await getM2MToken() + const url = `${config.TC_API}/members/${userHandle}` + const res = await request + .get(url) + .set('Authorization', `Bearer ${token}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json') + localLogger.debug({ context: 'getUserEmailByHandle', message: `response body: ${JSON.stringify(res.body)}` }) + return _.get(res, 'body.email') +} + module.exports = { getParamFromCliArgs, promptUser, @@ -1398,5 +1416,6 @@ module.exports = { createChallenge, updateChallenge, createChallengeResource, - extractWorkPeriods + extractWorkPeriods, + getUserEmailByHandle } diff --git a/src/eventHandlers/InterviewEventHandler.js b/src/eventHandlers/InterviewEventHandler.js index ccbbd10e..1a4daaba 100644 --- a/src/eventHandlers/InterviewEventHandler.js +++ b/src/eventHandlers/InterviewEventHandler.js @@ -19,18 +19,19 @@ async function sendInvitationEmail (payload) { // get job candidate user details const jobCandidate = await models.JobCandidate.findById(interview.jobCandidateId) - const jobCandidateUser = await helper.getUserById(jobCandidate.userId, true) + const jobCandidateUser = await helper.getUserById(jobCandidate.userId) + const jobCandidateUserEmail = await helper.getUserEmailByHandle(jobCandidateUser.handle) // get customer details const job = await jobCandidate.getJob() - const interviewerList = interview.attendeesList teamService.sendEmail({}, { template: 'interview-invitation', - cc: interview.attendeesList, + cc: [jobCandidateUserEmail, ...interview.attendeesList], data: { interviewType: interview.xaiTemplate, interviewRound: interview.round, interviewDuration: Interviews.XaiTemplate[interview.xaiTemplate], + interviewerList: interview.attendeesList, jobName: job.title, candidateName: `${jobCandidateUser.firstName} ${jobCandidateUser.lastName}`, candidateId: interview.jobCandidateId diff --git a/src/services/InterviewService.js b/src/services/InterviewService.js index d4f67576..e1c57e7e 100644 --- a/src/services/InterviewService.js +++ b/src/services/InterviewService.js @@ -20,12 +20,14 @@ const esClient = helper.getESClient() * Ensures user is permitted for the operation. * * @param {Object} currentUser the user who perform this operation. + * @param {String} jobCandidateId the job candidate id * @throws {errors.ForbiddenError} */ -function ensureUserIsPermitted (currentUser) { - const isUserPermitted = currentUser.hasManagePermission || currentUser.isMachine - if (isUserPermitted !== true) { - throw new errors.ForbiddenError('You are not allowed to perform this action!') +async function ensureUserIsPermitted (currentUser, jobCandidateId) { + if (!currentUser.hasManagePermission && !currentUser.isMachine) { + const jobCandidate = await models.JobCandidate.findById(jobCandidateId) + const job = jobCandidate.getJob() + await helper.checkIsMemberOfProject(currentUser.userId, job.projectId) } } @@ -58,7 +60,7 @@ function handleSequelizeError (err, jobCandidateId) { */ async function getInterviewByRound (currentUser, jobCandidateId, round, fromDb = false) { // check permission - ensureUserIsPermitted(currentUser) + await ensureUserIsPermitted(currentUser, jobCandidateId) if (!fromDb) { try { // get job candidate from ES @@ -113,7 +115,7 @@ getInterviewByRound.schema = Joi.object().keys({ */ async function requestInterview (currentUser, jobCandidateId, interview) { // check permission - ensureUserIsPermitted(currentUser) + await ensureUserIsPermitted(currentUser, jobCandidateId) interview.id = uuid() interview.jobCandidateId = jobCandidateId @@ -168,7 +170,7 @@ requestInterview.schema = Joi.object().keys({ */ async function partiallyUpdateInterview (currentUser, jobCandidateId, round, data) { // check permission - ensureUserIsPermitted(currentUser) + await ensureUserIsPermitted(currentUser, jobCandidateId) const interview = await Interview.findOne({ where: { @@ -234,7 +236,7 @@ partiallyUpdateInterview.schema = Joi.object().keys({ */ async function searchInterviews (currentUser, jobCandidateId, criteria) { // check permission - ensureUserIsPermitted(currentUser) + await ensureUserIsPermitted(currentUser, jobCandidateId) const { page, perPage } = criteria