Merge pull request #478 from jaredevantabor/session-fixes

Properly handle idle/expired session across tabs
This commit is contained in:
jaredevantabor
2015-10-16 20:27:48 -07:00
4 changed files with 73 additions and 74 deletions

View File

@@ -1022,7 +1022,7 @@ var tower = angular.module('Tower', [
// If browser refresh, set the user_is_superuser value // If browser refresh, set the user_is_superuser value
$rootScope.user_is_superuser = Authorization.getUserInfo('is_superuser'); $rootScope.user_is_superuser = Authorization.getUserInfo('is_superuser');
// when the user refreshes we want to open the socket, except if the user is on the login page, which should happen after the user logs in (see the AuthService module for that call to OpenSocket) // when the user refreshes we want to open the socket, except if the user is on the login page, which should happen after the user logs in (see the AuthService module for that call to OpenSocket)
if($location.$$url !== '/login'){ if(!_.contains($location.$$url, '/login')){
$rootScope.sessionTimer = Timer.init(); $rootScope.sessionTimer = Timer.init();
$rootScope.$emit('OpenSocket'); $rootScope.$emit('OpenSocket');
pendoService.issuePendoIdentity(); pendoService.issuePendoIdentity();

View File

@@ -23,33 +23,35 @@
*/ */
export default export default
['$rootScope', '$cookieStore', 'transitionTo', 'CreateDialog', 'Authorization', ['$rootScope', '$cookieStore', 'transitionTo', 'CreateDialog', 'Authorization',
'Store', 'Store', '$interval',
function ($rootScope, $cookieStore, transitionTo, CreateDialog, Authorization, function ($rootScope, $cookieStore, transitionTo, CreateDialog, Authorization,
Store) { Store, $interval) {
return { return {
sessionTime: null, sessionTime: null,
timeout: null, timeout: null,
getSessionTime: function () { getSessionTime: function () {
// var sessionTime; if(Store('sessionTime_'+$rootScope.current_user.id)){
// if(this.sessionTime){ return Store('sessionTime_'+$rootScope.current_user.id);
// return this.sessionTime; }
// } else {
// else { return 0;
// sessionTime = Store('sessionTime').time; }
// return sessionTime;
// }
return (this.sessionTime) ? this.sessionTime : Store('sessionTime');//$cookieStore.get('sessionTime');
}, },
isExpired: function () { isExpired: function (increase) {
var stime = this.getSessionTime(), var stime = this.getSessionTime(),
now = new Date().getTime(); now = new Date().getTime();
if ((stime - now) <= 0) { if ((stime - now) <= 0) {
//expired //expired
return true; return true;
} else { }
else if(increase){
return false;
}
else{
// not expired. move timer forward. // not expired. move timer forward.
this.moveForward(); this.moveForward();
return false; return false;
@@ -62,7 +64,7 @@ export default
diff = stime-now; diff = stime-now;
if(diff < 61){ if(diff < 61){
return true; return diff;
} }
else { else {
return false; return false;
@@ -88,75 +90,72 @@ export default
var tm, t; var tm, t;
tm = ($AnsibleConfig.session_timeout) ? $AnsibleConfig.session_timeout : 1800; tm = ($AnsibleConfig.session_timeout) ? $AnsibleConfig.session_timeout : 1800;
t = new Date().getTime() + (tm * 1000); t = new Date().getTime() + (tm * 1000);
this.sessionTime = t; Store('sessionTime_'+$rootScope.current_user.id, t);
// $cookieStore.put('sessionTime', t);
Store('sessionTime', t);
$rootScope.sessionExpired = false; $rootScope.sessionExpired = false;
$cookieStore.put('sessionExpired', false); $cookieStore.put('sessionExpired', false);
this.startTimers(); this.startTimers();
}, },
startTimers: function() { startTimers: function(){
var that = this, var that = this;
tm = ($AnsibleConfig.session_timeout) ? $AnsibleConfig.session_timeout : 1800,
t = tm - 60;
this.clearTimers(); this.clearTimers();
$rootScope.expireTimer = $interval(function() {
// make a timeout that will go off in 30 mins to log them out var idle = that.isIdle();
// unless they extend their time if(idle !== false){
$rootScope.endTimer = setTimeout(function(){ if($('#idle-modal').is(':visible')){
that.expireSession('idle'); $('#remaining_seconds').html(Math.round(idle));
}, tm * 1000);
// notify the user a minute before the end of their session that
// their session is about to expire
if($rootScope.idleTimer){
clearTimeout($rootScope.idleTimer);
}
$rootScope.idleTimer = setTimeout(function() {
if(that.isIdle() === true){
var buttons = [{
"label": "Continue",
"onClick": function() {
// make a rest call here to force the API to
// move the session time forward
Authorization.getUser();
that.moveForward();
$(this).dialog('close');
},
"class": "btn btn-primary",
"id": "idle-modal-button"
}];
if ($rootScope.removeIdleDialogReady) {
$rootScope.removeIdleDialogReady();
} }
$rootScope.removeIdleDialogReady = $rootScope.$on('IdleDialogReady', function() { else {
$('#idle-modal').show(); var buttons = [{
$('#idle-modal').dialog('open'); "label": "Continue",
}); "onClick": function() {
CreateDialog({ // make a rest call here to force the API to
id: 'idle-modal' , // move the session time forward
title: "Idle Session", Authorization.getUser();
scope: $rootScope, that.moveForward();
buttons: buttons, $(this).dialog('close');
width: 470, },
height: 240, "class": "btn btn-primary",
minWidth: 200, "id": "idle-modal-button"
callback: 'IdleDialogReady' }];
});
}
}, t * 1000);
if ($rootScope.removeIdleDialogReady) {
$rootScope.removeIdleDialogReady();
}
$rootScope.removeIdleDialogReady = $rootScope.$on('IdleDialogReady', function() {
$('#idle-modal').show();
$('#idle-modal').dialog('open');
});
CreateDialog({
id: 'idle-modal' ,
title: "Idle Session",
scope: $rootScope,
buttons: buttons,
width: 470,
height: 240,
minWidth: 200,
callback: 'IdleDialogReady'
});
}
}
else if(!idle){
if($('#idle-modal').is(':visible')){
$('#idle-modal').dialog('close');
}
}
if (that.isExpired(true)) {
if($('#idle-modal').dialog('isOpen')){
$('#idle-modal').dialog('close');
}
that.expireSession('idle');
}
}, 1000);
}, },
clearTimers: function(){ clearTimers: function(){
clearTimeout($rootScope.idleTimer); $interval.cancel($rootScope.expireTimer);
clearTimeout($rootScope.endTimer);
}, },
init: function () { init: function () {

View File

@@ -165,6 +165,7 @@ export default ['$log', '$cookieStore', '$compile', '$window', '$rootScope', '$l
Authorization.getUser() Authorization.getUser()
.success(function (data) { .success(function (data) {
Authorization.setUserInfo(data); Authorization.setUserInfo(data);
$rootScope.sessionTimer = Timer.init();
$rootScope.user_is_superuser = data.results[0].is_superuser; $rootScope.user_is_superuser = data.results[0].is_superuser;
scope.$emit('AuthorizationGetLicense'); scope.$emit('AuthorizationGetLicense');
}) })
@@ -187,7 +188,6 @@ export default ['$log', '$cookieStore', '$compile', '$window', '$rootScope', '$l
.then(function (data) { .then(function (data) {
$('#login-modal').modal('hide'); $('#login-modal').modal('hide');
Authorization.setToken(data.data.token, data.data.expires); Authorization.setToken(data.data.token, data.data.expires);
$rootScope.sessionTimer = Timer.init();
scope.$emit('AuthorizationGetUser'); scope.$emit('AuthorizationGetUser');
}, },
function (data) { function (data) {

View File

@@ -58,7 +58,7 @@
<!-- Password Dialog --> <!-- Password Dialog -->
<div id="password-modal" style="display: none;"></div> <div id="password-modal" style="display: none;"></div>
<div id="idle-modal" style="display:none">Your session will expire in 1 minute, would you like to continue?</div> <div id="idle-modal" style="display:none">Your session will expire in <span id="remaining_seconds"></span> seconds, would you like to continue?</div>
<!-- Generic Form dialog --> <!-- Generic Form dialog -->
<div id="form-modal" class="modal fade"> <div id="form-modal" class="modal fade">