"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = selectDistributionCert;
function _open() {
const data = _interopRequireDefault(require("open"));
_open = function () {
return data;
};
return data;
}
function _ora() {
const data = _interopRequireDefault(require("ora"));
_ora = function () {
return data;
};
return data;
}
function _xdl() {
const data = require("@expo/xdl");
_xdl = function () {
return data;
};
return data;
}
function appleApi() {
const data = _interopRequireWildcard(require("../build/ios/appleApi"));
appleApi = function () {
return data;
};
return data;
}
function credentials() {
const data = _interopRequireWildcard(require("../build/ios/credentials"));
credentials = function () {
return data;
};
return data;
}
function _promptForCredentials() {
const data = _interopRequireDefault(require("../build/ios/credentials/prompt/promptForCredentials"));
_promptForCredentials = function () {
return data;
};
return data;
}
function _log() {
const data = _interopRequireDefault(require("../../log"));
_log = function () {
return data;
};
return data;
}
function _prompt() {
const data = _interopRequireDefault(require("../../prompt"));
_prompt = function () {
return data;
};
return data;
}
function _tagger() {
const data = require("./tagger");
_tagger = function () {
return data;
};
return data;
}
function _selectUtils() {
const data = require("./selectUtils");
_selectUtils = function () {
return data;
};
return data;
}
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
async function selectDistributionCert(context, options = {}) {
const certificates = context.username ? await chooseUnrevokedDistributionCert(context) : [];
const choices = [...certificates]; // autoselect creds if we find valid ones
if (certificates.length > 0 && !options.disableAutoSelectExisting) {
const autoselectedCertificate = (0, _selectUtils().choosePreferredCreds)(context, certificates);
(0, _log().default)(`Using Distribution Certificate: ${autoselectedCertificate.name}`);
return autoselectedCertificate.value;
}
if (!options.disableCreate) {
choices.push({
name: '[Create a new certificate] (Recommended)',
value: 'GENERATE'
});
}
choices.push({
name: '[Upload an existing certificate]',
value: 'UPLOAD'
});
choices.push({
name: '[Show me more info about these choices] ℹ️',
value: 'INFO'
});
const {
promptValue
} = await (0, _prompt().default)({
type: 'list',
name: 'promptValue',
message: 'Select an iOS distribution certificate to use for code signing:',
pageSize: Infinity,
choices
});
if (promptValue === 'GENERATE') {
return await generateDistributionCert(context);
} else if (promptValue === 'UPLOAD') {
const {
credentials: userProvidedCredentials,
metadata
} = await (0, _promptForCredentials().default)(context, ['distributionCert']);
const distributionCert = userProvidedCredentials.distributionCert;
distributionCert.distCertSerialNumber = metadata.distCertSerialNumber;
const isValid = await validateUploadedCertificate(context, distributionCert);
if (!isValid) {
return await selectDistributionCert(context, {
disableAutoSelectExisting: true
});
} // tag for updating to Expo servers
(0, _tagger().tagForUpdate)(distributionCert);
} else if (promptValue === 'INFO') {
(0, _open().default)('https://docs.expo.io/versions/latest/guides/adhoc-builds/#distribution-certificate-cli-options');
return await selectDistributionCert(context);
} else {
return promptValue; // this should be an unrevoked cert from the Expo servers
}
}
async function validateUploadedCertificate(context, distributionCert) {
const spinner = (0, _ora().default)(`Checking validity of distribution certificate on Apple Developer Portal...`).start();
const formattedDistCertArray = _xdl().Credentials.Ios.formatDistCerts([distributionCert], {
provideFullCertificate: true
});
const filteredFormattedDistCertArray = await filterRevokedDistributionCerts(context, formattedDistCertArray);
const isValidCert = filteredFormattedDistCertArray.length > 0;
if (isValidCert) {
const successMsg = `Successfully validated Distribution Certificate you uploaded against Apple Servers`;
spinner.succeed(successMsg);
} else {
const failureMsg = `The Distribution Certificate you uploaded is not valid. Please check that you uploaded your certificate to the Apple Servers. See docs.expo.io/versions/latest/guides/adhoc-builds for more details on uploading your credentials.`;
spinner.fail(failureMsg);
}
return isValidCert;
}
async function chooseUnrevokedDistributionCert(context) {
const certsOnExpoServer = await _xdl().Credentials.Ios.getExistingDistCerts(context.username, context.team.id, {
provideFullCertificate: true
});
if (certsOnExpoServer.length === 0) {
return []; // no certs stored on server
}
const spinner = (0, _ora().default)(`Checking validity of distribution certificates on Apple Developer Portal...`).start();
const validCertsOnExpoServer = await filterRevokedDistributionCerts(context, certsOnExpoServer);
const numValidCerts = validCertsOnExpoServer.length;
const numRevokedCerts = certsOnExpoServer.length - validCertsOnExpoServer.length;
const statusToDisplay = `Distribution Certificate: You have ${numValidCerts} valid and ${numRevokedCerts} revoked certificates on the Expo servers.`;
if (numValidCerts > 0) {
spinner.succeed(statusToDisplay);
} else {
spinner.warn(statusToDisplay);
}
return validCertsOnExpoServer;
}
async function filterRevokedDistributionCerts(context, distributionCerts) {
// if the credentials are valid, check it against apple to make sure it hasnt been revoked
const distCertManager = appleApi().createManagers(context).distributionCert;
const certsOnAppleServer = await distCertManager.list();
const validCertSerialsOnAppleServer = certsOnAppleServer.filter( // remove expired certs
cert => cert.expires > Math.floor(Date.now() / 1000)).map(cert => cert.serialNumber);
const validCertsOnExpoServer = distributionCerts.filter(cert => {
const serialNumber = cert.value && cert.value.distCertSerialNumber;
return validCertSerialsOnAppleServer.includes(serialNumber);
});
return validCertsOnExpoServer;
}
async function generateDistributionCert(context) {
const manager = appleApi().createManagers(context).distributionCert;
try {
const distributionCert = await manager.create({}); // tag for updating to Expo servers
(0, _tagger().tagForUpdate)(distributionCert);
return distributionCert;
} catch (e) {
if (e.code === 'APPLE_DIST_CERTS_TOO_MANY_GENERATED_ERROR') {
const certificates = await manager.list();
_log().default.warn(`Maximum number (${certificates.length}) of certificates generated.`);
const {
answer
} = await (0, _prompt().default)({
type: 'list',
name: 'answer',
message: 'Please revoke or reuse an existing certificate:',
choices: [{
key: 'r',
name: 'Choose certificates to revoke and try again',
value: 'REVOKE'
}, {
key: 'e',
name: 'Use an existing certificate',
value: 'USE_EXISTING'
}, {
name: '[Show me more info about these choices] ℹ️',
value: 'INFO'
}]
});
if (answer === 'REVOKE') {
await credentials().revoke(context, ['distributionCert']);
return await generateDistributionCert(context);
} else if (answer === 'USE_EXISTING') {
return await selectDistributionCert(context, {
disableCreate: true,
disableAutoSelectExisting: true
});
} else if (answer === 'INFO') {
(0, _open().default)('https://docs.expo.io/versions/latest/guides/adhoc-builds/#distribution-certificate-cli-options');
return await generateDistributionCert(context);
}
}
throw new Error(e);
}
}
//# sourceMappingURL=../../__sourcemaps__/commands/client/selectDistributionCert.js.map