diff --git a/database/db.go b/database/db.go index 744f1401..78270dbb 100644 --- a/database/db.go +++ b/database/db.go @@ -22,7 +22,6 @@ var db *gorm.DB const ( defaultUsername = "admin" defaultPassword = "admin" - defaultSecret = "" ) func initModels() error { @@ -53,7 +52,6 @@ func initUser() error { user := &model.User{ Username: defaultUsername, Password: defaultPassword, - LoginSecret: defaultSecret, } return db.Create(user).Error } diff --git a/database/model/model.go b/database/model/model.go index e9d1836f..ca430826 100644 --- a/database/model/model.go +++ b/database/model/model.go @@ -24,7 +24,6 @@ type User struct { Id int `json:"id" gorm:"primaryKey;autoIncrement"` Username string `json:"username"` Password string `json:"password"` - LoginSecret string `json:"loginSecret"` } type Inbound struct { diff --git a/go.mod b/go.mod index 82aee875..66ebce41 100644 --- a/go.mod +++ b/go.mod @@ -78,6 +78,7 @@ require ( github.com/valyala/fastjson v1.6.4 // indirect github.com/vishvananda/netlink v1.3.0 // indirect github.com/vishvananda/netns v0.0.5 // indirect + github.com/xlzd/gotp v0.1.0 // indirect github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/automaxprocs v1.6.0 // indirect diff --git a/go.sum b/go.sum index e49e9645..8fca69a2 100644 --- a/go.sum +++ b/go.sum @@ -187,6 +187,8 @@ github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= +github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po= +github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 h1:g1Cj7d+my6k/HHxLAyxPwyX8i7FGRr6ulBDMkBzg2BM= github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463/go.mod h1:BjIOLmkEEtAgloAiVUcYj0Mt+YU00JARZw8AEU0IwAg= github.com/xtls/xray-core v1.250306.1-0.20250430044058-87ab8e512882 h1:O/aN4TCrJ+fmaDOBoQhtTRev2hVHIENy2EJ70jQcyEY= diff --git a/main.go b/main.go index 84ffca6e..c9e26bd4 100644 --- a/main.go +++ b/main.go @@ -343,36 +343,6 @@ func migrateDb() { fmt.Println("Migration done!") } -func removeSecret() { - userService := service.UserService{} - - secretExists, err := userService.CheckSecretExistence() - if err != nil { - fmt.Println("Error checking secret existence:", err) - return - } - - if !secretExists { - fmt.Println("No secret exists to remove.") - return - } - - err = userService.RemoveUserSecret() - if err != nil { - fmt.Println("Error removing secret:", err) - return - } - - settingService := service.SettingService{} - err = settingService.SetSecretStatus(false) - if err != nil { - fmt.Println("Error updating secret status:", err) - return - } - - fmt.Println("Secret removed successfully.") -} - func main() { if len(os.Args) < 2 { runWebServer() @@ -400,10 +370,8 @@ func main() { var reset bool var show bool var getCert bool - var remove_secret bool settingCmd.BoolVar(&reset, "reset", false, "Reset all settings") settingCmd.BoolVar(&show, "show", false, "Display current settings") - settingCmd.BoolVar(&remove_secret, "remove_secret", false, "Remove secret key") settingCmd.IntVar(&port, "port", 0, "Set panel port number") settingCmd.StringVar(&username, "username", "", "Set login username") settingCmd.StringVar(&password, "password", "", "Set login password") @@ -467,9 +435,6 @@ func main() { if (tgbottoken != "") || (tgbotchatid != "") || (tgbotRuntime != "") { updateTgbotSetting(tgbottoken, tgbotchatid, tgbotRuntime) } - if remove_secret { - removeSecret() - } if enabletgbot { updateTgbotEnableSts(enabletgbot) } diff --git a/web/assets/js/model/setting.js b/web/assets/js/model/setting.js index 6c8abe0d..89ea171f 100644 --- a/web/assets/js/model/setting.js +++ b/web/assets/js/model/setting.js @@ -23,8 +23,9 @@ class AllSetting { this.tgBotLoginNotify = true; this.tgCpu = 80; this.tgLang = "en-US"; + this.twoFactorEnable = false; + this.twoFactorToken = ""; this.xrayTemplateConfig = ""; - this.secretEnable = false; this.subEnable = false; this.subTitle = ""; this.subListen = ""; diff --git a/web/assets/js/util/index.js b/web/assets/js/util/index.js index a13006d4..0d869af6 100644 --- a/web/assets/js/util/index.js +++ b/web/assets/js/util/index.js @@ -145,6 +145,33 @@ class RandomUtil { return Base64.alternativeEncode(String.fromCharCode(...array)); } + + static randomBase32String(length = 16) { + const array = new Uint8Array(length); + + window.crypto.getRandomValues(array); + + const base32Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; + let result = ''; + let bits = 0; + let buffer = 0; + + for (let i = 0; i < array.length; i++) { + buffer = (buffer << 8) | array[i]; + bits += 8; + + while (bits >= 5) { + bits -= 5; + result += base32Chars[(buffer >>> bits) & 0x1F]; + } + } + + if (bits > 0) { + result += base32Chars[(buffer << (5 - bits)) & 0x1F]; + } + + return result; + } } class ObjectUtil { diff --git a/web/controller/index.go b/web/controller/index.go index 9af4ed7f..c19d1b6e 100644 --- a/web/controller/index.go +++ b/web/controller/index.go @@ -14,9 +14,9 @@ import ( ) type LoginForm struct { - Username string `json:"username" form:"username"` - Password string `json:"password" form:"password"` - LoginSecret string `json:"loginSecret" form:"loginSecret"` + Username string `json:"username" form:"username"` + Password string `json:"password" form:"password"` + TwoFactorCode string `json:"twoFactorCode" form:"twoFactorCode"` } type IndexController struct { @@ -37,7 +37,7 @@ func (a *IndexController) initRouter(g *gin.RouterGroup) { g.GET("/", a.index) g.POST("/login", a.login) g.GET("/logout", a.logout) - g.POST("/getSecretStatus", a.getSecretStatus) + g.POST("/getTwoFactorEnable", a.getTwoFactorEnable) } func (a *IndexController) index(c *gin.Context) { @@ -64,14 +64,13 @@ func (a *IndexController) login(c *gin.Context) { return } - user := a.userService.CheckUser(form.Username, form.Password, form.LoginSecret) + user := a.userService.CheckUser(form.Username, form.Password, form.TwoFactorCode) timeStr := time.Now().Format("2006-01-02 15:04:05") safeUser := template.HTMLEscapeString(form.Username) safePass := template.HTMLEscapeString(form.Password) - safeSecret := template.HTMLEscapeString(form.LoginSecret) if user == nil { - logger.Warningf("wrong username: \"%s\", password: \"%s\", secret: \"%s\", IP: \"%s\"", safeUser, safePass, safeSecret, getRemoteIp(c)) + logger.Warningf("wrong username: \"%s\", password: \"%s\", IP: \"%s\"", safeUser, safePass, getRemoteIp(c)) a.tgbot.UserLoginNotify(safeUser, safePass, getRemoteIp(c), timeStr, 0) pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.wrongUsernameOrPassword")) return @@ -108,8 +107,8 @@ func (a *IndexController) logout(c *gin.Context) { c.Redirect(http.StatusTemporaryRedirect, c.GetString("base_path")) } -func (a *IndexController) getSecretStatus(c *gin.Context) { - status, err := a.settingService.GetSecretStatus() +func (a *IndexController) getTwoFactorEnable(c *gin.Context) { + status, err := a.settingService.GetTwoFactorEnable() if err == nil { jsonObj(c, status, nil) } diff --git a/web/controller/setting.go b/web/controller/setting.go index d04969dc..bb17c4b3 100644 --- a/web/controller/setting.go +++ b/web/controller/setting.go @@ -18,10 +18,6 @@ type updateUserForm struct { NewPassword string `json:"newPassword" form:"newPassword"` } -type updateSecretForm struct { - LoginSecret string `json:"loginSecret" form:"loginSecret"` -} - type SettingController struct { settingService service.SettingService userService service.UserService @@ -43,8 +39,6 @@ func (a *SettingController) initRouter(g *gin.RouterGroup) { g.POST("/updateUser", a.updateUser) g.POST("/restartPanel", a.restartPanel) g.GET("/getDefaultJsonConfig", a.getDefaultXrayConfig) - g.POST("/updateUserSecret", a.updateSecret) - g.POST("/getUserSecret", a.getUserSecret) } func (a *SettingController) getAllSetting(c *gin.Context) { @@ -106,29 +100,6 @@ func (a *SettingController) restartPanel(c *gin.Context) { jsonMsg(c, I18nWeb(c, "pages.settings.restartPanel"), err) } -func (a *SettingController) updateSecret(c *gin.Context) { - form := &updateSecretForm{} - err := c.ShouldBind(form) - if err != nil { - jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err) - } - user := session.GetLoginUser(c) - err = a.userService.UpdateUserSecret(user.Id, form.LoginSecret) - if err == nil { - user.LoginSecret = form.LoginSecret - session.SetLoginUser(c, user) - } - jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifyUser"), err) -} - -func (a *SettingController) getUserSecret(c *gin.Context) { - loginUser := session.GetLoginUser(c) - user := a.userService.GetUserSecret(loginUser.Id) - if user != nil { - jsonObj(c, user, nil) - } -} - func (a *SettingController) getDefaultXrayConfig(c *gin.Context) { defaultJsonConfig, err := a.settingService.GetDefaultXrayConfig() if err != nil { diff --git a/web/entity/entity.go b/web/entity/entity.go index 872901b8..543b80e0 100644 --- a/web/entity/entity.go +++ b/web/entity/entity.go @@ -38,7 +38,8 @@ type AllSetting struct { TgCpu int `json:"tgCpu" form:"tgCpu"` TgLang string `json:"tgLang" form:"tgLang"` TimeLocation string `json:"timeLocation" form:"timeLocation"` - SecretEnable bool `json:"secretEnable" form:"secretEnable"` + TwoFactorEnable bool `json:"twoFactorEnable" form:"twoFactorEnable"` + TwoFactorToken string `json:"twoFactorToken" form:"twoFactorToken"` SubEnable bool `json:"subEnable" form:"subEnable"` SubTitle string `json:"subTitle" form:"subTitle"` SubListen string `json:"subListen" form:"subListen"` diff --git a/web/html/login.html b/web/html/login.html index 9f292d84..515ea2b3 100644 --- a/web/html/login.html +++ b/web/html/login.html @@ -512,11 +512,11 @@ - - + + - + @@ -549,14 +549,14 @@ user: { username: "", password: "", - loginSecret: "" + twoFactorCode: "" }, - secretEnable: false, + twoFactorEnable: false, lang: "" }, async mounted() { this.lang = LanguageManager.getLanguage(); - this.secretEnable = await this.getSecretStatus(); + this.twoFactorEnable = await this.getTwoFactorEnable(); }, methods: { async login() { @@ -567,12 +567,12 @@ location.href = basePath + 'panel/'; } }, - async getSecretStatus() { + async getTwoFactorEnable() { this.loading = true; - const msg = await HttpUtil.post('/getSecretStatus'); + const msg = await HttpUtil.post('/getTwoFactorEnable'); this.loading = false; if (msg.success) { - this.secretEnable = msg.obj; + this.twoFactorEnable = msg.obj; return msg.obj; } }, diff --git a/web/html/settings.html b/web/html/settings.html index 82e636d9..75cadc51 100644 --- a/web/html/settings.html +++ b/web/html/settings.html @@ -133,7 +133,6 @@ data: { themeSwitcher, spinning: false, - changeSecret: false, oldAllSetting: new AllSetting(), allSetting: new AllSetting(), saveBtnDisable: true, @@ -258,7 +257,6 @@ app.changeRemarkSample(); this.saveBtnDisable = true; } - await this.fetchUserSecret(); }, async updateAllSetting() { this.loading(true); @@ -302,38 +300,11 @@ window.location.replace(url); } }, - async fetchUserSecret() { - this.loading(true); - const userMessage = await HttpUtil.post("/panel/setting/getUserSecret", this.user); - if (userMessage.success) { - this.user = userMessage.obj; - } - this.loading(false); - }, - async updateSecret() { - this.loading(true); - const msg = await HttpUtil.post("/panel/setting/updateUserSecret", this.user); - if (msg && msg.obj) { - this.user = msg.obj; - } - this.loading(false); - await this.updateAllSetting(); - }, - async getNewSecret() { - if (!this.changeSecret) { - this.changeSecret = true; - this.user.loginSecret = ''; - const newSecret = RandomUtil.randomSeq(64); - await PromiseUtil.sleep(1000); - this.user.loginSecret = newSecret; - this.changeSecret = false; - } - }, - async toggleToken(value) { - if (value) { - await this.getNewSecret(); + toggleTwoFactor(newValue) { + if (newValue) { + this.allSetting.twoFactorToken = RandomUtil.randomBase32String(); } else { - this.user.loginSecret = ""; + this.allSetting.twoFactorToken = ""; } }, addNoise() { diff --git a/web/html/settings/panel/security.html b/web/html/settings/panel/security.html index 48e7796f..4abad4c7 100644 --- a/web/html/settings/panel/security.html +++ b/web/html/settings/panel/security.html @@ -31,30 +31,23 @@ - + - - + + - - - + + + - - - - {{ i18n "confirm"}} - - - {{end}} \ No newline at end of file diff --git a/web/service/setting.go b/web/service/setting.go index 5443760c..62d66c11 100644 --- a/web/service/setting.go +++ b/web/service/setting.go @@ -48,7 +48,8 @@ var defaultValueMap = map[string]string{ "tgBotLoginNotify": "true", "tgCpu": "80", "tgLang": "en-US", - "secretEnable": "false", + "twoFactorEnable": "false", + "twoFactorToken": "", "subEnable": "false", "subTitle": "", "subListen": "", @@ -166,8 +167,7 @@ func (s *SettingService) ResetSettings() error { return err } return db.Model(model.User{}). - Where("1 = 1"). - Update("login_secret", "").Error + Where("1 = 1").Error } func (s *SettingService) getSetting(key string) (*model.Setting, error) { @@ -318,6 +318,14 @@ func (s *SettingService) GetTgLang() (string, error) { return s.getString("tgLang") } +func (s *SettingService) GetTwoFactorEnable() (bool, error) { + return s.getBool("twoFactorEnable") +} + +func (s *SettingService) GetTwoFactorToken() (string, error) { + return s.getString("twoFactorToken") +} + func (s *SettingService) GetPort() (int, error) { return s.getInt("webPort") } @@ -358,14 +366,6 @@ func (s *SettingService) GetRemarkModel() (string, error) { return s.getString("remarkModel") } -func (s *SettingService) GetSecretStatus() (bool, error) { - return s.getBool("secretEnable") -} - -func (s *SettingService) SetSecretStatus(value bool) error { - return s.setBool("secretEnable", value) -} - func (s *SettingService) GetSecret() ([]byte, error) { secret, err := s.getString("secret") if secret == defaultValueMap["secret"] { diff --git a/web/service/user.go b/web/service/user.go index 7438cf1a..ed8fb5b4 100644 --- a/web/service/user.go +++ b/web/service/user.go @@ -8,9 +8,12 @@ import ( "x-ui/logger" "gorm.io/gorm" + "github.com/xlzd/gotp" ) -type UserService struct{} +type UserService struct { + settingService SettingService +} func (s *UserService) GetFirstUser() (*model.User, error) { db := database.GetDB() @@ -25,12 +28,12 @@ func (s *UserService) GetFirstUser() (*model.User, error) { return user, nil } -func (s *UserService) CheckUser(username string, password string, secret string) *model.User { +func (s *UserService) CheckUser(username string, password string, twoFactorCode string) *model.User { db := database.GetDB() user := &model.User{} err := db.Model(model.User{}). - Where("username = ? and password = ? and login_secret = ?", username, password, secret). + Where("username = ? and password = ?", username, password). First(user). Error if err == gorm.ErrRecordNotFound { @@ -39,6 +42,24 @@ func (s *UserService) CheckUser(username string, password string, secret string) logger.Warning("check user err:", err) return nil } + twoFactorEnable, err := s.settingService.GetTwoFactorEnable(); + if err != nil { + logger.Warning("check two factor err:", err) + return nil + } + if twoFactorEnable { + twoFactorToken, err := s.settingService.GetTwoFactorToken(); + + if err != nil { + logger.Warning("check two factor token err:", err) + return nil + } + + if gotp.NewDefaultTOTP(twoFactorToken).Now() != twoFactorCode { + return nil + } + } + return user } @@ -50,50 +71,6 @@ func (s *UserService) UpdateUser(id int, username string, password string) error Error } -func (s *UserService) UpdateUserSecret(id int, secret string) error { - db := database.GetDB() - return db.Model(model.User{}). - Where("id = ?", id). - Update("login_secret", secret). - Error -} - -func (s *UserService) RemoveUserSecret() error { - db := database.GetDB() - return db.Model(model.User{}). - Where("1 = 1"). - Update("login_secret", ""). - Error -} - -func (s *UserService) GetUserSecret(id int) *model.User { - db := database.GetDB() - user := &model.User{} - err := db.Model(model.User{}). - Where("id = ?", id). - First(user). - Error - if err == gorm.ErrRecordNotFound { - return nil - } - return user -} - -func (s *UserService) CheckSecretExistence() (bool, error) { - db := database.GetDB() - - var count int64 - err := db.Model(model.User{}). - Where("login_secret IS NOT NULL"). - Count(&count). - Error - if err != nil { - return false, err - } - - return count > 0, nil -} - func (s *UserService) UpdateFirstUser(username string, password string) error { if username == "" { return errors.New("username can not be empty") diff --git a/web/translation/translate.ar_EG.toml b/web/translation/translate.ar_EG.toml index 229f1320..81547465 100644 --- a/web/translation/translate.ar_EG.toml +++ b/web/translation/translate.ar_EG.toml @@ -51,7 +51,7 @@ "install" = "تثبيت" "clients" = "عملاء" "usage" = "استخدام" -"secretToken" = "توكن سري" +"twoFactorCode" = "الكود" "remained" = "المتبقي" "security" = "أمان" "secAlertTitle" = "تنبيه أمني" @@ -87,7 +87,7 @@ "invalidFormData" = "تنسيق البيانات المدخلة مش صحيح." "emptyUsername" = "اسم المستخدم مطلوب" "emptyPassword" = "الباسورد مطلوب" -"wrongUsernameOrPassword" = "اسم المستخدم أو الباسورد أو السر مش صحيح." +"wrongUsernameOrPassword" = "اسم المستخدم أو كلمة المرور أو كود المصادقة الثنائية غير صحيح." "successLogin" = "تسجيل دخول ناجح" [pages.index] @@ -497,11 +497,11 @@ [pages.settings.security] "admin" = "بيانات الأدمن" -"secret" = "توكن سري" -"loginSecurity" = "أمان تسجيل الدخول" -"loginSecurityDesc" = "بيضيف طبقة مصادقة إضافية لزيادة الأمان." -"secretToken" = "توكن سري" -"secretTokenDesc" = "احتفظ بالتوكن ده في مكان آمن. التوكن ده مطلوب لتسجيل الدخول ومش ممكن تسترجعه لو ضاع." +"twoFactor" = "المصادقة الثنائية" +"twoFactorEnable" = "تفعيل المصادقة الثنائية" +"twoFactorEnableDesc" = "يضيف طبقة إضافية من المصادقة لتعزيز الأمان." +"twoFactorToken" = "رمز المصادقة الثنائية" +"twoFactorTokenDesc" = "يرجى حفظ هذا الرمز بشكل آمن في تطبيق المصادقة." [pages.settings.toasts] "modifySettings" = "تعديل الإعدادات" diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index c691cbdd..2afb7c15 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -51,7 +51,7 @@ "install" = "Install" "clients" = "Clients" "usage" = "Usage" -"secretToken" = "Secret Token" +"twoFactorCode" = "Code" "remained" = "Remained" "security" = "Security" "secAlertTitle" = "Security Alert" @@ -87,7 +87,7 @@ "invalidFormData" = "The Input data format is invalid." "emptyUsername" = "Username is required" "emptyPassword" = "Password is required" -"wrongUsernameOrPassword" = "Invalid username or password or secret." +"wrongUsernameOrPassword" = "Invalid username or password or two-factor code." "successLogin" = "Login" [pages.index] @@ -497,11 +497,11 @@ [pages.settings.security] "admin" = "Admin credentials" -"secret" = "Secret Token" -"loginSecurity" = "Secure Login" -"loginSecurityDesc" = "Adds an additional layer of authentication to provide more security." -"secretToken" = "Secret Token" -"secretTokenDesc" = "Please securely store this token in a safe place. This token is required for login and cannot be recovered." +"twoFactor" = "Two-factor authentication" +"twoFactorEnable" = "Enable 2FA" +"twoFactorEnableDesc" = "Adds an additional layer of authentication to provide more security." +"twoFactorToken" = "2FA token" +"twoFactorTokenDesc" = "Please securely store this token in a authentication app." [pages.settings.toasts] "modifySettings" = "Modify Settings" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index d989b3e9..92a4d64e 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -51,7 +51,7 @@ "install" = "Instalar" "clients" = "Clientes" "usage" = "Uso" -"secretToken" = "Token Secreto" +"twoFactorCode" = "Código" "remained" = "Restante" "security" = "Seguridad" "secAlertTitle" = "Alerta de Seguridad" @@ -87,7 +87,7 @@ "invalidFormData" = "El formato de los datos de entrada es inválido." "emptyUsername" = "Por favor ingresa el nombre de usuario." "emptyPassword" = "Por favor ingresa la contraseña." -"wrongUsernameOrPassword" = "Nombre de usuario o contraseña inválidos." +"wrongUsernameOrPassword" = "Nombre de usuario, contraseña o código de dos factores incorrecto." "successLogin" = "Inicio de Sesión Exitoso" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "Credenciales de administrador" -"secret" = "Token Secreto" -"loginSecurity" = "Seguridad de Inicio de Sesión" -"loginSecurityDesc" = "Habilitar un paso adicional de seguridad para el inicio de sesión de usuarios." -"secretToken" = "Token Secreto" -"secretTokenDesc" = "Por favor, copia y guarda este token de forma segura en un lugar seguro. Este token es necesario para iniciar sesión y no se puede recuperar con la herramienta de comando x-ui." +"twoFactor" = "Autenticación de dos factores" +"twoFactorEnable" = "Habilitar 2FA" +"twoFactorEnableDesc" = "Añade una capa adicional de autenticación para mayor seguridad." +"twoFactorToken" = "Token de 2FA" +"twoFactorTokenDesc" = "Guarde este token de forma segura en una aplicación de autenticación." [pages.settings.toasts] "modifySettings" = "Modificar Configuraciones " diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index 96a39ca9..dccb17e5 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -51,7 +51,7 @@ "install" = "نصب" "clients" = "کاربران" "usage" = "استفاده" -"secretToken" = "توکن امنیتی" +"twoFactorCode" = "کد" "remained" = "باقی‌مانده" "security" = "امنیت" "secAlertTitle" = "هشدار‌امنیتی" @@ -87,7 +87,7 @@ "invalidFormData" = "اطلاعات به‌درستی وارد نشده‌است" "emptyUsername" = "لطفا یک نام‌کاربری وارد کنید‌" "emptyPassword" = "لطفا یک رمزعبور وارد کنید" -"wrongUsernameOrPassword" = "نام‌کاربری یا رمزعبور‌اشتباه‌است" +"wrongUsernameOrPassword" = "نام کاربری، رمز عبور یا کد دو مرحله‌ای نامعتبر است." "successLogin" = "ورود" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "اعتبارنامه‌های ادمین" -"secret" = "توکن مخفی" -"loginSecurity" = "ورود ایمن" -"loginSecurityDesc" = "یک لایه اضافی از احراز هویت برای ایجاد امنیت بیشتر اضافه می کند" -"secretToken" = "توکن مخفی" -"secretTokenDesc" = "لطفاً این توکن را در مکانی امن ذخیره کنید. این توکن برای ورود به سیستم مورد نیاز است و قابل بازیابی نیست" +"twoFactor" = "احراز هویت دو مرحله‌ای" +"twoFactorEnable" = "فعال‌سازی 2FA" +"twoFactorEnableDesc" = "یک لایه اضافی امنیتی برای احراز هویت فراهم می‌کند." +"twoFactorToken" = "توکن 2FA" +"twoFactorTokenDesc" = "لطفاً این توکن را در یک برنامه احراز هویت ذخیره کنید." [pages.settings.toasts] "modifySettings" = "ویرایش تنظیمات" diff --git a/web/translation/translate.id_ID.toml b/web/translation/translate.id_ID.toml index f2277a27..191f6311 100644 --- a/web/translation/translate.id_ID.toml +++ b/web/translation/translate.id_ID.toml @@ -51,7 +51,7 @@ "install" = "Instal" "clients" = "Klien" "usage" = "Penggunaan" -"secretToken" = "Token Rahasia" +"twoFactorCode" = "Kode" "remained" = "Tersisa" "security" = "Keamanan" "secAlertTitle" = "Peringatan keamanan" @@ -87,7 +87,7 @@ "invalidFormData" = "Format data input tidak valid." "emptyUsername" = "Nama Pengguna diperlukan" "emptyPassword" = "Kata Sandi diperlukan" -"wrongUsernameOrPassword" = "Nama pengguna atau kata sandi tidak valid." +"wrongUsernameOrPassword" = "Username, kata sandi, atau kode dua faktor tidak valid." "successLogin" = "Login berhasil" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "Kredensial admin" -"secret" = "Token Rahasia" -"loginSecurity" = "Login Aman" -"loginSecurityDesc" = "Menambahkan lapisan otentikasi tambahan untuk memberikan keamanan lebih." -"secretToken" = "Token Rahasia" -"secretTokenDesc" = "Simpan token ini dengan aman di tempat yang aman. Token ini diperlukan untuk login dan tidak dapat dipulihkan." +"twoFactor" = "Autentikasi dua faktor" +"twoFactorEnable" = "Aktifkan 2FA" +"twoFactorEnableDesc" = "Menambahkan lapisan autentikasi tambahan untuk keamanan lebih." +"twoFactorToken" = "Token 2FA" +"twoFactorTokenDesc" = "Harap simpan token ini dengan aman di aplikasi autentikasi." [pages.settings.toasts] "modifySettings" = "Ubah Pengaturan" diff --git a/web/translation/translate.ja_JP.toml b/web/translation/translate.ja_JP.toml index 2c8df756..3966ac4b 100644 --- a/web/translation/translate.ja_JP.toml +++ b/web/translation/translate.ja_JP.toml @@ -51,7 +51,7 @@ "install" = "インストール" "clients" = "クライアント" "usage" = "利用状況" -"secretToken" = "シークレットトークン" +"twoFactorCode" = "コード" "remained" = "残り" "security" = "セキュリティ" "secAlertTitle" = "セキュリティアラート" @@ -87,7 +87,7 @@ "invalidFormData" = "データ形式エラー" "emptyUsername" = "ユーザー名を入力してください" "emptyPassword" = "パスワードを入力してください" -"wrongUsernameOrPassword" = "ユーザー名またはパスワードが間違っています" +"wrongUsernameOrPassword" = "ユーザー名、パスワード、または二段階認証コードが無効です。" "successLogin" = "ログイン成功" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "管理者の資格情報" -"secret" = "セキュリティトークン" -"loginSecurity" = "ログインセキュリティ" -"loginSecurityDesc" = "追加の認証を追加してセキュリティを向上させる" -"secretToken" = "セキュリティトークン" -"secretTokenDesc" = "このトークンを安全な場所に保管してください。このトークンはログインに使用され、紛失すると回復できません。" +"twoFactor" = "二段階認証" +"twoFactorEnable" = "2FAを有効化" +"twoFactorEnableDesc" = "セキュリティを強化するために追加の認証層を追加します。" +"twoFactorToken" = "2FAトークン" +"twoFactorTokenDesc" = "このトークンを認証アプリに安全に保存してください。" [pages.settings.toasts] "modifySettings" = "設定を変更" diff --git a/web/translation/translate.pt_BR.toml b/web/translation/translate.pt_BR.toml index 87a44ca6..f6c2e88d 100644 --- a/web/translation/translate.pt_BR.toml +++ b/web/translation/translate.pt_BR.toml @@ -51,7 +51,7 @@ "install" = "Instalar" "clients" = "Clientes" "usage" = "Uso" -"secretToken" = "Token Secreto" +"twoFactorCode" = "Código" "remained" = "Restante" "security" = "Segurança" "secAlertTitle" = "Alerta de Segurança" @@ -87,7 +87,7 @@ "invalidFormData" = "O formato dos dados de entrada é inválido." "emptyUsername" = "Nome de usuário é obrigatório" "emptyPassword" = "Senha é obrigatória" -"wrongUsernameOrPassword" = "Nome de usuário, senha ou segredo inválidos." +"wrongUsernameOrPassword" = "Nome de usuário, senha ou código de dois fatores inválido." "successLogin" = "Login realizado com sucesso" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "Credenciais de administrador" -"secret" = "Token Secreto" -"loginSecurity" = "Login Seguro" -"loginSecurityDesc" = "Adiciona uma camada extra de autenticação para fornecer mais segurança." -"secretToken" = "Token Secreto" -"secretTokenDesc" = "Por favor, armazene este token em um local seguro. Este token é necessário para o login e não pode ser recuperado." +"twoFactor" = "Autenticação de dois fatores" +"twoFactorEnable" = "Ativar 2FA" +"twoFactorEnableDesc" = "Adiciona uma camada extra de autenticação para mais segurança." +"twoFactorToken" = "Token 2FA" +"twoFactorTokenDesc" = "Guarde este token com segurança em um aplicativo de autenticação." [pages.settings.toasts] "modifySettings" = "Modificar Configurações" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index 47891227..634d393d 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -51,7 +51,7 @@ "install" = "Установка" "clients" = "Клиенты" "usage" = "Использование" -"secretToken" = "Секретный токен" +"twoFactorCode" = "Код" "remained" = "Остаток" "security" = "Безопасность" "secAlertTitle" = "Предупреждение системы безопасности" @@ -87,7 +87,7 @@ "invalidFormData" = "Недопустимый формат данных" "emptyUsername" = "Введите имя пользователя" "emptyPassword" = "Введите пароль" -"wrongUsernameOrPassword" = "Неверное имя пользователя, пароль или секретный токен." +"wrongUsernameOrPassword" = "Неверное имя пользователя, пароль или код двухфакторной аутентификации." "successLogin" = "Успешный вход" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "Учетные данные администратора" -"secret" = "Секретный токен" -"loginSecurity" = "Безопасность входа" -"loginSecurityDesc" = "Включить дополнительные меры безопасности входа пользователя" -"secretToken" = "Секретный токен" -"secretTokenDesc" = "Пожалуйста, скопируйте и сохраните этот токен в безопасном месте. Этот токен необходим для входа в систему и не может быть восстановлен с помощью инструмента x-ui" +"twoFactor" = "Двухфакторная аутентификация" +"twoFactorEnable" = "Включить 2FA" +"twoFactorEnableDesc" = "Добавляет дополнительный уровень аутентификации для повышения безопасности." +"twoFactorToken" = "Токен 2FA" +"twoFactorTokenDesc" = "Пожалуйста, сохраните этот токен в приложении для аутентификации." [pages.settings.toasts] "modifySettings" = "Настройки изменены" diff --git a/web/translation/translate.tr_TR.toml b/web/translation/translate.tr_TR.toml index 2b617ca5..a43b68fb 100644 --- a/web/translation/translate.tr_TR.toml +++ b/web/translation/translate.tr_TR.toml @@ -51,7 +51,7 @@ "install" = "Yükle" "clients" = "Müşteriler" "usage" = "Kullanım" -"secretToken" = "Gizli Anahtar" +"twoFactorCode" = "Kod" "remained" = "Kalan" "security" = "Güvenlik" "secAlertTitle" = "Güvenlik Uyarısı" @@ -87,7 +87,7 @@ "invalidFormData" = "Girdi verisi formatı geçersiz." "emptyUsername" = "Kullanıcı adı gerekli" "emptyPassword" = "Şifre gerekli" -"wrongUsernameOrPassword" = "Geçersiz kullanıcı adı veya şifre veya gizli anahtar." +"wrongUsernameOrPassword" = "Geçersiz kullanıcı adı, şifre veya iki adımlı doğrulama kodu." "successLogin" = "Giriş Başarılı" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "Yönetici kimlik bilgileri" -"secret" = "Gizli Anahtar" -"loginSecurity" = "Güvenli Giriş" -"loginSecurityDesc" = "Daha fazla güvenlik sağlamak için ek bir kimlik doğrulama katmanı ekler." -"secretToken" = "Gizli Anahtar" -"secretTokenDesc" = "Bu anahtarı güvenli bir yerde saklayın. Bu anahtar giriş için gereklidir ve geri alınamaz." +"twoFactor" = "İki adımlı doğrulama" +"twoFactorEnable" = "2FA'yı Etkinleştir" +"twoFactorEnableDesc" = "Daha fazla güvenlik için ek bir doğrulama katmanı ekler." +"twoFactorToken" = "2FA Token" +"twoFactorTokenDesc" = "Lütfen bu token'ı bir doğrulama uygulamasında güvenle saklayın." [pages.settings.toasts] "modifySettings" = "Ayarları Değiştir" diff --git a/web/translation/translate.uk_UA.toml b/web/translation/translate.uk_UA.toml index ad3aea41..4825ea37 100644 --- a/web/translation/translate.uk_UA.toml +++ b/web/translation/translate.uk_UA.toml @@ -51,7 +51,7 @@ "install" = "Встановити" "clients" = "Клієнти" "usage" = "Використання" -"secretToken" = "Секретний маркер" +"twoFactorCode" = "Код" "remained" = "Залишилося" "security" = "Беспека" "secAlertTitle" = "Попередження системи безпеки" @@ -87,7 +87,7 @@ "invalidFormData" = "Формат вхідних даних недійсний." "emptyUsername" = "Потрібне ім'я користувача" "emptyPassword" = "Потрібен пароль" -"wrongUsernameOrPassword" = "Невірне ім'я користувача або пароль." +"wrongUsernameOrPassword" = "Невірне ім’я користувача, пароль або код двофакторної аутентифікації." "successLogin" = "Вхід" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "Облікові дані адміністратора" -"secret" = "Секретний маркер" -"loginSecurity" = "Безпечний вхід" -"loginSecurityDesc" = "Додає додатковий рівень автентифікації для забезпечення більшої безпеки." -"secretToken" = "Секретний маркер" -"secretTokenDesc" = "Будь ласка, надійно зберігайте цей маркер у безпечному місці. Цей маркер потрібен для входу, і його неможливо відновити." +"twoFactor" = "Двофакторна аутентифікація" +"twoFactorEnable" = "Увімкнути 2FA" +"twoFactorEnableDesc" = "Додає додатковий рівень аутентифікації для підвищення безпеки." +"twoFactorToken" = "Токен 2FA" +"twoFactorTokenDesc" = "Будь ласка, збережіть цей токен у захищеному додатку для аутентифікації." [pages.settings.toasts] "modifySettings" = "Змінити налаштування" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index 3a825770..ef10ddc7 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -51,7 +51,7 @@ "install" = "Cài đặt" "clients" = "Các khách hàng" "usage" = "Sử dụng" -"secretToken" = "Mã bí mật" +"twoFactorCode" = "Mã" "remained" = "Còn lại" "security" = "Bảo vệ" "secAlertTitle" = "Cảnh báo an ninh-Tiếng Việt by Ohoang7" @@ -87,7 +87,7 @@ "invalidFormData" = "Dạng dữ liệu nhập không hợp lệ." "emptyUsername" = "Vui lòng nhập tên người dùng." "emptyPassword" = "Vui lòng nhập mật khẩu." -"wrongUsernameOrPassword" = "Tên người dùng hoặc mật khẩu không đúng." +"wrongUsernameOrPassword" = "Tên người dùng, mật khẩu hoặc mã xác thực hai yếu tố không hợp lệ." "successLogin" = "Đăng nhập thành công." [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "Thông tin đăng nhập quản trị viên" -"secret" = "Mã thông báo bí mật" -"loginSecurity" = "Bảo mật đăng nhập" -"loginSecurityDesc" = "Bật bước bảo mật đăng nhập bổ sung cho người dùng" -"secretToken" = "Mã bí mật" -"secretTokenDesc" = "Vui lòng sao chép và lưu trữ mã này một cách an toàn ở nơi an toàn. Mã này cần thiết để đăng nhập và không thể phục hồi từ công cụ lệnh x-ui." +"twoFactor" = "Xác thực hai yếu tố" +"twoFactorEnable" = "Bật 2FA" +"twoFactorEnableDesc" = "Thêm một lớp bảo mật bổ sung để tăng cường an toàn." +"twoFactorToken" = "Token 2FA" +"twoFactorTokenDesc" = "Vui lòng lưu token này vào ứng dụng xác thực một cách an toàn." [pages.settings.toasts] "modifySettings" = "Chỉnh sửa cài đặt " diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml index 750db7e6..3769d89a 100644 --- a/web/translation/translate.zh_CN.toml +++ b/web/translation/translate.zh_CN.toml @@ -51,7 +51,7 @@ "install" = "安装" "clients" = "客户端" "usage" = "使用情况" -"secretToken" = "安全密钥" +"twoFactorCode" = "代码" "remained" = "剩余" "security" = "安全" "secAlertTitle" = "安全警报" @@ -87,7 +87,7 @@ "invalidFormData" = "数据格式错误" "emptyUsername" = "请输入用户名" "emptyPassword" = "请输入密码" -"wrongUsernameOrPassword" = "用户名或密码错误" +"wrongUsernameOrPassword" = "用户名、密码或双重验证码无效。" "successLogin" = "登录" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "管理员凭据" -"secret" = "安全令牌" -"loginSecurity" = "登录安全" -"loginSecurityDesc" = "添加额外的身份验证以提高安全性" -"secretToken" = "安全令牌" -"secretTokenDesc" = "请将此令牌存储在安全的地方。此令牌用于登录,丢失无法恢复。" +"twoFactor" = "双重验证" +"twoFactorEnable" = "启用2FA" +"twoFactorEnableDesc" = "增加额外的验证层以提高安全性。" +"twoFactorToken" = "2FA令牌" +"twoFactorTokenDesc" = "请将此令牌安全地保存在验证应用中。" [pages.settings.toasts] "modifySettings" = "修改设置" diff --git a/web/translation/translate.zh_TW.toml b/web/translation/translate.zh_TW.toml index abc953f5..8dfc13a5 100644 --- a/web/translation/translate.zh_TW.toml +++ b/web/translation/translate.zh_TW.toml @@ -51,7 +51,7 @@ "install" = "安裝" "clients" = "客戶端" "usage" = "使用情況" -"secretToken" = "安全金鑰" +"twoFactorCode" = "代碼" "remained" = "剩餘" "security" = "安全" "secAlertTitle" = "安全警報" @@ -87,7 +87,7 @@ "invalidFormData" = "資料格式錯誤" "emptyUsername" = "請輸入使用者名稱" "emptyPassword" = "請輸入密碼" -"wrongUsernameOrPassword" = "使用者名稱或密碼錯誤" +"wrongUsernameOrPassword" = "用戶名、密碼或雙重驗證碼無效。" "successLogin" = "登入" [pages.index] @@ -499,11 +499,11 @@ [pages.settings.security] "admin" = "管理員憑證" -"secret" = "安全令牌" -"loginSecurity" = "登入安全" -"loginSecurityDesc" = "新增額外的身份驗證以提高安全性" -"secretToken" = "安全令牌" -"secretTokenDesc" = "請將此令牌儲存在安全的地方。此令牌用於登入,丟失無法恢復。" +"twoFactor" = "雙重驗證" +"twoFactorEnable" = "啟用2FA" +"twoFactorEnableDesc" = "增加額外的驗證層以提高安全性。" +"twoFactorToken" = "2FA令牌" +"twoFactorTokenDesc" = "請將此令牌安全地保存在驗證應用中。" [pages.settings.toasts] "modifySettings" = "修改設定" diff --git a/x-ui.sh b/x-ui.sh index c8df6735..a7cee914 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -184,10 +184,8 @@ reset_user() { 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 - /usr/local/x-ui/x-ui setting -remove_secret >/dev/null 2>&1 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 "${yellow} Panel login secret token disabled ${plain}" echo -e "${green} Please use the new login username and password to access the X-UI panel. Also remember them! ${plain}" confirm_restart } @@ -1731,7 +1729,7 @@ show_menu() { │ ${green}4.${plain} Legacy Version │ │ ${green}5.${plain} Uninstall │ │────────────────────────────────────────────────│ -│ ${green}6.${plain} Reset Username & Password & Secret Token │ +│ ${green}6.${plain} Reset Username & Password │ │ ${green}7.${plain} Reset Web Base Path │ │ ${green}8.${plain} Reset Settings │ │ ${green}9.${plain} Change Port │