AMBARI-13512. Show a warning popup before user is about to be logged out (rzang)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ac51d8b6 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ac51d8b6 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ac51d8b6 Branch: refs/heads/branch-dev-patch-upgrade Commit: ac51d8b6cee62aee30b940d38da10f0f266ba7a5 Parents: 8ef5beb Author: Richard Zang <rz...@apache.org> Authored: Wed Oct 21 15:30:30 2015 -0700 Committer: Richard Zang <rz...@apache.org> Committed: Wed Oct 21 15:31:21 2015 -0700 ---------------------------------------------------------------------- .../app/scripts/controllers/mainCtrl.js | 49 +++++++++++++----- .../ui/admin-web/app/scripts/services/Auth.js | 5 ++ .../app/views/modals/TimeoutWarning.html | 28 +++++++++++ ambari-web/app/config.js | 1 + ambari-web/app/controllers/main.js | 52 ++++++++++++++++---- ambari-web/app/messages.js | 5 ++ 6 files changed, 119 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/ac51d8b6/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/mainCtrl.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/mainCtrl.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/mainCtrl.js index 2c9e1c9..1213d0d 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/mainCtrl.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/controllers/mainCtrl.js @@ -20,12 +20,6 @@ angular.module('ambariAdminConsole') .controller('MainCtrl',['$scope','$rootScope','$window','Auth', 'Alert', '$modal', 'Cluster', 'View', function($scope, $rootScope, $window, Auth, Alert, $modal, Cluster, View) { $scope.signOut = function() { - var data = JSON.parse(localStorage.ambari); - delete data.app.authenticated; - delete data.app.loginName; - delete data.app.user; - localStorage.ambari = JSON.stringify(data); - $scope.hello = "hello"; Auth.signout().finally(function() { $window.location.pathname = ''; }); @@ -93,7 +87,6 @@ angular.module('ambariAdminConsole') var lastActiveTime = Date.now(); var keepActive = function() { - //console.error('keepActive'); if (active) { lastActiveTime = Date.now(); } @@ -104,15 +97,46 @@ angular.module('ambariAdminConsole') $(window).bind('click', keepActive); var checkActiveness = function() { - //console.error("checkActiveness " + lastActiveTime + " : " + Date.now()); - if (Date.now() - lastActiveTime > TIME_OUT) { - //console.error("LOGOUT!"); + var remainTime = TIME_OUT - (Date.now() - lastActiveTime); + if (remainTime < 0) { active = false; $(window).unbind('mousemove', keepActive); $(window).unbind('keypress', keepActive); $(window).unbind('click', keepActive); clearInterval($rootScope.userActivityTimeoutInterval); $scope.signOut(); + } else if (remainTime < 60000 && !$rootScope.timeoutModal) { + $rootScope.timeoutModal = $modal.open({ + templateUrl: 'views/modals/TimeoutWarning.html', + backdrop: false, + controller: ['$scope', 'Auth', function($scope, Auth) { + $scope.remainTime = 60; + $scope.title = 'Automatic Logout'; + $scope.primaryText = 'Remain Logged In'; + $scope.secondaryText = 'Log Out Now'; + $scope.remain = function() { + $rootScope.timeoutModal.close(); + delete $rootScope.timeoutModal; + }; + $scope.logout = function() { + $rootScope.timeoutModal.close(); + delete $rootScope.timeoutModal; + Auth.signout().finally(function() { + $window.location.pathname = ''; + }); + }; + $scope.countDown = function() { + $scope.remainTime--; + $scope.$apply(); + if ($scope.remainTime == 0) { + Auth.signout().finally(function() { + $window.location.pathname = ''; + }); + } + }; + setInterval($scope.countDown, 1000); + }] + }); } }; $rootScope.userActivityTimeoutInterval = window.setInterval(checkActiveness, 1000); @@ -125,8 +149,9 @@ angular.module('ambariAdminConsole') if (!$rootScope.userActivityTimeoutInterval) { Cluster.getAmbariTimeout().then(function(timeout) { - if (Number(timeout) > 0) - $scope.startInactiveTimeoutMonitoring(timeout * 1000); + $rootScope.userTimeout = Number(timeout) * 1000; + if ($rootScope.userTimeout > 0) + $scope.startInactiveTimeoutMonitoring($rootScope.userTimeout); }); } if (!$rootScope.noopPollingInterval) { http://git-wip-us.apache.org/repos/asf/ambari/blob/ac51d8b6/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Auth.js ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Auth.js b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Auth.js index a73c540..14c04c1 100644 --- a/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Auth.js +++ b/ambari-admin/src/main/resources/ui/admin-web/app/scripts/services/Auth.js @@ -29,6 +29,11 @@ angular.module('ambariAdminConsole') } return { signout: function() { + var data = JSON.parse(localStorage.ambari); + delete data.app.authenticated; + delete data.app.loginName; + delete data.app.user; + localStorage.ambari = JSON.stringify(data); // Workaround for sign off within Basic Authorization var origin = $window.location.protocol + '//' + Date.now() + ':' + Date.now() + '@' + $window.location.hostname + ($window.location.port ? ':' + $window.location.port : ''); http://git-wip-us.apache.org/repos/asf/ambari/blob/ac51d8b6/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/TimeoutWarning.html ---------------------------------------------------------------------- diff --git a/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/TimeoutWarning.html b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/TimeoutWarning.html new file mode 100644 index 0000000..ad5c3a0 --- /dev/null +++ b/ambari-admin/src/main/resources/ui/admin-web/app/views/modals/TimeoutWarning.html @@ -0,0 +1,28 @@ +<!-- +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +--> + +<div class="modal-header"> + <h4 class="modal-title">{{title}}</h4> +</div> +<div class="modal-body"> + You will be automatically logged out in <b>{{remainTime}}</b> seconds due to inactivity. +</div> +<div class="modal-footer"> + <button class="btn btn-default" ng-click="logout()">{{secondaryText}}</button> + <button class="btn btn-primary" ng-click="remain()">{{primaryText}}</button> +</div> http://git-wip-us.apache.org/repos/asf/ambari/blob/ac51d8b6/ambari-web/app/config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/config.js b/ambari-web/app/config.js index 26f0553..2ab8544 100644 --- a/ambari-web/app/config.js +++ b/ambari-web/app/config.js @@ -56,6 +56,7 @@ App.isStormMetricsSupported = true; App.healthStatusRed = '#ff0000'; App.healthStatusGreen = '#5AB400'; App.healthStatusOrange = '#FF8E00'; +App.inactivityRemainTime = 60; // in seconds App.stackVersionsAvailable = true; http://git-wip-us.apache.org/repos/asf/ambari/blob/ac51d8b6/ambari-web/app/controllers/main.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main.js b/ambari-web/app/controllers/main.js index fb73770..0f6e33a 100644 --- a/ambari-web/app/controllers/main.js +++ b/ambari-web/app/controllers/main.js @@ -25,6 +25,7 @@ App.MainController = Em.Controller.extend({ checkActivenessInterval: null, lastUserActiveTime: null, userTimeOut: 0, + userTimeOutModal: null, updateTitle: function(){ var name = App.router.get('clusterController.clusterName'); @@ -191,7 +192,6 @@ App.MainController = Em.Controller.extend({ }, monitorInactivity: function() { - //console.error('======MONITOR==START========'); var timeout = Number(App.router.get('clusterController.ambariProperties')['user.inactivity.timeout.default']); var readonly_timeout = Number(App.router.get('clusterController.ambariProperties')['user.inactivity.timeout.role.readonly.default']); var isAdmin = App.get('isAdmin'); @@ -218,7 +218,6 @@ App.MainController = Em.Controller.extend({ /* this will be triggerred by user driven events: 'mousemove', 'keypress' and 'click' */ keepActive: function() { var scope = App.router.get('mainController'); - //console.error('keepActive'); if (scope.get('isUserActive')) { scope.set('lastUserActiveTime', Date.now()); } @@ -226,13 +225,48 @@ App.MainController = Em.Controller.extend({ checkActiveness: function() { var scope = App.router.get('mainController'); - //console.error("checkActiveness " + scope.get('lastUserActiveTime') + " : " + Date.now()); - if (Date.now() - scope.get('lastUserActiveTime') > scope.get('userTimeOut') && !scope.isOnWizard()) { - scope.set('isUserActive', false); - //console.error("LOGOUT!"); - scope.unbindActivityEventMonitors(); - clearInterval(scope.get('checkActivenessInterval')); - App.router.logOff({}); + if (!scope.isOnWizard()) { + var remainTime = scope.get('userTimeOut') - (Date.now() - scope.get('lastUserActiveTime')); + if (remainTime < 0) { + scope.set('isUserActive', false); + scope.unbindActivityEventMonitors(); + clearInterval(scope.get('checkActivenessInterval')); + App.router.logOff({}); + } else if (remainTime < App.inactivityRemainTime * 1000 && !scope.userTimeOutModal) { + // show alert 60 seconds before logging user out + scope.userTimeOutModal = App.ModalPopup.show({ + primary: Em.I18n.t('common.timeout.warning.popup.primary'), + secondary: Em.I18n.t('common.timeout.warning.popup.secondary'), + third: false, + header: Em.I18n.t('common.timeout.warning.popup.header'), + showCloseButton: false, + bodyClass: Ember.View.extend({ + template: Ember.Handlebars.compile('<p>{{view.beforeMsg}}<b>{{view.remainTime}}</b>{{view.afterMsg}}</p>'), + beforeMsg: Em.I18n.t('common.timeout.warning.popup.body.before'), + afterMsg: Em.I18n.t('common.timeout.warning.popup.body.after'), + remainTime: App.inactivityRemainTime, + didInsertElement: function() { + var self = this; + setInterval(function(){self.countDown();}, 1000) + }, + countDown: function() { + this.set('remainTime', this.get('remainTime') - 1); + if (this.get('remainTime') == 0) { + App.router.logOff({}); + } + } + }), + onPrimary: function() { + scope.userTimeOutModal.hide(); + delete scope.userTimeOutModal; + }, + onSecondary: function() { + scope.userTimeOutModal.hide(); + delete scope.userTimeOutModal; + App.router.logOff({}); + } + }); + } } }, http://git-wip-us.apache.org/repos/asf/ambari/blob/ac51d8b6/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index 1c19b7d..8ee266c 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -284,6 +284,11 @@ Em.I18n.translations = { 'common.loading.eclipses': 'Loading...', 'common.running': 'Running', 'common.stopped': 'Stopped', + 'common.timeout.warning.popup.header': 'Automatic Logout', + 'common.timeout.warning.popup.body.before': 'You will be automatically logged out in ', + 'common.timeout.warning.popup.body.after': ' seconds due to inactivity', + 'common.timeout.warning.popup.primary': 'Remain Logged In', + 'common.timeout.warning.popup.secondary': 'Log Out Now', 'models.alert_instance.tiggered.verbose': "Occurred on {0} <br> Checked on {1}", 'models.alert_definition.triggered.verbose': "Occurred on {0}",