1
0
Эх сурвалжийг харах

chore: reset two-factor authentication after changing admin credentials (#3029)

* chore: add `resetTwoFactor` argument for main.go

fixes #3025

* chore: reset two-factor authentication after changing admin credentials

* chore: reset two-factor authentication after changing admin credentials

---------

Co-authored-by: somebodywashere <[email protected]>
Co-authored-by: Sanaei <[email protected]>
Shishkevich D. 23 цаг өмнө
parent
commit
5d11e6e13f

+ 15 - 2
main.go

@@ -232,7 +232,7 @@ func updateTgbotSetting(tgBotToken string, tgBotChatid string, tgBotRuntime stri
 	}
 }
 
-func updateSetting(port int, username string, password string, webBasePath string, listenIP string) {
+func updateSetting(port int, username string, password string, webBasePath string, listenIP string, resetTwoFactor bool) {
 	err := database.InitDB(config.GetDBPath())
 	if err != nil {
 		fmt.Println("Database initialization failed:", err)
@@ -269,6 +269,17 @@ func updateSetting(port int, username string, password string, webBasePath strin
 		}
 	}
 
+	if resetTwoFactor {
+		err := settingService.SetTwoFactorEnable(false)
+
+		if err != nil {
+			fmt.Println("Failed to reset two-factor authentication:", err)
+		} else {
+			settingService.SetTwoFactorToken("")
+			fmt.Println("Two-factor authentication reset successfully")
+		}
+	}
+
 	if listenIP != "" {
 		err := settingService.SetListen(listenIP)
 		if err != nil {
@@ -376,6 +387,7 @@ func main() {
 	var reset bool
 	var show bool
 	var getCert bool
+	var resetTwoFactor bool
 	settingCmd.BoolVar(&reset, "reset", false, "Reset all settings")
 	settingCmd.BoolVar(&show, "show", false, "Display current settings")
 	settingCmd.IntVar(&port, "port", 0, "Set panel port number")
@@ -383,6 +395,7 @@ func main() {
 	settingCmd.StringVar(&password, "password", "", "Set login password")
 	settingCmd.StringVar(&webBasePath, "webBasePath", "", "Set base path for Panel")
 	settingCmd.StringVar(&listenIP, "listenIP", "", "set panel listenIP IP")
+	settingCmd.BoolVar(&resetTwoFactor, "resetTwoFactor", false, "Reset two-factor authentication settings")
 	settingCmd.BoolVar(&getListen, "getListen", false, "Display current panel listenIP IP")
 	settingCmd.BoolVar(&getCert, "getCert", false, "Display current certificate settings")
 	settingCmd.StringVar(&webCertFile, "webCert", "", "Set path to public key file for panel")
@@ -427,7 +440,7 @@ func main() {
 		if reset {
 			resetSetting()
 		} else {
-			updateSetting(port, username, password, webBasePath, listenIP)
+			updateSetting(port, username, password, webBasePath, listenIP, resetTwoFactor)
 		}
 		if show {
 			showSetting(show)

+ 5 - 13
web/html/modals/two_factor_modal.html

@@ -15,8 +15,8 @@
         <p>{{ i18n "pages.settings.security.twoFactorModalSecondStep" }}</p>
         <a-input v-model.trim="twoFactorModal.enteredCode" :style="{ width: '100%' }"></a-input>
     </template>
-    <template v-if="twoFactorModal.type === 'remove'">
-        <p>{{ i18n "pages.settings.security.twoFactorModalRemoveStep" }}</p>
+    <template v-if="twoFactorModal.type === 'confirm'">
+        <p>[[ twoFactorModal.description ]]</p>
         <a-input v-model.trim="twoFactorModal.enteredCode" :style="{ width: '100%' }"></a-input>
     </template>
     <template slot="footer">
@@ -32,6 +32,7 @@
 <script>
     const twoFactorModal = {
         title: '',
+        description: '',
         fileName: '',
         token: '',
         enteredCode: '',
@@ -45,17 +46,6 @@
                 ObjectUtil.execute(twoFactorModal.confirm, true)
 
                 twoFactorModal.close()
-
-                switch (twoFactorModal.type) {
-                    case 'set':
-                        Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalSetSuccess" }}')
-                        break;
-                    case 'remove':
-                        Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalDeleteSuccess" }}')
-                        break;
-                    default:
-                        break;
-                }
             } else {
                 Vue.prototype.$message['error']('{{ i18n "pages.settings.security.twoFactorModalError" }}')
             }
@@ -67,11 +57,13 @@
         },
         show: function ({
             title = '',
+            description = '',
             token = '',
             type = 'set',
             confirm = (success) => { }
         }) {
             this.title = title;
+            this.description = description;
             this.token = token;
             this.visible = true;
             this.confirm = confirm;

+ 30 - 7
web/html/settings.html

@@ -310,12 +310,30 @@
         }
       },
       async updateUser() {
-        this.loading(true);
-        const msg = await HttpUtil.post("/panel/setting/updateUser", this.user);
-        this.loading(false);
-        if (msg.success) {
-          this.user = {};
-          window.location.replace(basePath + "logout");
+        const sendUpdateUserRequest = async () => {
+          this.loading(true);
+          const msg = await HttpUtil.post("/panel/setting/updateUser", this.user);
+          this.loading(false);
+          if (msg.success) {
+            this.user = {};
+            window.location.replace(basePath + "logout");
+          }
+        }
+
+        if (this.allSetting.twoFactorEnable) {
+          twoFactorModal.show({
+            title: '{{ i18n "pages.settings.security.twoFactorModalChangeCredentialsTitle" }}',
+            description: '{{ i18n "pages.settings.security.twoFactorModalChangeCredentialsStep" }}',
+            token: this.allSetting.twoFactorToken,
+            type: 'confirm',
+            confirm: (success) => {
+              if (success) {
+                sendUpdateUserRequest();
+              }
+            }
+          })
+        } else {
+          sendUpdateUserRequest();
         }
       },
       async restartPanel() {
@@ -353,6 +371,8 @@
             type: 'set',
             confirm: (success) => {
               if (success) {
+                Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalSetSuccess" }}')
+
                 this.allSetting.twoFactorToken = newTwoFactorToken
               }
 
@@ -362,10 +382,13 @@
         } else {
           twoFactorModal.show({
             title: '{{ i18n "pages.settings.security.twoFactorModalDeleteTitle" }}',
+            description: '{{ i18n "pages.settings.security.twoFactorModalRemoveStep" }}',
             token: this.allSetting.twoFactorToken,
-            type: 'remove',
+            type: 'confirm',
             confirm: (success) => {
               if (success) {
+                Vue.prototype.$message['success']('{{ i18n "pages.settings.security.twoFactorModalDeleteSuccess" }}')
+
                 this.allSetting.twoFactorEnable = false
                 this.allSetting.twoFactorToken = ""
               }

+ 8 - 0
web/service/setting.go

@@ -322,10 +322,18 @@ func (s *SettingService) GetTwoFactorEnable() (bool, error) {
 	return s.getBool("twoFactorEnable")
 }
 
+func (s *SettingService) SetTwoFactorEnable(value bool) error {
+	return s.setBool("twoFactorEnable", value)
+}
+
 func (s *SettingService) GetTwoFactorToken() (string, error) {
 	return s.getString("twoFactorToken")
 }
 
+func (s *SettingService) SetTwoFactorToken(value string) error {
+	return s.setString("twoFactorToken", value)
+}
+
 func (s *SettingService) GetPort() (int, error) {
 	return s.getInt("webPort")
 }

+ 10 - 0
web/service/user.go

@@ -79,6 +79,16 @@ func (s *UserService) UpdateUser(id int, username string, password string) error
 		return err
 	}
 
+	twoFactorEnable, err := s.settingService.GetTwoFactorEnable()
+	if err != nil {
+		return err
+	}
+
+	if twoFactorEnable {
+		s.settingService.SetTwoFactorEnable(false)
+		s.settingService.SetTwoFactorToken("")
+	}
+
 	return db.Model(model.User{}).
 		Where("id = ?", id).
 		Updates(map[string]any{"username": username, "password": hashedPassword}).

+ 2 - 0
web/translation/translate.ar_EG.toml

@@ -542,6 +542,8 @@
 "twoFactorModalFirstStep" = "1. امسح رمز QR هذا في تطبيق المصادقة أو انسخ الرمز الموجود بجانب رمز QR والصقه في التطبيق"
 "twoFactorModalSecondStep" = "2. أدخل الرمز من التطبيق"
 "twoFactorModalRemoveStep" = "أدخل الرمز من التطبيق لإزالة المصادقة الثنائية."
+"twoFactorModalChangeCredentialsTitle" = "تغيير بيانات الاعتماد"
+"twoFactorModalChangeCredentialsStep" = "أدخل الرمز من التطبيق لتغيير بيانات اعتماد المسؤول."
 "twoFactorModalSetSuccess" = "تم إنشاء المصادقة الثنائية بنجاح"
 "twoFactorModalDeleteSuccess" = "تم حذف المصادقة الثنائية بنجاح"
 "twoFactorModalError" = "رمز خاطئ"

+ 2 - 0
web/translation/translate.en_US.toml

@@ -541,6 +541,8 @@
 "twoFactorModalFirstStep" = "1. Scan this QR code in the app for authentication or copy the token near the QR code and paste it into the app"
 "twoFactorModalSecondStep" = "2. Enter the code from the app"
 "twoFactorModalRemoveStep" = "Enter the code from the application to remove two-factor authentication."
+"twoFactorModalChangeCredentialsTitle" = "Change credentials"
+"twoFactorModalChangeCredentialsStep" = "Enter the code from the application to change administrator credentials."
 "twoFactorModalSetSuccess" = "Two-factor authentication has been successfully established"
 "twoFactorModalDeleteSuccess" = "Two-factor authentication has been successfully deleted"
 "twoFactorModalError" = "Wrong code"

+ 2 - 0
web/translation/translate.es_ES.toml

@@ -544,6 +544,8 @@
 "twoFactorModalFirstStep" = "1. Escanea este código QR en la aplicación de autenticación o copia el token cerca del código QR y pégalo en la aplicación"
 "twoFactorModalSecondStep" = "2. Ingresa el código de la aplicación"
 "twoFactorModalRemoveStep" = "Ingresa el código de la aplicación para eliminar la autenticación de dos factores."
+"twoFactorModalChangeCredentialsTitle" = "Cambiar credenciales"
+"twoFactorModalChangeCredentialsStep" = "Ingrese el código de la aplicación para cambiar las credenciales del administrador."
 "twoFactorModalSetSuccess" = "La autenticación de dos factores se ha establecido con éxito"
 "twoFactorModalDeleteSuccess" = "La autenticación de dos factores se ha eliminado con éxito"
 "twoFactorModalError" = "Código incorrecto"

+ 2 - 0
web/translation/translate.fa_IR.toml

@@ -544,6 +544,8 @@
 "twoFactorModalFirstStep" = "1. این کد QR را در برنامه احراز هویت اسکن کنید یا توکن کنار کد QR را کپی کرده و در برنامه بچسبانید"
 "twoFactorModalSecondStep" = "2. کد را از برنامه وارد کنید"
 "twoFactorModalRemoveStep" = "برای حذف احراز هویت دو مرحله‌ای، کد را از برنامه وارد کنید."
+"twoFactorModalChangeCredentialsTitle" = "تغییر اعتبارنامه‌ها"
+"twoFactorModalChangeCredentialsStep" = "برای تغییر اعتبارنامه‌های مدیر، کد را از برنامه وارد کنید."
 "twoFactorModalSetSuccess" = "احراز هویت دو مرحله‌ای با موفقیت برقرار شد"
 "twoFactorModalDeleteSuccess" = "احراز هویت دو مرحله‌ای با موفقیت حذف شد"
 "twoFactorModalError" = "کد نادرست"

+ 2 - 0
web/translation/translate.id_ID.toml

@@ -545,6 +545,8 @@
 "twoFactorModalFirstStep" = "1. Pindai kode QR ini di aplikasi autentikasi atau salin token di dekat kode QR dan tempelkan ke aplikasi"
 "twoFactorModalSecondStep" = "2. Masukkan kode dari aplikasi"
 "twoFactorModalRemoveStep" = "Masukkan kode dari aplikasi untuk menghapus autentikasi dua faktor."
+"twoFactorModalChangeCredentialsTitle" = "Ubah kredensial"
+"twoFactorModalChangeCredentialsStep" = "Masukkan kode dari aplikasi untuk mengubah kredensial administrator."
 "twoFactorModalSetSuccess" = "Autentikasi dua faktor telah berhasil dibuat"
 "twoFactorModalDeleteSuccess" = "Autentikasi dua faktor telah berhasil dihapus"
 "twoFactorModalError" = "Kode salah"

+ 2 - 0
web/translation/translate.ja_JP.toml

@@ -544,6 +544,8 @@
 "twoFactorModalFirstStep" = "1. 認証アプリでこのQRコードをスキャンするか、QRコード近くのトークンをコピーしてアプリに貼り付けます"
 "twoFactorModalSecondStep" = "2. アプリからコードを入力してください"
 "twoFactorModalRemoveStep" = "二段階認証を削除するには、アプリからコードを入力してください。"
+"twoFactorModalChangeCredentialsTitle" = "認証情報の変更"
+"twoFactorModalChangeCredentialsStep" = "管理者の認証情報を変更するには、アプリケーションからコードを入力してください。"
 "twoFactorModalSetSuccess" = "二要素認証が正常に設定されました"
 "twoFactorModalDeleteSuccess" = "二要素認証が正常に削除されました"
 "twoFactorModalError" = "コードが間違っています"

+ 2 - 0
web/translation/translate.pt_BR.toml

@@ -544,6 +544,8 @@
 "twoFactorModalFirstStep" = "1. Escaneie este QR code no aplicativo de autenticação ou copie o token próximo ao QR code e cole no aplicativo"
 "twoFactorModalSecondStep" = "2. Digite o código do aplicativo"
 "twoFactorModalRemoveStep" = "Digite o código do aplicativo para remover a autenticação de dois fatores."
+"twoFactorModalChangeCredentialsTitle" = "Alterar credenciais"
+"twoFactorModalChangeCredentialsStep" = "Insira o código do aplicativo para alterar as credenciais do administrador."
 "twoFactorModalSetSuccess" = "A autenticação de dois fatores foi estabelecida com sucesso"
 "twoFactorModalDeleteSuccess" = "A autenticação de dois fatores foi excluída com sucesso"
 "twoFactorModalError" = "Código incorreto"

+ 2 - 0
web/translation/translate.ru_RU.toml

@@ -544,6 +544,8 @@
 "twoFactorModalFirstStep" = "1. Отсканируйте этот QR-код в приложении для аутентификации или скопируйте токен рядом с QR-кодом и вставьте его в приложение"
 "twoFactorModalSecondStep" = "2. Введите код из приложения"
 "twoFactorModalRemoveStep" = "Введите код из приложения, чтобы отключить двухфакторную аутентификацию."
+"twoFactorModalChangeCredentialsTitle" = "Изменить учетные данные"
+"twoFactorModalChangeCredentialsStep" = "Введите код из приложения, чтобы изменить учетные данные администратора."
 "twoFactorModalSetSuccess" = "Двухфакторная аутентификация была успешно установлена"
 "twoFactorModalDeleteSuccess" = "Двухфакторная аутентификация была успешно удалена"
 "twoFactorModalError" = "Неверный код"

+ 2 - 0
web/translation/translate.tr_TR.toml

@@ -544,6 +544,8 @@
 "twoFactorModalFirstStep" = "1. Bu QR kodunu doğrulama uygulamasında tarayın veya QR kodunun yanındaki token'ı kopyalayıp uygulamaya yapıştırın"
 "twoFactorModalSecondStep" = "2. Uygulamadaki kodu girin"
 "twoFactorModalRemoveStep" = "İki adımlı doğrulamayı kaldırmak için uygulamadaki kodu girin."
+"twoFactorModalChangeCredentialsTitle" = "Kimlik bilgilerini değiştir"
+"twoFactorModalChangeCredentialsStep" = "Yönetici kimlik bilgilerini değiştirmek için uygulamadaki kodu girin."
 "twoFactorModalSetSuccess" = "İki faktörlü kimlik doğrulama başarıyla kuruldu"
 "twoFactorModalDeleteSuccess" = "İki faktörlü kimlik doğrulama başarıyla silindi"
 "twoFactorModalError" = "Yanlış kod"

+ 2 - 0
web/translation/translate.uk_UA.toml

@@ -544,6 +544,8 @@
 "twoFactorModalFirstStep" = "1. Відскануйте цей QR-код у програмі для аутентифікації або скопіюйте токен біля QR-коду та вставте його в програму"
 "twoFactorModalSecondStep" = "2. Введіть код з програми"
 "twoFactorModalRemoveStep" = "Введіть код з програми, щоб вимкнути двофакторну аутентифікацію."
+"twoFactorModalChangeCredentialsTitle" = "Змінити облікові дані"
+"twoFactorModalChangeCredentialsStep" = "Введіть код з додатку, щоб змінити облікові дані адміністратора."
 "twoFactorModalSetSuccess" = "Двофакторна аутентифікація була успішно встановлена"
 "twoFactorModalDeleteSuccess" = "Двофакторна аутентифікація була успішно видалена"
 "twoFactorModalError" = "Невірний код"

+ 2 - 0
web/translation/translate.vi_VN.toml

@@ -544,6 +544,8 @@
 "twoFactorModalFirstStep" = "1. Quét mã QR này trong ứng dụng xác thực hoặc sao chép mã token gần mã QR và dán vào ứng dụng"
 "twoFactorModalSecondStep" = "2. Nhập mã từ ứng dụng"
 "twoFactorModalRemoveStep" = "Nhập mã từ ứng dụng để xóa xác thực hai yếu tố."
+"twoFactorModalChangeCredentialsTitle" = "Thay đổi thông tin xác thực"
+"twoFactorModalChangeCredentialsStep" = "Nhập mã từ ứng dụng để thay đổi thông tin xác thực quản trị viên."
 "twoFactorModalSetSuccess" = "Xác thực hai yếu tố đã được thiết lập thành công"
 "twoFactorModalDeleteSuccess" = "Xác thực hai yếu tố đã được xóa thành công"
 "twoFactorModalError" = "Mã sai"

+ 2 - 0
web/translation/translate.zh_CN.toml

@@ -544,6 +544,8 @@
 "twoFactorModalFirstStep" = "1. 在认证应用程序中扫描此QR码,或复制QR码附近的令牌并粘贴到应用程序中"
 "twoFactorModalSecondStep" = "2. 输入应用程序中的验证码"
 "twoFactorModalRemoveStep" = "输入应用程序中的验证码以移除双重认证。"
+"twoFactorModalChangeCredentialsTitle" = "更改凭据"
+"twoFactorModalChangeCredentialsStep" = "输入应用程序中的代码以更改管理员凭据。"
 "twoFactorModalSetSuccess" = "双因素认证已成功建立"
 "twoFactorModalDeleteSuccess" = "双因素认证已成功删除"
 "twoFactorModalError" = "验证码错误"

+ 2 - 0
web/translation/translate.zh_TW.toml

@@ -546,6 +546,8 @@
 "twoFactorModalFirstStep" = "1. 在認證應用程式中掃描此QR碼,或複製QR碼附近的令牌並貼到應用程式中"
 "twoFactorModalSecondStep" = "2. 輸入應用程式中的驗證碼"
 "twoFactorModalRemoveStep" = "輸入應用程式中的驗證碼以移除雙重認證。"
+"twoFactorModalChangeCredentialsTitle" = "更改憑證"
+"twoFactorModalChangeCredentialsStep" = "輸入應用程式中的代碼以更改管理員憑證。"
 "twoFactorModalSetSuccess" = "雙重身份驗證已成功建立"
 "twoFactorModalDeleteSuccess" = "雙重身份驗證已成功刪除"
 "twoFactorModalError" = "驗證碼錯誤"

+ 10 - 1
x-ui.sh

@@ -179,11 +179,20 @@ reset_user() {
         fi
         return 0
     fi
+    
     read -rp "Please set the login username [default is a random username]: " config_account
     [[ -z $config_account ]] && config_account=$(date +%s%N | md5sum | cut -c 1-8)
     read -rp "Please set the login password [default is a random password]: " config_password
     [[ -z $config_password ]] && config_password=$(date +%s%N | md5sum | cut -c 1-8)
-    /usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} >/dev/null 2>&1
+
+    read -rp "Do you want to disable currently configured two-factor authentication? (y/n): " twoFactorConfirm
+    if [[ $twoFactorConfirm != "y" && $twoFactorConfirm != "Y" ]]; then
+        /usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} -resetTwoFactor false >/dev/null 2>&1
+    else
+        /usr/local/x-ui/x-ui setting -username ${config_account} -password ${config_password} -resetTwoFactor true >/dev/null 2>&1
+        echo -e "Two factor authentication has been disabled."
+    fi
+    
     echo -e "Panel login username has been reset to: ${green} ${config_account} ${plain}"
     echo -e "Panel login password has been reset to: ${green} ${config_password} ${plain}"
     echo -e "${green} Please use the new login username and password to access the X-UI panel. Also remember them! ${plain}"