From 0c230336c5dba012d16cf4d736c9979166e771f8 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Fri, 31 May 2019 09:58:23 -0700 Subject: [PATCH] New session idle timeout setting, changes to devices view. --- meshuser.js | 1 + package.json | 2 +- sample-config.json | 2 ++ views/default-min.handlebars | 2 +- views/default-mobile-min.handlebars | 2 +- views/default-mobile.handlebars | 22 +++++++++--- views/default.handlebars | 54 +++++++++++++++++++++-------- 7 files changed, 63 insertions(+), 22 deletions(-) diff --git a/meshuser.js b/meshuser.js index 2df5b8b9..9b80a399 100644 --- a/meshuser.js +++ b/meshuser.js @@ -286,6 +286,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var serverinfo = { name: domain.dns ? domain.dns : parent.certificates.CommonName, mpsname: parent.certificates.AmtMpsName, mpsport: mpsport, mpspass: args.mpspass, port: httpport, emailcheck: ((parent.parent.mailserver != null) && (domain.auth != 'sspi') && (domain.auth != 'ldap')), domainauth: ((domain.auth == 'sspi') || (domain.auth == 'ldap')) }; if (args.notls == true) { serverinfo.https = false; } else { serverinfo.https = true; serverinfo.redirport = args.redirport; } if (typeof domain.userconsentflags == 'number') { serverinfo.consent = domain.userconsentflags; } + if ((typeof domain.usersessionidletimeout == 'number') && (domain.usersessionidletimeout > 0)) { serverinfo.timeout = (domain.usersessionidletimeout * 60 * 1000); } // Send server information try { ws.send(JSON.stringify({ action: 'serverinfo', serverinfo: serverinfo })); } catch (ex) { } diff --git a/package.json b/package.json index 554d4283..58377497 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.3.5-o", + "version": "0.3.5-p", "keywords": [ "Remote Management", "Intel AMT", diff --git a/sample-config.json b/sample-config.json index d2ed42a4..207f5e44 100644 --- a/sample-config.json +++ b/sample-config.json @@ -67,6 +67,8 @@ "_UserBlockedIP": "127.0.0.1,::1,192.168.0.100", "_AgentAllowedIP": "192.168.0.100/24", "_AgentBlockedIP": "127.0.0.1,::1", + "___UserSessionIdleTimeout__" : "Number of user idle minutes before auto-disconnect", + "_UserSessionIdleTimeout" : 30, "__UserConsentFlags__" : "Set to: 1 for desktop, 2 for terminal, 3 for files, 7 for all", "_UserConsentFlags" : 7, "_Limits": { diff --git a/views/default-min.handlebars b/views/default-min.handlebars index dcf6bd93..e6a4b6fb 100644 --- a/views/default-min.handlebars +++ b/views/default-min.handlebars @@ -1 +1 @@ - {{{title}}}
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file + {{{title}}}
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file diff --git a/views/default-mobile-min.handlebars b/views/default-mobile-min.handlebars index b66f19ed..91a36370 100644 --- a/views/default-mobile-min.handlebars +++ b/views/default-mobile-min.handlebars @@ -1 +1 @@ - {{{title}}}
{{{title}}}
{{{title2}}}
\ No newline at end of file + {{{title}}}
{{{title}}}
{{{title2}}}
\ No newline at end of file diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index de300305..df553c77 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -594,6 +594,7 @@ var files; var passRequirements = "{{{passRequirements}}}"; if (passRequirements != "") { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } + var sessionActivity = Date.now(); function startup() { if ((features & 32) == 0) { @@ -673,11 +674,14 @@ } function addLetterS(x) { return (x > 1) ? 's' : ''; } + function setSessionActivity() { sessionActivity = Date.now(); } + function checkIdleSessionTimeout() { var delta = (Date.now() - sessionActivity); if (delta > serverinfo.timeout) { window.location.href = 'logout'; } } function onMessage(server, message) { switch (message.action) { case 'serverinfo': { serverinfo = message.serverinfo; + if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); } QV('p3AccountActions', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide Account Actions if in single user mode or domain authentication QV('logoutMenuOption', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide logout if in single user mode or domain authentication break; @@ -2158,6 +2162,7 @@ } function connectDesktop(e, contype) { + setSessionActivity(); if (desktop == null) { desktopNode = currentNode; if (contype == 2) { @@ -2354,6 +2359,7 @@ // Show process dialogs function toggleDeskTools() { + setSessionActivity(); if (xxdialogMode) return; if (QS('DeskTools').display == 'none') { QV('DeskTools', true); @@ -2366,6 +2372,7 @@ // Refresh all of the desktop tool panels function refreshDeskTools() { + setSessionActivity(); QV('DeskToolsRefreshButton', false); setTimeout(refreshDeskToolsEx, 500); meshserver.send({ action: 'msg', type: 'ps', nodeid: currentNode._id }); @@ -2393,6 +2400,7 @@ // Save the desktop image to file function deskSaveImage() { + setSessionActivity(); if (xxdialogMode || desktop == null || desktop.State != 3) return; var d = new Date(), n = 'Desktop-' + currentNode.name + '-' + d.getFullYear() + "-" + ("0" + (d.getMonth() + 1)).slice(-2) + "-" + ("0" + d.getDate()).slice(-2) + "-" + ("0" + d.getHours()).slice(-2) + "-" + ("0" + d.getMinutes()).slice(-2); Q("Desk")['toBlob'](function (blob) { saveAs(blob, n + ".jpg"); }); @@ -2407,15 +2415,16 @@ function deskGetDisplayNumbers(e) { desktop.m.GetDisplayNumbers(); } function deskSetDisplay(e) { + setSessionActivity(); var display = 0, txt = Q('termdisplays').value; if (txt == "All Displays") display = 65535; else display = parseInt(txt.substring(8)); desktop.m.SetDisplay(display); } - function dmousedown(e) { if ((!xxdialogMode && desktop != null) && Q('DeskControl').checked) desktop.m.mousedown(e) } - function dmouseup(e) { if ((!xxdialogMode && desktop != null) && Q('DeskControl').checked) desktop.m.mouseup(e) } - function dmousemove(e) { if ((!xxdialogMode && desktop != null) && Q('DeskControl').checked) desktop.m.mousemove(e) } - function dmousewheel(e) { if ((!xxdialogMode && desktop != null) && Q('DeskControl').checked && desktop.m.mousewheel) { desktop.m.mousewheel(e); haltEvent(e); return true; } return false; } + function dmousedown(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null) && Q('DeskControl').checked) desktop.m.mousedown(e) } + function dmouseup(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null) && Q('DeskControl').checked) desktop.m.mouseup(e) } + function dmousemove(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null) && Q('DeskControl').checked) desktop.m.mousemove(e) } + function dmousewheel(e) { setSessionActivity(); if ((!xxdialogMode && desktop != null) && Q('DeskControl').checked && desktop.m.mousewheel) { desktop.m.mousewheel(e); haltEvent(e); return true; } return false; } function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } } function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, 'Stop process #' + id + ' "' + name + '"?', id); } function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type: 'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); } @@ -2435,6 +2444,7 @@ } function onFilesStateChange(xfiles, state) { + setSessionActivity(); p13Connect.value = (state == 0) ? 'Connect' : 'Disconnect'; var str = StatusStrs[state]; if (files.webRtcActive == true) { str += ', WebRTC'; } @@ -2494,6 +2504,7 @@ var p13filetreelocation = []; function p13gotFiles(data) { + setSessionActivity(); //console.log('p13gotFiles', data); if ((data.length > 0) && (data.charCodeAt(0) != 123)) { p13gotDownloadBinaryData(data); return; } //console.log('p13gotFiles', data); @@ -3069,6 +3080,7 @@ var xxcurrentView = -1; function go(x) { + setSessionActivity(); if (xxdialogMode || xxcurrentView == x) return; updateFooterMenu(); setDialogMode(0); @@ -3090,6 +3102,7 @@ // Display a dialog box // Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only) function setDialogMode(x, y, b, f, c, tag) { + setSessionActivity(); xxdialogMode = x; xxdialogFunc = f; xxdialogButtons = b; @@ -3106,6 +3119,7 @@ } function dialogclose(x) { + setSessionActivity(); var f = xxdialogFunc; var b = xxdialogButtons; var t = xxdialogTag; diff --git a/views/default.handlebars b/views/default.handlebars index b468e4e7..e6df758e 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -60,7 +60,7 @@
-

{{{logoutControl}}}

+

{{{logoutControl}}}

@@ -937,6 +937,7 @@ var webPageStackMenu = false; var webPageFullScreen = true; var nightMode = (getstore('_nightMode', '0') == '1'); + var sessionActivity = Date.now(); // Console Message Display Timers var p11DeskConsoleMsgTimer = null; @@ -1280,6 +1281,19 @@ } function addLetterS(x) { return (x > 1) ? 's' : ''; } + function setSessionActivity() { sessionActivity = Date.now(); QH('idleTimeoutNotify', ''); } + function checkIdleSessionTimeout() { + var delta = (Date.now() - sessionActivity); + if (delta > serverinfo.timeout) { window.location.href = 'logout'; } else { + var ds = Math.round((serverinfo.timeout - delta) / 1000); + if (ds <= 60) { + QH('idleTimeoutNotify', '
' + ds + ' second' + addLetterS(ds) + ' until disconnect'); + } else { + ds = Math.round(ds / 60); + if (ds <= 5) { QH('idleTimeoutNotify', '
' + ds + ' minute' + addLetterS(ds) + ' until disconnect'); } + } + } + } function onMessage(server, message) { switch (message.action) { @@ -1298,6 +1312,7 @@ } case 'serverinfo': { serverinfo = message.serverinfo; + if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); } break; } case 'userinfo': { @@ -1993,6 +2008,7 @@ } function ondockeypress(e) { + setSessionActivity(); if (!xxdialogMode && xxcurrentView == 11 && desktop && Q("DeskControl").checked) { // Check what keys we are allows to send if (currentNode != null) { @@ -2052,6 +2068,7 @@ } function ondockeydown(e) { + setSessionActivity(); if (!xxdialogMode && xxcurrentView == 11 && desktop && Q("DeskControl").checked) { // Check what keys we are allows to send if (currentNode != null) { @@ -2086,6 +2103,7 @@ } function ondockeyup(e) { + setSessionActivity(); if (!xxdialogMode && xxcurrentView == 11 && desktop && Q("DeskControl").checked) { // Check what keys we are allows to send if (currentNode != null) { @@ -2109,6 +2127,7 @@ // Highlights the device being hovered function devMouseHover(element, over) { + setSessionActivity(); var view = Q('viewselect').value; if (view == 1) { var e = element.children[1].children[1]; @@ -2203,8 +2222,8 @@ if ((view == 1) && (current != null)) { if (c == 2) { r += '
'; } if (r != '') { r += ''; } } if (view == 2) { r += '
'; } r += '
'; - r += getMeshActions(mesh2, meshrights); - r += '' + EscapeHtml(meshes[node.meshid].name) + '' + extra + '
'; + r += '' + extra; + r += '' + EscapeHtml(meshes[node.meshid].name) + '' + getMeshActions(mesh2, meshrights) + '
'; if (view == 2) { r += '
'; } current = node.meshid; displayedMeshes[current] = 1; @@ -2216,7 +2235,7 @@ if (pwr !== current) { deviceHeaderSet(); if ((view == 1) && (current !== null)) { if (c == 2) { r += '
'; } if (r != '') { r += ''; } } - r += '
' + PowerStateStr2(node.pwr) + '
'; + r += '
' + PowerStateStr2(node.pwr) + '
'; current = pwr; c = 0; } @@ -2289,7 +2308,7 @@ for (var i in groups) { groupNames.push(i); } groupNames.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); }); for (var j in groupNames) { - var i = groupNames[j]; r += '
' + i + ', ' + groupCount[i] + ' device' + ((groupCount[i] > 1)?'s':'') + '
' + groups[i]; + var i = groupNames[j]; r += '
' + groupCount[i] + ' node' + ((groupCount[i] > 1) ? 's' : '') + '' + i + '
' + groups[i]; } } @@ -2304,7 +2323,7 @@ if ((view == 1) && (c == 2)) r += '
'; // Adds device padding - // Display all empty meshes, we need to do this because users can add devices to these at any time. + // Display all empty device groups, we need to do this because users can add devices to these at any time. if ((sort == 0) && (Q('SearchInput').value == '') && (view < 3)) { for (var i in meshes) { var mesh = meshes[i], meshlink = mesh.links[userinfo._id]; @@ -2312,9 +2331,9 @@ var meshrights = meshlink.rights; if (displayedMeshes[mesh._id] == null) { if ((current != '') && (r != '')) { r += ''; } - r += '
'; + r += ''; + r += ''; if (mesh.mtype == 1) { r += '
' + EscapeHtml(mesh.name) + ''; r += getMeshActions(mesh, meshrights); - r += '' + EscapeHtml(mesh.name) + '
No Intel® AMT devices in this mesh'; if ((meshrights & 4) != 0) { r += ', add one'; } @@ -2805,7 +2824,7 @@ function deviceHeaderSet() { if (deviceHeaderId == 0) { deviceHeaderId = 1; return; } - deviceHeaders["DevxHeader" + deviceHeaderId] = ', ' + deviceHeaderTotal + ((deviceHeaderTotal == 1) ? ' node' : ' nodes'); + deviceHeaders["DevxHeader" + deviceHeaderId] = deviceHeaderTotal + ((deviceHeaderTotal == 1) ? ' node' : ' nodes'); //var title = ''; //for (x in deviceHeaderCount) { if (title.length > 0) title += ', '; title += deviceHeaderCount[x] + ' ' + PowerStateStr2(x); } //deviceHeadersTitles["DevxHeader" + deviceHeaderId] = title; @@ -4873,10 +4892,10 @@ dblClickDetectArgs.y = e.clientY; } - function dmousedown(e) { e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedown(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedown(e); } } dblClickDetect(e); } - function dmouseup(e) { e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mouseup(e); desktop.m.sendKeepAlive(); } else { desktop.m.mouseup(e); } } - function dmousemove(e) { e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousemove(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousemove(e); } } } - function dmousewheel(e) { e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousewheel(e); desktop.m.sendKeepAlive(); } else { if (desktop.m.mousewheel) { desktop.m.mousewheel(e); } } haltEvent(e); return true; } return false; } + function dmousedown(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedown(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedown(e); } } dblClickDetect(e); } + function dmouseup(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mouseup(e); desktop.m.sendKeepAlive(); } else { desktop.m.mouseup(e); } } + function dmousemove(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousemove(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousemove(e); } } } + function dmousewheel(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && Q('DeskControl').checked) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousewheel(e); desktop.m.sendKeepAlive(); } else { if (desktop.m.mousewheel) { desktop.m.mousewheel(e); } } haltEvent(e); return true; } return false; } function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } } function stopProcess(id, name) { setDialogMode(2, "Process Control", 3, stopProcessEx, 'Stop process #' + id + ' "' + name + '"?', id); } function stopProcessEx(buttons, tag) { meshserver.send({ action: 'msg', type:'pskill', nodeid: currentNode._id, value: tag }); setTimeout(refreshDeskTools, 300); } @@ -7837,6 +7856,7 @@ // Display a dialog box // Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only) function setDialogMode(x, y, b, f, c, tag) { + setSessionActivity(); QV('uiMenu', false); xxdialogMode = x; xxdialogFunc = f; @@ -7855,20 +7875,23 @@ } function dialogclose(x) { + setSessionActivity(); var f = xxdialogFunc, b = xxdialogButtons, t = xxdialogTag; setDialogMode(); if (((b & 8) || x) && f) f(x, t); } function center() { + setSessionActivity(); if (xxcurrentView == 11) { deskAdjust(); } else if (xxcurrentView == 10) { masterUpdate(256); } else if (xxcurrentView == 1) { masterUpdate(4); } } - function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); } - function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); } + function messagebox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t, 1); } + function statusbox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t); } function goBack() { + setSessionActivity(); if (xxdialogMode) return; if (fullscreen) { deskToggleFull(); } if ((xxcurrentView >= 10) && (xxcurrentView < 20)) { go(1); } // Return to My Devices @@ -7877,6 +7900,7 @@ } function go(x) { + setSessionActivity(); if (xxdialogMode || xxcurrentView == x) return; QV('uiMenu', false);