in routes/org/team/index.ts [191:425]
export async function submitTeamJoinRequest(
providers: IProviders,
activeContext: IndividualContext,
team: Team,
optionalJustification: string,
correlationId: string,
hostname: string
): Promise<ITeamJoinRequestSubmitOutcome> {
const { approvalProvider, config, mailProvider, mailAddressProvider, insights, operations } = providers;
const organization = team.organization;
const broadAccessTeams = new Set(organization.broadAccessTeams);
if (!approvalProvider) {
return { error: new Error('No approval provider available') };
}
const username = activeContext.getGitHubIdentity().username;
if (!username) {
return { error: new Error('Active context required') };
}
if (broadAccessTeams.has(team.id)) {
try {
await team.addMembership(username);
} catch (error) {
insights?.trackEvent({
name: 'GitHubJoinAllMembersTeamFailure',
properties: {
organization: organization.name,
username: username,
error: error.message,
},
});
return { error: wrapError(error, `We had trouble adding you to the ${organization.name} organization. ${username}`) };
}
insights?.trackEvent({
name: 'GitHubJoinAllMembersTeamSuccess',
properties: {
organization: organization.name,
username: username,
},
});
return { message: `You have joined ${team.name} broad access team successfully`, redirect: `${organization.baseUrl}teams` };
}
const justification = optionalJustification || 'N/A';
const approvalTypesValues = config.github.approvalTypes.repo;
if (approvalTypesValues.length === 0) {
return { error: new Error('No team join approval providers configured.') };
}
const approvalTypes = new Set(approvalTypesValues);
const mailProviderInUse = approvalTypes.has('mail');
if (!mailProviderInUse) {
return { error: new Error('No configured approval providers configured.') };
}
const approverMailAddresses = [];
if (mailProviderInUse && !mailProvider) {
return { error: wrapError(null, 'No mail provider is enabled, yet this application is configured to use a mail provider.') };
}
const displayHostname = hostname;
const approvalScheme = displayHostname === 'localhost' && config.webServer.allowHttp === true ? 'http' : 'https';
const reposSiteBaseUrl = `${approvalScheme}://${displayHostname}/`;
const approvalBaseUrl = `${reposSiteBaseUrl}approvals/`;
const personName = activeContext.corporateIdentity.displayName || activeContext.corporateIdentity.username;
let personMail = null;
let requestId = null;
let approvalRequest = new TeamJoinApprovalEntity();
try {
const upn = activeContext.corporateIdentity.username;
personMail = await operations.getMailAddressFromCorporateUsername(upn);
const isMember = await team.isMember(username);
if (isMember === true) {
return { error: wrapError(null, 'You are already a member of the team ' + team.name, true) };
}
const maintainers = (await team.getOfficialMaintainers()).filter(maintainer => {
return maintainer && maintainer.login && maintainer.link;
});
approvalRequest.thirdPartyUsername = activeContext.getGitHubIdentity().username;
approvalRequest.thirdPartyId = activeContext.getGitHubIdentity().id;
approvalRequest.justification = justification;
approvalRequest.created = new Date();
approvalRequest.active = true;
approvalRequest.organizationName = team.organization.name;
approvalRequest.teamId = String(team.id);
approvalRequest.teamName = team.name;
approvalRequest.corporateUsername = activeContext.corporateIdentity.username;
approvalRequest.corporateDisplayName = activeContext.corporateIdentity.displayName;
approvalRequest.corporateId = activeContext.corporateIdentity.id;
const mnt = [];
for (let i = 0; i < maintainers.length; i++) {
const maintainer = maintainers[i];
mnt.push('@' + maintainer.login);
const ml = maintainer ? maintainer.link as ICorporateLink : null;
const approverUpn = ml && ml.corporateUsername ? ml.corporateUsername : null;
if (approverUpn) {
const mailAddress = await operations.getMailAddressFromCorporateUsername(approverUpn);
if (mailAddress) {
approverMailAddresses.push(mailAddress);
}
}
}
const newRequestId = await approvalProvider.createTeamJoinApprovalEntity(approvalRequest);
requestId = newRequestId;
if (mailProviderInUse) {
const approversAsString = approverMailAddresses.join(', ');
const mail = {
to: approverMailAddresses,
subject: `${personName} wants to join your ${team.name} team in the ${team.organization.name} GitHub org`,
correlationId,
content: undefined,
};
const contentOptions = {
reason: (`You are receiving this e-mail because you are a team maintainer for the GitHub team "${team.name}" in the ${team.organization.name} organization.
To stop receiving these mails, you can remove your team maintainer status on GitHub.
This mail was sent to: ${approversAsString}`),
category: ['request', 'repos'],
headline: `${team.name} permission request`,
notification: 'action',
app: 'Microsoft GitHub',
correlationId,
version: config.logging.version,
actionUrl: approvalBaseUrl + requestId,
reposSiteUrl: reposSiteBaseUrl,
approvalRequest: approvalRequest,
team: team.name,
org: team.organization.name,
personName: personName,
personMail: personMail,
};
try {
insights?.trackEvent({
name: 'ReposTeamRequestMailRenderData',
properties: {
data: JSON.stringify(contentOptions),
},
});
mail.content = await operations.emailRender('membershipApprovals/pleaseApprove', contentOptions);
} catch (renderError) {
insights?.trackException({
exception: renderError,
properties: {
content: contentOptions,
eventName: 'ReposTeamRequestPleaseApproveMailRenderFailure',
},
});
throw renderError;
}
let customData: any = {};
try {
insights?.trackEvent({
name: 'ReposTeamRequestMailSendStart',
properties: {
mail: JSON.stringify(mail),
},
});
const mailResult = await operations.sendMail(mail);
customData = {
content: contentOptions,
receipt: mailResult,
eventName: undefined,
};
insights?.trackEvent({ name: 'ReposTeamRequestPleaseApproveMailSuccess', properties: customData });
} catch (mailError) {
customData.eventName = 'ReposTeamRequestPleaseApproveMailFailure';
insights?.trackException({ exception: mailError, properties: customData });
}
// Add to the approval to log who was sent the mail
const approval = await approvalProvider.getApprovalEntity(requestId);
approval.mailSentToApprovers = approversAsString;
// approval.mailSentTo = personMail;
await approvalProvider.updateTeamApprovalEntity(approval);
}
if (mailProviderInUse) {
// Send requester mail
const mail = {
to: personMail,
subject: `Your ${team.organization.name} "${team.name}" permission request has been submitted`,
correlationId,
content: undefined,
};
const contentOptions = {
reason: (`You are receiving this e-mail because you requested to join this team.
This mail was sent to: ${personMail}`),
headline: 'Team request submitted',
notification: 'information',
app: 'Microsoft GitHub',
correlationId,
version: config.logging.version,
actionUrl: approvalBaseUrl + requestId,
reposSiteUrl: reposSiteBaseUrl,
approvalRequest: approvalRequest,
team: team.name,
org: team.organization.name,
personName: personName,
personMail: personMail,
};
try {
insights?.trackEvent({
name: 'ReposTeamRequestedMailRenderData',
properties: {
data: JSON.stringify(contentOptions),
},
});
mail.content = await operations.emailRender('membershipApprovals/requestSubmitted', contentOptions);
} catch (renderError) {
insights?.trackException({
exception: renderError,
properties: {
content: contentOptions,
eventName: 'ReposTeamRequestSubmittedMailRenderFailure',
},
});
throw renderError;
}
let customData: any = {};
try {
insights?.trackEvent({
name: 'ReposTeamRequestedMailSendStart',
properties: {
mail: JSON.stringify(mail),
},
});
const mailResult = await operations.sendMail(mail);
customData = {
content: contentOptions,
receipt: mailResult,
eventName: undefined,
};
insights?.trackEvent({ name: 'ReposTeamRequestSubmittedMailSuccess', properties: customData });
} catch (mailError) {
customData.eventName = 'ReposTeamRequestSubmittedMailFailure';
insights?.trackException({ exception: mailError, properties: customData });
}
}
} catch (error) {
return { error };
}
return { redirect: team.baseUrl };
}