From 9e94aba64915ebccf37e7aecfdbb76e73e36c672 Mon Sep 17 00:00:00 2001
From: "Shishkevich D." <135337715+shishkevichd@users.noreply.github.com>
Date: Wed, 7 May 2025 02:33:50 +0000
Subject: [PATCH] chore: replace two factor token input with qr-code
---
web/assets/js/util/index.js | 8 ++++++-
web/html/settings.html | 30 ++++++++++++++++++++++++++-
web/html/settings/panel/security.html | 15 +++++++++++---
3 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/web/assets/js/util/index.js b/web/assets/js/util/index.js
index 0d869af6..782b4377 100644
--- a/web/assets/js/util/index.js
+++ b/web/assets/js/util/index.js
@@ -512,7 +512,7 @@ class Wireguard {
}
class ClipboardManager {
- static copyText(content = "") {
+ static copyText(content = "", hasSuccessCopyMessage = false, successCopyMessage = '') {
// !! here old way of copying is used because not everyone can afford https connection
return new Promise((resolve) => {
try {
@@ -535,6 +535,12 @@ class ClipboardManager {
window.document.body.removeChild(textarea);
+ if (
+ hasSuccessCopyMessage
+ ) {
+ Vue.prototype.$message['success'](successCopyMessage)
+ }
+
resolve(true)
} catch {
resolve(false)
diff --git a/web/html/settings.html b/web/html/settings.html
index 75cadc51..f4134c76 100644
--- a/web/html/settings.html
+++ b/web/html/settings.html
@@ -122,6 +122,7 @@
{{template "js" .}}
+
{{template "component/aSidebar" .}}
{{template "component/aThemeSwitch" .}}
@@ -140,6 +141,7 @@
lang: LanguageManager.getLanguage(),
remarkModels: { i: 'Inbound', e: 'Email', o: 'Other' },
remarkSeparators: [' ', '-', '_', '@', ':', '~', '|', ',', '.', '/'],
+ twoFactor: { qrElement: null },
datepickerList: [{ name: 'Gregorian (Standard)', value: 'gregorian' }, { name: 'Jalalian (شمسی)', value: 'jalalian' }],
remarkSample: '',
defaultFragment: {
@@ -302,9 +304,22 @@
},
toggleTwoFactor(newValue) {
if (newValue) {
- this.allSetting.twoFactorToken = RandomUtil.randomBase32String();
+ const newTwoFactorToken = RandomUtil.randomBase32String();
+
+ this.allSetting.twoFactorToken = newTwoFactorToken;
+
+ this.twoFactor.qrElement = new QRious({
+ size: 150,
+ value: `otpauth://totp/3x-ui:Administrator?secret=${newTwoFactorToken}&issuer=3x-ui`,
+ background: 'white',
+ backgroundAlpha: 0,
+ foreground: 'black',
+ padding: 12,
+ level: 'L'
+ })
} else {
this.allSetting.twoFactorToken = "";
+ this.twoFactor.qrElement = null;
}
},
addNoise() {
@@ -497,6 +512,19 @@
},
async mounted() {
await this.getAllSetting();
+
+ if (this.allSetting.twoFactorEnable) {
+ this.twoFactor.qrElement = new QRious({
+ size: 150,
+ value: `otpauth://totp/3x-ui:Administrator?secret=${this.allSetting.twoFactorToken}&issuer=3x-ui`,
+ background: 'white',
+ backgroundAlpha: 0,
+ foreground: 'black',
+ padding: 12,
+ level: 'L'
+ })
+ }
+
while (true) {
await PromiseUtil.sleep(1000);
this.saveBtnDisable = this.oldAllSetting.equals(this.allSetting);
diff --git a/web/html/settings/panel/security.html b/web/html/settings/panel/security.html
index 4abad4c7..3afdc482 100644
--- a/web/html/settings/panel/security.html
+++ b/web/html/settings/panel/security.html
@@ -43,9 +43,18 @@
{{ i18n "pages.settings.security.twoFactorToken" }}
{{ i18n "pages.settings.security.twoFactorTokenDesc" }}
-
-
-
+
+
+
![]()
+
+
+
+ {{ i18n "copy" }}
+
+
+
+