diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js index 3957621aca..798fd7605a 100644 --- a/awx/ui/static/js/app.js +++ b/awx/ui/static/js/app.js @@ -25,6 +25,7 @@ angular.module('Tower', [ 'RestServices', 'AuthService', 'Utilities', + 'LicenseHelper', 'OrganizationFormDefinition', 'UserFormDefinition', 'FormGenerator', @@ -79,7 +80,6 @@ angular.module('Tower', [ 'md5Helper', 'AccessHelper', 'SelectionHelper', - 'License', 'HostGroupsFormDefinition', 'DashboardCountsWidget', 'JobStatusGraphWidget', @@ -420,10 +420,10 @@ angular.module('Tower', [ }]); }]) - .run(['$compile', '$cookieStore', '$rootScope', '$log', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'ViewLicense', - 'Timer', 'ClearScope', 'HideStream', 'Socket', 'LoadConfig', 'Store', 'ShowSocketHelp', - function ($compile, $cookieStore, $rootScope, $log, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense, - Timer, ClearScope, HideStream, Socket, LoadConfig, Store, ShowSocketHelp) { + .run(['$compile', '$cookieStore', '$rootScope', '$log', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'Timer', 'ClearScope', 'HideStream', 'Socket', + 'LoadConfig', 'Store', 'ShowSocketHelp', 'LicenseViewer', + function ($compile, $cookieStore, $rootScope, $log, CheckLicense, $location, Authorization, LoadBasePaths, Timer, ClearScope, HideStream, Socket, + LoadConfig, Store, ShowSocketHelp, LicenseViewer) { var e, html, sock, checkCount = 0; @@ -522,9 +522,11 @@ angular.module('Tower', [ if ($rootScope.current_user === undefined || $rootScope.current_user === null) { Authorization.restoreUserInfo(); //user must have hit browser refresh } - CheckLicense.test(); + if (!/^\/(login|logout)/.test(next.$$route.originalPath)) { + // if not headed to /login or /logout, then check the license + CheckLicense.test(); + } } - activateTab(); }); @@ -545,7 +547,7 @@ angular.module('Tower', [ }; $rootScope.viewLicense = function () { - ViewLicense(); + LicenseViewer.showViewer(); }; $rootScope.toggleTab = function(e, tab, tabs) { e.preventDefault(); diff --git a/awx/ui/static/js/forms/LicenseForm.js b/awx/ui/static/js/forms/LicenseForm.js index f13cefda11..fcea0fa4ee 100644 --- a/awx/ui/static/js/forms/LicenseForm.js +++ b/awx/ui/static/js/forms/LicenseForm.js @@ -25,13 +25,18 @@ angular.module('LicenseFormDefinition', []) fields: { license_status: { type: 'custom', - control: "
The Ansible Tower license is invalid. Please visit " + - "http://ansible.com/license to obtain a valid license key. " + - "Copy and paste the key in the field below and click the Submit button.
Thank you for using Ansible Tower. The Ansible Tower license " + - "has expired. You will no longer be able to run playbooks after " + this.getRemainingDays(license.grace_period_remaining) + " days
" + - "Please visit ansible.com/license to purchse a valid license. " + - "Copy and paste the new license key in the field below and click the Submit button.
Thank you for using Ansible Tower. The Ansible Tower license " + - "has expired, and the 30 day grace period has been exceeded. To continue using Tower to run playbooks and adding managed hosts a " + - "valid license key is required.
Please visit http://ansible.com/license to " + - "purchse a license. Copy and paste the new license key in the field below and click the Submit button.
"; - } - } - else if (this.getRemainingDays(license.time_remaining) < 15) { - html = "Thank you for using Ansible Tower. The Ansible Tower license " + - "has " + this.getRemainingDays(license.time_remaining) + " remaining.
" + - "Extend your Ansible Tower license by visiting http://ansible.com/license. " + - "Copy and paste the new license key in the field below and click the Submit button.
The Ansible Tower license has reached capacity for the number of " + - "managed hosts allowed. No additional hosts can be added.
To extend the Ansible Tower license please visit " + - "ansible.com/license. " + - "Copy and paste the new license key in the field below and click the Submit button.
"; - } - } else { - // No license - title = "License Required"; - html = "Thank you for trying Ansible Tower. A FREE trial license is available for various infrastructure sizes, as well as free unlimited use for up to ten nodes.
" + - "
Visit ansible.com/license to obtain a free license key. Copy and paste the key in the field below and " + - "click the Submit button.
To purchase a license or extend an existing license ' + - 'visit the Ansible online store, ' + - 'or visit support.ansible.com for assistance.
'; - - if (license && !Authorization.licenseTested()) { - // This is our first time evaluating the license - license.tested = true; - Store('license',license); //update with tested flag - $rootScope.license_tested = true; - $rootScope.version = license.version; - if (license.valid_key !== undefined && license.valid_key === false) { - // The license is invalid. Stop the user from logging in. - status = 'alert-danger'; - hdr = 'License Error'; - msg = 'There is a problem with the /etc/awx/license file on your Tower server. Check to make sure Tower can access ' + - 'the file.
' + purchase_msg; - Alert(hdr, msg, status, null, false, true); - } else if (license.demo !== undefined && license.demo === true) { - // demo - status = 'alert-info'; - hdr = 'Tower Demo'; - msg = 'Thank you for trying Ansible Tower. You can use this edition to manage up to 10 hosts free.
' + - purchase_msg; - Alert(hdr, msg, status); - } - if (license.date_expired !== undefined && license.date_expired === true) { - // expired - status = 'alert-info'; - hdr = 'License Expired'; - msg = 'Your Ansible Tower License has expired and is no longer compliant. You can continue, but you will be ' + - 'unable to add any additional hosts.
' + purchase_msg; - Alert(hdr, msg, status); - } else if (license.date_warning !== undefined && license.date_warning === true) { - status = 'alert-info'; - hdr = 'License Warning'; - msg = 'Your Ansible Tower license is about to expire!
' + purchase_msg; - Alert(hdr, msg, status); - } - if (license.free_instances !== undefined && parseInt(license.free_instances) <= 0) { - status = 'alert-info'; - hdr = 'License Warning'; - msg = 'Your Ansible Tower license has reached capacity for the number of managed ' + - 'hosts allowed. You will not be able to add any additional hosts.
' + purchase_msg; - Alert(hdr, msg, status, null, true); } } + //if (!access) { + // Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); + //} + //return access; }; - } -]); -*/ - + }]) + .factory('IsAdmin', ['$rootScope', function($rootScope) { + return function() { return ($rootScope.current_user && $rootScope.current_user.is_superuser); }; + }]); diff --git a/awx/ui/static/js/helpers/License.js b/awx/ui/static/js/helpers/License.js new file mode 100644 index 0000000000..baf98feed5 --- /dev/null +++ b/awx/ui/static/js/helpers/License.js @@ -0,0 +1,566 @@ + +/****************************************************** + * Copyright (c) 2014 AnsibleWorks, Inc. + * + * helpers/License.js + * + * Routines for checking and reporting license status + * + */ + +'use strict'; + +angular.module('LicenseHelper', ['RestServices', 'Utilities', 'LicenseUpdateFormDefinition', 'FormGenerator', 'ParseHelper', 'ModalDialog', 'VariablesHelper', 'LicenseFormDefinition', 'AccessHelper']) + + +.factory('CheckLicense', ['$rootScope', '$compile', 'CreateDialog', 'Store', 'LicenseUpdateForm', 'GenerateForm', 'TextareaResize', 'ToJSON', 'GetBasePath', 'Rest', 'ProcessErrors', 'Alert', 'IsAdmin', +function($rootScope, $compile, CreateDialog, Store, LicenseUpdateForm, GenerateForm, TextareaResize, ToJSON, GetBasePath, Rest, ProcessErrors, Alert, IsAdmin) { + return { + getRemainingDays: function(time_remaining) { + // assumes time_remaining will be in seconds + var tr = parseInt(time_remaining, 10); + return Math.floor(tr / 86400); + }, + + shouldNotify: function(license) { + if (license && typeof license === 'object' && Object.keys(license).length > 0) { + // we have a license object + if (!license.valid_key) { + // missing valid key + return true; + } + else if (license.free_instances <= 0) { + // host count exceeded + return true; + } + else if (this.getRemainingDays(license.time_remaining) < 15) { + // below 15 days remaining on license + return true; + } + return false; + } else { + // missing license object + return true; + } + }, + + isAdmin: function() { + return IsAdmin(); + }, + + getHTML: function(license, includeFormButton) { + var title, html, result = {}; + if (license && typeof license === 'object' && Object.keys(license).length > 0 && license.valid_key !== undefined) { + // we have a license + if (!license.valid_key) { + title = "Invalid License"; + html = "The Ansible Tower license is invalid. Please visit " + + "ansible.com/license to obtain a valid license key."; + } + else if (this.getRemainingDays(license.time_remaining) <= 0) { + if (parseInt(license.grace_period_remaining,10) > 86400) { + title = "License Expired"; + html = "
Thank you for using Ansible Tower. The Ansible Tower license " + + "has expired. You will no longer be able to add managed hosts or run playbooks after " + this.getRemainingDays(license.grace_period_remaining) + " days
" + + "Please visit ansible.com/license to purchse a valid license."; + } else { + title = "License Expired"; + html = "
Thank you for using Ansible Tower. The Ansible Tower license " + + "has expired, and the 30 day grace period has been exceeded. To continue using Tower to run playbooks and add managed hosts a " + + "valid license key is required.
Please visit ansible.com/license to purchse a license."; + } + } + else if (this.getRemainingDays(license.time_remaining) < 15) { + title = "License Warning"; + html = "
Thank you for using Ansible Tower. The Ansible Tower license " + + "has " + this.getRemainingDays(license.time_remaining) + " remaining. Once the license expires you will no longer be able to add managed hosts or run playbooks.
" + + "Extend your Ansible Tower license by visiting ansible.com/license."; + } + else if (license.free_instances <= 0) { + title = "Host Count Exceeded"; + html = "
The Ansible Tower license has reached capacity for the number of " + + "managed hosts allowed. No additional hosts can be added.
To extend the Ansible Tower license please visit " + + "ansible.com/license."; + } else { + // license is valid. the following text is displayed in the license viewer + title = "Update License"; // not actually used + html = "
The Ansible Tower license is valid. To extend or renew the license " + + "visit ansible.com/license."; + } + } else { + // No license + title = "License Required"; + html = "
Thank you for trying Ansible Tower. Without a valid license you will not be able to add managed hosts or " + + "run playbooks. A FREE trial license is available for various infrastructure sizes, as well as free unlimited use for up to ten nodes.
" + + "
Visit ansible.com/license to obtain a license key."; + } + + if (IsAdmin()) { + html += " Copy and paste the license key in the field below and click the Submit button."; + } + html += "
To purchase a license or extend an existing license ' + + 'visit the Ansible online store, ' + + 'or visit support.ansible.com for assistance.
'; + + if (license && !Authorization.licenseTested()) { + // This is our first time evaluating the license + license.tested = true; + Store('license',license); //update with tested flag + $rootScope.license_tested = true; + $rootScope.version = license.version; + if (license.valid_key !== undefined && license.valid_key === false) { + // The license is invalid. Stop the user from logging in. + status = 'alert-danger'; + hdr = 'License Error'; + msg = 'There is a problem with the /etc/awx/license file on your Tower server. Check to make sure Tower can access ' + + 'the file.
' + purchase_msg; + Alert(hdr, msg, status, null, false, true); + } else if (license.demo !== undefined && license.demo === true) { + // demo + status = 'alert-info'; + hdr = 'Tower Demo'; + msg = 'Thank you for trying Ansible Tower. You can use this edition to manage up to 10 hosts free.
' + + purchase_msg; + Alert(hdr, msg, status); + } + if (license.date_expired !== undefined && license.date_expired === true) { + // expired + status = 'alert-info'; + hdr = 'License Expired'; + msg = 'Your Ansible Tower License has expired and is no longer compliant. You can continue, but you will be ' + + 'unable to add any additional hosts.
' + purchase_msg; + Alert(hdr, msg, status); + } else if (license.date_warning !== undefined && license.date_warning === true) { + status = 'alert-info'; + hdr = 'License Warning'; + msg = 'Your Ansible Tower license is about to expire!
' + purchase_msg; + Alert(hdr, msg, status); + } + if (license.free_instances !== undefined && parseInt(license.free_instances) <= 0) { + status = 'alert-info'; + hdr = 'License Warning'; + msg = 'Your Ansible Tower license has reached capacity for the number of managed ' + + 'hosts allowed. You will not be able to add any additional hosts.
' + purchase_msg; + Alert(hdr, msg, status, null, true); + } + } + }; + } +]); +*/ \ No newline at end of file diff --git a/awx/ui/static/js/helpers/Variables.js b/awx/ui/static/js/helpers/Variables.js index c01d768fce..65a7f1e495 100644 --- a/awx/ui/static/js/helpers/Variables.js +++ b/awx/ui/static/js/helpers/Variables.js @@ -9,9 +9,9 @@ 'use strict'; angular.module('VariablesHelper', ['Utilities']) - + /** - variables: string containing YAML or JSON | a JSON object. + variables: string containing YAML or JSON | a JSON object. If JSON string, convert to JSON object and run through jsyaml.safeDump() to create a YAML document. If YAML, will attempt to load via jsyaml.safeLoad() and return a YAML document using jsyaml.safeDump(). In all cases @@ -73,11 +73,17 @@ angular.module('VariablesHelper', ['Utilities']) **/ .factory('ToJSON', ['$log', 'ProcessErrors', function($log, ProcessErrors) { - return function(parseType, variables, stringify) { + return function(parseType, variables, stringify, reviver) { var json_data, result; if (parseType === 'json') { try { - json_data = JSON.parse(variables); //make sure JSON parses + //parse a JSON string + if (reviver) { + json_data = JSON.parse(variables, reviver); + } + else { + json_data = JSON.parse(variables); + } } catch(e) { json_data = {}; diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index 05d454d377..8046e7710d 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -1224,9 +1224,13 @@ input[type="checkbox"].checkbox-no-label { /* End Jobs Page */ -/* License Accordion */ - #license-collapse .ui-accordion-content { - overflow: hidden; +/* license modal */ + #license-modal-dialog { + textarea:read-only, + input:read-only { + background-color: #F9F9F9; + border: 1px solid #F5F5F5; + } } /* Inventory nav links */ diff --git a/awx/ui/static/lib/ansible/license.js b/awx/ui/static/lib/ansible/license.js deleted file mode 100644 index 4c5ede7116..0000000000 --- a/awx/ui/static/lib/ansible/license.js +++ /dev/null @@ -1,126 +0,0 @@ -/********************************************* - * Copyright (c) 2014 AnsibleWorks, Inc. - * - * License.js - * - * View license info found in /api/vi/config/ - * - *****************************************/ - -'use strict'; - -angular.module('License', ['RestServices', 'Utilities', 'FormGenerator', 'PromptDialog', 'LicenseFormDefinition']) - .factory('ViewLicense', ['$location', '$rootScope', 'GenerateForm', 'Rest', 'Alert', 'GetBasePath', 'ProcessErrors', - 'FormatDate', 'Prompt', 'Empty', 'LicenseForm', - function ($location, $rootScope, GenerateForm, Rest, Alert, GetBasePath, ProcessErrors, FormatDate, Prompt, Empty, - LicenseForm) { - return function () { - - var defaultUrl = GetBasePath('config'), - generator = GenerateForm, - form = angular.copy(LicenseForm), - scope; - - // Retrieve detail record and prepopulate the form - Rest.setUrl(defaultUrl); - Rest.get() - .success(function (data) { - - var fld, dt, days, remainder, hours, minutes, seconds, license; - - for (fld in form.fields) { - if (fld !== 'time_remaining' && fld !== 'license_status') { - if (Empty(data.license_info[fld])) { - delete form.fields[fld]; - } - } - } - - if (data.license_info.is_aws || Empty(data.license_info.license_date)) { - delete form.fields.license_date; - delete form.fields.time_remaining; - } - - scope = generator.inject(form, { mode: 'edit', modal: true, related: false }); - generator.reset(); - - scope.formModalAction = function () { - $('#form-modal').modal("hide"); - }; - - scope.formModalActionLabel = 'OK'; - scope.formModalCancelShow = false; - scope.formModalInfo = 'Purchase/Extend License'; - scope.formModalHeader = "Ansible Tower v." + data.version + ""; - - // Respond to license button - scope.formModalInfoAction = function () { - Prompt({ - hdr: 'Tower Licensing', - body: "Ansible Tower licenses can be purchased or extended by visiting " + - "the Ansible online store. Would you like to purchase or extend your license now?
", - 'class': 'btn-primary', - action: function () { - window.open('http://www.ansible.com/ansible-pricing', 'storeWindow'); - } - }); - }; - - for (fld in form.fields) { - if (!Empty(data.license_info[fld])) { - scope[fld] = data.license_info[fld]; - } - } - - if (scope.license_date) { - dt = new Date(parseInt(scope.license_date, 10) * 1000); - scope.license_date = FormatDate(dt); - scope.time_remaining = scope.time_remaining * 1000; - days = parseInt(scope.time_remaining / 86400000, 10); - remainder = scope.time_remaining - (days * 86400000); - hours = parseInt(remainder / 3600000, 10); - remainder = remainder - (hours * 3600000); - minutes = parseInt(remainder / 60000, 10); - remainder = remainder - (minutes * 60000); - seconds = parseInt(remainder / 1000, 10); - scope.time_remaining = days + ' days ' + ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2) + ':' + - ('0' + seconds).slice(-2); - } - - if (parseInt(scope.free_instances) <= 0) { - scope.free_instances_class = 'field-failure'; - } else { - scope.free_instances_class = 'field-success'; - } - - license = data.license_info; - if (license.valid_key !== undefined && !license.valid_key) { - scope.license_status = 'Invalid'; - scope.status_color = 'license-invalid'; - } else if (license.demo !== undefined && license.demo) { - scope.license_status = 'Demo'; - scope.status_color = 'license-demo'; - } else if (license.date_expired !== undefined && license.date_expired) { - scope.license_status = 'Expired'; - scope.status_color = 'license-expired'; - } else if (license.date_warning !== undefined && license.date_warning) { - scope.license_status = 'Expiration Warning'; - scope.status_color = 'license-warning'; - } else if (license.free_instances !== undefined && parseInt(license.free_instances) <= 0) { - scope.license_status = 'No available managed hosts'; - scope.status_color = 'license-invalid'; - } else { - scope.license_status = 'Valid'; - scope.status_color = 'license-valid'; - } - - }) - .error(function (data, status) { - ProcessErrors($rootScope, data, status, null, { hdr: 'Error!', - msg: 'Failed to retrieve license. GET status: ' + status - }); - }); - }; - } - ]); \ No newline at end of file diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html index d2e3d144e5..bda08a056e 100644 --- a/awx/ui/templates/ui/index.html +++ b/awx/ui/templates/ui/index.html @@ -58,7 +58,6 @@ - @@ -157,6 +156,7 @@ +