This is an automated email from the ASF dual-hosted git repository. pinal pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/atlas.git
commit b2e164443d90b4a8a24b176eeeb1172b7e3faf54 Author: prasad pawar <prasad.pa...@freestoneinfotech.com> AuthorDate: Thu Aug 26 18:59:12 2021 +0530 ATLAS-4378: UI - Implement session timeout on Atlas UI. --- dashboardv2/public/css/scss/override.scss | 6 + .../js/external_lib/idealTimeout/store.min.js | 2 + dashboardv2/public/js/main.js | 27 +- dashboardv2/public/js/utils/Globals.js | 1 + dashboardv2/public/js/utils/Utils.js | 271 ++++++++++++++++++++- dashboardv3/public/css/scss/override.scss | 6 + .../js/external_lib/idealTimeout/store.min.js | 2 + dashboardv3/public/js/main.js | 27 +- dashboardv3/public/js/utils/Globals.js | 1 + dashboardv3/public/js/utils/Utils.js | 267 +++++++++++++++++++- 10 files changed, 604 insertions(+), 6 deletions(-) diff --git a/dashboardv2/public/css/scss/override.scss b/dashboardv2/public/css/scss/override.scss index c24b0c6..549ae3b 100644 --- a/dashboardv2/public/css/scss/override.scss +++ b/dashboardv2/public/css/scss/override.scss @@ -575,4 +575,10 @@ div.columnmanager-dropdown-container { ul { list-style: disc; } +} + +.ideal-timeout { + .modal-content { + border-radius: 0px !important; + } } \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/idealTimeout/store.min.js b/dashboardv2/public/js/external_lib/idealTimeout/store.min.js new file mode 100644 index 0000000..7334a7e --- /dev/null +++ b/dashboardv2/public/js/external_lib/idealTimeout/store.min.js @@ -0,0 +1,2 @@ +/* Copyright (c) 2010-2013 Marcus Westin */ +"use strict";(function(e,t){typeof define=="function"&&define.amd?define([],t):typeof exports=="object"?module.exports=t():e.store=t()})(this,function(){function o(){try{return r in t&&t[r]}catch(e){return!1}}var e={},t=window,n=t.document,r="localStorage",i="script",s;e.disabled=!1,e.version="1.3.17",e.set=function(e,t){},e.get=function(e,t){},e.has=function(t){return e.get(t)!==undefined},e.remove=function(e){},e.clear=function(){},e.transact=function(t,n,r){r==null&&(r=n,n=null),n==nu [...] \ No newline at end of file diff --git a/dashboardv2/public/js/main.js b/dashboardv2/public/js/main.js index 7c8bbb4..f2ea1d8 100644 --- a/dashboardv2/public/js/main.js +++ b/dashboardv2/public/js/main.js @@ -178,7 +178,8 @@ require.config({ 'jstree': 'libs/jstree/jstree.min', 'jquery-steps': 'libs/jquery-steps/jquery.steps.min', 'dropzone': 'libs/dropzone/js/dropzone-amd-module', - 'lossless-json': 'libs/lossless-json/lossless-json' + 'lossless-json': 'libs/lossless-json/lossless-json', + 'store': 'external_lib/idealTimeout/store.min' }, /** @@ -199,11 +200,12 @@ require(['App', 'collection/VEntityList', 'collection/VTagList', 'utils/Enums', + 'utils/Utils', 'utils/Overrides', 'bootstrap', 'd3', 'select2' -], function(App, Router, Helper, CommonViewFunction, Globals, UrlLinks, VEntityList, VTagList, Enums) { +], function(App, Router, Helper, CommonViewFunction, Globals, UrlLinks, VEntityList, VTagList, Enums, Utils) { var that = this; this.asyncFetchCounter = 5 + (Enums.addOnEntities.length + 1); // entity @@ -286,6 +288,27 @@ require(['App', if (response['atlas.tasks.enabled'] !== undefined) { Globals.isTasksEnabled = response['atlas.tasks.enabled']; } + if (response['atlas.session.timeout.secs']) { Globals.idealTimeoutSeconds = response['atlas.session.timeout.secs']; } + /* Atlas idealTimeout + redirectUrl: url to redirect after timeout + idealTimeLimit: timeout in seconds + activityEvents: ideal keyboard mouse events + dialogDisplayLimit: show popup before timeout in seconds + */ + $(document).ready(function() { + $(document).idleTimeout({ + redirectUrl: Utils.getBaseUrl(window.location.pathname) + '/index.html?action=timeout', // redirect to this url + idleTimeLimit: Globals.idealTimeoutSeconds, // 900 seconds + activityEvents: 'click keypress scroll wheel mousemove', // separate each event with a space + dialogDisplayLimit: 10, // Time to display the warning dialog before logout (and optional callback) in seconds + sessionKeepAliveTimer: false, // Set to false to disable pings. + onModalKeepAlive: function() { + CommonViewFunction.userDataFetch({ + url: UrlLinks.sessionApiUrl() + }) + } + }); + }); } --that.asyncFetchCounter; startApp(); diff --git a/dashboardv2/public/js/utils/Globals.js b/dashboardv2/public/js/utils/Globals.js index b0dc5cd..8fe8ebc 100644 --- a/dashboardv2/public/js/utils/Globals.js +++ b/dashboardv2/public/js/utils/Globals.js @@ -49,6 +49,7 @@ define(["require"], function(require) { Globals.isDebugMetricsEnabled = false; Globals.isTasksEnabled = false; + Globals.idealTimeoutSeconds = 900; return Globals; }); \ No newline at end of file diff --git a/dashboardv2/public/js/utils/Utils.js b/dashboardv2/public/js/utils/Utils.js index f426b6c..f2498d8 100644 --- a/dashboardv2/public/js/utils/Utils.js +++ b/dashboardv2/public/js/utils/Utils.js @@ -16,7 +16,7 @@ * limitations under the License. */ -define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'moment', 'moment-timezone', 'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, Messages, Enums, moment) { +define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'moment', 'store', 'modules/Modal', 'moment-timezone', 'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, Messages, Enums, moment, store, Modal) { 'use strict'; var Utils = {}; @@ -952,5 +952,274 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', } return dateValue; } + //------------------------------------------------idleTimeout----------------------------- + $.fn.idleTimeout = function(userRuntimeConfig) { + + //############################## + //## Public Configuration Variables + //############################## + var defaultConfig = { + redirectUrl: Utils.getBaseUrl(window.location.pathname) + '/index.html?action=timeout', // redirect to this url on logout. Set to "redirectUrl: false" to disable redirect + + // idle settings + idleTimeLimit: Globals.idealTimeoutSeconds, // 'No activity' time limit in seconds. 1200 = 20 Minutes + idleCheckHeartbeat: 2, // Frequency to check for idle timeouts in seconds + + // optional custom callback to perform before logout + customCallback: false, // set to false for no customCallback + // customCallback: function () { // define optional custom js function + // perform custom action before logout + // }, + + // configure which activity events to detect + // http://www.quirksmode.org/dom/events/ + // https://developer.mozilla.org/en-US/docs/Web/Reference/Events + activityEvents: 'click keypress scroll wheel mousewheel mousemove', // separate each event with a space + + // warning dialog box configuration + enableDialog: true, // set to false for logout without warning dialog + dialogDisplayLimit: 10, // Time to display the warning dialog before logout (and optional callback) in seconds. 180 = 3 Minutes + dialogTitle: 'Your session is about to expire!', // also displays on browser title bar + dialogText: 'Your session is about to expire.', + dialogTimeRemaining: 'You will be logged out in ', + dialogStayLoggedInButton: 'Stay Logged In', + dialogLogOutNowButton: 'Logout', + + // error message if https://github.com/marcuswestin/store.js not enabled + errorAlertMessage: 'Please disable "Private Mode", or upgrade to a modern browser. Or perhaps a dependent file missing. Please see: https://github.com/marcuswestin/store.js', + + // server-side session keep-alive timer + sessionKeepAliveTimer: 600, // ping the server at this interval in seconds. 600 = 10 Minutes. Set to false to disable pings + sessionKeepAliveUrl: window.location.href // set URL to ping - does not apply if sessionKeepAliveTimer: false + }, + + //############################## + //## Private Variables + //############################## + currentConfig = $.extend(defaultConfig, userRuntimeConfig), // merge default and user runtime configuration + origTitle = document.title, // save original browser title + activityDetector, + startKeepSessionAlive, stopKeepSessionAlive, keepSession, keepAlivePing, // session keep alive + idleTimer, remainingTimer, checkIdleTimeout, checkIdleTimeoutLoop, startIdleTimer, stopIdleTimer, // idle timer + openWarningDialog, dialogTimer, checkDialogTimeout, startDialogTimer, stopDialogTimer, isDialogOpen, destroyWarningDialog, countdownDisplay, // warning dialog + logoutUser; + + //############################## + //## Public Functions + //############################## + // trigger a manual user logout + // use this code snippet on your site's Logout button: $.fn.idleTimeout().logout(); + this.logout = function() { + store.set('idleTimerLoggedOut', true); + }; + + //############################## + //## Private Functions + //############################## + + //----------- KEEP SESSION ALIVE FUNCTIONS --------------// + startKeepSessionAlive = function() { + + keepSession = function() { + $.get(currentConfig.sessionKeepAliveUrl); + startKeepSessionAlive(); + }; + + keepAlivePing = setTimeout(keepSession, (currentConfig.sessionKeepAliveTimer * 1000)); + }; + + stopKeepSessionAlive = function() { + clearTimeout(keepAlivePing); + }; + + //----------- ACTIVITY DETECTION FUNCTION --------------// + activityDetector = function() { + + $('body').on(currentConfig.activityEvents, function() { + + if (!currentConfig.enableDialog || (currentConfig.enableDialog && isDialogOpen() !== true)) { + startIdleTimer(); + $('#activity').effect('shake'); // added for demonstration page + } + }); + }; + + //----------- IDLE TIMER FUNCTIONS --------------// + checkIdleTimeout = function() { + + var timeIdleTimeout = (store.get('idleTimerLastActivity') + (currentConfig.idleTimeLimit * 1000)); + + if ($.now() > timeIdleTimeout) { + + if (!currentConfig.enableDialog) { // warning dialog is disabled + logoutUser(); // immediately log out user when user is idle for idleTimeLimit + } else if (currentConfig.enableDialog && isDialogOpen() !== true) { + openWarningDialog(); + startDialogTimer(); // start timing the warning dialog + } + } else if (store.get('idleTimerLoggedOut') === true) { //a 'manual' user logout? + logoutUser(); + } else { + + if (currentConfig.enableDialog && isDialogOpen() === true) { + destroyWarningDialog(); + stopDialogTimer(); + } + } + }; + + startIdleTimer = function() { + stopIdleTimer(); + store.set('idleTimerLastActivity', $.now()); + checkIdleTimeoutLoop(); + }; + + checkIdleTimeoutLoop = function() { + checkIdleTimeout(); + idleTimer = setTimeout(checkIdleTimeoutLoop, (currentConfig.idleCheckHeartbeat * 1000)); + }; + + stopIdleTimer = function() { + clearTimeout(idleTimer); + }; + + //----------- WARNING DIALOG FUNCTIONS --------------// + openWarningDialog = function() { + + + var dialogContent = "<div id='idletimer_warning_dialog'><p>" + currentConfig.dialogText + "</p><p style='display:inline'>" + currentConfig.dialogTimeRemaining + ": <div style='display:inline' id='countdownDisplay'></div> secs.</p></div>"; + + var that = this, + modalObj = { + title: currentConfig.dialogTitle, + htmlContent: dialogContent, + okText: "Stay Signed-in", + cancelText: 'Logout', + mainClass: 'modal-lg', + allowCancel: true, + okCloses: false, + escape: false, + cancellable: true, + width: "500px", + mainClass: "ideal-timeout" + }; + var modal = new Modal(modalObj); + modal.open(); + modal.on('ok', function() { + if (userRuntimeConfig && userRuntimeConfig.onModalKeepAlive) { + userRuntimeConfig.onModalKeepAlive(); //hit session API + } + destroyWarningDialog(); + modal.close(); + stopDialogTimer(); + startIdleTimer(); + CommonViewFunction.userDataFetch({ + url: UrlLinks.sessionApiUrl() + }) + + }); + modal.on('closeModal', function() { + logoutUser(); + }); + + countdownDisplay(); + + // document.title = currentConfig.dialogTitle; + + if (currentConfig.sessionKeepAliveTimer) { + stopKeepSessionAlive(); + } + }; + + checkDialogTimeout = function() { + var timeDialogTimeout = (store.get('idleTimerLastActivity') + (currentConfig.idleTimeLimit * 1000) + (currentConfig.dialogDisplayLimit * 1000)); + + if (($.now() > timeDialogTimeout) || (store.get('idleTimerLoggedOut') === true)) { + logoutUser(); + } + }; + + startDialogTimer = function() { + dialogTimer = setInterval(checkDialogTimeout, (currentConfig.idleCheckHeartbeat * 1000)); + }; + + stopDialogTimer = function() { + clearInterval(dialogTimer); + clearInterval(remainingTimer); + }; + + isDialogOpen = function() { + var dialogOpen = $("#idletimer_warning_dialog").is(":visible"); + + if (dialogOpen === true) { + return true; + } + return false; + }; + + destroyWarningDialog = function() { + if (currentConfig.sessionKeepAliveTimer) { + startKeepSessionAlive(); + } + }; + + countdownDisplay = function() { + var dialogDisplaySeconds = currentConfig.dialogDisplayLimit, + mins, secs; + + remainingTimer = setInterval(function() { + mins = Math.floor(dialogDisplaySeconds / 60); // minutes + if (mins < 10) { mins = '0' + mins; } + secs = dialogDisplaySeconds - (mins * 60); // seconds + if (secs < 10) { secs = '0' + secs; } + $('#countdownDisplay').html(mins + ':' + secs); + dialogDisplaySeconds -= 1; + }, 1000); + }; + + //----------- LOGOUT USER FUNCTION --------------// + logoutUser = function() { + store.set('idleTimerLoggedOut', true); + + if (currentConfig.sessionKeepAliveTimer) { + stopKeepSessionAlive(); + } + + if (currentConfig.customCallback) { + currentConfig.customCallback(); + } + + if (currentConfig.redirectUrl) { + window.location.href = currentConfig.redirectUrl; + } + }; + + //############################### + // Build & Return the instance of the item as a plugin + // This is your construct. + //############################### + return this.each(function() { + + if (store.enabled) { + + store.set('idleTimerLastActivity', $.now()); + store.set('idleTimerLoggedOut', false); + + activityDetector(); + + if (currentConfig.sessionKeepAliveTimer) { + startKeepSessionAlive(); + } + + startIdleTimer(); + + } else { + alert(currentConfig.errorAlertMessage); + } + + }); + }; + + //------------------------------------------------ return Utils; }); \ No newline at end of file diff --git a/dashboardv3/public/css/scss/override.scss b/dashboardv3/public/css/scss/override.scss index c1841eb..2c3ea78 100644 --- a/dashboardv3/public/css/scss/override.scss +++ b/dashboardv3/public/css/scss/override.scss @@ -577,4 +577,10 @@ div.columnmanager-dropdown-container { ul { list-style: disc; } +} + +.ideal-timeout { + .modal-content { + border-radius: 0px !important; + } } \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/idealTimeout/store.min.js b/dashboardv3/public/js/external_lib/idealTimeout/store.min.js new file mode 100644 index 0000000..7334a7e --- /dev/null +++ b/dashboardv3/public/js/external_lib/idealTimeout/store.min.js @@ -0,0 +1,2 @@ +/* Copyright (c) 2010-2013 Marcus Westin */ +"use strict";(function(e,t){typeof define=="function"&&define.amd?define([],t):typeof exports=="object"?module.exports=t():e.store=t()})(this,function(){function o(){try{return r in t&&t[r]}catch(e){return!1}}var e={},t=window,n=t.document,r="localStorage",i="script",s;e.disabled=!1,e.version="1.3.17",e.set=function(e,t){},e.get=function(e,t){},e.has=function(t){return e.get(t)!==undefined},e.remove=function(e){},e.clear=function(){},e.transact=function(t,n,r){r==null&&(r=n,n=null),n==nu [...] \ No newline at end of file diff --git a/dashboardv3/public/js/main.js b/dashboardv3/public/js/main.js index 374641e..97e177c 100644 --- a/dashboardv3/public/js/main.js +++ b/dashboardv3/public/js/main.js @@ -207,7 +207,8 @@ require.config({ 'jstree': 'libs/jstree/jstree.min', 'jquery-steps': 'libs/jquery-steps/jquery.steps.min', 'dropzone': 'libs/dropzone/js/dropzone-amd-module', - 'lossless-json': 'libs/lossless-json/lossless-json' + 'lossless-json': 'libs/lossless-json/lossless-json', + 'store': 'external_lib/idealTimeout/store.min' }, /** @@ -228,11 +229,12 @@ require(['App', 'collection/VEntityList', 'collection/VTagList', 'utils/Enums', + 'utils/Utils', 'utils/Overrides', 'bootstrap', 'd3', 'select2' -], function(App, Router, Helper, CommonViewFunction, Globals, UrlLinks, VEntityList, VTagList, Enums) { +], function(App, Router, Helper, CommonViewFunction, Globals, UrlLinks, VEntityList, VTagList, Enums, Utils) { var that = this; this.asyncFetchCounter = 5 + (Enums.addOnEntities.length + 1); // entity @@ -315,6 +317,27 @@ require(['App', if (response['atlas.tasks.enabled'] !== undefined) { Globals.isTasksEnabled = response['atlas.tasks.enabled']; } + if (response['atlas.session.timeout.secs']) { Globals.idealTimeoutSeconds = response['atlas.session.timeout.secs']; } + /* Atlas idealTimeout + redirectUrl: url to redirect after timeout + idealTimeLimit: timeout in seconds + activityEvents: ideal keyboard mouse events + dialogDisplayLimit: show popup before timeout in seconds + */ + $(document).ready(function() { + $(document).idleTimeout({ + redirectUrl: Utils.getBaseUrl(window.location.pathname) + '/index.html?action=timeout', // redirect to this url + idleTimeLimit: Globals.idealTimeoutSeconds, // 900 seconds + activityEvents: 'click keypress scroll wheel mousemove', // separate each event with a space + dialogDisplayLimit: 10, // Time to display the warning dialog before logout (and optional callback) in seconds + sessionKeepAliveTimer: false, // Set to false to disable pings. + onModalKeepAlive: function() { + CommonViewFunction.userDataFetch({ + url: UrlLinks.sessionApiUrl() + }) + } + }); + }); } --that.asyncFetchCounter; startApp(); diff --git a/dashboardv3/public/js/utils/Globals.js b/dashboardv3/public/js/utils/Globals.js index b0dc5cd..8fe8ebc 100644 --- a/dashboardv3/public/js/utils/Globals.js +++ b/dashboardv3/public/js/utils/Globals.js @@ -49,6 +49,7 @@ define(["require"], function(require) { Globals.isDebugMetricsEnabled = false; Globals.isTasksEnabled = false; + Globals.idealTimeoutSeconds = 900; return Globals; }); \ No newline at end of file diff --git a/dashboardv3/public/js/utils/Utils.js b/dashboardv3/public/js/utils/Utils.js index 1a73b7c..c3122fc 100644 --- a/dashboardv3/public/js/utils/Utils.js +++ b/dashboardv3/public/js/utils/Utils.js @@ -16,7 +16,7 @@ * limitations under the License. */ -define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'moment', 'moment-timezone', 'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, Messages, Enums, moment) { +define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'moment', 'store', 'modules/Modal', 'moment-timezone', 'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, Messages, Enums, moment, store, Modal) { 'use strict'; var Utils = {}; @@ -964,5 +964,270 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', } return dateValue; } + //------------------------------------------------idleTimeout----------------------------- + $.fn.idleTimeout = function(userRuntimeConfig) { + + //############################## + //## Public Configuration Variables + //############################## + var defaultConfig = { + redirectUrl: Utils.getBaseUrl(window.location.pathname) + '/index.html?action=timeout', // redirect to this url on logout. Set to "redirectUrl: false" to disable redirect + + // idle settings + idleTimeLimit: Globals.idealTimeoutSeconds, // 'No activity' time limit in seconds. 1200 = 20 Minutes + idleCheckHeartbeat: 2, // Frequency to check for idle timeouts in seconds + + // optional custom callback to perform before logout + customCallback: false, // set to false for no customCallback + // customCallback: function () { // define optional custom js function + // perform custom action before logout + // }, + + // configure which activity events to detect + // http://www.quirksmode.org/dom/events/ + // https://developer.mozilla.org/en-US/docs/Web/Reference/Events + activityEvents: 'click keypress scroll wheel mousewheel mousemove', // separate each event with a space + + // warning dialog box configuration + enableDialog: true, // set to false for logout without warning dialog + dialogDisplayLimit: 10, // Time to display the warning dialog before logout (and optional callback) in seconds. 180 = 3 Minutes + dialogTitle: 'Your session is about to expire!', // also displays on browser title bar + dialogText: 'Your session is about to expire.', + dialogTimeRemaining: 'You will be logged out in ', + dialogStayLoggedInButton: 'Stay Logged In', + dialogLogOutNowButton: 'Logout', + + // error message if https://github.com/marcuswestin/store.js not enabled + errorAlertMessage: 'Please disable "Private Mode", or upgrade to a modern browser. Or perhaps a dependent file missing. Please see: https://github.com/marcuswestin/store.js', + + // server-side session keep-alive timer + sessionKeepAliveTimer: 600, // ping the server at this interval in seconds. 600 = 10 Minutes. Set to false to disable pings + sessionKeepAliveUrl: window.location.href // set URL to ping - does not apply if sessionKeepAliveTimer: false + }, + + //############################## + //## Private Variables + //############################## + currentConfig = $.extend(defaultConfig, userRuntimeConfig), // merge default and user runtime configuration + origTitle = document.title, // save original browser title + activityDetector, + startKeepSessionAlive, stopKeepSessionAlive, keepSession, keepAlivePing, // session keep alive + idleTimer, remainingTimer, checkIdleTimeout, checkIdleTimeoutLoop, startIdleTimer, stopIdleTimer, // idle timer + openWarningDialog, dialogTimer, checkDialogTimeout, startDialogTimer, stopDialogTimer, isDialogOpen, destroyWarningDialog, countdownDisplay, // warning dialog + logoutUser; + + //############################## + //## Public Functions + //############################## + // trigger a manual user logout + // use this code snippet on your site's Logout button: $.fn.idleTimeout().logout(); + this.logout = function() { + store.set('idleTimerLoggedOut', true); + }; + + //############################## + //## Private Functions + //############################## + + //----------- KEEP SESSION ALIVE FUNCTIONS --------------// + startKeepSessionAlive = function() { + + keepSession = function() { + $.get(currentConfig.sessionKeepAliveUrl); + startKeepSessionAlive(); + }; + + keepAlivePing = setTimeout(keepSession, (currentConfig.sessionKeepAliveTimer * 1000)); + }; + + stopKeepSessionAlive = function() { + clearTimeout(keepAlivePing); + }; + + //----------- ACTIVITY DETECTION FUNCTION --------------// + activityDetector = function() { + + $('body').on(currentConfig.activityEvents, function() { + + if (!currentConfig.enableDialog || (currentConfig.enableDialog && isDialogOpen() !== true)) { + startIdleTimer(); + $('#activity').effect('shake'); // added for demonstration page + } + }); + }; + + //----------- IDLE TIMER FUNCTIONS --------------// + checkIdleTimeout = function() { + + var timeIdleTimeout = (store.get('idleTimerLastActivity') + (currentConfig.idleTimeLimit * 1000)); + + if ($.now() > timeIdleTimeout) { + + if (!currentConfig.enableDialog) { // warning dialog is disabled + logoutUser(); // immediately log out user when user is idle for idleTimeLimit + } else if (currentConfig.enableDialog && isDialogOpen() !== true) { + openWarningDialog(); + startDialogTimer(); // start timing the warning dialog + } + } else if (store.get('idleTimerLoggedOut') === true) { //a 'manual' user logout? + logoutUser(); + } else { + + if (currentConfig.enableDialog && isDialogOpen() === true) { + destroyWarningDialog(); + stopDialogTimer(); + } + } + }; + + startIdleTimer = function() { + stopIdleTimer(); + store.set('idleTimerLastActivity', $.now()); + checkIdleTimeoutLoop(); + }; + + checkIdleTimeoutLoop = function() { + checkIdleTimeout(); + idleTimer = setTimeout(checkIdleTimeoutLoop, (currentConfig.idleCheckHeartbeat * 1000)); + }; + + stopIdleTimer = function() { + clearTimeout(idleTimer); + }; + + //----------- WARNING DIALOG FUNCTIONS --------------// + openWarningDialog = function() { + + + var dialogContent = "<div id='idletimer_warning_dialog'><p>" + currentConfig.dialogText + "</p><p style='display:inline'>" + currentConfig.dialogTimeRemaining + ": <div style='display:inline' id='countdownDisplay'></div> secs.</p></div>"; + + var that = this, + modalObj = { + title: currentConfig.dialogTitle, + htmlContent: dialogContent, + okText: "Stay Signed-in", + cancelText: 'Logout', + mainClass: 'modal-lg', + allowCancel: true, + okCloses: false, + escape: false, + cancellable: true, + width: "500px", + mainClass: "ideal-timeout" + }; + var modal = new Modal(modalObj); + modal.open(); + modal.on('ok', function() { + if (userRuntimeConfig && userRuntimeConfig.onModalKeepAlive) { + userRuntimeConfig.onModalKeepAlive(); //hit session API + } + destroyWarningDialog(); + modal.close(); + stopDialogTimer(); + startIdleTimer(); + }); + modal.on('closeModal', function() { + logoutUser(); + }); + + countdownDisplay(); + + // document.title = currentConfig.dialogTitle; + + if (currentConfig.sessionKeepAliveTimer) { + stopKeepSessionAlive(); + } + }; + + checkDialogTimeout = function() { + var timeDialogTimeout = (store.get('idleTimerLastActivity') + (currentConfig.idleTimeLimit * 1000) + (currentConfig.dialogDisplayLimit * 1000)); + + if (($.now() > timeDialogTimeout) || (store.get('idleTimerLoggedOut') === true)) { + logoutUser(); + } + }; + + startDialogTimer = function() { + dialogTimer = setInterval(checkDialogTimeout, (currentConfig.idleCheckHeartbeat * 1000)); + }; + + stopDialogTimer = function() { + clearInterval(dialogTimer); + clearInterval(remainingTimer); + }; + + isDialogOpen = function() { + var dialogOpen = $("#idletimer_warning_dialog").is(":visible"); + + if (dialogOpen === true) { + return true; + } + return false; + }; + + destroyWarningDialog = function() { + if (currentConfig.sessionKeepAliveTimer) { + startKeepSessionAlive(); + } + }; + + countdownDisplay = function() { + var dialogDisplaySeconds = currentConfig.dialogDisplayLimit, + mins, secs; + + remainingTimer = setInterval(function() { + mins = Math.floor(dialogDisplaySeconds / 60); // minutes + if (mins < 10) { mins = '0' + mins; } + secs = dialogDisplaySeconds - (mins * 60); // seconds + if (secs < 10) { secs = '0' + secs; } + $('#countdownDisplay').html(mins + ':' + secs); + dialogDisplaySeconds -= 1; + }, 1000); + }; + + //----------- LOGOUT USER FUNCTION --------------// + logoutUser = function() { + store.set('idleTimerLoggedOut', true); + + if (currentConfig.sessionKeepAliveTimer) { + stopKeepSessionAlive(); + } + + if (currentConfig.customCallback) { + currentConfig.customCallback(); + } + + if (currentConfig.redirectUrl) { + window.location.href = currentConfig.redirectUrl; + } + }; + + //############################### + // Build & Return the instance of the item as a plugin + // This is your construct. + //############################### + return this.each(function() { + + if (store.enabled) { + + store.set('idleTimerLastActivity', $.now()); + store.set('idleTimerLoggedOut', false); + + activityDetector(); + + if (currentConfig.sessionKeepAliveTimer) { + startKeepSessionAlive(); + } + + startIdleTimer(); + + } else { + alert(currentConfig.errorAlertMessage); + } + + }); + }; + + //------------------------------------------------ return Utils; }); \ No newline at end of file