Added public agent install invitation link support.
This commit is contained in:
parent
7bc5394fcc
commit
b676ab7e16
|
@ -260,6 +260,7 @@
|
|||
<Content Include="readme.txt" />
|
||||
<Content Include="sample-config.json" />
|
||||
<Content Include="SourceFileList.txt" />
|
||||
<Content Include="views\agentinvite.handlebars" />
|
||||
<Content Include="views\default-min.handlebars" />
|
||||
<Content Include="views\default-mobile-min.handlebars" />
|
||||
<Content Include="views\default-mobile.handlebars" />
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1549,8 +1549,14 @@ function CreateMeshCentralServer(config, args) {
|
|||
if ((o.time == null) || (o.time == null) || (typeof o.time != 'number')) { obj.debug(1, 'ERR: Bad cookie due to invalid time'); return null; }
|
||||
o.time = o.time * 1000; // Decode the cookie creation time
|
||||
o.dtime = Date.now() - o.time; // Decode how long ago the cookie was created (in milliseconds)
|
||||
if (timeout == null) { timeout = 2; }
|
||||
if ((o.dtime > (timeout * 60000)) || (o.dtime < -30000)) { obj.debug(1, 'ERR: Bad cookie due to timeout'); return null; } // The cookie is only valid 120 seconds, or 30 seconds back in time (in case other server's clock is not quite right)
|
||||
if ((o.expire) == null || (typeof o.expire != 'number')) {
|
||||
// Use a fixed cookie expire time
|
||||
if (timeout == null) { timeout = 2; }
|
||||
if ((o.dtime > (timeout * 60000)) || (o.dtime < -30000)) { obj.debug(1, 'ERR: Bad cookie due to timeout'); return null; } // The cookie is only valid 120 seconds, or 30 seconds back in time (in case other server's clock is not quite right)
|
||||
} else {
|
||||
// An expire time is included in the cookie (in minutes), use this.
|
||||
if ((o.dtime > (o.expire * 60000)) || (o.dtime < -30000)) { obj.debug(1, 'ERR: Bad cookie due to timeout'); return null; } // The cookie is only valid 120 seconds, or 30 seconds back in time (in case other server's clock is not quite right)
|
||||
}
|
||||
return o;
|
||||
} catch (ex) { obj.debug(1, 'ERR: Bad AESGCM cookie due to exception: ' + ex); return null; }
|
||||
};
|
||||
|
@ -1571,8 +1577,14 @@ function CreateMeshCentralServer(config, args) {
|
|||
if ((o.time == null) || (o.time == null) || (typeof o.time != 'number')) { obj.debug(1, 'ERR: Bad cookie due to invalid time'); return null; }
|
||||
o.time = o.time * 1000; // Decode the cookie creation time
|
||||
o.dtime = Date.now() - o.time; // Decode how long ago the cookie was created (in milliseconds)
|
||||
if (timeout == null) { timeout = 2; }
|
||||
if ((o.dtime > (timeout * 60000)) || (o.dtime < -30000)) { obj.debug(1, 'ERR: Bad cookie due to timeout'); return null; } // The cookie is only valid 120 seconds, or 30 seconds back in time (in case other server's clock is not quite right)
|
||||
if ((o.expire) == null || (typeof o.expire != 'number')) {
|
||||
// Use a fixed cookie expire time
|
||||
if (timeout == null) { timeout = 2; }
|
||||
if ((o.dtime > (timeout * 60000)) || (o.dtime < -30000)) { obj.debug(1, 'ERR: Bad cookie due to timeout'); return null; } // The cookie is only valid 120 seconds, or 30 seconds back in time (in case other server's clock is not quite right)
|
||||
} else {
|
||||
// An expire time is included in the cookie (in minutes), use this.
|
||||
if ((o.dtime > (o.expire * 60000)) || (o.dtime < -30000)) { obj.debug(1, 'ERR: Bad cookie due to timeout'); return null; } // The cookie is only valid 120 seconds, or 30 seconds back in time (in case other server's clock is not quite right)
|
||||
}
|
||||
return o;
|
||||
} catch (ex) { obj.debug(1, 'ERR: Bad AESSHA cookie due to exception: ' + ex); return null; }
|
||||
};
|
||||
|
|
11
meshuser.js
11
meshuser.js
|
@ -2499,6 +2499,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
|
||||
break;
|
||||
}
|
||||
case 'createInviteLink': {
|
||||
if (common.validateString(command.meshid, 8, 128) == false) break; // Check the meshid
|
||||
if (common.validateInt(command.expire, 1, 99999) == false) break; // Check the expire time in hours
|
||||
if (common.validateInt(command.flags, 0, 256) == false) break; // Check the flags
|
||||
var mesh = parent.meshes[command.meshid];
|
||||
if (mesh == null) break;
|
||||
const inviteCookie = parent.parent.encodeCookie({ a: 4, mid: command.meshid, f: command.flags, expire: command.expire * 60 }, parent.parent.loginCookieEncryptionKey);
|
||||
if (inviteCookie == null) break;
|
||||
ws.send(JSON.stringify({ action: 'createInviteLink', meshid: command.meshid, expire: command.expire, cookie: inviteCookie }));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Unknown user action
|
||||
console.log('Unknown action from user ' + user.name + ': ' + command.action + '.');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.3.5-v",
|
||||
"version": "0.3.5-x",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
|
@ -0,0 +1,293 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||
<meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
|
||||
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
|
||||
<title>MeshCentral - Agent Installation</title>
|
||||
<style>
|
||||
.tab {
|
||||
overflow: hidden;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.tab button {
|
||||
background-color: inherit;
|
||||
float: left;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
padding: 14px 16px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.tab button:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.tab button.active {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.tabcontent {
|
||||
display: none;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body id="body" onload="if (typeof(startup) !== 'undefined') startup();" style="display:none;overflow:hidden">
|
||||
<div id="container">
|
||||
<!-- Begin Masthead -->
|
||||
<div id="masthead" class=noselect style="background:url(logo.png) 0px 0px;background-color:#036;background-repeat:no-repeat;height:66px;width:100%;overflow:hidden;">
|
||||
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:20px; padding-top:8px">
|
||||
<strong><font style="font-size:46px; font-family: Arial, Helvetica, sans-serif;">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left; height: 66px; color:#c8c8c8; padding-left:5px; padding-top:14px">
|
||||
<strong><font style="font-size:14px; font-family: Arial, Helvetica, sans-serif;">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
<p id="logoutControl" style="color:white;font-size:11px;margin: 10px 10px 0;">{{{logoutControl}}}</p>
|
||||
</div>
|
||||
<div id="page_leftbar">
|
||||
<div style="height:16px"></div>
|
||||
</div>
|
||||
<div id=topbar class="noselect style3" style="height:24px;position:relative">
|
||||
<div id=uiMenuButton title="User interface selection" onclick="showUserInterfaceSelectMenu()">
|
||||
♦
|
||||
<div id=uiMenu style="display:none">
|
||||
<div id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface"><div class="uiSelector1"></div></div>
|
||||
<div id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface"><div class="uiSelector2"></div></div>
|
||||
<div id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface"><div class="uiSelector3"></div></div>
|
||||
<div id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Toggle night mode"><div class="uiSelector4"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="column_l" style="max-height:calc(100vh - 135px);overflow-y:auto">
|
||||
<h1>Agent Installation<span id="groupname"></span></h1>
|
||||
<p>
|
||||
You have been invited to install a software that will allow a remote operator to fully access your computer remotely including the desktop and files.
|
||||
Only follow the instructions below if this invitation was expected and you know who will be accessing your computer.
|
||||
Selecting your operation system and follow the instructions below.
|
||||
</p>
|
||||
<div>
|
||||
<div class="tab">
|
||||
<button id="twintab64" class="tablinks" onclick="openTab(event, 'wintab64')">Windows 64bit</button>
|
||||
<button id="twintab32" class="tablinks" onclick="openTab(event, 'wintab32')">Windows 32bit</button>
|
||||
<button id="tlinuxtab" class="tablinks" onclick="openTab(event, 'linuxtab')">Linux</button>
|
||||
<button id="tmacostab" class="tablinks" onclick="openTab(event, 'macostab')">MacOS</button>
|
||||
</div>
|
||||
|
||||
<div id="wintab64" class="tabcontent" style="background-color:white;color:black">
|
||||
<h3>Microsoft™ Windows 64bit</h3>
|
||||
<p><a id="win64url">Download the software here</a>, run it and press "Install" or "Connect".</p>
|
||||
<div style="text-align:center">
|
||||
<img src="images/winagent.png" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="wintab32" class="tabcontent" style="background-color:white;color:black">
|
||||
<h3>Microsoft™ Windows 32bit</h3>
|
||||
<p><a id="win32url">Download the software here</a>, run it and press "Install" or "Connect".</p>
|
||||
<div style="text-align:center">
|
||||
<img src="images/winagent.png" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="linuxtab" class="tabcontent" style="background-color:white;color:black">
|
||||
<h3>Linux</h3>
|
||||
<p>To install, cut and paste the following command in a root terminal.</p>
|
||||
<div id="linuxinstall" style="font-family:courier,'courier new',monospace;margin-left:30px"></div>
|
||||
<input type="button" value="Copy to clipboard" style="margin-left:30px;margin-top:4px" onclick="copyToClipLinuxInstall()" />
|
||||
<p>To uninstall, cut and paste the following command as root.</p>
|
||||
<div id="unlinuxinstall" style="font-family:courier,'courier new',monospace;margin-left:30px"></div>
|
||||
<input type="button" value="Copy to clipboard" style="margin-left:30px;margin-top:4px" onclick="copyToClipLinuxUnInstall()" />
|
||||
<br /><br />
|
||||
</div>
|
||||
|
||||
<div id="macostab" class="tabcontent" style="background-color:white;color:black">
|
||||
<h3>Apple™ MacOS</h3>
|
||||
<p><a id="macosurl">Download the installer here</a>, right click on it and select "Open", then follow the instructions.</p>
|
||||
<div style="text-align:center">
|
||||
<img src="images/macosagent.png" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<table cellpadding="0" cellspacing="10" style="width: 100%">
|
||||
<tr>
|
||||
<td style="text-align:left"></td>
|
||||
<td style="text-align:right"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
'use strict';
|
||||
var uiMode = parseInt(getstore('uiMode', 1));
|
||||
var webPageStackMenu = false;
|
||||
var webPageFullScreen = true;
|
||||
var nightMode = (getstore('_nightMode', '0') == '1');
|
||||
var domain = "{{{domain}}}";
|
||||
var domainUrl = "{{{domainurl}}}";
|
||||
var meshid = "{{{meshid}}}";
|
||||
var serverPort = "{{{serverport}}}";
|
||||
var serverHttps = "{{{serverhttps}}}";
|
||||
var serverNoProxy = "{{{servernoproxy}}}";
|
||||
var installFlags = "{{{installflags}}}";
|
||||
var groupName = decodeURIComponent("{{{meshname}}}");
|
||||
if (groupName != '') { QH('groupname', ' - ' + groupName); }
|
||||
userInterfaceSelectMenu();
|
||||
setup();
|
||||
|
||||
// Toggle user interface menu
|
||||
function showUserInterfaceSelectMenu() {
|
||||
Q('uiViewButton1').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton2').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton3').classList.remove('uiSelectorSel');
|
||||
Q('uiViewButton4').classList.remove('uiSelectorSel');
|
||||
try { Q('uiViewButton' + uiMode).classList.add('uiSelectorSel'); } catch (ex) { }
|
||||
QV('uiMenu', (QS('uiMenu').display == 'none'));
|
||||
if (nightMode) { Q('uiViewButton4').classList.add('uiSelectorSel'); }
|
||||
}
|
||||
|
||||
function userInterfaceSelectMenu(s) {
|
||||
if (s) { uiMode = s; putstore('uiMode', uiMode); }
|
||||
webPageFullScreen = (uiMode < 3);
|
||||
webPageStackMenu = true;//(uiMode > 1);
|
||||
toggleFullScreen(0);
|
||||
toggleStackMenu(0);
|
||||
QC('column_l').add('room4submenu');
|
||||
}
|
||||
|
||||
function toggleNightMode() {
|
||||
nightMode = !nightMode;
|
||||
if (nightMode) { QC('body').add('night'); } else { QC('body').remove('night'); }
|
||||
putstore('_nightMode', nightMode ? '1' : '0');
|
||||
}
|
||||
|
||||
// Toggle the web page to full screen
|
||||
function toggleFullScreen(toggle) {
|
||||
if (toggle === 1) { webPageFullScreen = !webPageFullScreen; putstore('webPageFullScreen', webPageFullScreen); }
|
||||
var hide = 0;
|
||||
//if (args.hide) { hide = parseInt(args.hide); }
|
||||
if (webPageFullScreen == false) {
|
||||
QC('body').remove("menu_stack");
|
||||
QC('body').remove("fullscreen");
|
||||
QC('body').remove("arg_hide");
|
||||
//if (xxcurrentView >= 10) QC('column_l').add('room4submenu');
|
||||
//QV('UserDummyMenuSpan', false);
|
||||
//QV('page_leftbar', false);
|
||||
} else {
|
||||
QC('body').add("fullscreen");
|
||||
if (hide & 16) QC('body').add("arg_hide"); // This is replacement for QV('page_leftbar', !(hide & 16));
|
||||
//QV('UserDummyMenuSpan', (xxcurrentView < 10) && webPageFullScreen);
|
||||
//QV('page_leftbar', true);
|
||||
}
|
||||
QV('body', true);
|
||||
}
|
||||
|
||||
// If FullScreen, toggle menu to be horisontal or vertical
|
||||
function toggleStackMenu(toggle) {
|
||||
if (webPageFullScreen == true) {
|
||||
if (toggle === 1) {
|
||||
webPageStackMenu = !webPageStackMenu;
|
||||
putstore('webPageStackMenu', webPageStackMenu);
|
||||
}
|
||||
if (webPageStackMenu == false) {
|
||||
QC('body').remove("menu_stack");
|
||||
} else {
|
||||
QC('body').add("menu_stack");
|
||||
//if (xxcurrentView >= 10) QC('column_l').remove('room4submenu');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
|
||||
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
|
||||
|
||||
function openTab(evt, tabname) {
|
||||
// Declare all variables
|
||||
var i, tabcontent, tablinks;
|
||||
|
||||
// Get all elements with class="tabcontent" and hide them
|
||||
tabcontent = document.getElementsByClassName("tabcontent");
|
||||
for (i = 0; i < tabcontent.length; i++) {
|
||||
tabcontent[i].style.display = "none";
|
||||
}
|
||||
|
||||
// Get all elements with class="tablinks" and remove the class "active"
|
||||
tablinks = document.getElementsByClassName("tablinks");
|
||||
for (i = 0; i < tablinks.length; i++) {
|
||||
tablinks[i].className = tablinks[i].className.replace(" active", "");
|
||||
}
|
||||
|
||||
// Show the current tab, and add an "active" class to the button that opened the tab
|
||||
document.getElementById(tabname).style.display = "block";
|
||||
if (evt != null) { evt.currentTarget.className += " active"; } else { document.getElementById('t' + tabname).className += " active"; }
|
||||
}
|
||||
|
||||
var linuxInstall, linuxUnInstall;
|
||||
function setup() {
|
||||
var servername = window.location.hostname;
|
||||
var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
|
||||
|
||||
// Windows 64bit Setup
|
||||
var url = 'meshagents?id=4&meshid=' + meshid;
|
||||
if (installFlags != 0) { url += ('&installflags=' + installFlags); }
|
||||
Q('win64url').href = url;
|
||||
|
||||
// Windows 32bit Setup
|
||||
url = 'meshagents?id=3&meshid=' + meshid;
|
||||
if (installFlags != 0) { url += ('&installflags=' + installFlags); }
|
||||
Q('win32url').href = url;
|
||||
|
||||
// MacOS Setup
|
||||
url = 'meshagents?id=16&meshid=' + meshid;
|
||||
Q('macosurl').href = url;
|
||||
|
||||
// Linux Setup
|
||||
if (serverHttps == 1) {
|
||||
var portStr = (serverPort == 443) ? '' : (":" + serverPort);
|
||||
if (serverNoProxy == 0) {
|
||||
linuxInstall = "(wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-check-certificate -O ./meshinstall.sh || wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://" + servername + portStr + domainUrlNoSlash + " '" + meshid + "'\r\n";
|
||||
linuxUnInstall = "(wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-check-certificate -O ./meshinstall.sh || wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n";
|
||||
} else {
|
||||
// Server asked that agent be installed to preferably not use a HTTP proxy.
|
||||
linuxInstall = "wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh https://" + servername + portStr + domainUrlNoSlash + " '" + meshid + "'\r\n";
|
||||
linuxUnInstall = "wget https://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n";
|
||||
}
|
||||
} else {
|
||||
var portStr = (serverPort == 80) ? '' : (":" + serverPort);
|
||||
if (serverNoProxy == 0) {
|
||||
linuxInstall = "(wget http://" + servername + portStr + domainUrl + "meshagents?script=1 -O ./meshinstall.sh || wget http://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://" + servername + portStr + domainUrlNoSlash + " '" + meshid + "'\r\n";
|
||||
linuxUnInstall = "(wget http://" + servername + portStr + domainUrl + "meshagents?script=1 -O ./meshinstall.sh || wget http://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy -O ./meshinstall.sh) && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n";
|
||||
} else {
|
||||
// Server asked that agent be installed to preferably not use a HTTP proxy.
|
||||
linuxInstall = "wget http://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh http://" + servername + portStr + domainUrlNoSlash + " '" + meshid + "'\r\n";
|
||||
linuxUnInstall = "wget http://" + servername + portStr + domainUrl + "meshagents?script=1 --no-proxy -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh uninstall\r\n";
|
||||
}
|
||||
}
|
||||
QH('linuxinstall', linuxInstall);
|
||||
QH('unlinuxinstall', linuxUnInstall);
|
||||
|
||||
// Attempt to detect the most likely operating system for this browser
|
||||
if (navigator.userAgent.indexOf('Win64')) { openTab(null, 'wintab64'); }
|
||||
else if (navigator.userAgent.indexOf('Windows')) { openTab(null, 'wintab32'); }
|
||||
else if (navigator.userAgent.indexOf('Linux')) { openTab(null, 'linuxtab'); }
|
||||
else if (navigator.userAgent.indexOf('Macintosh')) { openTab(null, 'macostab'); }
|
||||
else { openTab(null, 'wintab64'); }
|
||||
}
|
||||
|
||||
function copyToClipLinuxInstall() { navigator.clipboard.writeText(linuxInstall); }
|
||||
function copyToClipLinuxUnInstall() { navigator.clipboard.writeText(linuxUnInstall); }
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1977,6 +1977,28 @@
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'createInviteLink': { // Agent installation invitation link
|
||||
if (xxdialogTag != message.meshid) break;
|
||||
var servername = serverinfo.name;
|
||||
if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
|
||||
var domainUrlNoSlash = domainUrl.substring(0, domainUrl.length - 1);
|
||||
var url;
|
||||
if (serverinfo.https == true) {
|
||||
var portStr = (serverinfo.port == 443) ? '' : (":" + serverinfo.port);
|
||||
url = "https://" + servername + portStr + domainUrl + "agentinvite?c=" + message.cookie;
|
||||
} else {
|
||||
var portStr = (serverinfo.port == 80) ? '' : (":" + serverinfo.port);
|
||||
url = "http://" + servername + portStr + domainUrl + "agentinvite?c=" + message.cookie;
|
||||
}
|
||||
Q('agentInvitationLink').href = url;
|
||||
var t = message.expire + ' hour' + addLetterS(message.expire);
|
||||
if (message.expire == 24) { t = '1 day'; }
|
||||
if (message.expire == 168) { t = '1 week'; }
|
||||
if (message.expire == 5040) { t = '1 month'; }
|
||||
QH('agentInvitationLink', 'Invitation Link (' + t + ')');
|
||||
QV('agentInvitationLinkDiv', true);
|
||||
break;
|
||||
}
|
||||
case 'stopped': { // Server is stopping.
|
||||
// Disconnect
|
||||
autoReconnect = false;
|
||||
|
@ -2547,9 +2569,7 @@
|
|||
}
|
||||
if (mesh.mtype == 2) {
|
||||
r += ' <a style=cursor:pointer;font-size:10px title="Add a new computer to this mesh by installing the mesh agent." onclick=addAgentToMesh(\"' + mesh._id + '\")>Add Agent</a>';
|
||||
if (features & 64) {
|
||||
r += ' <a style=cursor:pointer;font-size:10px title="Invite someone to install the mesh agent on this mesh." onclick=inviteAgentToMesh(\"' + mesh._id + '\")>Invite</a>';
|
||||
}
|
||||
r += ' <a style=cursor:pointer;font-size:10px title="Invite someone to install the mesh agent on this mesh." onclick=inviteAgentToMesh(\"' + mesh._id + '\")>Invite</a>';
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -2673,23 +2693,51 @@
|
|||
|
||||
function inviteAgentToMesh(meshid) {
|
||||
if (xxdialogMode) return;
|
||||
var mesh = meshes[meshid];
|
||||
var x = "Invite someone to install the mesh agent. An email with be sent with the link to the mesh agent installation for " + EscapeHtml(mesh.name) + ".<br /><br />";
|
||||
x += addHtmlValue('Name (optional)', '<input id=agentInviteName value="" style=width:230px maxlength=64 />');
|
||||
x += addHtmlValue('Email', '<input id=agentInviteEmail style=width:230px placeholder="example@email.com" onkeyup=validateAgentInvite()></input>');
|
||||
x += addHtmlValue('Operating System', '<select id=agentInviteNameOs style=width:236px><option value=0>Any supported</option><option value=1>Windows only</option><option value=3>Apple MacOS only</option><option value=2>Linux only</option></select>');
|
||||
x += addHtmlValue('Installation Type', '<select id=agentInviteType style=width:236px><option value=0>Background and interactive</option><option value=2>Background only</option><option value=1>Interactive only</option></select>');
|
||||
x += addHtmlValue('Message<br />(optional)', '<textarea id=agentInviteMessage value="" style=width:230px;height:100px;resize:none maxlength=1024 /></textarea>');
|
||||
var x = '', mesh = meshes[meshid];
|
||||
if (features & 64) {
|
||||
x += addHtmlValue('Invitation Type', '<select id=d2InviteType onchange=d2ChangedInviteType() style=width:236px><option value=0>Link invitation</option><option value=1>Email invitation</option></select>') + "<hr />";
|
||||
x += "<div id=emailInviteDiv style=display:none>Invite someone to install the mesh agent. An email with be sent with the link to the mesh agent installation for the \"" + EscapeHtml(mesh.name) + "\" device group.<br /><br />";
|
||||
x += addHtmlValue('Name (optional)', '<input id=agentInviteName value="" style=width:230px maxlength=64 />');
|
||||
x += addHtmlValue('Email', '<input id=agentInviteEmail style=width:230px placeholder="example@email.com" onkeyup=validateAgentInvite()></input>');
|
||||
x += addHtmlValue('Operating System', '<select id=agentInviteNameOs style=width:236px><option value=0>Any supported</option><option value=1>Windows only</option><option value=3>Apple MacOS only</option><option value=2>Linux only</option></select>');
|
||||
x += addHtmlValue('Installation Type', '<select id=agentInviteType style=width:236px><option value=0>Background and interactive</option><option value=2>Background only</option><option value=1>Interactive only</option></select>');
|
||||
x += addHtmlValue('Message<br />(optional)', '<textarea id=agentInviteMessage value="" style=width:230px;height:100px;resize:none maxlength=1024 /></textarea>');
|
||||
x += '</div>';
|
||||
}
|
||||
x += '<div id=urlInviteDiv>Invite someone to install the mesh agent by sharing a invitation link. This link points the user to installation instructions for the \"' + EscapeHtml(mesh.name) + '\" device group. The link is public and no account this server is needed.<br /><br />';
|
||||
x += addHtmlValue('Link Expiration', '<select id=d2inviteExpire style=width:236px onchange=d2RequestInvitationLink()><option value=1>1 hour</option><option value=8>8 hours</option><option value=24>1 day</option><option value=168>1 week</option><option value=5040>1 month</option></select>');
|
||||
x += '<div id=agentInvitationLinkDiv style="text-align:center;font-size:large;margin:16px;display:none"><a id=agentInvitationLink target="_blank" href="" style=cursor:pointer></a> <img src=images/link4.png height=10 width=10 title="Copy link to clipboard" style=cursor:pointer onclick=d2CopyInviteToClip()></div></div>';
|
||||
setDialogMode(2, "Invite", 3, performAgentInvite, x, meshid);
|
||||
validateAgentInvite();
|
||||
d2RequestInvitationLink();
|
||||
}
|
||||
|
||||
function d2RequestInvitationLink() {
|
||||
meshserver.send({ action: 'createInviteLink', meshid: xxdialogTag, expire: parseInt(Q('d2inviteExpire').value), flags: 0 });
|
||||
}
|
||||
|
||||
function d2ChangedInviteType() {
|
||||
QV('urlInviteDiv', Q('d2InviteType').value == 0);
|
||||
if (features & 64) { QV('emailInviteDiv', Q('d2InviteType').value == 1); }
|
||||
validateAgentInvite();
|
||||
}
|
||||
|
||||
function d2CopyInviteToClip() { navigator.clipboard.writeText(Q('agentInvitationLink').href); }
|
||||
|
||||
function validateAgentInvite() {
|
||||
QE('idx_dlgOkButton', checkEmail(Q('agentInviteEmail').value));
|
||||
if ((features & 64) && (Q('d2InviteType').value == 1)) {
|
||||
QE('idx_dlgOkButton', checkEmail(Q('agentInviteEmail').value));
|
||||
QV('idx_dlgCancelButton', true);
|
||||
} else {
|
||||
QE('idx_dlgOkButton', true);
|
||||
QV('idx_dlgCancelButton', false);
|
||||
}
|
||||
}
|
||||
|
||||
function performAgentInvite(button, meshid) {
|
||||
meshserver.send({ action: 'inviteAgent', meshid: meshid, email: Q('agentInviteEmail').value, name: Q('agentInviteName').value, os: Q('agentInviteNameOs').value, flags: Q('agentInviteType').value, msg: Q('agentInviteMessage').value });
|
||||
if ((features & 64) && (Q('d2InviteType').value == 1)) {
|
||||
meshserver.send({ action: 'inviteAgent', meshid: meshid, email: Q('agentInviteEmail').value, name: Q('agentInviteName').value, os: Q('agentInviteNameOs').value, flags: Q('agentInviteType').value, msg: Q('agentInviteMessage').value });
|
||||
}
|
||||
}
|
||||
|
||||
function addAgentToMesh(meshid) {
|
||||
|
@ -6196,9 +6244,7 @@
|
|||
}
|
||||
if (currentMesh.mtype == 2) {
|
||||
x += '<a onclick=addAgentToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px title="Add a new computer to this mesh by installing the mesh agent."><img src=images/icon-addnew.png border=0 height=12 width=12> Install</a>';
|
||||
if (features & 64) {
|
||||
x += '<a onclick=inviteAgentToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px title="Invite someone to install the mesh agent on this mesh."><img src=images/icon-addnew.png border=0 height=12 width=12> Invite</a>';
|
||||
}
|
||||
x += '<a onclick=inviteAgentToMesh(\"' + currentMesh._id + '\") style=cursor:pointer;margin-right:10px title="Invite someone to install the mesh agent on this mesh."><img src=images/icon-addnew.png border=0 height=12 width=12> Invite</a>';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
25
webserver.js
25
webserver.js
|
@ -1063,6 +1063,30 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
}
|
||||
}
|
||||
|
||||
// Called to process an agent invite request
|
||||
function handleAgentInviteRequest(req, res) {
|
||||
const domain = checkUserIpAddress(req, res);
|
||||
if ((domain == null) || ((req.query.m == null) && (req.query.c == null))) { res.sendStatus(404); return; }
|
||||
if (req.query.c != null) {
|
||||
// A cookie is specified in the query string, use that
|
||||
var cookie = obj.parent.decodeCookie(req.query.c, obj.parent.loginCookieEncryptionKey);
|
||||
if (cookie == null) { res.sendStatus(404); return; }
|
||||
var mesh = obj.meshes[cookie.mid];
|
||||
if (mesh == null) { res.sendStatus(404); return; }
|
||||
var installflags = cookie.f;
|
||||
if (typeof installflags != 'number') { installflags = 0; }
|
||||
res.render(obj.path.join(obj.parent.webViewsPath, 'agentinvite'), { title: domain.title, title2: domain.title2, domainurl: domain.url, meshid: mesh._id.split('/')[2], serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: ((args.notls == true) ? '0' : '1'), servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name), installflags: installflags });
|
||||
} else if (req.query.m != null) {
|
||||
// The MeshId is specified in the query string, use that
|
||||
var mesh = obj.meshes['mesh/' + domain.id + '/' + req.query.m.toLowerCase()];
|
||||
if (mesh == null) { res.sendStatus(404); return; }
|
||||
var installflags = 0;
|
||||
if (req.query.f) { installflags = parseInt(req.query.f); }
|
||||
if (typeof installflags != 'number') { installflags = 0; }
|
||||
res.render(obj.path.join(obj.parent.webViewsPath, 'agentinvite'), { title: domain.title, title2: domain.title2, domainurl: domain.url, meshid: mesh._id.split('/')[2], serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: ((args.notls == true) ? '0' : '1'), servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name), installflags: installflags });
|
||||
}
|
||||
}
|
||||
|
||||
function handleDeleteAccountRequest(req, res) {
|
||||
const domain = checkUserIpAddress(req, res);
|
||||
if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { res.sendStatus(404); return; }
|
||||
|
@ -2670,6 +2694,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
obj.app.post(url + 'resetpassword', handleResetPasswordRequest);
|
||||
obj.app.post(url + 'resetaccount', handleResetAccountRequest);
|
||||
obj.app.get(url + 'checkmail', handleCheckMailRequest);
|
||||
obj.app.get(url + 'agentinvite', handleAgentInviteRequest);
|
||||
obj.app.post(url + 'amtevents.ashx', obj.handleAmtEventRequest);
|
||||
obj.app.get(url + 'meshagents', obj.handleMeshAgentRequest);
|
||||
obj.app.get(url + 'messenger', handleMessengerRequest);
|
||||
|
|
Loading…
Reference in New Issue