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