"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; function _path() { const data = _interopRequireDefault(require("path")); _path = function () { return data; }; return data; } function _chalk() { const data = _interopRequireDefault(require("chalk")); _chalk = function () { return data; }; return data; } function _fsExtra() { const data = _interopRequireDefault(require("fs-extra")); _fsExtra = function () { return data; }; return data; } function _get() { const data = _interopRequireDefault(require("lodash/get")); _get = function () { return data; }; return data; } function _xdl() { const data = require("@expo/xdl"); _xdl = function () { return data; }; return data; } function _credentials() { const data = require("../../credentials"); _credentials = function () { return data; }; return data; } function _AndroidCredentials() { const data = require("../../credentials/views/AndroidCredentials"); _AndroidCredentials = 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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } class AppSigningOptInProcess { // Keystore used to sign production app // Keystore used to sign app before uploading to Google Play store // private signing key and public cert extracted from signKeystore and encrypted using Google Play encryption key. // public cert extracted from upload keystore constructor(projectDir) { _defineProperty(this, "projectDir", ''); _defineProperty(this, "signKeystore", ''); _defineProperty(this, "uploadKeystore", ''); _defineProperty(this, "privateSigningKey", ''); _defineProperty(this, "publicUploadCert", ''); _defineProperty(this, "uploadKeystoreCredentials", {}); _defineProperty(this, "signKeystoreCredentials", {}); this.projectDir = projectDir; } async run() { const ctx = new (_credentials().Context)(); await ctx.init(this.projectDir); await this.init(ctx.manifest.slug); const view = new (_AndroidCredentials().DownloadKeystore)(ctx.manifest.slug); await view.fetch(ctx); await view.save(ctx, this.signKeystore, true); this.signKeystoreCredentials = { keystorePassword: (0, _get().default)(view, 'credentials.keystorePassword'), keyAlias: (0, _get().default)(view, 'credentials.keyAlias'), keyPassword: (0, _get().default)(view, 'credentials.keyPassword') }; try { await this.exportPrivateKey(); await this.prepareKeystores(ctx.user.username, ctx.manifest); } catch (error) { _log().default.error(error); await this.cleanup(true); return; } await this.afterStoreSubmit(ctx.user.username, ctx.manifest); } async init(slug) { _log().default.warn('Make sure you are not using Google Play App Signing already as this process will remove your current keystore from Expo servers.'); (0, _log().default)(`You can check whether you are using Google Play App Signing here: ${_chalk().default.underline('https://play.google.com/apps/publish')}. Select your app and go to "Release management" → "App signing" tab. If you are already using Google Play App Signing, there will be a message that says, "App Signing by Google Play is enabled for this app", at the top of the page.`); const confirmQuestion = [{ type: 'confirm', name: 'confirm', message: 'Is Google Play App Signing enabled for this app?' }]; const { confirm: confirmEnabled } = await (0, _prompt().default)(confirmQuestion); if (confirmEnabled) { (0, _log().default)('Google Play App Signing is already enabled; there is nothing to do here.'); process.exit(0); } this.signKeystore = _path().default.join(this.projectDir, `${slug}_sign.jks.bak`); this.uploadKeystore = _path().default.join(this.projectDir, `${slug}_upload.jks.tmp`); this.privateSigningKey = _path().default.join(this.projectDir, `${slug}_private_sign_key`); this.publicUploadCert = _path().default.join(this.projectDir, `${slug}_upload_cert.pem`); await this.cleanup(true); } async exportPrivateKey() { (0, _log().default)(`Go to the "App signing" tab in the Google Play console, select "${_chalk().default.bold('Export and upload a key (not using a Java keystore)')}" and copy the encryption key that is listed in step 1.`); const encryptKeyQuestion = [{ type: 'input', name: 'encryptionKey', message: 'Google Play encryption key', validate: value => value.length === 136 && /^[A-Fa-f0-9]+$/.test(value) || 'Encryption key needs to be a hex-encoded 68-byte string (a 4-byte identity followed by a 64-byte P-256 point).' }]; const { encryptionKey } = await (0, _prompt().default)(encryptKeyQuestion); await _xdl().AndroidCredentials.exportPrivateKey({ keystorePath: this.signKeystore, ...this.signKeystoreCredentials }, encryptionKey, this.privateSigningKey); } async prepareKeystores(username, exp) { (0, _log().default)(`Saving upload keystore to ${this.uploadKeystore}...`); this.uploadKeystoreCredentials = await _xdl().AndroidCredentials.generateUploadKeystore(this.uploadKeystore, (0, _get().default)(exp, 'android.package'), `@${username}/${exp.slug}`); (0, _log().default)(`Saving upload certificate to ${this.publicUploadCert}`); await _xdl().AndroidCredentials.exportCertBase64({ keystorePath: this.uploadKeystore, keystorePassword: this.uploadKeystoreCredentials.keystorePassword, keyAlias: this.uploadKeystoreCredentials.keyAlias }, this.publicUploadCert); await _xdl().AndroidCredentials.logKeystoreCredentials(this.uploadKeystoreCredentials, 'Credentials for upload keystore'); (0, _log().default)('App signing certificate'); await _xdl().AndroidCredentials.logKeystoreHashes({ keystorePath: this.signKeystore, ...this.signKeystoreCredentials }); (0, _log().default)('Upload certificate'); await _xdl().AndroidCredentials.logKeystoreHashes({ keystorePath: this.uploadKeystore, ...this.uploadKeystoreCredentials }); } async afterStoreSubmit(username, exp) { _log().default.warn(`On the previously opened Google Play console page, upload ${_chalk().default.underline(this.privateSigningKey)} as "${_chalk().default.bold('APP SIGNING PRIVATE KEY')}" and ${_chalk().default.underline(this.publicUploadCert)} as "${_chalk().default.bold('UPLOAD KEY PUBLIC CERTIFICATE')}"`); _log().default.warn(`The next step will ${_chalk().default.red('remove your current keystore from Expo servers')}. Make sure that private key is uploaded successfully and compare the hashes displayed above with the ones printed in the console.`); const { confirm: confirmUpload } = await (0, _prompt().default)([{ type: 'confirm', name: 'confirm', message: 'Is App Signing by Google Play enabled succesfully?', default: false }]); if (!confirmUpload) { await this.cleanup(true); _log().default.error('Aborting, no changes were applied'); process.exit(1); } await _xdl().Credentials.updateCredentialsForPlatform('android', { keystorePassword: this.uploadKeystoreCredentials.keystorePassword, keystoreAlias: this.uploadKeystoreCredentials.keyAlias, keyPassword: this.uploadKeystoreCredentials.keyPassword, keystore: (await _fsExtra().default.readFile(this.uploadKeystore)).toString('base64') }, [], { platform: 'android', username, experienceName: `@${username}/${exp.slug}` }); (0, _log().default)(`The original keystore is stored in ${this.signKeystore}; remove it only if you are sure that Google Play App Signing is enabled for your app.`); _xdl().AndroidCredentials.logKeystoreCredentials(this.signKeystoreCredentials, 'Credentials for original keystore'); await this.cleanup(); } async cleanup(all = false) { tryUnlink(this.uploadKeystore); tryUnlink(this.publicUploadCert); tryUnlink(this.privateSigningKey); if (all) { tryUnlink(this.signKeystore); } } } exports.default = AppSigningOptInProcess; async function tryUnlink(file) { try { await _fsExtra().default.unlink(file); } catch (err) {} } //# sourceMappingURL=../../__sourcemaps__/commands/google-play/AppSigningOptIn.js.map