From 8669744a6e9c6f7ff044a70544d391a6d1452e00 Mon Sep 17 00:00:00 2001 From: DimitarTachev Date: Wed, 16 Oct 2019 16:24:17 +0300 Subject: [PATCH] fix: add more signing validations --- lib/commands/build.ts | 11 ++++++++--- lib/commands/debug.ts | 15 ++++++++++++--- lib/commands/deploy.ts | 11 ++++++++--- lib/commands/run.ts | 11 ++++++++--- lib/commands/test.ts | 18 ++++++++++++++++++ lib/common/helpers.ts | 15 +++++++++++++++ lib/constants.ts | 4 +++- .../android/android-bundle-tool-service.ts | 5 +++-- 8 files changed, 75 insertions(+), 15 deletions(-) diff --git a/lib/commands/build.ts b/lib/commands/build.ts index 7746a5c37d..4afff5e3bf 100644 --- a/lib/commands/build.ts +++ b/lib/commands/build.ts @@ -1,5 +1,6 @@ -import { ANDROID_RELEASE_BUILD_ERROR_MESSAGE, AndroidAppBundleMessages } from "../constants"; +import { ANDROID_RELEASE_BUILD_ERROR_MESSAGE, AndroidAppBundleMessages, ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE } from "../constants"; import { ValidatePlatformCommandBase } from "./command-base"; +import { hasValidAndroidSigning } from "../common/helpers"; export abstract class BuildCommandBase extends ValidatePlatformCommandBase { constructor($options: IOptions, @@ -123,8 +124,12 @@ export class BuildAndroidCommand extends BuildCommandBase implements ICommand { this.$androidBundleValidatorHelper.validateRuntimeVersion(this.$projectData); let canExecute = await super.canExecuteCommandBase(platform, { notConfiguredEnvOptions: { hideSyncToPreviewAppOption: true } }); if (canExecute) { - if (this.$options.release && (!this.$options.keyStorePath || !this.$options.keyStorePassword || !this.$options.keyStoreAlias || !this.$options.keyStoreAliasPassword)) { - this.$errors.failWithHelp(ANDROID_RELEASE_BUILD_ERROR_MESSAGE); + if ((this.$options.release || this.$options.aab) && !hasValidAndroidSigning(this.$options)) { + if (this.$options.release) { + this.$errors.failWithHelp(ANDROID_RELEASE_BUILD_ERROR_MESSAGE); + } else { + this.$errors.failWithHelp(ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE); + } } canExecute = await super.validateArgs(args, platform); diff --git a/lib/commands/debug.ts b/lib/commands/debug.ts index 4badca995b..16e23bc2e2 100644 --- a/lib/commands/debug.ts +++ b/lib/commands/debug.ts @@ -1,5 +1,7 @@ import { cache } from "../common/decorators"; import { ValidatePlatformCommandBase } from "./command-base"; +import { hasValidAndroidSigning } from "../common/helpers"; +import { ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE } from "../constants"; export class DebugPlatformCommand extends ValidatePlatformCommandBase implements ICommand { public allowedParameters: ICommandParameter[] = []; @@ -155,7 +157,8 @@ export class DebugAndroidCommand implements ICommand { private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, private $injector: IInjector, private $projectData: IProjectData, - private $markingModeService: IMarkingModeService) { + private $markingModeService: IMarkingModeService, + private $options: IOptions) { this.$projectData.initializeProjectData(); } @@ -164,8 +167,14 @@ export class DebugAndroidCommand implements ICommand { return this.debugPlatformCommand.execute(args); } public async canExecute(args: string[]): Promise { - const result = await this.debugPlatformCommand.canExecute(args); - return result; + const canExecuteBase = await this.debugPlatformCommand.canExecute(args); + if (canExecuteBase) { + if (this.$options.aab && !hasValidAndroidSigning(this.$options)) { + this.$errors.failWithHelp(ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE); + } + } + + return canExecuteBase; } public platform = this.$devicePlatformsConstants.Android; diff --git a/lib/commands/deploy.ts b/lib/commands/deploy.ts index 618126e98c..0d8a55169e 100644 --- a/lib/commands/deploy.ts +++ b/lib/commands/deploy.ts @@ -1,6 +1,7 @@ -import { ANDROID_RELEASE_BUILD_ERROR_MESSAGE } from "../constants"; +import { ANDROID_RELEASE_BUILD_ERROR_MESSAGE, ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE } from "../constants"; import { ValidatePlatformCommandBase } from "./command-base"; import { DeployCommandHelper } from "../helpers/deploy-command-helper"; +import { hasValidAndroidSigning } from "../common/helpers"; export class DeployOnDeviceCommand extends ValidatePlatformCommandBase implements ICommand { public allowedParameters: ICommandParameter[] = []; @@ -47,8 +48,12 @@ export class DeployOnDeviceCommand extends ValidatePlatformCommandBase implement return false; } - if (this.$mobileHelper.isAndroidPlatform(platform) && this.$options.release && (!this.$options.keyStorePath || !this.$options.keyStorePassword || !this.$options.keyStoreAlias || !this.$options.keyStoreAliasPassword)) { - this.$errors.failWithHelp(ANDROID_RELEASE_BUILD_ERROR_MESSAGE); + if (this.$mobileHelper.isAndroidPlatform(platform) && (this.$options.release || this.$options.aab) && !hasValidAndroidSigning(this.$options)) { + if (this.$options.release) { + this.$errors.failWithHelp(ANDROID_RELEASE_BUILD_ERROR_MESSAGE); + } else { + this.$errors.failWithHelp(ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE); + } } const result = await super.canExecuteCommandBase(platform, { validateOptions: true }); diff --git a/lib/commands/run.ts b/lib/commands/run.ts index 8dbed16a68..e90d9ab9ad 100644 --- a/lib/commands/run.ts +++ b/lib/commands/run.ts @@ -1,6 +1,7 @@ import { ERROR_NO_VALID_SUBCOMMAND_FORMAT } from "../common/constants"; -import { ANDROID_RELEASE_BUILD_ERROR_MESSAGE } from "../constants"; +import { ANDROID_RELEASE_BUILD_ERROR_MESSAGE, ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE } from "../constants"; import { cache } from "../common/decorators"; +import { hasValidAndroidSigning } from "../common/helpers"; export class RunCommandBase implements ICommand { private liveSyncCommandHelperAdditionalOptions: ILiveSyncCommandHelperAdditionalOptions = {}; @@ -126,8 +127,12 @@ export class RunAndroidCommand implements ICommand { this.$errors.fail(`Applications for platform ${this.$devicePlatformsConstants.Android} can not be built on this OS`); } - if (this.$options.release && (!this.$options.keyStorePath || !this.$options.keyStorePassword || !this.$options.keyStoreAlias || !this.$options.keyStoreAliasPassword)) { - this.$errors.failWithHelp(ANDROID_RELEASE_BUILD_ERROR_MESSAGE); + if ((this.$options.release || this.$options.aab) && !hasValidAndroidSigning(this.$options)) { + if (this.$options.release) { + this.$errors.failWithHelp(ANDROID_RELEASE_BUILD_ERROR_MESSAGE); + } else { + this.$errors.failWithHelp(ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE); + } } return this.$platformValidationService.validateOptions(this.$options.provision, this.$options.teamId, this.$projectData, this.$devicePlatformsConstants.Android.toLowerCase()); diff --git a/lib/commands/test.ts b/lib/commands/test.ts index a6c8998ae5..f21a1fca27 100644 --- a/lib/commands/test.ts +++ b/lib/commands/test.ts @@ -1,3 +1,6 @@ +import { hasValidAndroidSigning } from "../common/helpers"; +import { ANDROID_RELEASE_BUILD_ERROR_MESSAGE, ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE } from "../constants"; + abstract class TestCommandBase { public allowedParameters: ICommandParameter[] = []; public dashedOptions = { @@ -111,6 +114,21 @@ class TestAndroidCommand extends TestCommandBase implements ICommand { await this.$markingModeService.handleMarkingModeFullDeprecation({ projectDir: this.$projectData.projectDir, skipWarnings: true }); await super.execute(args); } + + async canExecute(args: string[]): Promise { + const canExecuteBase = await super.canExecute(args); + if (canExecuteBase) { + if ((this.$options.release || this.$options.aab) && !hasValidAndroidSigning(this.$options)) { + if (this.$options.release) { + this.$errors.failWithHelp(ANDROID_RELEASE_BUILD_ERROR_MESSAGE); + } else { + this.$errors.failWithHelp(ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE); + } + } + } + + return canExecuteBase; + } } class TestIosCommand extends TestCommandBase implements ICommand { diff --git a/lib/common/helpers.ts b/lib/common/helpers.ts index 31e5e64a8b..178c048b5e 100644 --- a/lib/common/helpers.ts +++ b/lib/common/helpers.ts @@ -736,4 +736,19 @@ export function annotate(fn: any) { return $inject; } +/** + * Returns true if all Android signing options are provided, false otherwise. + * @param {IAndroidSigningData} signingData The signing data to be validated. + * @return {void} + */ +export function hasValidAndroidSigning(signingData: Partial): boolean { + const isValid = signingData && + signingData.keyStorePath && + signingData.keyStorePassword && + signingData.keyStoreAlias && + signingData.keyStoreAliasPassword; + + return !!isValid; +} + //--- end part copied from AngularJS diff --git a/lib/constants.ts b/lib/constants.ts index 1e59c809f5..014c1eae9f 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -150,7 +150,9 @@ export const DEBUGGER_DETACHED_EVENT_NAME = "debuggerDetached"; export const VERSION_STRING = "version"; export const INSPECTOR_CACHE_DIRNAME = "ios-inspector"; export const POST_INSTALL_COMMAND_NAME = "post-install-cli"; -export const ANDROID_RELEASE_BUILD_ERROR_MESSAGE = "When producing a release build, you need to specify all --key-store-* options."; +const ANDROID_SIGNING_REQUIRED_MESSAGE = "you need to specify all --key-store-* options."; +export const ANDROID_RELEASE_BUILD_ERROR_MESSAGE = `When producing a release build, ${ANDROID_SIGNING_REQUIRED_MESSAGE}`; +export const ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE = `When producing Android App Bundle, ${ANDROID_SIGNING_REQUIRED_MESSAGE}`; export const CACACHE_DIRECTORY_NAME = "_cacache"; export const FILES_CHANGE_EVENT_NAME = "filesChangeEvent"; diff --git a/lib/services/android/android-bundle-tool-service.ts b/lib/services/android/android-bundle-tool-service.ts index fb38e55c3c..bac1eaa0c2 100644 --- a/lib/services/android/android-bundle-tool-service.ts +++ b/lib/services/android/android-bundle-tool-service.ts @@ -1,4 +1,5 @@ import { resolve, join } from "path"; +import { hasValidAndroidSigning } from "../../common/helpers"; export class AndroidBundleToolService implements IAndroidBundleToolService { private javaPath: string; @@ -12,8 +13,8 @@ export class AndroidBundleToolService implements IAndroidBundleToolService { } public async buildApks(options: IBuildApksOptions): Promise { - if (!options.signingData) { - this.$errors.fail(`Unable to build "apks" without a signing information.`); + if (!hasValidAndroidSigning(options.signingData)) { + this.$errors.fail(`Unable to build "apks" without a full signing information.`); } const aabToolResult = await this.execBundleTool([