diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js index 82728ebc3c..63e6607485 100644 --- a/awx/ui/static/js/app.js +++ b/awx/ui/static/js/app.js @@ -207,8 +207,8 @@ angular.module('ansible', [ otherwise({redirectTo: '/'}); }]) - .run(['$rootScope', '$location', 'Authorization','LoadBasePaths', - function($rootScope, $location, Authorization, LoadBasePaths) { + .run(['$rootScope', 'CheckLicense', '$location', 'Authorization','LoadBasePaths', + function($rootScope, CheckLicense, $location, Authorization, LoadBasePaths) { LoadBasePaths(); @@ -226,6 +226,7 @@ angular.module('ansible', [ if ($rootScope.current_user == undefined || $rootScope.current_user == null) { Authorization.restoreUserInfo(); //user must have hit browser refresh } + CheckLicense(); } // Make the correct tab active var base = ($location.path().replace(/^\//,'').split('/')[0]); @@ -236,13 +237,13 @@ angular.module('ansible', [ base.replace(/\_/g,' '); $('.nav-tabs a[href="#' + base + '"]').tab('show'); } - }); + }); if (! Authorization.isTokenValid() ) { // When the app first loads, redirect to login page $location.path('/login'); } - + // If browser refresh, activate the correct tab var base = ($location.path().replace(/^\//,'').split('/')[0]); if (base == '') { diff --git a/awx/ui/static/js/controllers/Authentication.js b/awx/ui/static/js/controllers/Authentication.js index 8d4b77bf63..c973160e24 100644 --- a/awx/ui/static/js/controllers/Authentication.js +++ b/awx/ui/static/js/controllers/Authentication.js @@ -41,20 +41,32 @@ function Authenticate($scope, $rootScope, $location, Authorization, ToggleClass, // Call the API to get an auth token $scope.systemLogin = function(username, password) { + $('.api-error').empty(); + var token; + Authorization.retrieveToken(username, password) .success( function(data, status, headers, config) { + token = data.token; Authorization.setToken(data.token); $scope.reset(); + // Get all the profile/access info regarding the logged in user Authorization.getUser() .success(function(data, status, headers, config) { $('#login-modal').modal('hide'); Authorization.setUserInfo(data); - $location.path('/organizations'); + Authorization.getLicense() + .success(function(data, status, headers, config) { + Authorization.setLicense(data['license_info']); + $location.path('/organizations'); + }) + .error(function(data, status, headers, config) { + Alert('Error', 'Failed to access user information. GET returned status: ' + status); + }); }) .error( function(data, status, headers, config) { - Alert('Error', 'Failed to get user data from /api/v1/me. GET status: ' + status); + Alert('Error', 'Failed to access license information. GET returned status: ' + status); }); }) .error( function(data, status, headers, config) { @@ -79,3 +91,6 @@ function Authenticate($scope, $rootScope, $location, Authorization, ToggleClass, }); } } + +Authenticate.$inject = ['$scope', '$rootScope', '$location', 'Authorization', 'ToggleClass', 'Alert']; + diff --git a/awx/ui/static/js/helpers/Access.js b/awx/ui/static/js/helpers/Access.js index f4e530680a..f33b93133c 100644 --- a/awx/ui/static/js/helpers/Access.js +++ b/awx/ui/static/js/helpers/Access.js @@ -3,9 +3,9 @@ * */ -angular.module('AccessHelper', ['RestServices', 'Utilities']) - .factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath','ProcessErrors', 'Alert', - function($rootScope, Alert, Rest, GetBasePath, ProcessErrors, Prompt) { +angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies']) + .factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath','ProcessErrors', + function($rootScope, Alert, Rest, GetBasePath, ProcessErrors) { return function(params) { var me = $rootScope.current_user; var access = false; @@ -33,4 +33,59 @@ angular.module('AccessHelper', ['RestServices', 'Utilities']) } return access; } + }]) + + .factory('CheckLicense', ['$rootScope', '$cookieStore', 'Alert', '$location', 'Authorization', + function($rootScope, $cookieStore, Alert, $location, Authorization) { + return function() { + // Check license status and alert the user, if needed + var status = 'success'; + var hdr, msg; + var license = $cookieStore.get('license'); + if (license && !Authorization.licenseTested()) { + // This is our first time evaluating the license + license['tested'] = true; + $cookieStore.remove('license'); + $cookieStore.put('license', license); + $rootScope.license_tested = true; + if (license['key_valid'] !== undefined && license['key_valid'] == false) { + // The license is invalid. Stop the user from logging in. + status = 'alert-error'; + hdr = 'License Error'; + msg = 'Something is wrong with your /etc/awx/license file on this server. ' + + 'Please contact info@ansibleworks.com for assistance.'; + //action = function() { window.location = '#/logout'; }; + Alert(hdr, msg, status, null, false, true); + } + else if (license['demo'] !== undefined && license['demo'] == true) { + // demo + status = 'alert-info'; + hdr = 'AWX Demo'; + msg = 'Thank you for trying AnsibleWorks AWX. You can use this edition to manage up to 5 hosts. ' + + 'Should you wish to acquire a license for additional servers, please visit ' + + 'ansibleworks.com/ansibleworks-awx, or ' + + 'contact info@ansibleworks.com for assistance.'; + Alert(hdr, msg, status); + } + if (license['date_warning'] !== undefined && license['date_warning'] == true) { + status = 'alert-info'; + hdr = 'License Expired'; + msg = 'Your AnsibleWorks AWX License has expired and is no longer compliant. ' + + 'You can continue, but you will be unable to add any additional hosts. Please ' + + 'visit ansibleworks.com/ansibleworks-awx ' + + 'for license and renewal information, or contact info@ansibleworks.com ' + + 'for assistance.'; + Alert(hdr, msg, status); + } + if (license['free_instances'] !== undefined && parseInt(license['free_instances']) <= 0) { + status = 'alert-info'; + hdr = 'License Warning'; + msg = 'Your AnsibleWorks AWX License has reached capacity for the number of managed ' + + 'hosts allowed. You will not be able to add any additional hosts. To extend your license, please visit ' + + 'ansibleworks.com/ansibleworks-awx., or ' + + 'contact info@ansibleworks.com for more information.'; + Alert(hdr, msg, status, null, true); + } + } + } }]); \ No newline at end of file diff --git a/awx/ui/static/lib/ansible/authenticate.js b/awx/ui/static/lib/ansible/authenticate.js index 05304b7a4c..7b60635fb6 100644 --- a/awx/ui/static/lib/ansible/authenticate.js +++ b/awx/ui/static/lib/ansible/authenticate.js @@ -69,6 +69,36 @@ angular.module('AuthService', ['ngCookies']) $rootScope.userLoggedIn = false; }, + getLicense: function() { + return $http({ + method: 'GET', + url: '/api/v1/config/', + headers: { 'Authorization': 'Token ' + this.getToken() } + }); + }, + + setLicense: function(license) { + license['tested'] = false; + $cookieStore.put('license', license); + }, + + licenseTested: function() { + var result; + if ($rootScope.license_test !== undefined) { + result = $rootScope.license_test; + } + else { + var license = $cookieStore.get('license'); + if (license && license.tested !== undefined) { + result = license.tested; + } + else { + result = false; + } + } + return result; + }, + getUser: function() { return $http({ method: 'GET', diff --git a/awx/ui/static/lib/ansible/rest-services.js b/awx/ui/static/lib/ansible/rest-services.js index 2438c223f6..3fa0bb91cd 100644 --- a/awx/ui/static/lib/ansible/rest-services.js +++ b/awx/ui/static/lib/ansible/rest-services.js @@ -16,7 +16,7 @@ angular.module('RestServices',['ngCookies','AuthService']) pReplace: function() { //in our url, replace :xx params with a value, assuming - // we can find it in user supplied params. + //we can find it in user supplied params. var key,rgx; for (key in this.params) { rgx = new RegExp("\\:" + key,'gm'); diff --git a/awx/ui/static/lib/ansible/utilities.js b/awx/ui/static/lib/ansible/utilities.js index c9db467d85..0b6c952042 100644 --- a/awx/ui/static/lib/ansible/utilities.js +++ b/awx/ui/static/lib/ansible/utilities.js @@ -27,13 +27,36 @@ angular.module('Utilities',[]) } }) - .factory('Alert', ['$rootScope', function($rootScope) { - return function(hdr, msg) { + .factory('Alert', ['$rootScope', '$location', function($rootScope, $location) { + return function(hdr, msg, cls, action, secondAlert, disableButtons) { // Pass in the header and message you want displayed on TB modal dialog found in index.html. - // Assumes an id of 'alert-modal' - $rootScope.alertHeader = hdr; - $rootScope.alertBody = msg; - $('#alert-modal').modal({ show: true, keyboard: true, backdrop: 'static' }); + // Assumes an #id of 'alert-modal'. Pass in an optional TB alert class (i.e. alert-error, alert-success, + // alert-info...). Pass an optional function(){}, if you want a specific action to occur when user + // clicks 'OK' button. Set secondAlert to true, when a second dialog is needed. + if (secondAlert) { + $rootScope.alertHeader2 = hdr; + $rootScope.alertBody2 = msg; + $rootScope.alertClass2 = (cls) ? cls : 'alert-error'; //default alert class is alert-error + $('#alert-modal2').modal({ show: true, keyboard: true , backdrop: 'static' }); + $rootScope.disableButtons2 = (disableButtons) ? true : false; + if (action) { + $('#alert-modal2').on('hidden', function() { + action(); + }); + } + } + else { + $rootScope.alertHeader = hdr; + $rootScope.alertBody = msg; + $rootScope.alertClass = (cls) ? cls : 'alert-error'; //default alert class is alert-error + $('#alert-modal').modal({ show: true, keyboard: true , backdrop: 'static' }); + $rootScope.disableButtons = (disableButtons) ? true : false; + if (action) { + $('#alert-modal').on('hidden', function() { + action(); + }); + } + } } }]) diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html index 4aac6ac39e..cc6da81654 100644 --- a/awx/ui/templates/ui/index.html +++ b/awx/ui/templates/ui/index.html @@ -14,6 +14,7 @@ + {% if settings.USE_MINIFIED_JS %} {# FIXME: Change to use minified JS once we are building it. #} {% else %} @@ -189,18 +190,31 @@ - + +