From e2b711c6dbce4e518a5d8efd9a0e3a89ce3aa347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 17 Nov 2023 14:41:45 +0100 Subject: [PATCH] feature/Add user inactivity log off feature --- src/main/webapp/media/js/inactivity-timer.js | 36 ++++++ src/main/webapp/media/js/inactivity.js | 105 ++++++++++++++++++ src/main/webapp/templates-hidden/default.html | 5 +- 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/main/webapp/media/js/inactivity-timer.js create mode 100644 src/main/webapp/media/js/inactivity.js diff --git a/src/main/webapp/media/js/inactivity-timer.js b/src/main/webapp/media/js/inactivity-timer.js new file mode 100644 index 00000000..93b48826 --- /dev/null +++ b/src/main/webapp/media/js/inactivity-timer.js @@ -0,0 +1,36 @@ +function addSeconds(date, seconds) { + date.setSeconds(date.getSeconds() + seconds); + return date; +} + +export function showCountdownTimer() { + + // Get current date and time + var now = new Date().getTime(); + let distance = countDownDate - now; + + // Output the result in an element with id="countdown-timer-span" + let elementId = ("countdown-timer-span"); + document.getElementById(elementId).innerHTML = "in " + Math.floor(distance / 1000) + "s"; + + // If the count down is over release resources + if (distance < 0) { + destroyCountdownTimer(); + } +} + + +// Set the date we're counting down to +let countDownDate = addSeconds(new Date(), 5); + +let showTimerInterval = null; + +export function destroyCountdownTimer() { + clearInterval(showTimerInterval); +} + +export function resetCountdownTimer(seconds) { + destroyCountdownTimer(); // Destroy previous timer if any + countDownDate = addSeconds(new Date(), seconds); // Set the date we're counting down to + showTimerInterval = setInterval(showCountdownTimer, 1000); // Update the count down every 1 second +} \ No newline at end of file diff --git a/src/main/webapp/media/js/inactivity.js b/src/main/webapp/media/js/inactivity.js new file mode 100644 index 00000000..52249f45 --- /dev/null +++ b/src/main/webapp/media/js/inactivity.js @@ -0,0 +1,105 @@ +import * as countdownTimer from './inactivity-timer.js' + +// holds the idle duration in ms (current value = 301 seconds) +var timeoutIntervalInMillis = 5 * 60 * 1000 + 1000; +// holds the timeout variables for easy destruction and reconstruction of the setTimeout hooks +var timeHook = null; + +function initializeTimeHook() { + // this method has the purpose of creating our timehooks and scheduling the call to our logout function when the idle time has been reached + if (timeHook == null) { + timeHook = setTimeout( function () { destroyTimeHook(); logout(); }.bind(this), timeoutIntervalInMillis); + } +} + +function destroyTimeHook() { + // this method has the sole purpose of destroying any time hooks we might have created + clearTimeout(timeHook); + timeHook = null; +} + +function resetTimeHook(event) { + // this method replaces the current time hook with a new time hook + destroyTimeHook(); + initializeTimeHook(); + countdownTimer.resetCountdownTimer(timeoutIntervalInMillis / 1000); + // show event type, element and coordinates of the click + // console.log(event.type + " at " + event.currentTarget); + // console.log("Coordinates: " + event.clientX + ":" + event.clientY); + console.log("Reset inactivity of a user"); +} + +function setupListeners() { + // here we setup the event listener for the mouse click operation + document.addEventListener("click", resetTimeHook); + document.addEventListener("mousemove", resetTimeHook); + document.addEventListener("mousedown", resetTimeHook); + document.addEventListener("keypress", resetTimeHook); + document.addEventListener("touchmove", resetTimeHook); + console.log("Listeners for user inactivity activated"); +} + +function destroyListeners() { + // here we destroy event listeners for the mouse click operation + document.removeEventListener("click", resetTimeHook); + document.removeEventListener("mousemove", resetTimeHook); + document.removeEventListener("mousedown", resetTimeHook); + document.removeEventListener("keypress", resetTimeHook); + document.removeEventListener("touchmove", resetTimeHook); + console.log("Listeners for user inactivity deactivated"); +} + +function logout() { + destroyListeners(); + countdownTimer.destroyCountdownTimer(); + console.log("Logging you out due to inactivity.."); + const logoffButton = document.getElementById("logout"); + logoffButton.click(); +} + +async function makeObpApiCall() { + let timeoutInSeconds; + try { + let obpApiHost = document.getElementById("api_home_link"); + if(obpApiHost) { + obpApiHost = obpApiHost.href.split("?")[0]; + } + console.log(obpApiHost); + const response = await fetch(`${obpApiHost}/obp/v5.1.0/ui/suggested-session-timeout`); + const json = await response.json(); + if(json.timeout_in_seconds) { + timeoutInSeconds = json.timeout_in_seconds; + console.log(`Suggested value ${timeoutInSeconds} is used`); + } else { + timeoutInSeconds = 5 * 60 + 1; // Set default value to 301 seconds + console.log(`Default value ${timeoutInSeconds} is used`); + } + } catch (e) { + console.error(e); + } + return timeoutInSeconds; +} + +async function getSuggestedSessionTimeout() { + if(!sessionStorage.getItem("suggested-session-timeout-in-seconds")) { + let timeoutInSeconds = await makeObpApiCall(); + sessionStorage.setItem("suggested-session-timeout-in-seconds", timeoutInSeconds); + } + return sessionStorage.getItem("suggested-session-timeout-in-seconds") * 1000 + 1000; // We need timeout in millis +} + +// self executing function to trigger the operation on page load +(async function () { + timeoutIntervalInMillis = await getSuggestedSessionTimeout(); // Try to get suggested value + const logoffButton = document.getElementById("countdown-timer-span"); + if(logoffButton) { + // to prevent any lingering timeout handlers preventing memory leaks + destroyTimeHook(); + // setup a fresh time hook + initializeTimeHook(); + // setup initial event listeners + setupListeners(); + // Reset countdown timer + countdownTimer.resetCountdownTimer(timeoutIntervalInMillis / 1000); + } +})(); \ No newline at end of file diff --git a/src/main/webapp/templates-hidden/default.html b/src/main/webapp/templates-hidden/default.html index 8503b9d4..ad392b09 100755 --- a/src/main/webapp/templates-hidden/default.html +++ b/src/main/webapp/templates-hidden/default.html @@ -53,6 +53,9 @@ + + + @@ -93,7 +96,7 @@
- Log off + Log off