mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-03-09 15:40:18 +00:00
Added one time passwords for user 2-factor login.
This commit is contained in:
parent
cebb0ce63e
commit
632d190d23
8 changed files with 202 additions and 123 deletions
File diff suppressed because one or more lines are too long
|
@ -241,6 +241,7 @@
|
|||
<span id="otpAuth" style="display:none"><a onclick="account_addOtp()" style="cursor:pointer">Add 2-step login</a><br /></span>
|
||||
<span id="otpAuthRemove" style="display:none"><a onclick="account_removeOtp()" style="cursor:pointer">Remove 2-step login</a><br /></span>
|
||||
</div>
|
||||
<div id="manageOtp" style="margin-top:5px;display:none"><a onclick="account_manageOtp(0)" style="cursor:pointer">One-time passwords</a></div>
|
||||
<div style="margin-top:5px"><a onclick="account_showChangeEmail()" style="cursor:pointer">Change email address</a></div>
|
||||
<div style="margin-top:5px"><a onclick="account_showChangePassword()" style="cursor:pointer">Change password</a></div>
|
||||
<div style="margin-top:5px"><a onclick="account_showDeleteAccount()" style="cursor:pointer">Delete account</a></div>
|
||||
|
@ -649,6 +650,13 @@
|
|||
xdr.send();
|
||||
}
|
||||
|
||||
function updateSelf() {
|
||||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('otpAuth', ((features & 4096) != 0) && (userinfo.otpsecret != 1));
|
||||
QV('otpAuthRemove', ((features & 4096) != 0) && (userinfo.otpsecret == 1));
|
||||
QV('manageOtp', ((features & 4096) != 0) && (userinfo.otpsecret == 1));
|
||||
}
|
||||
|
||||
function onMessage(server, message) {
|
||||
switch (message.action) {
|
||||
case 'serverinfo': {
|
||||
|
@ -661,9 +669,7 @@
|
|||
userinfo = message.userinfo;
|
||||
QH('p3userName', userinfo.name);
|
||||
//updateSiteAdmin();
|
||||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('otpAuth', ((features & 4096) != 0) && (userinfo.otpsecret != 1));
|
||||
QV('otpAuthRemove', ((features & 4096) != 0) && (userinfo.otpsecret == 1));
|
||||
updateSelf();
|
||||
break;
|
||||
}
|
||||
case 'users': {
|
||||
|
@ -744,6 +750,29 @@
|
|||
setDialogMode(2, "Remove 2-Step Login", 1, null, message.success ? "<b style=color:green>2-step login activation removed</b>. You can reactivate this feature at any time." : "<b style=color:red>2-step login activation removal failed</b>. Try again.");
|
||||
break;
|
||||
}
|
||||
case 'otpauth-getpasswords': {
|
||||
if (xxdialogMode) return;
|
||||
var x = "One time tokens can be used as secondary authentication. Generate a set, print them and keep them in a safe place.";
|
||||
x += "<div style='border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px'><div style='padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold'><table style=width:100%;text-align:center>";
|
||||
if (message.passwords) {
|
||||
var j = 0;
|
||||
for (var i in message.passwords) {
|
||||
if (++j % 2) { x += '<tr>'; }
|
||||
var p = '' + message.passwords[i].p;
|
||||
while (p.length < 8) { p = '0' + p; }
|
||||
if (message.passwords[i].u === true) { x += '<td>' + p.substring(0, 4) + ' ' + p.substring(4); } else { x += '<td><strike style=color:#BBB>' + p.substring(0, 4) + ' ' + p.substring(4); + '</strike>'; }
|
||||
}
|
||||
} else {
|
||||
x += '<tr><td>No Active Tokens';
|
||||
}
|
||||
x += "</table></div></div><br />";
|
||||
x += "<div><input type=button value='Close' onclick=setDialogMode(0) style=float:right></input>";
|
||||
x += "<input type=button value='New Tokens' onclick='account_manageOtp(1);'></input>";
|
||||
if (message.passwords != null) { x += "<input type=button value='Clear' onclick='account_manageOtp(2);'></input>"; }
|
||||
x += "</div><br />";
|
||||
setDialogMode(2, "One-Time Passwords", 8, null, x, 'otpauth-manage');
|
||||
break;
|
||||
}
|
||||
case 'event': {
|
||||
/*
|
||||
if (!message.event.nolog) {
|
||||
|
@ -762,7 +791,7 @@
|
|||
if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
|
||||
userinfo = message.event.account;
|
||||
if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
|
||||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
updateSelf();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1012,6 +1041,12 @@
|
|||
setDialogMode(2, "Remove 2-Step Login", 3, function () { meshserver.send({ action: 'otpauth-clear' }); }, "Confirm removal of 2-step login?");
|
||||
}
|
||||
|
||||
function account_manageOtp(action) {
|
||||
if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-manage')) { dialogclose(0); }
|
||||
if (xxdialogMode || (userinfo.otpsecret != 1) || ((features & 4096) == 0)) return;
|
||||
meshserver.send({ action: 'otpauth-getpasswords', subaction: action });
|
||||
}
|
||||
|
||||
function account_showVerifyEmail() {
|
||||
if (xxdialogMode || (userinfo.emailVerified == true) || (serverinfo.emailcheck != true)) return;
|
||||
var x = "Click ok to send a verification mail to:<br /><div style=padding:8px><b>" + EscapeHtml(userinfo.email) + "</b></div>Please wait a few minute to receive the verification.";
|
||||
|
|
|
@ -251,6 +251,7 @@
|
|||
<span id="verifyEmailId" style="display:none"><a onclick="account_showVerifyEmail()" style="cursor:pointer">Verify email</a><br /></span>
|
||||
<span id="otpAuth" style="display:none"><a onclick="account_addOtp()" style="cursor:pointer">Add 2-step login</a><br /></span>
|
||||
<span id="otpAuthRemove" style="display:none"><a onclick="account_removeOtp()" style="cursor:pointer">Remove 2-step login</a><br /></span>
|
||||
<span id="manageOtp" style="display:none"><a onclick="account_manageOtp(0)" style="cursor:pointer">Manage one time passwords</a><br /></span>
|
||||
<a onclick="account_showChangeEmail()" style="cursor:pointer">Change email address</a><br />
|
||||
<a onclick="account_showChangePassword()" style="cursor:pointer">Change password</a><br />
|
||||
<a onclick="account_showDeleteAccount()" style="cursor:pointer">Delete account</a><br />
|
||||
|
@ -357,10 +358,10 @@
|
|||
<h1>My Server</h1>
|
||||
<p id="p2ServerActions"><strong>Server actions</strong></p>
|
||||
<p style="margin-left:40px">
|
||||
<a id="p2ServerActionsBackup" href="/backup.zip" rel="noreferrer noopener" target="_blank" style="cursor:pointer">Download server backup</a><br />
|
||||
<a id="p2ServerActionsRestore" onclick="server_showRestoreDlg()" style="cursor:pointer">Restore server with backup</a><br />
|
||||
<a id="p2ServerActionsVersion" onclick="server_showVersionDlg()" style="cursor:pointer">Check server version</a><br />
|
||||
<a id="p2ServerActionsErrors" onclick="server_showErrorsDlg()" style="cursor:pointer">Show server error log</a><br />
|
||||
<div id="p2ServerActionsBackup" style="margin-left:40px"><a href="/backup.zip" rel="noreferrer noopener" target="_blank" style="cursor:pointer">Download server backup</a></div>
|
||||
<div id="p2ServerActionsRestore" style="margin-left:40px"><a onclick="server_showRestoreDlg()" style="cursor:pointer">Restore server with backup</a></div>
|
||||
<div id="p2ServerActionsVersion" style="margin-left:40px"><a onclick="server_showVersionDlg()" style="cursor:pointer">Check server version</a></div>
|
||||
<div id="p2ServerActionsErrors" style="margin-left:40px"><a onclick="server_showErrorsDlg()" style="cursor:pointer">Show server error log</a></div>
|
||||
</p>
|
||||
<br /><strong>Server Statistics</strong><br /><br />
|
||||
<div id="serverStats" style="margin-left:40px">
|
||||
|
@ -1107,7 +1108,7 @@
|
|||
// Update account actions
|
||||
QV('p2AccountActions', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide Account Actions if in single user mode or domain authentication
|
||||
QV('p2ServerActions', siteRights & 21);
|
||||
QV('LeftMenuMyServer', siteRights & 21);
|
||||
QV('LeftMenuMyServer', siteRights & 21); // 16 + 4 + 1
|
||||
QV('MainMenuMyServer', siteRights & 21);
|
||||
QV('p2ServerActionsBackup', siteRights & 1);
|
||||
QV('p2ServerActionsRestore', siteRights & 4);
|
||||
|
@ -1132,6 +1133,9 @@
|
|||
}
|
||||
meshserver.send({ action: 'events', limit: parseInt(p3limitdropdown.value) });
|
||||
QV('p2deleteall', userinfo.siteadmin == 0xFFFFFFFF);
|
||||
QV('ServerConsole', userinfo.siteadmin === 0xFFFFFFFF);
|
||||
if ((xxcurrentView == 115) && (userinfo.siteadmin != 0xFFFFFFFF)) { go(6); }
|
||||
if ((xxcurrentView == 6) && ((userinfo.siteadmin & 21) == 0)) { go(1); }
|
||||
|
||||
// If we are site administrator, register to get server statistics
|
||||
if ((siteRights & 21) != 0) { meshserver.send({ action: 'serverstats', interval: 10000 }); }
|
||||
|
@ -1162,6 +1166,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
function updateSelf() {
|
||||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('verifyEmailId2', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('otpAuth', ((features & 4096) != 0) && (userinfo.otpsecret != 1));
|
||||
QV('otpAuthRemove', ((features & 4096) != 0) && (userinfo.otpsecret == 1));
|
||||
QV('manageOtp', ((features & 4096) != 0) && (userinfo.otpsecret == 1));
|
||||
}
|
||||
|
||||
function onMessage(server, message) {
|
||||
switch (message.action) {
|
||||
case 'serverstats': {
|
||||
|
@ -1180,10 +1192,7 @@
|
|||
case 'userinfo': {
|
||||
userinfo = message.userinfo;
|
||||
updateSiteAdmin();
|
||||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('verifyEmailId2', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('otpAuth', ((features & 4096) != 0) && (userinfo.otpsecret != 1));
|
||||
QV('otpAuthRemove', ((features & 4096) != 0) && (userinfo.otpsecret == 1));
|
||||
updateSelf();
|
||||
break;
|
||||
}
|
||||
case 'users': {
|
||||
|
@ -1406,6 +1415,29 @@
|
|||
setDialogMode(2, "Remove 2-Step Login", 1, null, message.success ? "<b style=color:green>2-step login activation removed</b>. You can reactivate this feature at any time." : "<b style=color:red>2-step login activation removal failed</b>. Try again.");
|
||||
break;
|
||||
}
|
||||
case 'otpauth-getpasswords': {
|
||||
if (xxdialogMode) return;
|
||||
var x = "One time tokens can be used as secondary authentication. Generate a set, print them and keep them in a safe place.";
|
||||
x += "<div style='border-radius:6px;border: 2px dashed #888;width:100%;margin-top:8px'><div style='padding:8px;font-family:Arial, Helvetica, sans-serif;font-size:20px;font-weight:bold'><table style=width:100%;text-align:center>";
|
||||
if (message.passwords) {
|
||||
var j = 0;
|
||||
for (var i in message.passwords) {
|
||||
if (++j % 2) { x += '<tr>'; }
|
||||
var p = '' + message.passwords[i].p;
|
||||
while (p.length < 8) { p = '0' + p; }
|
||||
if (message.passwords[i].u === true) { x += '<td>' + p.substring(0, 4) + ' ' + p.substring(4); } else { x += '<td><strike style=color:#BBB>' + p.substring(0, 4) + ' ' + p.substring(4); + '</strike>'; }
|
||||
}
|
||||
} else {
|
||||
x += '<tr><td>No Active Tokens';
|
||||
}
|
||||
x += "</table></div></div><br />";
|
||||
x += "<div><input type=button value='Close' onclick=setDialogMode(0) style=float:right></input>";
|
||||
x += "<input type=button value='Generate New Tokens' onclick='account_manageOtp(1);'></input>";
|
||||
if (message.passwords != null) { x += "<input type=button value='Clear Tokens' onclick='account_manageOtp(2);'></input>"; }
|
||||
x += "</div><br />";
|
||||
setDialogMode(2, "Manage One Time Passwords", 8, null, x, 'otpauth-manage');
|
||||
break;
|
||||
}
|
||||
case 'event': {
|
||||
if (!message.event.nolog) {
|
||||
events.unshift(message.event);
|
||||
|
@ -1423,8 +1455,7 @@
|
|||
if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
|
||||
userinfo = message.event.account;
|
||||
if (oldsiteadmin != newsiteadmin) updateSiteAdmin();
|
||||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('verifyEmailId2', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
updateSelf();
|
||||
}
|
||||
if (users == null) break;
|
||||
users[message.event.account._id] = message.event.account;
|
||||
|
@ -4612,7 +4643,7 @@
|
|||
var h = '';
|
||||
if (f.t < 3) {
|
||||
var right = '', title = '';
|
||||
h = "<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value='" + f.nx + "'> <span style=float:right title=\"" + title + "\">" + right + "</span><span><div class=fileIcon" + f.t + "></div><a style=cursor:pointer onclick=p13folderset(\"" + encodeURIComponent(f.nx) + "\")>" + shortname + "</a></span></div>";
|
||||
h = "<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value='" + f.nx + "'> <span style=float:right title=\"" + title + "\">" + right + "</span><span><div class=fileIcon" + f.t + " onclick=p13folderset(\"" + encodeURIComponent(f.nx) + "\")></div><a style=cursor:pointer onclick=p13folderset(\"" + encodeURIComponent(f.nx) + "\")>" + shortname + "</a></span></div>";
|
||||
} else {
|
||||
var link = shortname;
|
||||
if (f.s > 0) { link = "<a rel=\"noreferrer noopener\" target=\"_blank\" style=cursor:pointer onclick=\"p13downloadfile('" + encodeURIComponent(newlinkpath + '/' + name) + "','" + encodeURIComponent(name) + "'," + f.s + ")\">" + shortname + "</a>"; }
|
||||
|
@ -5208,6 +5239,12 @@
|
|||
setDialogMode(2, "Remove 2-Step Login", 3, function () { meshserver.send({ action: 'otpauth-clear' }); }, "Confirm removal of 2-step login?");
|
||||
}
|
||||
|
||||
function account_manageOtp(action) {
|
||||
if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-manage')) { dialogclose(0); }
|
||||
if (xxdialogMode || (userinfo.otpsecret != 1) || ((features & 4096) == 0)) return;
|
||||
meshserver.send({ action: 'otpauth-getpasswords', subaction: action });
|
||||
}
|
||||
|
||||
function account_showVerifyEmail() {
|
||||
if (xxdialogMode || (userinfo.emailVerified == true) || (serverinfo.emailcheck != true)) return;
|
||||
var x = "Click ok to send a verification mail to:<br /><div style=padding:8px><b>" + EscapeHtml(userinfo.email) + "</b></div>Please wait a few minute to receive the verification.";
|
||||
|
@ -5679,7 +5716,7 @@
|
|||
var h = '';
|
||||
if (f.t < 3 || f.t == 4) {
|
||||
var right = (f.t == 1 || f.t == 4)?p5getQuotabar(f):'', title = '';
|
||||
h = "<div class=filelist file=999><input file=999 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value='" + name + "'> <span style=float:right title=\"" + title + "\">" + right + "</span><span><div class=fileIcon" + f.t + "></div><a style=cursor:pointer onclick=p5folderset(\"" + encodeURIComponent(f.nx) + "\")>" + shortname + "</a></span></div>";
|
||||
h = "<div class=filelist file=999><input file=999 style=float:left name=fc class=fcb type=checkbox onchange=p5setActions() value='" + name + "'> <span style=float:right title=\"" + title + "\">" + right + "</span><span><div class=fileIcon" + f.t + " onclick=p5folderset(\"" + encodeURIComponent(f.nx) + "\")></div><a style=cursor:pointer onclick=p5folderset(\"" + encodeURIComponent(f.nx) + "\")>" + shortname + "</a></span></div>";
|
||||
} else {
|
||||
var link = shortname;
|
||||
var publiclink = '';
|
||||
|
@ -6403,7 +6440,7 @@
|
|||
var h = '';
|
||||
if (f.t < 3) {
|
||||
var title = '';
|
||||
h = "<div class=filelist file=999><span style=float:right title=\"" + title + "\"></span><span><div class=fileIcon" + f.t + "></div> <a style=cursor:pointer onclick=d3folderset(\"" + encodeURIComponent(f.nx) + "\")>" + shortname + "</a></span></div>";
|
||||
h = "<div class=filelist file=999><span style=float:right title=\"" + title + "\"></span><span><div class=fileIcon" + f.t + " onclick=d3folderset(\"" + encodeURIComponent(f.nx) + "\")></div> <a style=cursor:pointer onclick=d3folderset(\"" + encodeURIComponent(f.nx) + "\")>" + shortname + "</a></span></div>";
|
||||
} else {
|
||||
var link = shortname;
|
||||
//if (f.s > 0) { link = "<a rel=\"noreferrer noopener\" target=\"_blank\" href=\"downloadfile.ashx?link=" + encodeURIComponent(filetreelinkpath + '/' + f.nx) + "\">" + shortname + "</a>"; }
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td align=right width=100>Login token:</td>
|
||||
<td><input id=tokenInput type=text name=token maxlength=6 onkeypress="return (event.keyCode == 8) || (event.keyCode == 13) || (event.charCode >= 48 && event.charCode <= 57)" onkeyup=checkToken(event) onkeydown=checkToken(event) /></td>
|
||||
<td><input id=tokenInput type=text name=token maxlength=12 onkeypress="return (event.keyCode == 8) || (event.keyCode == 13) || (event.charCode >= 48 && event.charCode <= 57)" onkeyup=checkToken(event) onkeydown=checkToken(event) /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2>
|
||||
|
@ -328,7 +328,12 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
function checkToken() { QE('tokenOkButton', Q('tokenInput').value.length == 6); }
|
||||
function checkToken() {
|
||||
var t1 = Q('tokenInput').value;
|
||||
var t2 = t1.replace(/\D/g, '');
|
||||
if (t1 != t2) { Q('tokenInput').value = t2; }
|
||||
QE('tokenOkButton', (Q('tokenInput').value.length == 6) || (Q('tokenInput').value.length == 8));
|
||||
}
|
||||
|
||||
//
|
||||
// POPUP DIALOG
|
||||
|
|
|
@ -221,7 +221,7 @@
|
|||
<table>
|
||||
<tr>
|
||||
<td align=right width=100>Login token:</td>
|
||||
<td><input id=tokenInput type=text name=token maxlength=6 onkeypress="return (event.keyCode == 8) || (event.keyCode == 13) || (event.charCode >= 48 && event.charCode <= 57)" onkeyup=checkToken(event) onkeydown=checkToken(event) /></td>
|
||||
<td><input id=tokenInput type=text name=token maxlength=12 onkeypress="return (event.keyCode == 8) || (event.keyCode == 13) || (event.charCode >= 48 && event.charCode <= 57)" onkeyup=checkToken(event) onkeydown=checkToken(event) /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2>
|
||||
|
@ -423,7 +423,12 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
function checkToken() { QE('tokenOkButton', Q('tokenInput').value.length == 6); }
|
||||
function checkToken() {
|
||||
var t1 = Q('tokenInput').value;
|
||||
var t2 = t1.replace(/\D/g, '');
|
||||
if (t1 != t2) { Q('tokenInput').value = t2; }
|
||||
QE('tokenOkButton', (Q('tokenInput').value.length == 6) || (Q('tokenInput').value.length == 8));
|
||||
}
|
||||
|
||||
//
|
||||
// POPUP DIALOG
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue