export async function submitTeamJoinRequest()

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 };
}