fix 2fa modal issues in modern ui #6925

Signed-off-by: si458 <simonsmith5521@gmail.com>

si458 committed Mar 26, 2025 at 14:54 UTC fee02a17ff0b5cde2c683ce7f94d474e799a67dc
2 files changed +18 -18
views/default.handlebars
-1
@@ -12920,7 +12920,6 @@
12920 if (serverinfo.discordUrl) { x += '<div id=d2discordurl style=display:none><br /><a href=' + serverinfo.discordUrl + ' target="_discord">' + "Join this Discord server to receive notifications." + '</a></div>'; }
12921 x += '<div id=d2callmebotinfo style=display:none><br /><a href=https://www.callmebot.com/blog/free-api-signal-send-messages/ target="_callmebot">' + "Signal" + '</a>, <a href=https://www.callmebot.com/blog/free-api-whatsapp-messages/ target="_callmebot">' + "Whatsapp" + '</a>, <a href=https://www.callmebot.com/blog/free-api-facebook-messenger/ target="_callmebot">' + "Facebook" + '</a>, <a href=https://www.callmebot.com/blog/telegram-text-messages/ target="_callmebot">' + "Telegram" + '</a></div>';
12922 x += '<div id=d2pushoverinfo style=display:none><br /><a href=https://pushover.net/ target="_pushover">' + "Information at Pushover.net" + '</a></div>';
12923 - console.log(serverinfo.userMsgNftyUrl);
12923 x += '<div id=d2ntfyinfo style=display:none><br /><a href="' + (serverinfo.userMsgNftyUrl ? serverinfo.userMsgNftyUrl : 'https://ntfy.sh/') + '" target="_ntfy">' + "Free service at ntfy.sh" + '</a></div>';
12924 x += '<div id=d2slackinfo style=display:none><br /><a href=https://api.slack.com/messaging/webhooks target="_slack">' + "Slack Webhook Setup" + '</a></div>';
12925 setDialogMode(2, "Messaging Notifications", 3, account_manageMessagingAdd, x, 'verifyMessaging');
views/default3.handlebars
+18 -17
@@ -3506,7 +3506,7 @@
3506 var secret = message.secret;
3507 if (secret.length == 52) { secret = secret.split(/(.............)/).filter(Boolean).join(' '); }
3508 else if (secret.length == 32) { secret = secret.split(/(....)/).filter(Boolean).join(' '); secret = secret.substring(0, 20) + '<br/>' + secret.substring(20) }
3509 - QH('d2optinfo', '<table style=width:380px><tr><td style=vertical-align:top>' + format("Install" + ' <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" rel="noreferrer noopener" target=_blank>' + "Google Authenticator" + '</a> ' + "or a compatible application and scan the barcode, use <a href=\"{0}\" rel=\"noreferrer noopener\" target=_blank>this link</a> or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login.", message.url) + '<br /><br />' + 'Secret <img src=images/link4.png height=10 width=10 title="' + "Copy Secret to clipboard" + '" style=cursor:pointer onclick=d2CopySecretToClip()>' + '<br /><tt id=d2optsecret secret="' + message.secret + '" style=font-size:12px>' + secret + '</tt><br /><br /></td><td style=width:1px;vertical-align:top><a href="' + message.url + '" rel="noreferrer noopener" target=_blank><div id="qrcode"></div></a></td><tr><td colspan=2 style="text-align:center;border-top:1px solid black"><br />' + "Enter the token here for 2-step login:" + ' <input type=text autocomplete="one-time-code" inputmode="numeric" pattern="[0-9]*" onkeypress="return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></td></table>');
3509 + QH('d2optinfo', '<table><tr><td style=vertical-align:top>' + format("Install" + ' <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" rel="noreferrer noopener" target=_blank>' + "Google Authenticator" + '</a> ' + "or a compatible application and scan the barcode, use <a href=\"{0}\" rel=\"noreferrer noopener\" target=_blank>this link</a> or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login.", message.url) + '<br /><br />' + 'Secret <img src=images/link4.png height=10 width=10 title="' + "Copy Secret to clipboard" + '" style=cursor:pointer onclick=d2CopySecretToClip()>' + '<br /><tt id=d2optsecret secret="' + message.secret + '" style=font-size:12px>' + secret + '</tt><br /><br /></td><td style=width:1px;vertical-align:top><a href="' + message.url + '" rel="noreferrer noopener" target=_blank><div id="qrcode"></div></a></td><tr><td colspan=2 style="text-align:center;border-top:1px solid black"><br />' + "Enter the token here for 2-step login:" + ' <input type=text autocomplete="one-time-code" inputmode="numeric" pattern="[0-9]*" onkeypress="return (event.keyCode == 8) || (event.charCode >= 48 && event.charCode <= 57)" onkeyup=account_addOtpCheck(event) onkeydown=account_addOtpCheck() maxlength=6 id=d2otpauthinput type=text></td></table>');
3510 new QRCode(Q('qrcode'), { text: message.url, width: 128, height: 128, colorDark: '#000000', colorLight: '#EEE', correctLevel: QRCode.CorrectLevel.H });
3511 QV('idx_dlgOkButton', true);
3512 QE('idx_dlgOkButton', false);
@@ -3528,7 +3528,7 @@
3528 break;
3529 }
3530 case 'otpauth-getpasswords': {
3531 - if (xxdialogMode) return;
3531 + if (xxdialogMode == 2 && (xxdialogTag != 'otpauth-manage')) return;
3532 var x = "One time tokens can be used as secondary authentication. Generate a set, print them and keep them in a safe place.";
3533 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 class=selecttext style=width:100%;text-align:center>';
3534 if (message.passwords) {
@@ -3549,13 +3549,15 @@
3549 x += '<tr><td>' + "No Active Tokens";
3550 }
3551 x += '</table></div></div><br />';
3552 - x += '<div>';
3553 - x += '<input type=button value="' + "Generate New Tokens" + '" onclick="account_manageOtp(1);"></input>';
3552 + x += '<div class="btn-group">';
3553 + x += '<button type=button class="btn btn-warning" onclick="account_manageOtp(1);">' + "Generate New Tokens" + '</input>';
3554 if (message.passwords != null) {
3555 - x += '<input type=button value="' + "Clear Tokens" + '" onclick="account_manageOtp(2);"></input>';
3556 - x += '&nbsp;<img src=images/link4.png height=10 width=10 title="' + "Copy valid codes to clipboard" + '" style=cursor:pointer onclick=copyTextToClip2("' + encodeURIComponentEx(clipb) + '")>';
3555 + x += '<button type=button class="btn btn-danger" onclick="account_manageOtp(2);">' + "Clear Tokens" + '</button></div>';
3556 + x += '&nbsp;<i class="fa-regular fa-clipboard" title="' + "Copy valid codes to clipboard" + '" style="cursor:pointer" onclick=copyTextToClip2("' + encodeURIComponentEx(clipb) + '")></i>';
3557 + } else {
3558 + x += '</div>'
3559 }
3558 - x += '</div><br />';
3560 + xxdialogTag = 'otpauth-manage';
3561 setModalContent('xxAddAgent', "Manage Backup Codes", x);
3562 showModal('xxAddAgentModal', 'idx_dlgOkButton');
3563 break;
@@ -3569,7 +3571,7 @@
3571 if (message.keys && message.keys.length > 0) {
3572 for (var i in message.keys) {
3573 var key = message.keys[i], type = (key.type == 2) ? 'OTP' : 'WebAuthn';
3572 - x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td><input type=button value="' + "Remove" + '" onclick=account_removehkey(' + key.i + ')></input>' + end;
3574 + x += start + '<tr style=margin:5px><td style=width:30px><img width=24 height=18 src="images/hardware-key-' + type + '-24.png" style=margin-top:4px><td style=width:250px>' + key.name + '<td style=text-align:right><button type=button class="btn btn-danger" onclick=account_removehkey(' + key.i + ')>' + "Remove" + '</button>' + end;
3575 }
3576 } else {
3577 x += start + '<tr style=text-align:center><td>' + "No Keys Configured" + end;
@@ -3578,12 +3580,13 @@
3580 x += '<div>';
3581 var hkeycount = (typeof userinfo.otphkeys == 'number') ? userinfo.otphkeys : 0;
3582 if ((typeof serverinfo.maxfidokeys != 'number') || (serverinfo.maxfidokeys > hkeycount)) { // Check if we we reached maximum hardware keys
3581 - if ((features & 0x00020000) != 0) { x += '<input id=d2addkey3 type=button value="' + "Add Key" + '" onclick="account_addhkey(3);"></input>'; }
3582 - if ((features & 0x00004000) != 0) { x += '<input id=d2addkey2 type=button value="' + "Add YubiKey&reg; OTP" + '" onclick="account_addhkey(2);"></input>'; }
3583 + if ((features & 0x00020000) != 0) { x += '<button class="btn btn-primary" id=d2addkey3 type=button onclick="account_addhkey(3);">' + "Add Key" + '</input>'; }
3584 + if ((features & 0x00004000) != 0) { x += '<button class="btn btn-primary" id=d2addkey2 type=button onclick="account_addhkey(2);">' + "Add YubiKey&reg; OTP" +'</input>'; }
3585 } else {
3586 x += "Maximum keys reached.";
3587 }
3588 x += '</div><br />';
3589 + xxdialogTag = 'otpauth-hardware-manage';
3590 setModalContent('xxAddAgent', "Manage Security Keys", x);
3591 showModal('xxAddAgentModal', 'idx_dlgOkButton');
3592 if (u2fSupported() == false) { QE('d2addkey1', false); }
@@ -3619,7 +3622,6 @@
3622 navigator.credentials.create({ publicKey: publicKey }).then(function (newCredentialInfo) {
3623 // Public key credential
3624 meshserver.send({ action: 'webauthn-endregister', response: { rawId: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.rawId))), response: { attestationObject: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.response.attestationObject))), clientDataJSON: btoa(String.fromCharCode.apply(null, new Uint8Array(newCredentialInfo.response.clientDataJSON))) }, type: newCredentialInfo.type } });
3622 - setDialogMode(0);
3625 }, function (error) {
3626 // Error
3627 console.log("ERROR: " + error);
@@ -13764,12 +13766,11 @@
13766 if (serverinfo.discordUrl) { x += '<div id=d2discordurl style=display:none><br /><a href=' + serverinfo.discordUrl + ' target="_discord">' + "Join this Discord server to receive notifications." + '</a></div>'; }
13767 x += '<div id=d2callmebotinfo style=display:none><br /><a href=https://www.callmebot.com/blog/free-api-signal-send-messages/ target="_callmebot">' + "Signal" + '</a>, <a href=https://www.callmebot.com/blog/free-api-whatsapp-messages/ target="_callmebot">' + "Whatsapp" + '</a>, <a href=https://www.callmebot.com/blog/free-api-facebook-messenger/ target="_callmebot">' + "Facebook" + '</a>, <a href=https://www.callmebot.com/blog/telegram-text-messages/ target="_callmebot">' + "Telegram" + '</a></div>';
13768 x += '<div id=d2pushoverinfo style=display:none><br /><a href=https://pushover.net/ target="_pushover">' + "Information at Pushover.net" + '</a></div>';
13767 - console.log(serverinfo.userMsgNftyUrl);
13769 x += '<div id=d2ntfyinfo style=display:none><br /><a href="' + (serverinfo.userMsgNftyUrl ? serverinfo.userMsgNftyUrl : 'https://ntfy.sh/') + '" target="_ntfy">' + "Free service at ntfy.sh" + '</a></div>';
13770 x += '<div id=d2slackinfo style=display:none><br /><a href=https://api.slack.com/messaging/webhooks target="_slack">' + "Slack Webhook Setup" + '</a></div>';
13771 xxdialogTag = 'VerifyMessaging';
13772 setModalContent('xxAddAgent', "Messaging Notifications", x);
13772 - showModal('xxAddAgentModal', 'idx_dlgOkButton', account_manageMessagingAdd());
13773 + showModal('xxAddAgentModal', 'idx_dlgOkButton', () => account_manageMessagingAdd());
13774 Q('d2handleinput').focus();
13775 account_manageMessagingValidate();
13776 }
@@ -13791,7 +13792,7 @@
13792 else { Q('d2handleinput')['placeholder'] = "Username"; }
13793 var ok = (Q('d2handleinput').value.length > 0); QE('idx_dlgOkButton', ok); if ((x == 1) && ok) { dialogclose(1); }
13794 }
13794 - function account_manageMessagingAdd() { if (Q('d2handleinput').value.length == 0) return; QE('d2handleinput', false); meshserver.send({ action: 'verifyMessaging', service: Q('d2serviceselect').value, handle: Q('d2handleinput').value }); }
13795 + function account_manageMessagingAdd() { if (Q('d2handleinput').value.length == 0) return; QE('d2handleinput', false); meshserver.send({ action: 'verifyMessaging', service: Q('d2serviceselect').value, handle: Q('d2handleinput').value }); return false; }
13796 function account_manageMessagingConfirm(b, tag) { meshserver.send({ action: 'confirmMessaging', code: Q('d2phoneCodeInput').value, cookie: tag }); }
13797 function account_manageMessagingRemove() { if (Q('d2delPhone').checked) { meshserver.send({ action: 'removeMessaging' }); } }
13798
@@ -13835,7 +13836,7 @@
13836 if (xxdialogMode || (userinfo.otpsecret == 1) || ((features & 4096) == 0)) return;
13837 xxdialogTag = 'otpauth-request';
13838 setModalContent('xxAddAgent', "Authenticator App", ('<div id=d2optinfo>' + "Loading..." + '</div>'));
13838 - showModal('xxAddAgentModal', 'idx_dlgOkButton', function () { meshserver.send({ action: 'otpauth-setup', secret: Q('d2optsecret').attributes.secret.value, token: Q('d2otpauthinput').value }); });
13839 + showModal('xxAddAgentModal', 'idx_dlgOkButton', function () { meshserver.send({ action: 'otpauth-setup', secret: Q('d2optsecret').attributes.secret.value, token: Q('d2otpauthinput').value }); return false; });
13840 meshserver.send({ action: 'otpauth-request' });
13841 }
13842
@@ -13852,8 +13853,7 @@
13853 }
13854
13855 function account_manageOtp(action) {
13855 - if ((xxdialogMode == 2) && (xxdialogTag == 'otpauth-manage')) { dialogclose(0); }
13856 - if (xxdialogMode || ((features & 4096) == 0)) return false;
13856 + if ((features & 4096) == 0) return false;
13857 if (count2factoraAuths() > 0) { meshserver.send({ action: 'otpauth-getpasswords', subaction: action }); }
13858 return false;
13859 }
@@ -13921,6 +13921,7 @@
13921 showModal('xxAddAgentModal', 'idx_dlgOkButton');
13922 } else if (type == 3) {
13923 meshserver.send({ action: 'webauthn-startregister', name: name });
13924 + return false;
13925 }
13926 }
13927