export async function createRepositoryFromClient()

in api/client/newOrgRepo.ts [164:334]


export async function createRepositoryFromClient(req: ILocalApiRequest, res, next) {
  const providers = getProviders(req);
  const { insights, diagnosticsDrop, customizedNewRepositoryLogic, graphProvider } = providers;
  const individualContext = req.individualContext || req.apiContext;
  const config = getProviders(req).config;;
  const organization = (req.organization || (req as any).aeOrganization) as Organization;
  const existingRepoId = req.body.existingrepoid;
  const correlationId = req.correlationId;
  const debugValues = req.body.debugValues || {};
  const corporateId = individualContext.corporateIdentity.id;
  const customContext = customizedNewRepositoryLogic?.createContext(req);
  const additionalTelemetryProperties = customizedNewRepositoryLogic?.getAdditionalTelemetryProperties(customContext) || {};
  insights.trackEvent({
    name: 'CreateRepositoryFromClientStart',
    properties: Object.assign({
      debugValues,
      correlationId,
      body: JSON.stringify(req.body),
      query: JSON.stringify(req.query),
      corporateId,
    }, additionalTelemetryProperties),
  });
  if (diagnosticsDrop) {
    diagnosticsDrop.setObject(`newrepo.${organization.name}.${correlationId}`, Object.assign({
      debugValues,
      correlationId,
      body: req.body,
      query: req.query,
      corporateId,
    }, additionalTelemetryProperties));
  }
  if (organization.createRepositoriesOnGitHub && !(existingRepoId && organization.isNewRepositoryLockdownSystemEnabled())) {
    return next(jsonError(`The GitHub organization ${organization.name} is configured as "createRepositoriesOnGitHub": repos should be created on GitHub.com directly and not through this wizard.`, 400));
  }
  const body = req.body;
  if (!body) {
    return next(jsonError('No body', 400));
  }
  try {
    await customizedNewRepositoryLogic?.validateRequest(customContext, req);
  } catch (validationError) {
    return next(jsonError(validationError, 400));
  }
  req.apiVersion = (req.query['api-version'] || req.headers['api-version'] || '2017-07-27') as string;
  if (req.apiContext && req.apiContext.getGitHubIdentity()) {
    body['ms.onBehalfOf'] = req.apiContext.getGitHubIdentity().username;
  }
  // these fields do not need translation: name, description, private
  let isApproved = customizedNewRepositoryLogic ? customizedNewRepositoryLogic.skipApproval(customContext, body) : false;
  const approvalTypesToIds = config.github.approvalTypes.fields.approvalTypesToIds;
  if (!isApproved) {
    if (approvalTypesToIds[body.approvalType]) {
      body.approvalType = approvalTypesToIds[body.approvalType];
    } else {
      let valid = false;
      Object.getOwnPropertyNames(approvalTypesToIds).forEach(key => {
        if (approvalTypesToIds[key] === body.approvalType) {
          valid = true;
        }
      });
      if (!valid) {
        return next(jsonError('The approval type is not supported or approved at this time', 400));
      }
    }
  }
  // Property supporting private repos from the client
  if (body.visibility === 'private') {
    body.private = true;
    delete body.visibility;
  } else if (body.visibility === 'internal') {
    // visibility: internal is legitimate for GHEC or GHAE users
    body.private = true;
  }
  translateValue(body, 'approvalType', 'ms.approval');
  translateValue(body, 'approvalUrl', 'ms.approval-url');
  translateValue(body, 'justification', 'ms.justification');
  translateValue(body, 'legalEntity', 'ms.entity');
  translateValue(body, 'projectType', 'ms.project-type');
  // Team permissions
  let sufficientTeamsOk = false;
  if (customizedNewRepositoryLogic?.sufficientTeamsConfigured) {
    sufficientTeamsOk = customizedNewRepositoryLogic.sufficientTeamsConfigured(customContext, body);
  }
  if (!sufficientTeamsOk) {
    if (!body.selectedAdminTeams || !body.selectedAdminTeams.length) {
      return next(jsonError('No administration team(s) provided in the request', 400));
    }
  }
  translateTeams(body);
  try {
    // Initial repo contents and license
    const templates = _.keyBy(organization.getRepositoryCreateMetadata().templates, 'id');
    const template = templates[body.template];
    // if (!template) {
    // return next(jsonError('There was a configuration problem, the template metadata was not available for this request', 400));
    // }
    translateValue(body, 'template', 'ms.template');
    body['ms.license'] = template && (template.spdx || template.name); // Today this is the "template name" or SPDX if available
    translateValue(body, 'gitIgnoreTemplate', 'gitignore_template');
  } catch (templateError) {
    insights?.trackException({ exception: templateError });
    console.warn(`Optional template error: ${templateError}`);
  }
  if (!body['ms.notify']) {
    try {
      if (graphProvider && individualContext?.corporateIdentity?.id) {
        const info = await graphProvider.getUserById(individualContext.corporateIdentity.id);
        if (info?.mail) {
          body['ms.notify'] = info.mail;
        }
      }
    } catch (graphError) {
      insights?.trackException({ exception: graphError });
      console.warn(`Retrieving user mail address error: ${graphError}`);
    }
  }
  if (!body['ms.notify']) {
    body['ms.notify'] = individualContext?.link?.corporateMailAddress || req.knownRequesterMailAddress || config.brand.operationsMail || config.brand.supportMail;
  }
  // these fields are currently ignored: orgName
  delete body.orgName;
  customizedNewRepositoryLogic?.stripRequestBody(customContext, body);
  insights.trackEvent({
    name: 'ApiClientNewOrgRepoStart',
    properties: {
      body: JSON.stringify(req.body),
    },
  });
  let success: ICreateRepositoryApiResult = null;
  try {
    const newRepositoryParameters = customizedNewRepositoryLogic?.additionalCreateRepositoryParameters ?
      Object.assign(body, customizedNewRepositoryLogic.additionalCreateRepositoryParameters(customContext)) : body;
    success = await CreateRepository(req, organization, customizedNewRepositoryLogic, customContext, newRepositoryParameters, CreateRepositoryEntrypoint.Client, individualContext);
  } catch (createRepositoryError) {
    insights.trackEvent({
      name: 'ApiClientNewOrgRepoError',
      properties: {
        error: createRepositoryError.message,
        encoded: JSON.stringify(createRepositoryError),
      },
    });
    if (!createRepositoryError.json) {
      createRepositoryError = jsonError(createRepositoryError, 400);
    }
    return next(createRepositoryError);
  }
  let message = success.github ? `Your new repo, ${success.github.name}, has been created:` : 'Your repo request has been submitted.';
  if (existingRepoId && success.github) {
    message = `Your repository ${success.github.name} is classified and the repo is now ready, unlocked, with your selected team permissions assigned.`;
  }
  const output = {
    ...success,
    title: existingRepoId ? 'Repository unlocked' : 'Repository created',
    message,
    url: null,
    messages: null,
  };
  if (success.github) {
    output.url = success.github.html_url;
  }
  output.messages = output['tasks'];
  delete output['tasks'];
  insights.trackEvent({
    name: 'ApiClientNewOrgRepoSuccessful',
    properties: {
      body: JSON.stringify(body),
      success: JSON.stringify(output),
    },
  });
  return res.json(output);
}