diff --git a/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.controller.js b/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.controller.js index d3ef949ca6..d916e3a53a 100644 --- a/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.controller.js +++ b/awx/ui/client/src/configuration/forms/auth-form/configuration-auth.controller.js @@ -197,7 +197,7 @@ export default [ formDef: formDefs.ldap5, id: 'auth-ldap5-form', name: 'ldap5' - }, + } ]; var forms = _.map(authForms, 'formDef'); _.each(forms, function(form) { diff --git a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js b/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js index e897a6ba4e..8822f531bd 100644 --- a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js +++ b/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js @@ -67,6 +67,18 @@ export default ['i18n', function(i18n) { rows: 6, codeMirror: true, class: 'Form-textAreaLabel Form-formGroup--fullWidth' + }, + AWX_ISOLATED_CHECK_INTERVAL: { + type: 'text', + reset: 'AWX_ISOLATED_CHECK_INTERVAL' + }, + AWX_ISOLATED_LAUNCH_TIMEOUT: { + type: 'text', + reset: 'AWX_ISOLATED_LAUNCH_TIMEOUT' + }, + AWX_ISOLATED_CONNECTION_TIMEOUT: { + type: 'text', + reset: 'AWX_ISOLATED_CONNECTION_TIMEOUT' } }, buttons: { diff --git a/awx/ui/client/src/configuration/forms/settings-form.controller.js b/awx/ui/client/src/configuration/forms/settings-form.controller.js index 57216d9b85..57bb59e68f 100644 --- a/awx/ui/client/src/configuration/forms/settings-form.controller.js +++ b/awx/ui/client/src/configuration/forms/settings-form.controller.js @@ -92,10 +92,15 @@ export default [ var populateFromApi = function() { SettingsService.getCurrentValues() .then(function(data) { + // these two values need to be unnested from the + // OAUTH2_PROVIDER key + data.ACCESS_TOKEN_EXPIRE_SECONDS = data + .OAUTH2_PROVIDER.ACCESS_TOKEN_EXPIRE_SECONDS; + data.AUTHORIZATION_CODE_EXPIRE_SECONDS = data + .OAUTH2_PROVIDER.AUTHORIZATION_CODE_EXPIRE_SECONDS; var currentKeys = _.keys(data); $scope.requiredLogValues = {}; _.each(currentKeys, function(key) { - if(key === "LOG_AGGREGATOR_HOST") { $scope.requiredLogValues.LOG_AGGREGATOR_HOST = data[key]; } @@ -232,7 +237,18 @@ export default [ $scope.resetValue = function(key) { Wait('start'); var payload = {}; - payload[key] = $scope.configDataResolve[key].default; + if (key === 'ACCESS_TOKEN_EXPIRE_SECONDS' || key === 'AUTHORIZATION_CODE_EXPIRE_SECONDS') { + // the reset for these two keys needs to be nested under OAUTH2_PROVIDER + if (payload.OAUTH2_PROVIDER === undefined) { + payload.OAUTH2_PROVIDER = { + ACCESS_TOKEN_EXPIRE_SECONDS: $scope.ACCESS_TOKEN_EXPIRE_SECONDS, + AUTHORIZATION_CODE_EXPIRE_SECONDS: $scope.AUTHORIZATION_CODE_EXPIRE_SECONDS + }; + } + payload.OAUTH2_PROVIDER[key] = $scope.configDataResolve[key].default; + } else { + payload[key] = $scope.configDataResolve[key].default; + } SettingsService.patchConfiguration(payload) .then(function() { $scope[key] = $scope.configDataResolve[key].default; @@ -310,7 +326,16 @@ export default [ var keys = _.keys(formDefs[formTracker.getCurrent()].fields); var payload = {}; _.each(keys, function(key) { - if($scope.configDataResolve[key].type === 'choice' || multiselectDropdowns.indexOf(key) !== -1) { + if (key === 'ACCESS_TOKEN_EXPIRE_SECONDS' || key === 'AUTHORIZATION_CODE_EXPIRE_SECONDS') { + // These two values need to be POSTed nested under the OAUTH2_PROVIDER key + if (payload.OAUTH2_PROVIDER === undefined) { + payload.OAUTH2_PROVIDER = { + ACCESS_TOKEN_EXPIRE_SECONDS: $scope.ACCESS_TOKEN_EXPIRE_SECONDS, + AUTHORIZATION_CODE_EXPIRE_SECONDS: $scope.AUTHORIZATION_CODE_EXPIRE_SECONDS + }; + } + payload.OAUTH2_PROVIDER[key] = $scope[key]; + } else if($scope.configDataResolve[key].type === 'choice' || multiselectDropdowns.indexOf(key) !== -1) { //Parse dropdowns and dropdowns labeled as lists if($scope[key] === null) { payload[key] = null; @@ -518,7 +543,18 @@ export default [ var payload = {}; clearApiErrors(); _.each(keys, function(key) { - payload[key] = $scope.configDataResolve[key].default; + if (key === 'ACCESS_TOKEN_EXPIRE_SECONDS' || key === 'AUTHORIZATION_CODE_EXPIRE_SECONDS') { + // the reset for these two keys needs to be nested under OAUTH2_PROVIDER + if (payload.OAUTH2_PROVIDER === undefined) { + payload.OAUTH2_PROVIDER = { + ACCESS_TOKEN_EXPIRE_SECONDS: $scope.ACCESS_TOKEN_EXPIRE_SECONDS, + AUTHORIZATION_CODE_EXPIRE_SECONDS: $scope.AUTHORIZATION_CODE_EXPIRE_SECONDS + }; + } + payload.OAUTH2_PROVIDER[key] = $scope.configDataResolve[key].default; + } else { + payload[key] = $scope.configDataResolve[key].default; + } }); Wait('start'); diff --git a/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-misc.form.js b/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-misc.form.js index 2d5853f8e4..f9dddd237b 100644 --- a/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-misc.form.js +++ b/awx/ui/client/src/configuration/forms/system-form/sub-forms/system-misc.form.js @@ -43,6 +43,14 @@ export default ['i18n', function(i18n) { ALLOW_OAUTH2_FOR_EXTERNAL_USERS: { type: 'toggleSwitch', }, + ACCESS_TOKEN_EXPIRE_SECONDS: { + type: 'text', + reset: 'ACCESS_TOKEN_EXPIRE_SECONDS' + }, + AUTHORIZATION_CODE_EXPIRE_SECONDS: { + type: 'text', + reset: 'AUTHORIZATION_CODE_EXPIRE_SECONDS' + }, REMOTE_HOST_HEADERS: { type: 'textarea', reset: 'REMOTE_HOST_HEADERS' diff --git a/awx/ui/client/src/configuration/settings.service.js b/awx/ui/client/src/configuration/settings.service.js index 1d437dc2cd..62dedab140 100644 --- a/awx/ui/client/src/configuration/settings.service.js +++ b/awx/ui/client/src/configuration/settings.service.js @@ -4,8 +4,8 @@ * All Rights Reserved *************************************************/ -export default ['$rootScope', 'GetBasePath', 'ProcessErrors', '$q', '$http', 'Rest', - function($rootScope, GetBasePath, ProcessErrors, $q, $http, Rest) { +export default ['GetBasePath', '$q', 'Rest', 'i18n', + function(GetBasePath, $q, Rest, i18n) { var url = GetBasePath('settings') + 'all'; return { @@ -18,9 +18,35 @@ export default ['$rootScope', 'GetBasePath', 'ProcessErrors', '$q', '$http', 'Re .then(({data}) => { // Compare GET actions with PUT actions and flag discrepancies // for disabling in the UI - var getActions = data.actions.GET; + // + // since OAUTH2_PROVIDER returns two of the keys in a nested format, + // we need to split those out into the root of the options payload + // in order for them to be consumed + var appendOauth2ProviderKeys = (optsFromAPI) => { + var unnestOauth2ProviderKey = (key, help_text, label, parentKey) => { + optsFromAPI[key] = _.cloneDeep(optsFromAPI[parentKey]); + optsFromAPI[key].label = label; + optsFromAPI[key].help_text = help_text; + optsFromAPI[key].type = optsFromAPI[parentKey].child.type; + optsFromAPI[key].min_value = optsFromAPI[parentKey].child.min_value; + if (optsFromAPI[parentKey].default) { + optsFromAPI[key].default = optsFromAPI[parentKey].default[key]; + } + delete optsFromAPI[key].child; + }; + unnestOauth2ProviderKey('ACCESS_TOKEN_EXPIRE_SECONDS', + i18n._('The duration (in seconds) access tokens remain valid since their creation.'), + i18n._('Access Token Expiration'), + 'OAUTH2_PROVIDER'); + unnestOauth2ProviderKey('AUTHORIZATION_CODE_EXPIRE_SECONDS', + i18n._('The duration (in seconds) authorization codes remain valid since their creation.'), + i18n._('Authorization Code Expiration'), + 'OAUTH2_PROVIDER'); + return optsFromAPI; + }; + var getActions = appendOauth2ProviderKeys(data.actions.GET); var getKeys = _.keys(getActions); - var putActions = data.actions.PUT; + var putActions = appendOauth2ProviderKeys(data.actions.PUT); _.each(getKeys, function(key) { if(putActions && putActions[key]) {