diff --git a/awx/ui/client/features/credentials/add-credentials.controller.js b/awx/ui/client/features/credentials/add-credentials.controller.js index f0e4445669..5c9abcfbba 100644 --- a/awx/ui/client/features/credentials/add-credentials.controller.js +++ b/awx/ui/client/features/credentials/add-credentials.controller.js @@ -1,4 +1,4 @@ -function AddCredentialsController (models, $state, strings) { +function AddCredentialsController (models, $state, $scope, strings, componentsStrings) { const vm = this || {}; const { me, credential, credentialType, organization } = models; @@ -28,11 +28,27 @@ function AddCredentialsController (models, $state, strings) { vm.form.credential_type._model = credentialType; vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER'); + const gceFileInputSchema = { + id: 'gce_service_account_key', + type: 'file', + label: strings.get('inputs.GCE_FILE_INPUT_LABEL'), + help_text: strings.get('inputs.GCE_FILE_INPUT_HELP_TEXT'), + }; + + let gceFileInputPreEditValues; + vm.form.inputs = { _get: () => { credentialType.mergeInputProperties(); - return credentialType.get('inputs.fields'); + const fields = credentialType.get('inputs.fields'); + + if (credentialType.get('name') === 'Google Compute Engine') { + fields.splice(2, 0, gceFileInputSchema); + $scope.$watch(`vm.form.${gceFileInputSchema.id}._value`, vm.gceOnFileInputChanged); + } + + return fields; }, _source: vm.form.credential_type, _reference: 'vm.form.inputs', @@ -42,18 +58,66 @@ function AddCredentialsController (models, $state, strings) { vm.form.save = data => { data.user = me.get('id'); + delete data.inputs[gceFileInputSchema.id]; + return credential.request('post', { data }); }; vm.form.onSaveSuccess = res => { $state.go('credentials.edit', { credential_id: res.data.id }, { reload: true }); }; + + vm.gceOnFileInputChanged = (value, oldValue) => { + if (value === oldValue) return; + + const gceFileIsLoaded = !!value; + const gceFileInputState = vm.form[gceFileInputSchema.id]; + const { obj, error } = vm.gceParseFileInput(value); + + gceFileInputState._isValid = !error; + gceFileInputState._message = error ? componentsStrings.get('message.INVALID_INPUT') : ''; + + vm.form.project._disabled = gceFileIsLoaded; + vm.form.username._disabled = gceFileIsLoaded; + vm.form.ssh_key_data._disabled = gceFileIsLoaded; + vm.form.ssh_key_data._displayHint = !vm.form.ssh_key_data._disabled; + + if (gceFileIsLoaded) { + gceFileInputPreEditValues = Object.assign({}, { + project: vm.form.project._value, + ssh_key_data: vm.form.ssh_key_data._value, + username: vm.form.username._value + }); + vm.form.project._value = _.get(obj, 'project_id', ''); + vm.form.ssh_key_data._value = _.get(obj, 'private_key', ''); + vm.form.username._value = _.get(obj, 'client_email', ''); + } else { + vm.form.project._value = gceFileInputPreEditValues.project; + vm.form.ssh_key_data._value = gceFileInputPreEditValues.ssh_key_data; + vm.form.username._value = gceFileInputPreEditValues.username; + } + }; + + vm.gceParseFileInput = value => { + let obj; + let error; + + try { + obj = angular.fromJson(value); + } catch (err) { + error = err; + } + + return { obj, error }; + }; } AddCredentialsController.$inject = [ 'resolvedModels', '$state', - 'CredentialsStrings' + '$scope', + 'CredentialsStrings', + 'ComponentsStrings' ]; export default AddCredentialsController; diff --git a/awx/ui/client/features/credentials/add-edit-credentials.view.html b/awx/ui/client/features/credentials/add-edit-credentials.view.html index 39a4a1b20e..2019f403f1 100644 --- a/awx/ui/client/features/credentials/add-edit-credentials.view.html +++ b/awx/ui/client/features/credentials/add-edit-credentials.view.html @@ -14,9 +14,9 @@ - + - + {{:: vm.strings.get('inputs.GROUP_TITLE') }} diff --git a/awx/ui/client/features/credentials/credentials.strings.js b/awx/ui/client/features/credentials/credentials.strings.js index 958282aa09..cb6260ce55 100644 --- a/awx/ui/client/features/credentials/credentials.strings.js +++ b/awx/ui/client/features/credentials/credentials.strings.js @@ -17,7 +17,9 @@ function CredentialsStrings (BaseString) { ns.inputs = { GROUP_TITLE: t.s('Type Details'), ORGANIZATION_PLACEHOLDER: t.s('SELECT AN ORGANIZATION'), - CREDENTIAL_TYPE_PLACEHOLDER: t.s('SELECT A CREDENTIAL TYPE') + CREDENTIAL_TYPE_PLACEHOLDER: t.s('SELECT A CREDENTIAL TYPE'), + GCE_FILE_INPUT_LABEL: t.s('Service Account JSON File'), + GCE_FILE_INPUT_HELP_TEXT: t.s('Provide account information using Google Compute Engine JSON credentials file.') }; ns.add = { diff --git a/awx/ui/client/features/credentials/edit-credentials.controller.js b/awx/ui/client/features/credentials/edit-credentials.controller.js index e0a36c106f..a7629a68e1 100644 --- a/awx/ui/client/features/credentials/edit-credentials.controller.js +++ b/awx/ui/client/features/credentials/edit-credentials.controller.js @@ -1,4 +1,4 @@ -function EditCredentialsController (models, $state, $scope, strings) { +function EditCredentialsController (models, $state, $scope, strings, componentsStrings) { const vm = this || {}; const { me, credential, credentialType, organization } = models; @@ -64,15 +64,35 @@ function EditCredentialsController (models, $state, $scope, strings) { vm.form.credential_type._displayValue = credentialType.get('name'); vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER'); + const gceFileInputSchema = { + id: 'gce_service_account_key', + type: 'file', + label: strings.get('inputs.GCE_FILE_INPUT_LABEL'), + help_text: strings.get('inputs.GCE_FILE_INPUT_HELP_TEXT'), + }; + + let gceFileInputPreEditValues; + vm.form.inputs = { _get () { + let fields; + credentialType.mergeInputProperties(); if (credentialType.get('id') === credential.get('credential_type')) { - return credential.assignInputGroupValues(credentialType.get('inputs.fields')); + fields = credential.assignInputGroupValues(credentialType.get('inputs.fields')); + } else { + fields = credentialType.get('inputs.fields'); } - return credentialType.get('inputs.fields'); + if (credentialType.get('name') === 'Google Compute Engine') { + fields.splice(2, 0, gceFileInputSchema); + + $scope.$watch(`vm.form.${gceFileInputSchema.id}._value`, vm.gceOnFileInputChanged); + $scope.$watch('vm.form.ssh_key_data._isBeingReplaced', vm.gceOnReplaceKeyChanged); + } + + return fields; }, _source: vm.form.credential_type, _reference: 'vm.form.inputs', @@ -88,19 +108,70 @@ function EditCredentialsController (models, $state, $scope, strings) { data.user = me.get('id'); credential.unset('inputs'); + delete data.inputs[gceFileInputSchema.id]; + return credential.request('put', { data }); }; vm.form.onSaveSuccess = () => { $state.go('credentials.edit', { credential_id: credential.get('id') }, { reload: true }); }; + + vm.gceOnReplaceKeyChanged = value => { + vm.form[gceFileInputSchema.id]._disabled = !value; + }; + + vm.gceOnFileInputChanged = (value, oldValue) => { + if (value === oldValue) return; + + const gceFileIsLoaded = !!value; + const gceFileInputState = vm.form[gceFileInputSchema.id]; + const { obj, error } = vm.gceParseFileInput(value); + + gceFileInputState._isValid = !error; + gceFileInputState._message = error ? componentsStrings.get('message.INVALID_INPUT') : ''; + + vm.form.project._disabled = gceFileIsLoaded; + vm.form.username._disabled = gceFileIsLoaded; + vm.form.ssh_key_data._disabled = gceFileIsLoaded; + vm.form.ssh_key_data._displayHint = !vm.form.ssh_key_data._disabled; + + if (gceFileIsLoaded) { + gceFileInputPreEditValues = Object.assign({}, { + project: vm.form.project._value, + ssh_key_data: vm.form.ssh_key_data._value, + username: vm.form.username._value + }); + vm.form.project._value = _.get(obj, 'project_id', ''); + vm.form.ssh_key_data._value = _.get(obj, 'private_key', ''); + vm.form.username._value = _.get(obj, 'client_email', ''); + } else { + vm.form.project._value = gceFileInputPreEditValues.project; + vm.form.ssh_key_data._value = gceFileInputPreEditValues.ssh_key_data; + vm.form.username._value = gceFileInputPreEditValues.username; + } + }; + + vm.gceParseFileInput = value => { + let obj; + let error; + + try { + obj = angular.fromJson(value); + } catch (err) { + error = err; + } + + return { obj, error }; + }; } EditCredentialsController.$inject = [ 'resolvedModels', '$state', '$scope', - 'CredentialsStrings' + 'CredentialsStrings', + 'ComponentsStrings' ]; export default EditCredentialsController;