mirror of
https://github.com/ZwareBear/awx.git
synced 2026-05-15 01:38:37 -05: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:
@@ -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'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};}];
|
||||
@@ -0,0 +1,93 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
export default ['i18n', function(i18n) {
|
||||
return {
|
||||
|
||||
name: 'credentials',
|
||||
iterator: 'credential',
|
||||
selectTitle: i18n._('Add Credentials'),
|
||||
editTitle: i18n._('CREDENTIALS'),
|
||||
listTitle: i18n._('CREDENTIALS'),
|
||||
selectInstructions: "<p>Select existing credentials by clicking each credential or checking the related checkbox. When " +
|
||||
"finished, click the blue <em>Select</em> button, located bottom right.</p> <p>Create a brand new credential by clicking ",
|
||||
index: false,
|
||||
hover: true,
|
||||
emptyListText: i18n._('No Credentials Have Been Created'),
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: i18n._('Name'),
|
||||
columnClass: 'col-md-3 col-sm-9 col-xs-9',
|
||||
modalColumnClass: 'col-md-12',
|
||||
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',
|
||||
nosort: true,
|
||||
excludeModal: true,
|
||||
columnClass: 'col-md-2 hidden-sm hidden-xs'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addCredential()',
|
||||
awToolTip: i18n._('Create a new credential'),
|
||||
actionClass: 'btn List-buttonSubmit',
|
||||
buttonContent: '+ ' + i18n._('ADD'),
|
||||
ngShow: "true"
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
|
||||
columnClass: 'col-md-2 col-sm-3 col-xs-3',
|
||||
|
||||
edit: {
|
||||
ngClick: "editCredential(credential.id)",
|
||||
icon: 'fa-edit',
|
||||
label: i18n._('Edit'),
|
||||
"class": 'btn-sm',
|
||||
awToolTip: i18n._('Edit credential'),
|
||||
dataPlacement: 'top',
|
||||
ngShow: 'credential.summary_fields.user_capabilities.edit'
|
||||
},
|
||||
|
||||
view: {
|
||||
ngClick: "editCredential(credential.id)",
|
||||
label: i18n._('View'),
|
||||
"class": 'btn-sm',
|
||||
awToolTip: i18n._('View credential'),
|
||||
dataPlacement: 'top',
|
||||
ngShow: '!credential.summary_fields.user_capabilities.edit'
|
||||
},
|
||||
|
||||
"delete": {
|
||||
ngClick: "deleteCredential(credential.id, credential.name)",
|
||||
icon: 'fa-trash',
|
||||
label: i18n._('Delete'),
|
||||
"class": 'btn-sm',
|
||||
awToolTip: i18n._('Delete credential'),
|
||||
dataPlacement: 'top',
|
||||
ngShow: 'credential.summary_fields.user_capabilities.delete'
|
||||
}
|
||||
}
|
||||
};}];
|
||||
@@ -0,0 +1,105 @@
|
||||
export default
|
||||
function BecomeMethodChange(Empty, i18n) {
|
||||
return function(params) {
|
||||
var scope = params.scope;
|
||||
|
||||
if (!Empty(scope.kind)) {
|
||||
// Apply kind specific settings
|
||||
switch (scope.kind.value) {
|
||||
case 'aws':
|
||||
scope.aws_required = true;
|
||||
break;
|
||||
case 'rax':
|
||||
scope.rackspace_required = true;
|
||||
scope.username_required = true;
|
||||
break;
|
||||
case 'ssh':
|
||||
scope.usernameLabel = i18n._('Username'); //formally 'SSH Username'
|
||||
scope.becomeUsernameLabel = i18n._('Privilege Escalation Username');
|
||||
scope.becomePasswordLabel = i18n._('Privilege Escalation Password');
|
||||
break;
|
||||
case 'scm':
|
||||
scope.sshKeyDataLabel = i18n._('SCM Private Key');
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
break;
|
||||
case 'gce':
|
||||
scope.usernameLabel = i18n._('Service Account Email Address');
|
||||
scope.sshKeyDataLabel = i18n._('RSA Private Key');
|
||||
scope.email_required = true;
|
||||
scope.key_required = true;
|
||||
scope.project_required = true;
|
||||
scope.key_description = i18n._('Paste the contents of the PEM file associated with the service account email.');
|
||||
scope.projectLabel = i18n._("Project");
|
||||
scope.project_required = false;
|
||||
scope.projectPopOver = "<p>" + i18n._("The Project ID is the " +
|
||||
"GCE assigned identification. It is constructed as " +
|
||||
"two words followed by a three digit number. Such " +
|
||||
"as: ") + "</p><p>adjective-noun-000</p>";
|
||||
break;
|
||||
case 'azure':
|
||||
scope.sshKeyDataLabel = i18n._('Management Certificate');
|
||||
scope.subscription_required = true;
|
||||
scope.key_required = true;
|
||||
scope.key_description = i18n._("Paste the contents of the PEM file that corresponds to the certificate you uploaded in the Microsoft Azure console.");
|
||||
break;
|
||||
case 'azure_rm':
|
||||
scope.usernameLabel = i18n._("Username");
|
||||
scope.subscription_required = true;
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.azure_rm_required = true;
|
||||
break;
|
||||
case 'vmware':
|
||||
scope.username_required = true;
|
||||
scope.host_required = true;
|
||||
scope.password_required = true;
|
||||
scope.hostLabel = "vCenter Host";
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.hostPopOver = i18n._("Enter the hostname or IP address which corresponds to your VMware vCenter.");
|
||||
break;
|
||||
case 'openstack':
|
||||
scope.hostLabel = i18n._("Host (Authentication URL)");
|
||||
scope.projectLabel = i18n._("Project (Tenant Name)");
|
||||
scope.domainLabel = i18n._("Domain Name");
|
||||
scope.password_required = true;
|
||||
scope.project_required = true;
|
||||
scope.host_required = true;
|
||||
scope.username_required = true;
|
||||
scope.projectPopOver = "<p>" + i18n._("This is the tenant name. " +
|
||||
" This value is usually the same " +
|
||||
" as the username.") + "</p>";
|
||||
scope.hostPopOver = "<p>" + i18n._("The host to authenticate with.") +
|
||||
"<br />" + i18n.sprintf(i18n._("For example, %s"), "https://openstack.business.com/v2.0/");
|
||||
break;
|
||||
case 'satellite6':
|
||||
scope.username_required = true;
|
||||
scope.password_required = true;
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.host_required = true;
|
||||
scope.hostLabel = i18n._("Satellite 6 URL");
|
||||
scope.hostPopOver = i18n.sprintf(i18n._("Enter the URL which corresponds to your %s" +
|
||||
"Red Hat Satellite 6 server. %s" +
|
||||
"For example, %s"), "<br />", "<br />", "https://satellite.example.org");
|
||||
break;
|
||||
case 'cloudforms':
|
||||
scope.username_required = true;
|
||||
scope.password_required = true;
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.host_required = true;
|
||||
scope.hostLabel = i18n._("CloudForms URL");
|
||||
scope.hostPopOver = i18n.sprintf(i18n._("Enter the URL for the virtual machine which %s" +
|
||||
"corresponds to your CloudForm instance. %s" +
|
||||
"For example, %s"), "<br />", "<br />", "https://cloudforms.example.org");
|
||||
break;
|
||||
case 'net':
|
||||
scope.username_required = true;
|
||||
scope.password_required = false;
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.sshKeyDataLabel = i18n._('SSH Key');
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
BecomeMethodChange.$inject =
|
||||
[ 'Empty', 'i18n' ];
|
||||
@@ -0,0 +1,105 @@
|
||||
export default
|
||||
function CredentialFormSave($rootScope, $location, Rest, ProcessErrors, GetBasePath, CredentialForm, ReturnToCaller, Wait, $state, i18n) {
|
||||
return function(params) {
|
||||
var scope = params.scope,
|
||||
mode = params.mode,
|
||||
form = CredentialForm,
|
||||
data = {}, fld, url;
|
||||
|
||||
for (fld in form.fields) {
|
||||
if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
|
||||
fld !== 'ssh_password') {
|
||||
if (fld === "organization" && !scope[fld]) {
|
||||
data.user = $rootScope.current_user.id;
|
||||
} else if (scope[fld] === null) {
|
||||
data[fld] = "";
|
||||
} else {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data.kind = scope.kind.value;
|
||||
if (scope.become_method === null || typeof scope.become_method === 'undefined') {
|
||||
data.become_method = "";
|
||||
data.become_username = "";
|
||||
data.become_password = "";
|
||||
} else {
|
||||
data.become_method = (scope.become_method.value) ? scope.become_method.value : "";
|
||||
}
|
||||
switch (data.kind) {
|
||||
case 'ssh':
|
||||
data.password = scope.ssh_password;
|
||||
break;
|
||||
case 'aws':
|
||||
data.username = scope.access_key;
|
||||
data.password = scope.secret_key;
|
||||
break;
|
||||
case 'rax':
|
||||
data.password = scope.api_key;
|
||||
break;
|
||||
case 'gce':
|
||||
data.username = scope.email_address;
|
||||
data.project = scope.project;
|
||||
break;
|
||||
case 'azure':
|
||||
data.username = scope.subscription;
|
||||
}
|
||||
|
||||
Wait('start');
|
||||
if (mode === 'add') {
|
||||
url = GetBasePath("credentials");
|
||||
Rest.setUrl(url);
|
||||
Rest.post(data)
|
||||
.success(function (data) {
|
||||
scope.addedItem = data.id;
|
||||
|
||||
Wait('stop');
|
||||
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
if (base === 'credentials') {
|
||||
$state.go('credentials.edit', {credential_id: data.id}, {reload: true});
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
// TODO: hopefully this conditional error handling will to away in a future version of tower. The reason why we cannot
|
||||
// simply pass this error to ProcessErrors is because it will actually match the form element 'ssh_key_unlock' and show
|
||||
// the error there. The ssh_key_unlock field is not shown when the kind of credential is gce/azure and as a result the
|
||||
// error is never shown. In the future, the API will hopefully either behave or respond differently.
|
||||
if(status && status === 400 && data && data.ssh_key_unlock && (scope.kind.value === 'gce' || scope.kind.value === 'azure')) {
|
||||
scope.ssh_key_data_api_error = i18n._("Encrypted credentials are not supported.");
|
||||
}
|
||||
else {
|
||||
ProcessErrors(scope, data, status, form, {
|
||||
hdr: i18n._('Error!'),
|
||||
msg: i18n._('Failed to create new Credential. POST status: ') + status
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
url = GetBasePath('credentials') + scope.id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.put(data)
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
$state.go($state.current, {}, {reload: true});
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, form, {
|
||||
hdr: i18n._('Error!'),
|
||||
msg: i18n._('Failed to update Credential. PUT status: ') + status
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
CredentialFormSave.$inject =
|
||||
[ '$rootScope', '$location', 'Rest',
|
||||
'ProcessErrors', 'GetBasePath', 'CredentialForm',
|
||||
'ReturnToCaller', 'Wait', '$state', 'i18n'
|
||||
];
|
||||
@@ -0,0 +1,192 @@
|
||||
export default
|
||||
function KindChange(Empty, i18n) {
|
||||
return function(params) {
|
||||
var scope = params.scope,
|
||||
reset = params.reset,
|
||||
collapse, id;
|
||||
|
||||
$('.popover').each(function() {
|
||||
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
|
||||
$(this).remove();
|
||||
});
|
||||
$('.tooltip').each( function() {
|
||||
// close any lingering tool tipss
|
||||
$(this).hide();
|
||||
});
|
||||
// Put things in a default state
|
||||
scope.usernameLabel = i18n._('Username');
|
||||
scope.aws_required = false;
|
||||
scope.email_required = false;
|
||||
scope.rackspace_required = false;
|
||||
scope.sshKeyDataLabel = i18n._('Private Key');
|
||||
scope.username_required = false; // JT-- added username_required b/c mutliple 'kinds' need username to be required (GCE)
|
||||
scope.key_required = false; // JT -- doing the same for key and project
|
||||
scope.project_required = false;
|
||||
scope.subscription_required = false;
|
||||
scope.key_description = i18n.sprintf(i18n._("Paste the contents of the SSH private key file.%s or click to close%s"), "<div class=\"popover-footer\"><span class=\"key\">Esc</span>", "</div>");
|
||||
scope.host_required = false;
|
||||
scope.password_required = false;
|
||||
scope.hostLabel = '';
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
|
||||
$('.popover').each(function() {
|
||||
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
|
||||
$(this).remove();
|
||||
});
|
||||
$('.tooltip').each( function() {
|
||||
// close any lingering tool tipss
|
||||
$(this).hide();
|
||||
});
|
||||
// Put things in a default state
|
||||
scope.usernameLabel = i18n._('Username');
|
||||
scope.aws_required = false;
|
||||
scope.email_required = false;
|
||||
scope.rackspace_required = false;
|
||||
scope.sshKeyDataLabel = i18n._('Private Key');
|
||||
scope.username_required = false; // JT-- added username_required b/c mutliple 'kinds' need username to be required (GCE)
|
||||
scope.key_required = false; // JT -- doing the same for key and project
|
||||
scope.project_required = false;
|
||||
scope.domain_required = false;
|
||||
scope.subscription_required = false;
|
||||
scope.key_description = i18n._("Paste the contents of the SSH private key file.");
|
||||
scope.host_required = false;
|
||||
scope.password_required = false;
|
||||
scope.hostLabel = '';
|
||||
scope.projectLabel = '';
|
||||
scope.domainLabel = '';
|
||||
scope.project_required = false;
|
||||
scope.passwordLabel = i18n._('Password (API Key)');
|
||||
scope.projectPopOver = "<p>" + i18n._("The project value") + "</p>";
|
||||
scope.hostPopOver = "<p>" + i18n._("The host value") + "</p>";
|
||||
scope.ssh_key_data_api_error = '';
|
||||
|
||||
if (!Empty(scope.kind)) {
|
||||
// Apply kind specific settings
|
||||
switch (scope.kind.value) {
|
||||
case 'aws':
|
||||
scope.aws_required = true;
|
||||
break;
|
||||
case 'rax':
|
||||
scope.rackspace_required = true;
|
||||
scope.username_required = true;
|
||||
break;
|
||||
case 'ssh':
|
||||
scope.usernameLabel = i18n._('Username'); //formally 'SSH Username'
|
||||
scope.becomeUsernameLabel = i18n._('Privilege Escalation Username');
|
||||
scope.becomePasswordLabel = i18n._('Privilege Escalation Password');
|
||||
break;
|
||||
case 'scm':
|
||||
scope.sshKeyDataLabel = i18n._('SCM Private Key');
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
break;
|
||||
case 'gce':
|
||||
scope.usernameLabel = i18n._('Service Account Email Address');
|
||||
scope.sshKeyDataLabel = i18n._('RSA Private Key');
|
||||
scope.email_required = true;
|
||||
scope.key_required = true;
|
||||
scope.project_required = true;
|
||||
scope.key_description = i18n._('Paste the contents of the PEM file associated with the service account email.');
|
||||
scope.projectLabel = i18n._("Project");
|
||||
scope.project_required = false;
|
||||
scope.projectPopOver = "<p>" + i18n._("The Project ID is the " +
|
||||
"GCE assigned identification. It is constructed as " +
|
||||
"two words followed by a three digit number. Such " +
|
||||
"as: ") + "</p><p>adjective-noun-000</p>";
|
||||
break;
|
||||
case 'azure':
|
||||
scope.sshKeyDataLabel = i18n._('Management Certificate');
|
||||
scope.subscription_required = true;
|
||||
scope.key_required = true;
|
||||
scope.key_description = i18n._("Paste the contents of the PEM file that corresponds to the certificate you uploaded in the Microsoft Azure console.");
|
||||
break;
|
||||
case 'azure_rm':
|
||||
scope.usernameLabel = i18n._("Username");
|
||||
scope.subscription_required = true;
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.azure_rm_required = true;
|
||||
break;
|
||||
case 'vmware':
|
||||
scope.username_required = true;
|
||||
scope.host_required = true;
|
||||
scope.password_required = true;
|
||||
scope.hostLabel = "vCenter Host";
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.hostPopOver = i18n._("Enter the hostname or IP address which corresponds to your VMware vCenter.");
|
||||
break;
|
||||
case 'openstack':
|
||||
scope.hostLabel = i18n._("Host (Authentication URL)");
|
||||
scope.projectLabel = i18n._("Project (Tenant Name)");
|
||||
scope.domainLabel = i18n._("Domain Name");
|
||||
scope.password_required = true;
|
||||
scope.project_required = true;
|
||||
scope.host_required = true;
|
||||
scope.username_required = true;
|
||||
scope.projectPopOver = "<p>" + i18n._("This is the tenant name. " +
|
||||
" This value is usually the same " +
|
||||
" as the username.") + "</p>";
|
||||
scope.hostPopOver = "<p>" + i18n._("The host to authenticate with.") +
|
||||
"<br />" + i18n.sprintf(i18n._("For example, %s"), "https://openstack.business.com/v2.0/");
|
||||
break;
|
||||
case 'satellite6':
|
||||
scope.username_required = true;
|
||||
scope.password_required = true;
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.host_required = true;
|
||||
scope.hostLabel = i18n._("Satellite 6 URL");
|
||||
scope.hostPopOver = i18n.sprintf(i18n._("Enter the URL which corresponds to your %s" +
|
||||
"Red Hat Satellite 6 server. %s" +
|
||||
"For example, %s"), "<br />", "<br />", "https://satellite.example.org");
|
||||
break;
|
||||
case 'cloudforms':
|
||||
scope.username_required = true;
|
||||
scope.password_required = true;
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.host_required = true;
|
||||
scope.hostLabel = i18n._("CloudForms URL");
|
||||
scope.hostPopOver = i18n.sprintf(i18n._("Enter the URL for the virtual machine which %s" +
|
||||
"corresponds to your CloudForm instance. %s" +
|
||||
"For example, %s"), "<br />", "<br />", "https://cloudforms.example.org");
|
||||
break;
|
||||
case 'net':
|
||||
scope.username_required = true;
|
||||
scope.password_required = false;
|
||||
scope.passwordLabel = i18n._('Password');
|
||||
scope.sshKeyDataLabel = i18n._('SSH Key');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset all the field values related to Kind.
|
||||
if (reset) {
|
||||
scope.access_key = null;
|
||||
scope.secret_key = null;
|
||||
scope.api_key = null;
|
||||
scope.username = null;
|
||||
scope.password = null;
|
||||
scope.password_confirm = null;
|
||||
scope.ssh_key_data = null;
|
||||
scope.ssh_key_unlock = null;
|
||||
scope.ssh_key_unlock_confirm = null;
|
||||
scope.become_username = null;
|
||||
scope.become_password = null;
|
||||
scope.authorize = false;
|
||||
scope.authorize_password = null;
|
||||
}
|
||||
|
||||
// Collapse or open help widget based on whether scm value is selected
|
||||
collapse = $('#credential_kind').parent().find('.panel-collapse').first();
|
||||
id = collapse.attr('id');
|
||||
if (!Empty(scope.kind) && scope.kind.value !== '') {
|
||||
if ($('#' + id + '-icon').hasClass('icon-minus')) {
|
||||
scope.accordionToggle('#' + id);
|
||||
}
|
||||
} else {
|
||||
if ($('#' + id + '-icon').hasClass('icon-plus')) {
|
||||
scope.accordionToggle('#' + id);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
KindChange.$inject =
|
||||
[ 'Empty', 'i18n' ];
|
||||
@@ -0,0 +1,18 @@
|
||||
export default
|
||||
function OwnerChange() {
|
||||
return function(params) {
|
||||
var scope = params.scope,
|
||||
owner = scope.owner;
|
||||
if (owner === 'team') {
|
||||
scope.team_required = true;
|
||||
scope.user_required = false;
|
||||
scope.user = null;
|
||||
scope.user_username = null;
|
||||
} else {
|
||||
scope.team_required = false;
|
||||
scope.user_required = true;
|
||||
scope.team = null;
|
||||
scope.team_name = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2016 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
export default ['$scope', 'Rest', 'CredentialList', 'Prompt', 'ClearScope',
|
||||
'ProcessErrors', 'GetBasePath', 'Wait', '$state', '$filter', 'rbacUiControlService', 'Dataset', 'i18n',
|
||||
function($scope, Rest, CredentialList, Prompt, ClearScope,
|
||||
ProcessErrors, GetBasePath, Wait, $state, $filter, rbacUiControlService, Dataset,
|
||||
i18n) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
var list = CredentialList,
|
||||
defaultUrl = GetBasePath('credentials');
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
rbacUiControlService.canAdd('credentials')
|
||||
.then(function(params) {
|
||||
$scope.canAdd = params.canAdd;
|
||||
});
|
||||
|
||||
// search init
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||
|
||||
$scope.selected = [];
|
||||
}
|
||||
|
||||
$scope.$on(`${list.iterator}_options`, function(event, data){
|
||||
$scope.options = data.data.actions.GET;
|
||||
optionsRequestDataProcessing();
|
||||
});
|
||||
|
||||
$scope.$watchCollection(`${$scope.list.name}`, function() {
|
||||
optionsRequestDataProcessing();
|
||||
});
|
||||
|
||||
// iterate over the list and add fields like type label, after the
|
||||
// OPTIONS request returns, or the list is sorted/paginated/searched
|
||||
function optionsRequestDataProcessing(){
|
||||
if ($scope[list.name] !== undefined) {
|
||||
$scope[list.name].forEach(function(item, item_idx) {
|
||||
var itm = $scope[list.name][item_idx];
|
||||
|
||||
// Set the item type label
|
||||
if (list.fields.kind && $scope.options &&
|
||||
$scope.options.hasOwnProperty('kind')) {
|
||||
$scope.options.kind.choices.forEach(function(choice) {
|
||||
if (choice[0] === item.kind) {
|
||||
itm.kind_label = choice[1];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.addCredential = function() {
|
||||
$state.go('credentials.add');
|
||||
};
|
||||
|
||||
$scope.editCredential = function(id) {
|
||||
$state.go('credentials.edit', { credential_id: id });
|
||||
};
|
||||
|
||||
$scope.deleteCredential = function(id, name) {
|
||||
var action = function() {
|
||||
$('#prompt-modal').modal('hide');
|
||||
Wait('start');
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.success(function() {
|
||||
if (parseInt($state.params.credential_id) === id) {
|
||||
$state.go("^", null, { reload: true });
|
||||
} else {
|
||||
$state.go('.', null, {reload: true});
|
||||
}
|
||||
Wait('stop');
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({
|
||||
hdr: i18n._('Delete'),
|
||||
body: '<div class="Prompt-bodyQuery">' + i18n._('Are you sure you want to delete the credential below?') + '</div><div class="Prompt-bodyTarget">' + $filter('sanitize')(name) + '</div>',
|
||||
action: action,
|
||||
actionText: i18n._('DELETE')
|
||||
});
|
||||
};
|
||||
}
|
||||
];
|
||||
@@ -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);
|
||||
@@ -0,0 +1,36 @@
|
||||
/** @define OwnerList */
|
||||
@import "./client/src/shared/branding/colors.default.less";
|
||||
|
||||
.OwnerList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.OwnerList-seeBase {
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
|
||||
color: @default-link;
|
||||
text-transform: uppercase;
|
||||
padding: 2px 15px;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.OwnerList-seeBase:hover {
|
||||
color: @default-link-hov;
|
||||
}
|
||||
|
||||
.OwnerList-seeLess {
|
||||
.OwnerList-seeBase;
|
||||
}
|
||||
|
||||
.OwnerList-seeMore {
|
||||
.OwnerList-seeBase;
|
||||
}
|
||||
|
||||
.OwnerList-Container {
|
||||
margin-right: 5px;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export default
|
||||
[ 'templateUrl',
|
||||
function(templateUrl) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: false,
|
||||
templateUrl: templateUrl('credentials/ownerList'),
|
||||
link: function(scope) {
|
||||
scope.owners_list = scope.credential.summary_fields.owners && scope.credential.summary_fields.owners.length > 0 ? scope.credential.summary_fields.owners : [];
|
||||
}
|
||||
};
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,29 @@
|
||||
<div class="OwnerList" ng-init="ownersLimit = 5; ownersLimitConst = 5;">
|
||||
<div class="OwnerList-Container"
|
||||
ng-repeat="owner in owners_list | limitTo:ownersLimit">
|
||||
<a ng-if="owner.type === 'organization'"
|
||||
ui-sref="organizations.edit({ organization_id: owner.id })">
|
||||
{{ owner.name }}{{$last ? '' : ', '}}
|
||||
</a>
|
||||
<a ng-if="owner.type === 'user'"
|
||||
ui-sref="users.edit({ user_id: owner.id })">
|
||||
{{ owner.name }}{{$last ? '' : ', '}}
|
||||
</a>
|
||||
<a ng-if="owner.type === 'team'"
|
||||
ui-sref="teams.edit({ team_id: owner.id })">
|
||||
{{ owner.name }}{{$last ? '' : ', '}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="OwnerList-seeMore"
|
||||
ng-show="owners_list.length > ownersLimitConst && ownersLimit == ownersLimitConst"
|
||||
ng-click="ownersLimit = owners_list.length">
|
||||
View More
|
||||
</div>
|
||||
|
||||
<div class="OwnerList-seeLess"
|
||||
ng-show="owners_list.length > ownersLimitConst && ownersLimit != ownersLimitConst"
|
||||
ng-click="ownersLimit = ownersLimitConst">
|
||||
View Less
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user