mirror of
https://github.com/ansible/awx.git
synced 2024-11-02 09:51:09 +03:00
Remove old credentials files from features dir
* The non-refactored credentials code has been returned to its original location. Inventories and Jobs pull in Credentials based on its original location in the file structure. * Apply margin to individual inputs instead of panels to have consistent spacing at more narrow resolutions. * Add placeholder for a Lookup component which will be necessary to let users select an org for the credential.
This commit is contained in:
parent
e91d1e0eb0
commit
cea1f1bbe1
@ -10,7 +10,11 @@
|
||||
<at-form state="vm.form">
|
||||
<at-input-text col="4" tab="1" state="vm.form.name"></at-input-text>
|
||||
<at-input-text col="4" tab="2" state="vm.form.description"></at-input-text>
|
||||
<at-input-select col="4" tab="3" state="vm.form.credential_type"></at-input-select>
|
||||
<at-input-lookup col="4" tab="3" state="vm.form.organization"></at-input-lookup>
|
||||
|
||||
<at-divider></at-divider>
|
||||
|
||||
<at-input-select col="4" tab="4" state="vm.form.credential_type"></at-input-select>
|
||||
|
||||
<at-input-group col="4" tab="4" state="vm.form.inputs">
|
||||
Type Details
|
||||
|
@ -1,5 +1,5 @@
|
||||
import CredentialList from './credentials.list.js';
|
||||
import ListController from './list/credentials-list.controller';
|
||||
import CredentialList from '../../src/credentials/credentials.list';
|
||||
import ListController from '../../src/credentials/list/credentials-list.controller';
|
||||
import AddController from './add-credentials.controller.js';
|
||||
import EditController from './edit-credentials.controller.js';
|
||||
import { N_ } from '../../src/i18n';
|
||||
@ -111,7 +111,5 @@ config.$inject = [
|
||||
angular
|
||||
.module('at.features.credentials', [])
|
||||
.config(config)
|
||||
.factory('CredentialList', CredentialList)
|
||||
.controller('ListController', ListController)
|
||||
.controller('AddController', AddController)
|
||||
.controller('EditController', EditController);
|
||||
|
@ -4,3 +4,4 @@
|
||||
@import 'modal/_index';
|
||||
@import 'popover/_index';
|
||||
@import 'tabs/_index';
|
||||
@import 'utility/_index';
|
||||
|
@ -1,9 +1,11 @@
|
||||
import actionGroup from './action/action-group.directive';
|
||||
import divider from './utility/divider.directive';
|
||||
import form from './form/form.directive';
|
||||
import formAction from './form/action.directive';
|
||||
import inputCheckbox from './input/checkbox.directive';
|
||||
import inputGroup from './input/group.directive';
|
||||
import inputLabel from './input/label.directive';
|
||||
import inputLookup from './input/lookup.directive';
|
||||
import inputMessage from './input/message.directive';
|
||||
import inputNumber from './input/number.directive';
|
||||
import inputSelect from './input/select.directive';
|
||||
@ -24,11 +26,13 @@ import BaseInputController from './input/base.controller';
|
||||
angular
|
||||
.module('at.lib.components', [])
|
||||
.directive('atActionGroup', actionGroup)
|
||||
.directive('atDivider', divider)
|
||||
.directive('atForm', form)
|
||||
.directive('atFormAction', formAction)
|
||||
.directive('atInputCheckbox', inputCheckbox)
|
||||
.directive('atInputGroup', inputGroup)
|
||||
.directive('atInputLabel', inputLabel)
|
||||
.directive('atInputLookup', inputLookup)
|
||||
.directive('atInputMessage', inputMessage)
|
||||
.directive('atInputNumber', inputNumber)
|
||||
.directive('atInputSecret', inputSecret)
|
||||
|
@ -15,7 +15,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.at-Checkbox {
|
||||
.at-InputCheckbox {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
@ -26,8 +26,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.at-InputGroup-button {
|
||||
height: 100%;
|
||||
.at-InputContainer {
|
||||
margin-top: @at-space-6x;;
|
||||
}
|
||||
|
||||
.at-Input-button {
|
||||
@ -69,7 +69,6 @@
|
||||
|
||||
.at-InputGroup {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin: @at-space-6x 0 0 0;
|
||||
}
|
||||
|
||||
@ -81,11 +80,13 @@
|
||||
left: -@at-inset-width;
|
||||
}
|
||||
|
||||
.at-InputGroup-button {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.at-InputGroup-title {
|
||||
.at-mixin-Heading(@at-font-size-2x);
|
||||
margin-top: 0;
|
||||
margin-left: @at-space-5x;
|
||||
margin-bottom: @at-space-4x;
|
||||
margin: 0 0 0 @at-space-5x;
|
||||
}
|
||||
|
||||
.at-InputGroup-divider {
|
||||
@ -190,6 +191,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.at-Textarea {
|
||||
.at-InputTextarea {
|
||||
.at-mixin-FontFixedWidth();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="col-sm-{{::col}}">
|
||||
<div class="col-sm-{{::col}} at-InputContainer">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
<div class="checkbox at-Checkbox">
|
||||
<div class="checkbox at-InputCheckbox">
|
||||
<input type="checkbox"
|
||||
ng-class="{ 'at-Input--rejected': state.rejected }"
|
||||
ng-model="state._value"
|
||||
|
@ -59,7 +59,7 @@ function AtInputGroupController ($scope, $compile) {
|
||||
input = Object.assign(input, vm.getComponentType(input));
|
||||
|
||||
group.push(Object.assign({
|
||||
_element: vm.createElement(input, i),
|
||||
_element: vm.createComponent(input, i),
|
||||
_key: 'inputs',
|
||||
_group: true,
|
||||
_groupIndex: i
|
||||
@ -108,18 +108,6 @@ function AtInputGroupController ($scope, $compile) {
|
||||
return config;
|
||||
};
|
||||
|
||||
vm.createElement = (input, index) => {
|
||||
let tabindex = Number(scope.tab) + index;
|
||||
let col = input._expand ? 12 : scope.col;
|
||||
|
||||
let element =
|
||||
`<${input._component} col="${col}" tab="${tabindex}"
|
||||
state="${state._reference}._group[${index}]">
|
||||
</${input._component}>`;
|
||||
|
||||
return angular.element(element);
|
||||
};
|
||||
|
||||
vm.insert = group => {
|
||||
let container = document.createElement('div');
|
||||
let col = 1;
|
||||
@ -128,13 +116,13 @@ function AtInputGroupController ($scope, $compile) {
|
||||
|
||||
group.forEach((input, i) => {
|
||||
if (input._expand && !isDivided) {
|
||||
container.appendChild(vm.createInputDivider());
|
||||
container.appendChild(vm.createDivider()[0]);
|
||||
}
|
||||
|
||||
container.appendChild(input._element[0]);
|
||||
|
||||
if ((input._expand || col % colPerRow === 0) && i !== group.length -1) {
|
||||
container.appendChild(vm.createInputDivider());
|
||||
container.appendChild(vm.createDivider()[0]);
|
||||
isDivided = true;
|
||||
col = 0;
|
||||
} else {
|
||||
@ -147,8 +135,19 @@ function AtInputGroupController ($scope, $compile) {
|
||||
element.appendChild(container);
|
||||
};
|
||||
|
||||
vm.createInputDivider = () => {
|
||||
return angular.element(`<div class="at-InputGroup-divider"></div>`)[0];
|
||||
vm.createComponent = (input, index) => {
|
||||
let tabindex = Number(scope.tab) + index;
|
||||
let col = input._expand ? 12 : scope.col;
|
||||
|
||||
return angular.element(
|
||||
`<${input._component} col="${col}" tab="${tabindex}"
|
||||
state="${state._reference}._group[${index}]">
|
||||
</${input._component}>`
|
||||
);
|
||||
};
|
||||
|
||||
vm.createDivider = () => {
|
||||
return angular.element('<at-divider></at-divider>');
|
||||
};
|
||||
|
||||
vm.compile = group => {
|
||||
|
44
awx/ui/client/lib/components/input/lookup.directive.js
Normal file
44
awx/ui/client/lib/components/input/lookup.directive.js
Normal file
@ -0,0 +1,44 @@
|
||||
function atInputLookupLink (scope, element, attrs, controllers) {
|
||||
let formController = controllers[0];
|
||||
let inputController = controllers[1];
|
||||
|
||||
if (scope.tab === '1') {
|
||||
element.find('input')[0].focus();
|
||||
}
|
||||
|
||||
inputController.init(scope, element, formController);
|
||||
}
|
||||
|
||||
function AtInputLookupController (baseInputController) {
|
||||
let vm = this || {};
|
||||
|
||||
vm.init = (scope, element, form) => {
|
||||
baseInputController.call(vm, 'input', scope, element, form);
|
||||
|
||||
vm.check();
|
||||
};
|
||||
}
|
||||
|
||||
AtInputLookupController.$inject = ['BaseInputController'];
|
||||
|
||||
function atInputLookup (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
require: ['^^atForm', 'atInputLookup'],
|
||||
templateUrl: pathService.getPartialPath('components/input/lookup'),
|
||||
controller: AtInputLookupController,
|
||||
controllerAs: 'vm',
|
||||
link: atInputLookupLink,
|
||||
scope: {
|
||||
state: '=',
|
||||
col: '@',
|
||||
tab: '@'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
atInputLookup.$inject = ['PathService'];
|
||||
|
||||
export default atInputLookup;
|
24
awx/ui/client/lib/components/input/lookup.partial.html
Normal file
24
awx/ui/client/lib/components/input/lookup.partial.html
Normal file
@ -0,0 +1,24 @@
|
||||
<div class="col-sm-{{::col}} at-InputContainer">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn at-ButtonHollow--white at-Input-button"
|
||||
ng-disabled="state._disabled || form.disabled">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</span>
|
||||
<input type="text"
|
||||
class="form-control at-Input"
|
||||
ng-class="{ 'at-Input--rejected': state.rejected }"
|
||||
ng-model="state._value"
|
||||
ng-attr-tabindex="{{ tab || undefined }}"
|
||||
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||
ng-change="vm.check()"
|
||||
ng-disabled="state._disabled || form.disabled" />
|
||||
</div>
|
||||
|
||||
<at-input-message></at-input-message>
|
||||
</div>
|
||||
</div>
|
@ -1,4 +1,4 @@
|
||||
<div class="col-sm-{{::col}}">
|
||||
<div class="col-sm-{{::col}} at-InputContainer">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="col-sm-{{::col}}">
|
||||
<div class="col-sm-{{::col}} at-InputContainer">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="col-sm-{{::col}}">
|
||||
<div class="col-sm-{{::col}} at-InputContainer">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="col-sm-{{::col}}">
|
||||
<div class="col-sm-{{::col}} at-InputContainer">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="col-sm-{{::col}}">
|
||||
<div class="col-sm-{{::col}} at-InputContainer">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
ng-class="{'at-InputFile--drag': drag }"
|
||||
type="file"
|
||||
name="files" />
|
||||
<textarea class="form-control at-Input at-Textarea"
|
||||
<textarea class="form-control at-Input at-InputTextarea"
|
||||
ng-model="state[state._activeModel]"
|
||||
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||
|
@ -1,8 +1,8 @@
|
||||
<div class="col-sm-{{::col}}">
|
||||
<div class="col-sm-{{::col}} at-InputContainer">
|
||||
<div class="form-group at-u-flat">
|
||||
<at-input-label></at-input-label>
|
||||
|
||||
<textarea class="form-control at-Input at-Textarea"
|
||||
<textarea class="form-control at-Input at-InputTextarea"
|
||||
ng-model="state._value"
|
||||
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||
|
@ -15,7 +15,7 @@
|
||||
}
|
||||
|
||||
.at-Panel-body {
|
||||
margin: @at-space-6x 0 0 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
5
awx/ui/client/lib/components/utility/_index.less
Normal file
5
awx/ui/client/lib/components/utility/_index.less
Normal file
@ -0,0 +1,5 @@
|
||||
.at-Divider {
|
||||
clear: both;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
12
awx/ui/client/lib/components/utility/divider.directive.js
Normal file
12
awx/ui/client/lib/components/utility/divider.directive.js
Normal file
@ -0,0 +1,12 @@
|
||||
function atPanelBody (pathService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: pathService.getPartialPath('components/utility/divider'),
|
||||
scope: false
|
||||
};
|
||||
}
|
||||
|
||||
atPanelBody.$inject = ['PathService'];
|
||||
|
||||
export default atPanelBody;
|
@ -0,0 +1 @@
|
||||
<div class="at-Divider"></div>
|
@ -41,6 +41,7 @@ import portalMode from './portal-mode/main';
|
||||
import systemTracking from './system-tracking/main';
|
||||
import inventories from './inventories/main';
|
||||
import inventoryScripts from './inventory-scripts/main';
|
||||
import credentials from './credentials/main';
|
||||
import credentialTypes from './credential-types/main';
|
||||
import organizations from './organizations/main';
|
||||
import managementJobs from './management-jobs/main';
|
||||
@ -105,6 +106,7 @@ var tower = angular.module('Tower', [
|
||||
systemTracking.name,
|
||||
inventories.name,
|
||||
inventoryScripts.name,
|
||||
credentials.name,
|
||||
credentialTypes.name,
|
||||
organizations.name,
|
||||
managementJobs.name,
|
||||
|
475
awx/ui/client/src/credentials/credentials.form.js
Normal file
475
awx/ui/client/src/credentials/credentials.form.js
Normal file
@ -0,0 +1,475 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name forms.function:Credentials
|
||||
* @description This form is for adding/editing a Credential
|
||||
*/
|
||||
|
||||
export default ['i18n', function(i18n) {
|
||||
return {
|
||||
|
||||
addTitle: i18n._('CREATE CREDENTIAL'), //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
name: 'credential',
|
||||
// the top-most node of generated state tree
|
||||
stateTree: 'credentials',
|
||||
forceListeners: true,
|
||||
subFormTitles: {
|
||||
credentialSubForm: i18n._('Type Details'),
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: i18n._('Name'),
|
||||
type: 'text',
|
||||
required: true,
|
||||
autocomplete: false,
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
description: {
|
||||
label: i18n._('Description'),
|
||||
type: 'text',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
organization: {
|
||||
basePath: 'organizations',
|
||||
ngShow: 'canShareCredential',
|
||||
label: i18n._('Organization'),
|
||||
type: 'lookup',
|
||||
autopopulateLookup: false,
|
||||
list: 'OrganizationList',
|
||||
sourceModel: 'organization',
|
||||
sourceField: 'name',
|
||||
awPopOver: "<p>" + i18n._("If no organization is given, the credential can only be used by the user that creates the credential. Organization admins and system administrators can assign an organization so that roles for the credential can be assigned to users and teams in that organization.") + "</p>",
|
||||
dataTitle: i18n._('Organization') + ' ',
|
||||
dataPlacement: 'bottom',
|
||||
dataContainer: "body",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd) || !canEditOrg',
|
||||
awLookupWhen: '(credential_obj.summary_fields.user_capabilities.edit || canAdd) && canEditOrg'
|
||||
},
|
||||
kind: {
|
||||
label: i18n._('Type'),
|
||||
excludeModal: true,
|
||||
type: 'select',
|
||||
ngOptions: 'kind.label for kind in credential_kind_options track by kind.value', // select as label for value in array 'kind.label for kind in credential_kind_options',
|
||||
ngChange: 'kindChange()',
|
||||
required: true,
|
||||
awPopOver: '<dl>\n' +
|
||||
'<dt>' + i18n._('Machine') + '</dt>\n' +
|
||||
'<dd>' + i18n._('Authentication for remote machine access. This can include SSH keys, usernames, passwords, ' +
|
||||
'and sudo information. Machine credentials are used when submitting jobs to run playbooks against ' +
|
||||
'remote hosts.') + '</dd>' +
|
||||
'<dt>' + i18n._('Network') + '</dt>\n' +
|
||||
'<dd>' + i18n._('Authentication for network device access. This can include SSH keys, usernames, passwords, ' +
|
||||
'and authorize information. Network credentials are used when submitting jobs to run playbooks against ' +
|
||||
'network devices.') + '</dd>' +
|
||||
'<dt>' + i18n._('Source Control') + '</dt>\n' +
|
||||
'<dd>' + i18n._('Used to check out and synchronize playbook repositories with a remote source control ' +
|
||||
'management system such as Git, Subversion (svn), or Mercurial (hg). These credentials are ' +
|
||||
'used by Projects.') + '</dd>\n' +
|
||||
'<dt>' + i18n._('Others (Cloud Providers)') + '</dt>\n' +
|
||||
'<dd>' + i18n._('Usernames, passwords, and access keys for authenticating to the specified cloud or infrastructure ' +
|
||||
'provider. These are used for smart inventory sources and for cloud provisioning and deployment ' +
|
||||
'in playbook runs.') + '</dd>\n' +
|
||||
'</dl>\n',
|
||||
dataTitle: i18n._('Type'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
hasSubForm: true,
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
access_key: {
|
||||
label: i18n._('Access Key'),
|
||||
type: 'text',
|
||||
ngShow: "kind.value == 'aws'",
|
||||
awRequiredWhen: {
|
||||
reqExpression: "aws_required",
|
||||
init: false
|
||||
},
|
||||
autocomplete: false,
|
||||
apiField: 'username',
|
||||
subForm: 'credentialSubForm',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
secret_key: {
|
||||
label: i18n._('Secret Key'),
|
||||
type: 'sensitive',
|
||||
ngShow: "kind.value == 'aws'",
|
||||
ngDisabled: "secret_key_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
|
||||
awRequiredWhen: {
|
||||
reqExpression: "aws_required",
|
||||
init: false
|
||||
},
|
||||
autocomplete: false,
|
||||
clear: false,
|
||||
hasShowInputButton: true,
|
||||
apiField: 'password',
|
||||
subForm: 'credentialSubForm'
|
||||
},
|
||||
security_token: {
|
||||
label: i18n._('STS Token'),
|
||||
type: 'sensitive',
|
||||
ngShow: "kind.value == 'aws'",
|
||||
autocomplete: false,
|
||||
apiField: 'security_token',
|
||||
awPopOver: "<div>" + i18n._("Security Token Service (STS) is a web service that enables you to request temporary, limited-privilege credentials for AWS Identity and Access Management (IAM) users.") + "</div><div style='padding-top: 10px'>" +
|
||||
i18n.sprintf(i18n._("To learn more about the IAM STS Token, refer to the %sAmazon documentation%s."), "<a href='http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html' target='_blank'>", "</a>") + "</div>",
|
||||
hasShowInputButton: true,
|
||||
dataTitle: i18n._('STS Token'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
subForm: 'credentialSubForm',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"host": {
|
||||
labelBind: 'hostLabel',
|
||||
type: 'text',
|
||||
ngShow: "kind.value == 'vmware' || kind.value == 'openstack' || kind.value === 'satellite6' || kind.value === 'cloudforms'",
|
||||
awPopOverWatch: "hostPopOver",
|
||||
awPopOver: i18n._("set in helpers/credentials"),
|
||||
dataTitle: i18n._('Host'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
autocomplete: false,
|
||||
awRequiredWhen: {
|
||||
reqExpression: 'host_required',
|
||||
init: false
|
||||
},
|
||||
subForm: 'credentialSubForm',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"subscription": {
|
||||
label: i18n._("Subscription ID"),
|
||||
type: 'text',
|
||||
ngShow: "kind.value == 'azure' || kind.value == 'azure_rm'",
|
||||
awRequiredWhen: {
|
||||
reqExpression: 'subscription_required',
|
||||
init: false
|
||||
},
|
||||
|
||||
|
||||
autocomplete: false,
|
||||
awPopOver: '<p>' + i18n._('Subscription ID is an Azure construct, which is mapped to a username.') + '</p>',
|
||||
dataTitle: i18n._('Subscription ID'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
subForm: 'credentialSubForm',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"username": {
|
||||
labelBind: 'usernameLabel',
|
||||
type: 'text',
|
||||
ngShow: "kind.value && kind.value !== 'aws' && " +
|
||||
"kind.value !== 'gce' && kind.value!=='azure'",
|
||||
awRequiredWhen: {
|
||||
reqExpression: 'username_required',
|
||||
init: false
|
||||
},
|
||||
autocomplete: false,
|
||||
subForm: "credentialSubForm",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"email_address": {
|
||||
labelBind: 'usernameLabel',
|
||||
type: 'email',
|
||||
ngShow: "kind.value === 'gce'",
|
||||
awRequiredWhen: {
|
||||
reqExpression: 'email_required',
|
||||
init: false
|
||||
},
|
||||
autocomplete: false,
|
||||
awPopOver: '<p>' + i18n.sprintf(i18n._('The email address assigned to the Google Compute Engine %sservice account.'), '<b><i>') + '</b></i></p>',
|
||||
dataTitle: i18n._('Email'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
subForm: 'credentialSubForm',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"api_key": {
|
||||
label: i18n._('API Key'),
|
||||
type: 'sensitive',
|
||||
ngShow: "kind.value == 'rax'",
|
||||
awRequiredWhen: {
|
||||
reqExpression: "rackspace_required",
|
||||
init: false
|
||||
},
|
||||
autocomplete: false,
|
||||
hasShowInputButton: true,
|
||||
clear: false,
|
||||
subForm: 'credentialSubForm',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"password": {
|
||||
labelBind: 'passwordLabel',
|
||||
type: 'sensitive',
|
||||
ngShow: "kind.value == 'scm' || kind.value == 'vmware' || kind.value == 'openstack'|| kind.value == 'satellite6'|| kind.value == 'cloudforms'|| kind.value == 'net' || kind.value == 'azure_rm'",
|
||||
clear: false,
|
||||
autocomplete: false,
|
||||
hasShowInputButton: true,
|
||||
awRequiredWhen: {
|
||||
reqExpression: "password_required",
|
||||
init: false
|
||||
},
|
||||
subForm: "credentialSubForm",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"ssh_password": {
|
||||
label: i18n._('Password'),
|
||||
type: 'sensitive',
|
||||
ngShow: "kind.value == 'ssh'",
|
||||
ngDisabled: "ssh_password_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
|
||||
subCheckbox: {
|
||||
variable: 'ssh_password_ask',
|
||||
text: i18n._('Ask at runtime?'),
|
||||
ngChange: 'ask(\'ssh_password\', \'undefined\')',
|
||||
ngDisabled: false,
|
||||
},
|
||||
hasShowInputButton: true,
|
||||
autocomplete: false,
|
||||
subForm: 'credentialSubForm'
|
||||
},
|
||||
"ssh_key_data": {
|
||||
labelBind: 'sshKeyDataLabel',
|
||||
type: 'textarea',
|
||||
ngShow: "kind.value == 'ssh' || kind.value == 'scm' || " +
|
||||
"kind.value == 'gce' || kind.value == 'azure' || kind.value == 'net'",
|
||||
awRequiredWhen: {
|
||||
reqExpression: 'key_required',
|
||||
init: true
|
||||
},
|
||||
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
|
||||
elementClass: 'Form-monospace',
|
||||
|
||||
|
||||
awDropFile: true,
|
||||
rows: 10,
|
||||
awPopOver: i18n._("SSH key description"),
|
||||
awPopOverWatch: "key_description",
|
||||
dataTitle: i18n._('Private Key'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
subForm: "credentialSubForm",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"ssh_key_unlock": {
|
||||
label: i18n._('Private Key Passphrase'),
|
||||
type: 'sensitive',
|
||||
ngShow: "kind.value === 'ssh' || kind.value === 'scm' || kind.value === 'net'",
|
||||
ngDisabled: "keyEntered === false || ssh_key_unlock_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
|
||||
subCheckbox: {
|
||||
variable: 'ssh_key_unlock_ask',
|
||||
ngShow: "kind.value == 'ssh'",
|
||||
text: i18n._('Ask at runtime?'),
|
||||
ngChange: 'ask(\'ssh_key_unlock\', \'undefined\')',
|
||||
ngDisabled: "keyEntered === false"
|
||||
},
|
||||
hasShowInputButton: true,
|
||||
subForm: 'credentialSubForm'
|
||||
},
|
||||
"become_method": {
|
||||
label: i18n._("Privilege Escalation"),
|
||||
// hintText: "If your playbooks use privilege escalation (\"sudo: true\", \"su: true\", etc), you can specify the username to become, and the password to use here.",
|
||||
type: 'select',
|
||||
ngShow: "kind.value == 'ssh'",
|
||||
dataTitle: i18n._('Privilege Escalation'),
|
||||
ngOptions: 'become.label for become in become_options track by become.value',
|
||||
awPopOver: "<p>" + i18n.sprintf(i18n._("Specify a method for %s operations. " +
|
||||
"This is equivalent to specifying the %s parameter, where %s could be "+
|
||||
"%s"), "'become'", "<code>--become-method=BECOME_METHOD</code>", "<code>BECOME_METHOD</code>", "<code>sudo | su | pbrun | pfexec | runas</code>") + " <br>" + i18n.sprintf(i18n._("(defaults to %s)"), "<code>sudo</code>") + "</p>",
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
subForm: 'credentialSubForm',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)',
|
||||
ngChange: 'becomeMethodChange()',
|
||||
},
|
||||
"become_username": {
|
||||
labelBind: 'becomeUsernameLabel',
|
||||
type: 'text',
|
||||
ngShow: "(kind.value == 'ssh' && (become_method && become_method.value)) ",
|
||||
|
||||
|
||||
autocomplete: false,
|
||||
subForm: 'credentialSubForm',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"become_password": {
|
||||
labelBind: 'becomePasswordLabel',
|
||||
type: 'sensitive',
|
||||
ngShow: "(kind.value == 'ssh' && (become_method && become_method.value)) ",
|
||||
ngDisabled: "become_password_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
|
||||
subCheckbox: {
|
||||
variable: 'become_password_ask',
|
||||
text: i18n._('Ask at runtime?'),
|
||||
ngChange: 'ask(\'become_password\', \'undefined\')',
|
||||
ngDisabled: false,
|
||||
},
|
||||
hasShowInputButton: true,
|
||||
autocomplete: false,
|
||||
subForm: 'credentialSubForm'
|
||||
},
|
||||
client:{
|
||||
type: 'text',
|
||||
label: i18n._('Client ID'),
|
||||
subForm: 'credentialSubForm',
|
||||
ngShow: "kind.value === 'azure_rm'",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
secret:{
|
||||
type: 'sensitive',
|
||||
hasShowInputButton: true,
|
||||
autocomplete: false,
|
||||
label: i18n._('Client Secret'),
|
||||
subForm: 'credentialSubForm',
|
||||
ngShow: "kind.value === 'azure_rm'",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
tenant: {
|
||||
type: 'text',
|
||||
label: i18n._('Tenant ID'),
|
||||
subForm: 'credentialSubForm',
|
||||
ngShow: "kind.value === 'azure_rm'",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
authorize: {
|
||||
label: i18n._('Authorize'),
|
||||
type: 'checkbox',
|
||||
ngChange: "toggleCallback('host_config_key')",
|
||||
subForm: 'credentialSubForm',
|
||||
ngShow: "kind.value === 'net'",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
authorize_password: {
|
||||
label: i18n._('Authorize Password'),
|
||||
type: 'sensitive',
|
||||
hasShowInputButton: true,
|
||||
autocomplete: false,
|
||||
subForm: 'credentialSubForm',
|
||||
ngShow: "authorize && authorize !== 'false'",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"project": {
|
||||
labelBind: 'projectLabel',
|
||||
type: 'text',
|
||||
ngShow: "kind.value == 'gce' || kind.value == 'openstack'",
|
||||
awPopOverWatch: "projectPopOver",
|
||||
awPopOver: i18n._("set in helpers/credentials"),
|
||||
dataTitle: i18n._('Project Name'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
awRequiredWhen: {
|
||||
reqExpression: 'project_required',
|
||||
init: false
|
||||
},
|
||||
subForm: 'credentialSubForm',
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
"domain": {
|
||||
labelBind: 'domainLabel',
|
||||
type: 'text',
|
||||
ngShow: "kind.value == 'openstack'",
|
||||
awPopOver: "<p>" + i18n._("OpenStack domains define administrative " +
|
||||
"boundaries. It is only needed for Keystone v3 authentication URLs. " +
|
||||
"Common scenarios include:") + "<ul><li><b>" + i18n.sprintf(i18n._("v2 URLs%s - leave blank"), "</b>") + "</li>" +
|
||||
"<li><b>" + i18n.sprintf(i18n._("v3 default%s - set to 'default'"), "</b>") + "</br></li>" +
|
||||
"<li><b>" + i18n.sprintf(i18n._("v3 multi-domain%s - your domain name"), "</b>") + "</p></li></ul></p>",
|
||||
dataTitle: i18n._('Domain Name'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body",
|
||||
ngDisabled: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)',
|
||||
subForm: 'credentialSubForm'
|
||||
},
|
||||
"vault_password": {
|
||||
label: i18n._("Vault Password"),
|
||||
type: 'sensitive',
|
||||
ngShow: "kind.value == 'ssh'",
|
||||
ngDisabled: "vault_password_ask || !(credential_obj.summary_fields.user_capabilities.edit || canAdd)",
|
||||
subCheckbox: {
|
||||
variable: 'vault_password_ask',
|
||||
text: i18n._('Ask at runtime?'),
|
||||
ngChange: 'ask(\'vault_password\', \'undefined\')',
|
||||
ngDisabled: false,
|
||||
},
|
||||
hasShowInputButton: true,
|
||||
autocomplete: false,
|
||||
subForm: 'credentialSubForm'
|
||||
}
|
||||
},
|
||||
|
||||
buttons: {
|
||||
cancel: {
|
||||
ngClick: 'formCancel()',
|
||||
ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
close: {
|
||||
ngClick: 'formCancel()',
|
||||
ngShow: '!(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
save: {
|
||||
label: 'Save',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true,
|
||||
ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)' //Disable when $pristine or $invalid, optional
|
||||
}
|
||||
},
|
||||
|
||||
related: {
|
||||
permissions: {
|
||||
name: 'permissions',
|
||||
disabled: '(organization === undefined ? true : false)',
|
||||
// Do not transition the state if organization is undefined
|
||||
ngClick: `(organization === undefined ? true : false)||$state.go('credentials.edit.permissions')`,
|
||||
awToolTip: '{{permissionsTooltip}}',
|
||||
dataTipWatch: 'permissionsTooltip',
|
||||
awToolTipTabEnabledInEditMode: true,
|
||||
dataPlacement: 'right',
|
||||
basePath: 'api/v2/credentials/{{$stateParams.credential_id}}/access_list/',
|
||||
search: {
|
||||
order_by: 'username'
|
||||
},
|
||||
type: 'collection',
|
||||
title: i18n._('Permissions'),
|
||||
iterator: 'permission',
|
||||
index: false,
|
||||
open: false,
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "$state.go('.add')",
|
||||
label: 'Add',
|
||||
awToolTip: i18n._('Add a permission'),
|
||||
actionClass: 'btn List-buttonSubmit',
|
||||
buttonContent: '+ ' + i18n._('ADD'),
|
||||
ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: i18n._('User'),
|
||||
linkBase: 'users',
|
||||
class: 'col-lg-3 col-md-3 col-sm-3 col-xs-4'
|
||||
},
|
||||
role: {
|
||||
label: i18n._('Role'),
|
||||
type: 'role',
|
||||
nosort: true,
|
||||
class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4'
|
||||
},
|
||||
team_roles: {
|
||||
label: i18n._('Team Roles'),
|
||||
type: 'team_roles',
|
||||
nosort: true,
|
||||
class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};}];
|
@ -30,6 +30,13 @@ export default ['i18n', function(i18n) {
|
||||
awToolTip: '{{credential.description}}',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
kind: {
|
||||
label: i18n._('Type'),
|
||||
ngBind: 'credential.kind_label',
|
||||
excludeModal: true,
|
||||
nosort: true,
|
||||
columnClass: 'col-md-2 hidden-sm hidden-xs'
|
||||
},
|
||||
owners: {
|
||||
label: i18n._('Owners'),
|
||||
type: 'owners',
|
@ -65,7 +65,7 @@ export default ['$scope', 'Rest', 'CredentialList', 'Prompt', 'ClearScope',
|
||||
};
|
||||
|
||||
$scope.editCredential = function(id) {
|
||||
$state.go('credentials.edit', { id: id });
|
||||
$state.go('credentials.edit', { credential_id: id });
|
||||
};
|
||||
|
||||
$scope.deleteCredential = function(id, name) {
|
25
awx/ui/client/src/credentials/main.js
Normal file
25
awx/ui/client/src/credentials/main.js
Normal file
@ -0,0 +1,25 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2016 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import ownerList from './ownerList.directive';
|
||||
import CredentialsList from './list/credentials-list.controller';
|
||||
import BecomeMethodChange from './factories/become-method-change.factory';
|
||||
import CredentialFormSave from './factories/credential-form-save.factory';
|
||||
import KindChange from './factories/kind-change.factory';
|
||||
import OwnerChange from './factories/owner-change.factory';
|
||||
import CredentialList from './credentials.list';
|
||||
import CredentialForm from './credentials.form';
|
||||
|
||||
export default
|
||||
angular.module('credentials', [])
|
||||
.directive('ownerList', ownerList)
|
||||
.factory('BecomeMethodChange', BecomeMethodChange)
|
||||
.factory('CredentialFormSave', CredentialFormSave)
|
||||
.factory('KindChange', KindChange)
|
||||
.factory('OwnerChange', OwnerChange)
|
||||
.controller('CredentialsList', CredentialsList)
|
||||
.factory('CredentialList', CredentialList)
|
||||
.factory('CredentialForm', CredentialForm);
|
Loading…
Reference in New Issue
Block a user