feat: copy secret to register otp #551

This commit is contained in:
Jacky 2024-09-15 11:57:16 +08:00
parent 745e98d1a9
commit cb3599e721
No known key found for this signature in database
GPG key ID: 215C21B10DF38B4D
12 changed files with 434 additions and 366 deletions

View file

@ -1,245 +1,228 @@
package user
import (
"bytes"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/0xJacky/Nginx-UI/api"
"github.com/0xJacky/Nginx-UI/internal/crypto"
"github.com/0xJacky/Nginx-UI/internal/user"
"github.com/0xJacky/Nginx-UI/model"
"github.com/0xJacky/Nginx-UI/query"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/gin-gonic/gin"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp"
"image/jpeg"
"net/http"
"strings"
"bytes"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/0xJacky/Nginx-UI/api"
"github.com/0xJacky/Nginx-UI/internal/crypto"
"github.com/0xJacky/Nginx-UI/internal/user"
"github.com/0xJacky/Nginx-UI/model"
"github.com/0xJacky/Nginx-UI/query"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/gin-gonic/gin"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp"
"image/jpeg"
"net/http"
"strings"
)
func GenerateTOTP(c *gin.Context) {
u := api.CurrentUser(c)
u := api.CurrentUser(c)
issuer := fmt.Sprintf("Nginx UI %s", settings.ServerSettings.Name)
issuer = strings.TrimSpace(issuer)
issuer := fmt.Sprintf("Nginx UI %s", settings.ServerSettings.Name)
issuer = strings.TrimSpace(issuer)
otpOpts := totp.GenerateOpts{
Issuer: issuer,
AccountName: u.Name,
Period: 30, // seconds
Digits: otp.DigitsSix,
Algorithm: otp.AlgorithmSHA1,
}
otpKey, err := totp.Generate(otpOpts)
if err != nil {
api.ErrHandler(c, err)
return
}
ciphertext, err := crypto.AesEncrypt([]byte(otpKey.Secret()))
if err != nil {
api.ErrHandler(c, err)
return
}
otpOpts := totp.GenerateOpts{
Issuer: issuer,
AccountName: u.Name,
Period: 30, // seconds
Digits: otp.DigitsSix,
Algorithm: otp.AlgorithmSHA1,
}
otpKey, err := totp.Generate(otpOpts)
if err != nil {
api.ErrHandler(c, err)
return
}
qrCode, err := otpKey.Image(512, 512)
if err != nil {
api.ErrHandler(c, err)
return
}
qrCode, err := otpKey.Image(512, 512)
if err != nil {
api.ErrHandler(c, err)
return
}
// Encode the image to a buffer
var buf []byte
buffer := bytes.NewBuffer(buf)
err = jpeg.Encode(buffer, qrCode, nil)
if err != nil {
fmt.Println("Error encoding image:", err)
return
}
// Encode the image to a buffer
var buf []byte
buffer := bytes.NewBuffer(buf)
err = jpeg.Encode(buffer, qrCode, nil)
if err != nil {
fmt.Println("Error encoding image:", err)
return
}
// Convert the buffer to a base64 string
base64Str := "data:image/jpeg;base64," + base64.StdEncoding.EncodeToString(buffer.Bytes())
// Convert the buffer to a base64 string
base64Str := "data:image/jpeg;base64," + base64.StdEncoding.EncodeToString(buffer.Bytes())
c.JSON(http.StatusOK, gin.H{
"secret": base64.StdEncoding.EncodeToString(ciphertext),
"qr_code": base64Str,
})
c.JSON(http.StatusOK, gin.H{
"secret": otpKey.Secret(),
"qr_code": base64Str,
})
}
func EnrollTOTP(c *gin.Context) {
cUser := api.CurrentUser(c)
if cUser.EnabledOTP() {
c.JSON(http.StatusBadRequest, gin.H{
"message": "User already enrolled",
})
return
}
cUser := api.CurrentUser(c)
if cUser.EnabledOTP() {
c.JSON(http.StatusBadRequest, gin.H{
"message": "User already enrolled",
})
return
}
if settings.ServerSettings.Demo {
c.JSON(http.StatusBadRequest, gin.H{
"message": "This feature is disabled in demo mode",
})
return
}
if settings.ServerSettings.Demo {
c.JSON(http.StatusBadRequest, gin.H{
"message": "This feature is disabled in demo mode",
})
return
}
var json struct {
Secret string `json:"secret" binding:"required"`
Passcode string `json:"passcode" binding:"required"`
}
if !api.BindAndValid(c, &json) {
return
}
var json struct {
Secret string `json:"secret" binding:"required"`
Passcode string `json:"passcode" binding:"required"`
}
if !api.BindAndValid(c, &json) {
return
}
secret, err := base64.StdEncoding.DecodeString(json.Secret)
if err != nil {
api.ErrHandler(c, err)
return
}
if ok := totp.Validate(json.Passcode, json.Secret); !ok {
c.JSON(http.StatusNotAcceptable, gin.H{
"message": "Invalid passcode",
})
return
}
decrypted, err := crypto.AesDecrypt(secret)
if err != nil {
api.ErrHandler(c, err)
return
}
ciphertext, err := crypto.AesEncrypt([]byte(json.Secret))
if err != nil {
api.ErrHandler(c, err)
return
}
if ok := totp.Validate(json.Passcode, string(decrypted)); !ok {
c.JSON(http.StatusNotAcceptable, gin.H{
"message": "Invalid passcode",
})
return
}
u := query.Auth
_, err = u.Where(u.ID.Eq(cUser.ID)).Update(u.OTPSecret, ciphertext)
if err != nil {
api.ErrHandler(c, err)
return
}
ciphertext, err := crypto.AesEncrypt(decrypted)
if err != nil {
api.ErrHandler(c, err)
return
}
recoveryCode := sha1.Sum(ciphertext)
u := query.Auth
_, err = u.Where(u.ID.Eq(cUser.ID)).Update(u.OTPSecret, ciphertext)
if err != nil {
api.ErrHandler(c, err)
return
}
recoveryCode := sha1.Sum(ciphertext)
c.JSON(http.StatusOK, gin.H{
"message": "ok",
"recovery_code": hex.EncodeToString(recoveryCode[:]),
})
c.JSON(http.StatusOK, gin.H{
"message": "ok",
"recovery_code": hex.EncodeToString(recoveryCode[:]),
})
}
func ResetOTP(c *gin.Context) {
var json struct {
RecoveryCode string `json:"recovery_code"`
}
if !api.BindAndValid(c, &json) {
return
}
recoverCode, err := hex.DecodeString(json.RecoveryCode)
if err != nil {
api.ErrHandler(c, err)
return
}
cUser := api.CurrentUser(c)
k := sha1.Sum(cUser.OTPSecret)
if !bytes.Equal(k[:], recoverCode) {
c.JSON(http.StatusBadRequest, gin.H{
"message": "Invalid recovery code",
})
return
}
var json struct {
RecoveryCode string `json:"recovery_code"`
}
if !api.BindAndValid(c, &json) {
return
}
recoverCode, err := hex.DecodeString(json.RecoveryCode)
if err != nil {
api.ErrHandler(c, err)
return
}
cUser := api.CurrentUser(c)
k := sha1.Sum(cUser.OTPSecret)
if !bytes.Equal(k[:], recoverCode) {
c.JSON(http.StatusBadRequest, gin.H{
"message": "Invalid recovery code",
})
return
}
u := query.Auth
_, err = u.Where(u.ID.Eq(cUser.ID)).UpdateSimple(u.OTPSecret.Null())
if err != nil {
api.ErrHandler(c, err)
return
}
u := query.Auth
_, err = u.Where(u.ID.Eq(cUser.ID)).UpdateSimple(u.OTPSecret.Null())
if err != nil {
api.ErrHandler(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
}
func OTPStatus(c *gin.Context) {
status := false
u, ok := c.Get("user")
if ok {
status = u.(*model.Auth).EnabledOTP()
}
c.JSON(http.StatusOK, gin.H{
"status": status,
})
status := false
u, ok := c.Get("user")
if ok {
status = u.(*model.Auth).EnabledOTP()
}
c.JSON(http.StatusOK, gin.H{
"status": status,
})
}
func SecureSessionStatus(c *gin.Context) {
u, ok := c.Get("user")
if !ok || !u.(*model.Auth).EnabledOTP() {
c.JSON(http.StatusOK, gin.H{
"status": false,
})
return
}
ssid := c.GetHeader("X-Secure-Session-ID")
if ssid == "" {
ssid = c.Query("X-Secure-Session-ID")
}
if ssid == "" {
c.JSON(http.StatusOK, gin.H{
"status": false,
})
return
}
u, ok := c.Get("user")
if !ok || !u.(*model.Auth).EnabledOTP() {
c.JSON(http.StatusOK, gin.H{
"status": false,
})
return
}
ssid := c.GetHeader("X-Secure-Session-ID")
if ssid == "" {
ssid = c.Query("X-Secure-Session-ID")
}
if ssid == "" {
c.JSON(http.StatusOK, gin.H{
"status": false,
})
return
}
if user.VerifySecureSessionID(ssid, u.(*model.Auth).ID) {
c.JSON(http.StatusOK, gin.H{
"status": true,
})
return
}
if user.VerifySecureSessionID(ssid, u.(*model.Auth).ID) {
c.JSON(http.StatusOK, gin.H{
"status": true,
})
return
}
c.JSON(http.StatusOK, gin.H{
"status": false,
})
c.JSON(http.StatusOK, gin.H{
"status": false,
})
}
func StartSecure2FASession(c *gin.Context) {
var json struct {
OTP string `json:"otp"`
RecoveryCode string `json:"recovery_code"`
}
if !api.BindAndValid(c, &json) {
return
}
u := api.CurrentUser(c)
if !u.EnabledOTP() {
c.JSON(http.StatusBadRequest, gin.H{
"message": "User not configured with 2FA",
})
return
}
var json struct {
OTP string `json:"otp"`
RecoveryCode string `json:"recovery_code"`
}
if !api.BindAndValid(c, &json) {
return
}
u := api.CurrentUser(c)
if !u.EnabledOTP() {
c.JSON(http.StatusBadRequest, gin.H{
"message": "User not configured with 2FA",
})
return
}
if json.OTP == "" && json.RecoveryCode == "" {
c.JSON(http.StatusBadRequest, LoginResponse{
Message: "The user has enabled 2FA",
})
return
}
if json.OTP == "" && json.RecoveryCode == "" {
c.JSON(http.StatusBadRequest, LoginResponse{
Message: "The user has enabled 2FA",
})
return
}
if err := user.VerifyOTP(u, json.OTP, json.RecoveryCode); err != nil {
c.JSON(http.StatusBadRequest, LoginResponse{
Message: "Invalid 2FA or recovery code",
})
return
}
if err := user.VerifyOTP(u, json.OTP, json.RecoveryCode); err != nil {
c.JSON(http.StatusBadRequest, LoginResponse{
Message: "Invalid 2FA or recovery code",
})
return
}
sessionId := user.SetSecureSessionID(u.ID)
sessionId := user.SetSecureSessionID(u.ID)
c.JSON(http.StatusOK, gin.H{
"session_id": sessionId,
})
c.JSON(http.StatusOK, gin.H{
"session_id": sessionId,
})
}

View file

@ -13,7 +13,7 @@ msgstr ""
msgid "2FA"
msgstr ""
#: src/views/preference/components/TOTP.vue:88
#: src/views/preference/components/TOTP.vue:90
msgid "2FA Settings"
msgstr ""
@ -259,6 +259,10 @@ msgstr ""
msgid "CADir"
msgstr ""
#: src/views/preference/components/TOTP.vue:150
msgid "Can't scan? Use text key binding"
msgstr ""
#: src/components/ChatGPT/ChatGPT.vue:252
#: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:55
#: src/components/StdDesign/StdDataDisplay/StdCurd.vue:253
@ -452,11 +456,11 @@ msgstr ""
msgid "Credentials"
msgstr ""
#: src/views/preference/components/TOTP.vue:96
#: src/views/preference/components/TOTP.vue:98
msgid "Current account is enabled 2FA."
msgstr ""
#: src/views/preference/components/TOTP.vue:93
#: src/views/preference/components/TOTP.vue:95
msgid "Current account is not enabled 2FA."
msgstr ""
@ -753,12 +757,12 @@ msgstr ""
msgid "Enable %{conf_name} in %{node_name} successfully"
msgstr ""
#: src/views/preference/components/TOTP.vue:122
#: src/views/preference/components/TOTP.vue:124
#, fuzzy
msgid "Enable 2FA"
msgstr "Enabled"
#: src/views/preference/components/TOTP.vue:52
#: src/views/preference/components/TOTP.vue:54
#, fuzzy
msgid "Enable 2FA successfully"
msgstr "Enabled successfully"
@ -976,7 +980,7 @@ msgid ""
"ban threshold minutes, the ip will be banned for a period of time."
msgstr ""
#: src/views/preference/components/TOTP.vue:108
#: src/views/preference/components/TOTP.vue:110
msgid ""
"If you lose your mobile phone, you can use the recovery code to reset your "
"2FA."
@ -1013,12 +1017,12 @@ msgstr ""
msgid "Initialing core upgrader"
msgstr ""
#: src/views/preference/components/TOTP.vue:144
#: src/views/preference/components/TOTP.vue:157
msgid "Input the code from the app:"
msgstr ""
#: src/components/OTP/OTPAuthorization.vue:49
#: src/views/preference/components/TOTP.vue:157
#: src/views/preference/components/TOTP.vue:170
msgid "Input the recovery code:"
msgstr ""
@ -1631,15 +1635,15 @@ msgid "Recovered Successfully"
msgstr "Saved successfully"
#: src/components/OTP/OTPAuthorization.vue:56
#: src/views/preference/components/TOTP.vue:164
#: src/views/preference/components/TOTP.vue:177
msgid "Recovery"
msgstr ""
#: src/views/preference/components/TOTP.vue:101
#: src/views/preference/components/TOTP.vue:103
msgid "Recovery Code"
msgstr ""
#: src/views/preference/components/TOTP.vue:110
#: src/views/preference/components/TOTP.vue:112
msgid "Recovery Code:"
msgstr ""
@ -1779,7 +1783,7 @@ msgstr ""
msgid "Reset"
msgstr ""
#: src/views/preference/components/TOTP.vue:130
#: src/views/preference/components/TOTP.vue:132
msgid "Reset 2FA"
msgstr ""
@ -1832,7 +1836,7 @@ msgstr "Saved successfully"
msgid "Saved successfully"
msgstr "Saved successfully"
#: src/views/preference/components/TOTP.vue:91
#: src/views/preference/components/TOTP.vue:93
msgid "Scan the QR code with your mobile phone to add the account to the app."
msgstr ""
@ -1840,6 +1844,10 @@ msgstr ""
msgid "SDK"
msgstr ""
#: src/views/preference/components/TOTP.vue:149
msgid "Secret has been copied"
msgstr ""
#: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:155
msgid "Selector"
msgstr ""
@ -1862,8 +1870,8 @@ msgstr "Send"
#: src/views/environment/BatchUpgrader.vue:57
#: src/views/environment/Environment.vue:15 src/views/other/Install.vue:68
#: src/views/preference/AuthSettings.vue:49
#: src/views/preference/components/TOTP.vue:42
#: src/views/preference/components/TOTP.vue:55
#: src/views/preference/components/TOTP.vue:44
#: src/views/preference/components/TOTP.vue:57
#: src/views/preference/Preference.vue:83 src/views/stream/StreamList.vue:113
#: src/views/stream/StreamList.vue:81 src/views/system/Upgrade.vue:42
msgid "Server error"
@ -2112,7 +2120,7 @@ msgstr "Certificate Status"
msgid "The path exists, but the file is not a private key"
msgstr ""
#: src/views/preference/components/TOTP.vue:109
#: src/views/preference/components/TOTP.vue:111
msgid ""
"The recovery code is only displayed once, please save it in a safe place."
msgstr ""
@ -2185,7 +2193,7 @@ msgstr ""
msgid "Title"
msgstr ""
#: src/views/preference/components/TOTP.vue:90
#: src/views/preference/components/TOTP.vue:92
msgid ""
"To enable it, you need to install the Google or Microsoft Authenticator app "
"on your mobile phone."
@ -2207,7 +2215,7 @@ msgstr ""
msgid "Too many login failed attempts, please try again later"
msgstr ""
#: src/views/preference/components/TOTP.vue:89
#: src/views/preference/components/TOTP.vue:91
msgid ""
"TOTP is a two-factor authentication method that uses a time-based one-time "
"password algorithm."

View file

@ -20,7 +20,7 @@ msgstr ""
msgid "2FA"
msgstr "2FA"
#: src/views/preference/components/TOTP.vue:88
#: src/views/preference/components/TOTP.vue:90
msgid "2FA Settings"
msgstr "Configuración de 2FA"
@ -249,6 +249,10 @@ msgstr "Dir CA"
msgid "CADir"
msgstr "Directorio CA"
#: src/views/preference/components/TOTP.vue:150
msgid "Can't scan? Use text key binding"
msgstr ""
#: src/components/ChatGPT/ChatGPT.vue:252
#: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:55
#: src/components/StdDesign/StdDataDisplay/StdCurd.vue:253
@ -428,12 +432,12 @@ msgstr "Credencial"
msgid "Credentials"
msgstr "Credenciales"
#: src/views/preference/components/TOTP.vue:96
#: src/views/preference/components/TOTP.vue:98
msgid "Current account is enabled 2FA."
msgstr ""
"La cuenta actual tiene habilitada la autenticación de dos factores (2FA)."
#: src/views/preference/components/TOTP.vue:93
#: src/views/preference/components/TOTP.vue:95
msgid "Current account is not enabled 2FA."
msgstr ""
"La cuenta actual no tiene habilitada la autenticación de dos factores (2FA)."
@ -716,11 +720,11 @@ msgstr "Falló el habilitado de %{conf_name} en %{node_name}"
msgid "Enable %{conf_name} in %{node_name} successfully"
msgstr "Habilitado exitoso de %{conf_name} en %{node_name}"
#: src/views/preference/components/TOTP.vue:122
#: src/views/preference/components/TOTP.vue:124
msgid "Enable 2FA"
msgstr "Habilitar 2FA"
#: src/views/preference/components/TOTP.vue:52
#: src/views/preference/components/TOTP.vue:54
msgid "Enable 2FA successfully"
msgstr "Habilitar 2FA exitoso"
@ -932,7 +936,7 @@ msgstr ""
"el máximo de intentos en los minutos del umbral de prohibición, la IP será "
"bloqueada por un período de tiempo."
#: src/views/preference/components/TOTP.vue:108
#: src/views/preference/components/TOTP.vue:110
msgid ""
"If you lose your mobile phone, you can use the recovery code to reset your "
"2FA."
@ -972,12 +976,12 @@ msgstr "Error de actualización de kernel inicial"
msgid "Initialing core upgrader"
msgstr "Inicializando la actualización del kernel"
#: src/views/preference/components/TOTP.vue:144
#: src/views/preference/components/TOTP.vue:157
msgid "Input the code from the app:"
msgstr "Ingrese el código de la aplicación:"
#: src/components/OTP/OTPAuthorization.vue:49
#: src/views/preference/components/TOTP.vue:157
#: src/views/preference/components/TOTP.vue:170
msgid "Input the recovery code:"
msgstr "Ingrese el código de recuperación:"
@ -1575,15 +1579,15 @@ msgid "Recovered Successfully"
msgstr "Recuperado con éxito"
#: src/components/OTP/OTPAuthorization.vue:56
#: src/views/preference/components/TOTP.vue:164
#: src/views/preference/components/TOTP.vue:177
msgid "Recovery"
msgstr "Recuperación"
#: src/views/preference/components/TOTP.vue:101
#: src/views/preference/components/TOTP.vue:103
msgid "Recovery Code"
msgstr "Código de Recuperación"
#: src/views/preference/components/TOTP.vue:110
#: src/views/preference/components/TOTP.vue:112
msgid "Recovery Code:"
msgstr "Código de Recuperación:"
@ -1710,7 +1714,7 @@ msgstr "Pedido con parámetros incorrectos"
msgid "Reset"
msgstr "Limpiar"
#: src/views/preference/components/TOTP.vue:130
#: src/views/preference/components/TOTP.vue:132
msgid "Reset 2FA"
msgstr "Restablecer 2FA"
@ -1761,7 +1765,7 @@ msgstr "Guardado con éxito"
msgid "Saved successfully"
msgstr "Guardado con éxito"
#: src/views/preference/components/TOTP.vue:91
#: src/views/preference/components/TOTP.vue:93
msgid "Scan the QR code with your mobile phone to add the account to the app."
msgstr ""
"Escanee el código QR con su teléfono móvil para agregar la cuenta a la "
@ -1771,6 +1775,10 @@ msgstr ""
msgid "SDK"
msgstr "SDK"
#: src/views/preference/components/TOTP.vue:149
msgid "Secret has been copied"
msgstr ""
#: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:155
msgid "Selector"
msgstr "Seleccionador"
@ -1793,8 +1801,8 @@ msgstr "Enviado"
#: src/views/environment/BatchUpgrader.vue:57
#: src/views/environment/Environment.vue:15 src/views/other/Install.vue:68
#: src/views/preference/AuthSettings.vue:49
#: src/views/preference/components/TOTP.vue:42
#: src/views/preference/components/TOTP.vue:55
#: src/views/preference/components/TOTP.vue:44
#: src/views/preference/components/TOTP.vue:57
#: src/views/preference/Preference.vue:83 src/views/stream/StreamList.vue:113
#: src/views/stream/StreamList.vue:81 src/views/system/Upgrade.vue:42
msgid "Server error"
@ -2037,7 +2045,7 @@ msgstr "La ruta existe, pero el archivo no es un certificado"
msgid "The path exists, but the file is not a private key"
msgstr "La ruta existe, pero el archivo no es una clave privada"
#: src/views/preference/components/TOTP.vue:109
#: src/views/preference/components/TOTP.vue:111
msgid ""
"The recovery code is only displayed once, please save it in a safe place."
msgstr ""
@ -2118,7 +2126,7 @@ msgstr "Consejos"
msgid "Title"
msgstr "Título"
#: src/views/preference/components/TOTP.vue:90
#: src/views/preference/components/TOTP.vue:92
msgid ""
"To enable it, you need to install the Google or Microsoft Authenticator app "
"on your mobile phone."
@ -2148,7 +2156,7 @@ msgstr ""
"Demasiados intentos fallidos de inicio de sesión, por favor intente "
"nuevamente más tarde"
#: src/views/preference/components/TOTP.vue:89
#: src/views/preference/components/TOTP.vue:91
msgid ""
"TOTP is a two-factor authentication method that uses a time-based one-time "
"password algorithm."

View file

@ -15,7 +15,7 @@ msgstr ""
msgid "2FA"
msgstr ""
#: src/views/preference/components/TOTP.vue:88
#: src/views/preference/components/TOTP.vue:90
msgid "2FA Settings"
msgstr ""
@ -261,6 +261,10 @@ msgstr ""
msgid "CADir"
msgstr ""
#: src/views/preference/components/TOTP.vue:150
msgid "Can't scan? Use text key binding"
msgstr ""
#: src/components/ChatGPT/ChatGPT.vue:252
#: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:55
#: src/components/StdDesign/StdDataDisplay/StdCurd.vue:253
@ -452,11 +456,11 @@ msgstr "Identifiant"
msgid "Credentials"
msgstr "Identifiants"
#: src/views/preference/components/TOTP.vue:96
#: src/views/preference/components/TOTP.vue:98
msgid "Current account is enabled 2FA."
msgstr ""
#: src/views/preference/components/TOTP.vue:93
#: src/views/preference/components/TOTP.vue:95
msgid "Current account is not enabled 2FA."
msgstr ""
@ -753,12 +757,12 @@ msgstr ""
msgid "Enable %{conf_name} in %{node_name} successfully"
msgstr ""
#: src/views/preference/components/TOTP.vue:122
#: src/views/preference/components/TOTP.vue:124
#, fuzzy
msgid "Enable 2FA"
msgstr "Activé"
#: src/views/preference/components/TOTP.vue:52
#: src/views/preference/components/TOTP.vue:54
#, fuzzy
msgid "Enable 2FA successfully"
msgstr "Activé avec succès"
@ -977,7 +981,7 @@ msgid ""
"ban threshold minutes, the ip will be banned for a period of time."
msgstr ""
#: src/views/preference/components/TOTP.vue:108
#: src/views/preference/components/TOTP.vue:110
msgid ""
"If you lose your mobile phone, you can use the recovery code to reset your "
"2FA."
@ -1016,12 +1020,12 @@ msgstr "Erreur du programme de mise à niveau initial du core"
msgid "Initialing core upgrader"
msgstr "Initialisation du programme de mise à niveau du core"
#: src/views/preference/components/TOTP.vue:144
#: src/views/preference/components/TOTP.vue:157
msgid "Input the code from the app:"
msgstr ""
#: src/components/OTP/OTPAuthorization.vue:49
#: src/views/preference/components/TOTP.vue:157
#: src/views/preference/components/TOTP.vue:170
msgid "Input the recovery code:"
msgstr ""
@ -1637,15 +1641,15 @@ msgid "Recovered Successfully"
msgstr "Enregistré avec succès"
#: src/components/OTP/OTPAuthorization.vue:56
#: src/views/preference/components/TOTP.vue:164
#: src/views/preference/components/TOTP.vue:177
msgid "Recovery"
msgstr ""
#: src/views/preference/components/TOTP.vue:101
#: src/views/preference/components/TOTP.vue:103
msgid "Recovery Code"
msgstr ""
#: src/views/preference/components/TOTP.vue:110
#: src/views/preference/components/TOTP.vue:112
msgid "Recovery Code:"
msgstr ""
@ -1786,7 +1790,7 @@ msgstr ""
msgid "Reset"
msgstr "Réinitialiser"
#: src/views/preference/components/TOTP.vue:130
#: src/views/preference/components/TOTP.vue:132
#, fuzzy
msgid "Reset 2FA"
msgstr "Réinitialiser"
@ -1838,7 +1842,7 @@ msgstr "Sauvegarde réussie"
msgid "Saved successfully"
msgstr "Enregistré avec succès"
#: src/views/preference/components/TOTP.vue:91
#: src/views/preference/components/TOTP.vue:93
msgid "Scan the QR code with your mobile phone to add the account to the app."
msgstr ""
@ -1846,6 +1850,10 @@ msgstr ""
msgid "SDK"
msgstr ""
#: src/views/preference/components/TOTP.vue:149
msgid "Secret has been copied"
msgstr ""
#: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:155
msgid "Selector"
msgstr "Sélecteur"
@ -1868,8 +1876,8 @@ msgstr "Envoyer"
#: src/views/environment/BatchUpgrader.vue:57
#: src/views/environment/Environment.vue:15 src/views/other/Install.vue:68
#: src/views/preference/AuthSettings.vue:49
#: src/views/preference/components/TOTP.vue:42
#: src/views/preference/components/TOTP.vue:55
#: src/views/preference/components/TOTP.vue:44
#: src/views/preference/components/TOTP.vue:57
#: src/views/preference/Preference.vue:83 src/views/stream/StreamList.vue:113
#: src/views/stream/StreamList.vue:81 src/views/system/Upgrade.vue:42
msgid "Server error"
@ -2118,7 +2126,7 @@ msgstr "Chemin de la clé du certificat SSL"
msgid "The path exists, but the file is not a private key"
msgstr ""
#: src/views/preference/components/TOTP.vue:109
#: src/views/preference/components/TOTP.vue:111
msgid ""
"The recovery code is only displayed once, please save it in a safe place."
msgstr ""
@ -2195,7 +2203,7 @@ msgstr ""
msgid "Title"
msgstr ""
#: src/views/preference/components/TOTP.vue:90
#: src/views/preference/components/TOTP.vue:92
msgid ""
"To enable it, you need to install the Google or Microsoft Authenticator app "
"on your mobile phone."
@ -2221,7 +2229,7 @@ msgstr ""
msgid "Too many login failed attempts, please try again later"
msgstr ""
#: src/views/preference/components/TOTP.vue:89
#: src/views/preference/components/TOTP.vue:91
msgid ""
"TOTP is a two-factor authentication method that uses a time-based one-time "
"password algorithm."

View file

@ -18,7 +18,7 @@ msgstr ""
msgid "2FA"
msgstr "2FA"
#: src/views/preference/components/TOTP.vue:88
#: src/views/preference/components/TOTP.vue:90
msgid "2FA Settings"
msgstr "2FA 설정"
@ -247,6 +247,10 @@ msgstr "CA 디렉토리"
msgid "CADir"
msgstr "CA 디렉토리"
#: src/views/preference/components/TOTP.vue:150
msgid "Can't scan? Use text key binding"
msgstr ""
#: src/components/ChatGPT/ChatGPT.vue:252
#: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:55
#: src/components/StdDesign/StdDataDisplay/StdCurd.vue:253
@ -431,11 +435,11 @@ msgstr "인증 정보"
msgid "Credentials"
msgstr "인증 정보들"
#: src/views/preference/components/TOTP.vue:96
#: src/views/preference/components/TOTP.vue:98
msgid "Current account is enabled 2FA."
msgstr ""
#: src/views/preference/components/TOTP.vue:93
#: src/views/preference/components/TOTP.vue:95
msgid "Current account is not enabled 2FA."
msgstr ""
@ -716,12 +720,12 @@ msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
msgid "Enable %{conf_name} in %{node_name} successfully"
msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
#: src/views/preference/components/TOTP.vue:122
#: src/views/preference/components/TOTP.vue:124
#, fuzzy
msgid "Enable 2FA"
msgstr "활성화"
#: src/views/preference/components/TOTP.vue:52
#: src/views/preference/components/TOTP.vue:54
#, fuzzy
msgid "Enable 2FA successfully"
msgstr "성공적으로 활성화"
@ -938,7 +942,7 @@ msgid ""
"ban threshold minutes, the ip will be banned for a period of time."
msgstr ""
#: src/views/preference/components/TOTP.vue:108
#: src/views/preference/components/TOTP.vue:110
msgid ""
"If you lose your mobile phone, you can use the recovery code to reset your "
"2FA."
@ -976,12 +980,12 @@ msgstr "초기 코어 업그레이더 오류"
msgid "Initialing core upgrader"
msgstr "코어 업그레이더 초기화"
#: src/views/preference/components/TOTP.vue:144
#: src/views/preference/components/TOTP.vue:157
msgid "Input the code from the app:"
msgstr ""
#: src/components/OTP/OTPAuthorization.vue:49
#: src/views/preference/components/TOTP.vue:157
#: src/views/preference/components/TOTP.vue:170
msgid "Input the recovery code:"
msgstr ""
@ -1601,15 +1605,15 @@ msgid "Recovered Successfully"
msgstr "성공적으로 제거됨"
#: src/components/OTP/OTPAuthorization.vue:56
#: src/views/preference/components/TOTP.vue:164
#: src/views/preference/components/TOTP.vue:177
msgid "Recovery"
msgstr ""
#: src/views/preference/components/TOTP.vue:101
#: src/views/preference/components/TOTP.vue:103
msgid "Recovery Code"
msgstr ""
#: src/views/preference/components/TOTP.vue:110
#: src/views/preference/components/TOTP.vue:112
msgid "Recovery Code:"
msgstr ""
@ -1751,7 +1755,7 @@ msgstr "잘못된 매개변수로 요청됨"
msgid "Reset"
msgstr "재설정"
#: src/views/preference/components/TOTP.vue:130
#: src/views/preference/components/TOTP.vue:132
#, fuzzy
msgid "Reset 2FA"
msgstr "재설정"
@ -1805,7 +1809,7 @@ msgstr "성공적으로 저장됨"
msgid "Saved successfully"
msgstr "성공적으로 저장됨"
#: src/views/preference/components/TOTP.vue:91
#: src/views/preference/components/TOTP.vue:93
msgid "Scan the QR code with your mobile phone to add the account to the app."
msgstr ""
@ -1813,6 +1817,10 @@ msgstr ""
msgid "SDK"
msgstr ""
#: src/views/preference/components/TOTP.vue:149
msgid "Secret has been copied"
msgstr ""
#: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:155
msgid "Selector"
msgstr "선택"
@ -1835,8 +1843,8 @@ msgstr "보내기"
#: src/views/environment/BatchUpgrader.vue:57
#: src/views/environment/Environment.vue:15 src/views/other/Install.vue:68
#: src/views/preference/AuthSettings.vue:49
#: src/views/preference/components/TOTP.vue:42
#: src/views/preference/components/TOTP.vue:55
#: src/views/preference/components/TOTP.vue:44
#: src/views/preference/components/TOTP.vue:57
#: src/views/preference/Preference.vue:83 src/views/stream/StreamList.vue:113
#: src/views/stream/StreamList.vue:81 src/views/system/Upgrade.vue:42
msgid "Server error"
@ -2084,7 +2092,7 @@ msgstr "Certificate Status"
msgid "The path exists, but the file is not a private key"
msgstr "경로는 존재하지만 파일은 개인 키가 아닙니다"
#: src/views/preference/components/TOTP.vue:109
#: src/views/preference/components/TOTP.vue:111
msgid ""
"The recovery code is only displayed once, please save it in a safe place."
msgstr ""
@ -2159,7 +2167,7 @@ msgstr "팁"
msgid "Title"
msgstr "제목"
#: src/views/preference/components/TOTP.vue:90
#: src/views/preference/components/TOTP.vue:92
msgid ""
"To enable it, you need to install the Google or Microsoft Authenticator app "
"on your mobile phone."
@ -2184,7 +2192,7 @@ msgstr "토큰이 유효하지 않습니다"
msgid "Too many login failed attempts, please try again later"
msgstr ""
#: src/views/preference/components/TOTP.vue:89
#: src/views/preference/components/TOTP.vue:91
msgid ""
"TOTP is a two-factor authentication method that uses a time-based one-time "
"password algorithm."

View file

@ -6,7 +6,7 @@ msgstr ""
msgid "2FA"
msgstr ""
#: src/views/preference/components/TOTP.vue:88
#: src/views/preference/components/TOTP.vue:90
msgid "2FA Settings"
msgstr ""
@ -247,6 +247,10 @@ msgstr ""
msgid "CADir"
msgstr ""
#: src/views/preference/components/TOTP.vue:150
msgid "Can't scan? Use text key binding"
msgstr ""
#: src/components/ChatGPT/ChatGPT.vue:252
#: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:55
#: src/components/StdDesign/StdDataDisplay/StdCurd.vue:253
@ -428,11 +432,11 @@ msgstr ""
msgid "Credentials"
msgstr ""
#: src/views/preference/components/TOTP.vue:96
#: src/views/preference/components/TOTP.vue:98
msgid "Current account is enabled 2FA."
msgstr ""
#: src/views/preference/components/TOTP.vue:93
#: src/views/preference/components/TOTP.vue:95
msgid "Current account is not enabled 2FA."
msgstr ""
@ -718,11 +722,11 @@ msgstr ""
msgid "Enable %{conf_name} in %{node_name} successfully"
msgstr ""
#: src/views/preference/components/TOTP.vue:122
#: src/views/preference/components/TOTP.vue:124
msgid "Enable 2FA"
msgstr ""
#: src/views/preference/components/TOTP.vue:52
#: src/views/preference/components/TOTP.vue:54
msgid "Enable 2FA successfully"
msgstr ""
@ -937,7 +941,7 @@ msgstr ""
msgid "If the number of login failed attempts from a ip reach the max attempts in ban threshold minutes, the ip will be banned for a period of time."
msgstr ""
#: src/views/preference/components/TOTP.vue:108
#: src/views/preference/components/TOTP.vue:110
msgid "If you lose your mobile phone, you can use the recovery code to reset your 2FA."
msgstr ""
@ -971,12 +975,12 @@ msgstr ""
msgid "Initialing core upgrader"
msgstr ""
#: src/views/preference/components/TOTP.vue:144
#: src/views/preference/components/TOTP.vue:157
msgid "Input the code from the app:"
msgstr ""
#: src/components/OTP/OTPAuthorization.vue:49
#: src/views/preference/components/TOTP.vue:157
#: src/views/preference/components/TOTP.vue:170
msgid "Input the recovery code:"
msgstr ""
@ -1556,15 +1560,15 @@ msgid "Recovered Successfully"
msgstr ""
#: src/components/OTP/OTPAuthorization.vue:56
#: src/views/preference/components/TOTP.vue:164
#: src/views/preference/components/TOTP.vue:177
msgid "Recovery"
msgstr ""
#: src/views/preference/components/TOTP.vue:101
#: src/views/preference/components/TOTP.vue:103
msgid "Recovery Code"
msgstr ""
#: src/views/preference/components/TOTP.vue:110
#: src/views/preference/components/TOTP.vue:112
msgid "Recovery Code:"
msgstr ""
@ -1685,7 +1689,7 @@ msgstr ""
msgid "Reset"
msgstr ""
#: src/views/preference/components/TOTP.vue:130
#: src/views/preference/components/TOTP.vue:132
msgid "Reset 2FA"
msgstr ""
@ -1740,7 +1744,7 @@ msgstr ""
msgid "Saved successfully"
msgstr ""
#: src/views/preference/components/TOTP.vue:91
#: src/views/preference/components/TOTP.vue:93
msgid "Scan the QR code with your mobile phone to add the account to the app."
msgstr ""
@ -1748,6 +1752,10 @@ msgstr ""
msgid "SDK"
msgstr ""
#: src/views/preference/components/TOTP.vue:149
msgid "Secret has been copied"
msgstr ""
#: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:155
msgid "Selector"
msgstr ""
@ -1772,8 +1780,8 @@ msgstr ""
#: src/views/environment/Environment.vue:15
#: src/views/other/Install.vue:68
#: src/views/preference/AuthSettings.vue:49
#: src/views/preference/components/TOTP.vue:42
#: src/views/preference/components/TOTP.vue:55
#: src/views/preference/components/TOTP.vue:44
#: src/views/preference/components/TOTP.vue:57
#: src/views/preference/Preference.vue:83
#: src/views/stream/StreamList.vue:113
#: src/views/stream/StreamList.vue:81
@ -1993,7 +2001,7 @@ msgstr ""
msgid "The path exists, but the file is not a private key"
msgstr ""
#: src/views/preference/components/TOTP.vue:109
#: src/views/preference/components/TOTP.vue:111
msgid "The recovery code is only displayed once, please save it in a safe place."
msgstr ""
@ -2054,7 +2062,7 @@ msgstr ""
msgid "Title"
msgstr ""
#: src/views/preference/components/TOTP.vue:90
#: src/views/preference/components/TOTP.vue:92
msgid "To enable it, you need to install the Google or Microsoft Authenticator app on your mobile phone."
msgstr ""
@ -2070,7 +2078,7 @@ msgstr ""
msgid "Too many login failed attempts, please try again later"
msgstr ""
#: src/views/preference/components/TOTP.vue:89
#: src/views/preference/components/TOTP.vue:91
msgid "TOTP is a two-factor authentication method that uses a time-based one-time password algorithm."
msgstr ""

View file

@ -18,7 +18,7 @@ msgstr ""
msgid "2FA"
msgstr "2ФА"
#: src/views/preference/components/TOTP.vue:88
#: src/views/preference/components/TOTP.vue:90
msgid "2FA Settings"
msgstr "Настройки 2ФА"
@ -250,6 +250,10 @@ msgstr "Директория корневого сертификата"
msgid "CADir"
msgstr ""
#: src/views/preference/components/TOTP.vue:150
msgid "Can't scan? Use text key binding"
msgstr ""
#: src/components/ChatGPT/ChatGPT.vue:252
#: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:55
#: src/components/StdDesign/StdDataDisplay/StdCurd.vue:253
@ -429,11 +433,11 @@ msgstr "Учетные данные"
msgid "Credentials"
msgstr "Учетные данные"
#: src/views/preference/components/TOTP.vue:96
#: src/views/preference/components/TOTP.vue:98
msgid "Current account is enabled 2FA."
msgstr "Текущая учетная запись имеет включенную 2ФА."
#: src/views/preference/components/TOTP.vue:93
#: src/views/preference/components/TOTP.vue:95
msgid "Current account is not enabled 2FA."
msgstr ""
"Текущая учетная запись не имеет включенной двухфакторной аутентификации."
@ -716,11 +720,11 @@ msgstr "Включение %{conf_name} in %{node_name} нипалучилася
msgid "Enable %{conf_name} in %{node_name} successfully"
msgstr "Включение %{conf_name} in %{node_name} успешно"
#: src/views/preference/components/TOTP.vue:122
#: src/views/preference/components/TOTP.vue:124
msgid "Enable 2FA"
msgstr "Включить 2ФА"
#: src/views/preference/components/TOTP.vue:52
#: src/views/preference/components/TOTP.vue:54
msgid "Enable 2FA successfully"
msgstr "Двухфакторная аутентификация успешно включена"
@ -931,7 +935,7 @@ msgstr ""
"количества попыток в течение пороговых минут блокировки, IP будет "
"заблокирован на определенный период времени."
#: src/views/preference/components/TOTP.vue:108
#: src/views/preference/components/TOTP.vue:110
msgid ""
"If you lose your mobile phone, you can use the recovery code to reset your "
"2FA."
@ -971,12 +975,12 @@ msgstr "Ошибка первоначального обновления ядр
msgid "Initialing core upgrader"
msgstr "Инициализация программы обновления ядра"
#: src/views/preference/components/TOTP.vue:144
#: src/views/preference/components/TOTP.vue:157
msgid "Input the code from the app:"
msgstr "Введите код из приложения:"
#: src/components/OTP/OTPAuthorization.vue:49
#: src/views/preference/components/TOTP.vue:157
#: src/views/preference/components/TOTP.vue:170
msgid "Input the recovery code:"
msgstr "Введите код восстановления:"
@ -1573,15 +1577,15 @@ msgid "Recovered Successfully"
msgstr "Восстановлено успешно"
#: src/components/OTP/OTPAuthorization.vue:56
#: src/views/preference/components/TOTP.vue:164
#: src/views/preference/components/TOTP.vue:177
msgid "Recovery"
msgstr "Восстановление"
#: src/views/preference/components/TOTP.vue:101
#: src/views/preference/components/TOTP.vue:103
msgid "Recovery Code"
msgstr "Код восстановления"
#: src/views/preference/components/TOTP.vue:110
#: src/views/preference/components/TOTP.vue:112
msgid "Recovery Code:"
msgstr "Код восстановления:"
@ -1709,7 +1713,7 @@ msgstr "Запрос с неправильными параметрами"
msgid "Reset"
msgstr "Сброс"
#: src/views/preference/components/TOTP.vue:130
#: src/views/preference/components/TOTP.vue:132
msgid "Reset 2FA"
msgstr "Сброс 2FA"
@ -1760,7 +1764,7 @@ msgstr "Сохранено успешно"
msgid "Saved successfully"
msgstr "Успешно сохранено"
#: src/views/preference/components/TOTP.vue:91
#: src/views/preference/components/TOTP.vue:93
msgid "Scan the QR code with your mobile phone to add the account to the app."
msgstr ""
"Отсканируйте QR-код с помощью мобильного телефона, чтобы добавить учетную "
@ -1770,6 +1774,10 @@ msgstr ""
msgid "SDK"
msgstr "SDK"
#: src/views/preference/components/TOTP.vue:149
msgid "Secret has been copied"
msgstr ""
#: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:155
msgid "Selector"
msgstr "Выбор"
@ -1792,8 +1800,8 @@ msgstr "Отправлено"
#: src/views/environment/BatchUpgrader.vue:57
#: src/views/environment/Environment.vue:15 src/views/other/Install.vue:68
#: src/views/preference/AuthSettings.vue:49
#: src/views/preference/components/TOTP.vue:42
#: src/views/preference/components/TOTP.vue:55
#: src/views/preference/components/TOTP.vue:44
#: src/views/preference/components/TOTP.vue:57
#: src/views/preference/Preference.vue:83 src/views/stream/StreamList.vue:113
#: src/views/stream/StreamList.vue:81 src/views/system/Upgrade.vue:42
msgid "Server error"
@ -2034,7 +2042,7 @@ msgstr "Путь существует, но файл не является се
msgid "The path exists, but the file is not a private key"
msgstr "Путь существует, но файл не является приватным ключом"
#: src/views/preference/components/TOTP.vue:109
#: src/views/preference/components/TOTP.vue:111
msgid ""
"The recovery code is only displayed once, please save it in a safe place."
msgstr ""
@ -2115,7 +2123,7 @@ msgstr "Советы"
msgid "Title"
msgstr "Заголовок"
#: src/views/preference/components/TOTP.vue:90
#: src/views/preference/components/TOTP.vue:92
msgid ""
"To enable it, you need to install the Google or Microsoft Authenticator app "
"on your mobile phone."
@ -2143,7 +2151,7 @@ msgstr "Токен недействителен"
msgid "Too many login failed attempts, please try again later"
msgstr "Слишком много неудачных попыток входа, попробуйте позже"
#: src/views/preference/components/TOTP.vue:89
#: src/views/preference/components/TOTP.vue:91
msgid ""
"TOTP is a two-factor authentication method that uses a time-based one-time "
"password algorithm."

View file

@ -13,7 +13,7 @@ msgstr ""
msgid "2FA"
msgstr ""
#: src/views/preference/components/TOTP.vue:88
#: src/views/preference/components/TOTP.vue:90
msgid "2FA Settings"
msgstr ""
@ -261,6 +261,10 @@ msgstr ""
msgid "CADir"
msgstr ""
#: src/views/preference/components/TOTP.vue:150
msgid "Can't scan? Use text key binding"
msgstr ""
#: src/components/ChatGPT/ChatGPT.vue:252
#: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:55
#: src/components/StdDesign/StdDataDisplay/StdCurd.vue:253
@ -454,11 +458,11 @@ msgstr "Chứng chỉ"
msgid "Credentials"
msgstr "Chứng chỉ"
#: src/views/preference/components/TOTP.vue:96
#: src/views/preference/components/TOTP.vue:98
msgid "Current account is enabled 2FA."
msgstr ""
#: src/views/preference/components/TOTP.vue:93
#: src/views/preference/components/TOTP.vue:95
msgid "Current account is not enabled 2FA."
msgstr ""
@ -758,12 +762,12 @@ msgstr "Không thể bật %{conf_name} trên %{node_name}"
msgid "Enable %{conf_name} in %{node_name} successfully"
msgstr "Đã bật %{conf_name} trên %{node_name}"
#: src/views/preference/components/TOTP.vue:122
#: src/views/preference/components/TOTP.vue:124
#, fuzzy
msgid "Enable 2FA"
msgstr "Đã bật"
#: src/views/preference/components/TOTP.vue:52
#: src/views/preference/components/TOTP.vue:54
#, fuzzy
msgid "Enable 2FA successfully"
msgstr "Đã bật"
@ -983,7 +987,7 @@ msgid ""
"ban threshold minutes, the ip will be banned for a period of time."
msgstr ""
#: src/views/preference/components/TOTP.vue:108
#: src/views/preference/components/TOTP.vue:110
msgid ""
"If you lose your mobile phone, you can use the recovery code to reset your "
"2FA."
@ -1022,12 +1026,12 @@ msgstr "Không thể khởi tạo trình nâng cấp"
msgid "Initialing core upgrader"
msgstr "Đang khởi tạo trình nâng cấp"
#: src/views/preference/components/TOTP.vue:144
#: src/views/preference/components/TOTP.vue:157
msgid "Input the code from the app:"
msgstr ""
#: src/components/OTP/OTPAuthorization.vue:49
#: src/views/preference/components/TOTP.vue:157
#: src/views/preference/components/TOTP.vue:170
msgid "Input the recovery code:"
msgstr ""
@ -1644,15 +1648,15 @@ msgid "Recovered Successfully"
msgstr "Xoá thành công"
#: src/components/OTP/OTPAuthorization.vue:56
#: src/views/preference/components/TOTP.vue:164
#: src/views/preference/components/TOTP.vue:177
msgid "Recovery"
msgstr ""
#: src/views/preference/components/TOTP.vue:101
#: src/views/preference/components/TOTP.vue:103
msgid "Recovery Code"
msgstr ""
#: src/views/preference/components/TOTP.vue:110
#: src/views/preference/components/TOTP.vue:112
msgid "Recovery Code:"
msgstr ""
@ -1794,7 +1798,7 @@ msgstr "Yêu cầu có chứa tham số sai"
msgid "Reset"
msgstr "Đặt lại"
#: src/views/preference/components/TOTP.vue:130
#: src/views/preference/components/TOTP.vue:132
#, fuzzy
msgid "Reset 2FA"
msgstr "Đặt lại"
@ -1848,7 +1852,7 @@ msgstr "Lưu thành công"
msgid "Saved successfully"
msgstr "Lưu thành công"
#: src/views/preference/components/TOTP.vue:91
#: src/views/preference/components/TOTP.vue:93
msgid "Scan the QR code with your mobile phone to add the account to the app."
msgstr ""
@ -1856,6 +1860,10 @@ msgstr ""
msgid "SDK"
msgstr ""
#: src/views/preference/components/TOTP.vue:149
msgid "Secret has been copied"
msgstr ""
#: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:155
msgid "Selector"
msgstr "Bộ chọn"
@ -1878,8 +1886,8 @@ msgstr "Gửi"
#: src/views/environment/BatchUpgrader.vue:57
#: src/views/environment/Environment.vue:15 src/views/other/Install.vue:68
#: src/views/preference/AuthSettings.vue:49
#: src/views/preference/components/TOTP.vue:42
#: src/views/preference/components/TOTP.vue:55
#: src/views/preference/components/TOTP.vue:44
#: src/views/preference/components/TOTP.vue:57
#: src/views/preference/Preference.vue:83 src/views/stream/StreamList.vue:113
#: src/views/stream/StreamList.vue:81 src/views/system/Upgrade.vue:42
msgid "Server error"
@ -2122,7 +2130,7 @@ msgstr ""
msgid "The path exists, but the file is not a private key"
msgstr ""
#: src/views/preference/components/TOTP.vue:109
#: src/views/preference/components/TOTP.vue:111
msgid ""
"The recovery code is only displayed once, please save it in a safe place."
msgstr ""
@ -2194,7 +2202,7 @@ msgstr ""
msgid "Title"
msgstr "Tiêu đề"
#: src/views/preference/components/TOTP.vue:90
#: src/views/preference/components/TOTP.vue:92
msgid ""
"To enable it, you need to install the Google or Microsoft Authenticator app "
"on your mobile phone."
@ -2220,7 +2228,7 @@ msgstr ""
msgid "Too many login failed attempts, please try again later"
msgstr ""
#: src/views/preference/components/TOTP.vue:89
#: src/views/preference/components/TOTP.vue:91
msgid ""
"TOTP is a two-factor authentication method that uses a time-based one-time "
"password algorithm."

Binary file not shown.

View file

@ -17,7 +17,7 @@ msgstr ""
msgid "2FA"
msgstr "2FA"
#: src/views/preference/components/TOTP.vue:88
#: src/views/preference/components/TOTP.vue:90
msgid "2FA Settings"
msgstr "2FA 设置"
@ -246,6 +246,10 @@ msgstr "CA Dir"
msgid "CADir"
msgstr "CADir"
#: src/views/preference/components/TOTP.vue:150
msgid "Can't scan? Use text key binding"
msgstr "无法扫描?使用文本密钥绑定"
#: src/components/ChatGPT/ChatGPT.vue:252
#: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:55
#: src/components/StdDesign/StdDataDisplay/StdCurd.vue:253
@ -423,11 +427,11 @@ msgstr "DNS 凭证"
msgid "Credentials"
msgstr "凭证"
#: src/views/preference/components/TOTP.vue:96
#: src/views/preference/components/TOTP.vue:98
msgid "Current account is enabled 2FA."
msgstr "当前账户已启用二步验证。"
#: src/views/preference/components/TOTP.vue:93
#: src/views/preference/components/TOTP.vue:95
msgid "Current account is not enabled 2FA."
msgstr "当前用户未启用二步验证。"
@ -704,11 +708,11 @@ msgstr "在%{node_name}中启用%{conf_name}失败"
msgid "Enable %{conf_name} in %{node_name} successfully"
msgstr "成功启用%{node_name}中的%{conf_name}"
#: src/views/preference/components/TOTP.vue:122
#: src/views/preference/components/TOTP.vue:124
msgid "Enable 2FA"
msgstr "启用二步验证"
#: src/views/preference/components/TOTP.vue:52
#: src/views/preference/components/TOTP.vue:54
msgid "Enable 2FA successfully"
msgstr "二步验证启用成功"
@ -918,7 +922,7 @@ msgstr ""
"如果某个 IP 的登录失败次数达到禁用阈值分钟内的最大尝试次数,该 IP 将被禁止登"
"录一段时间。"
#: src/views/preference/components/TOTP.vue:108
#: src/views/preference/components/TOTP.vue:110
msgid ""
"If you lose your mobile phone, you can use the recovery code to reset your "
"2FA."
@ -954,12 +958,12 @@ msgstr "初始化核心升级程序错误"
msgid "Initialing core upgrader"
msgstr "初始化核心升级器"
#: src/views/preference/components/TOTP.vue:144
#: src/views/preference/components/TOTP.vue:157
msgid "Input the code from the app:"
msgstr "输入应用程序中的代码:"
#: src/components/OTP/OTPAuthorization.vue:49
#: src/views/preference/components/TOTP.vue:157
#: src/views/preference/components/TOTP.vue:170
msgid "Input the recovery code:"
msgstr "输入恢复代码:"
@ -1545,15 +1549,15 @@ msgid "Recovered Successfully"
msgstr "恢复成功"
#: src/components/OTP/OTPAuthorization.vue:56
#: src/views/preference/components/TOTP.vue:164
#: src/views/preference/components/TOTP.vue:177
msgid "Recovery"
msgstr "恢复"
#: src/views/preference/components/TOTP.vue:101
#: src/views/preference/components/TOTP.vue:103
msgid "Recovery Code"
msgstr "恢复代码"
#: src/views/preference/components/TOTP.vue:110
#: src/views/preference/components/TOTP.vue:112
msgid "Recovery Code:"
msgstr "恢复代码:"
@ -1680,7 +1684,7 @@ msgstr "请求参数错误"
msgid "Reset"
msgstr "重置"
#: src/views/preference/components/TOTP.vue:130
#: src/views/preference/components/TOTP.vue:132
msgid "Reset 2FA"
msgstr "重置二步验证"
@ -1731,7 +1735,7 @@ msgstr "保存成功"
msgid "Saved successfully"
msgstr "保存成功"
#: src/views/preference/components/TOTP.vue:91
#: src/views/preference/components/TOTP.vue:93
msgid "Scan the QR code with your mobile phone to add the account to the app."
msgstr "用手机扫描二维码,将账户添加到应用程序中。"
@ -1739,6 +1743,10 @@ msgstr "用手机扫描二维码,将账户添加到应用程序中。"
msgid "SDK"
msgstr "SDK"
#: src/views/preference/components/TOTP.vue:149
msgid "Secret has been copied"
msgstr "密钥已复制"
#: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:155
msgid "Selector"
msgstr "选择器"
@ -1761,8 +1769,8 @@ msgstr "上传"
#: src/views/environment/BatchUpgrader.vue:57
#: src/views/environment/Environment.vue:15 src/views/other/Install.vue:68
#: src/views/preference/AuthSettings.vue:49
#: src/views/preference/components/TOTP.vue:42
#: src/views/preference/components/TOTP.vue:55
#: src/views/preference/components/TOTP.vue:44
#: src/views/preference/components/TOTP.vue:57
#: src/views/preference/Preference.vue:83 src/views/stream/StreamList.vue:113
#: src/views/stream/StreamList.vue:81 src/views/system/Upgrade.vue:42
msgid "Server error"
@ -1992,7 +2000,7 @@ msgstr "路径存在,但文件不是证书"
msgid "The path exists, but the file is not a private key"
msgstr "路径存在,但文件不是私钥"
#: src/views/preference/components/TOTP.vue:109
#: src/views/preference/components/TOTP.vue:111
msgid ""
"The recovery code is only displayed once, please save it in a safe place."
msgstr "恢复密码只会显示一次,请妥善保存。"
@ -2064,7 +2072,7 @@ msgstr "提示"
msgid "Title"
msgstr "标题"
#: src/views/preference/components/TOTP.vue:90
#: src/views/preference/components/TOTP.vue:92
msgid ""
"To enable it, you need to install the Google or Microsoft Authenticator app "
"on your mobile phone."
@ -2089,7 +2097,7 @@ msgstr "Token 无效"
msgid "Too many login failed attempts, please try again later"
msgstr "登录失败次数过多,请稍后再试"
#: src/views/preference/components/TOTP.vue:89
#: src/views/preference/components/TOTP.vue:91
msgid ""
"TOTP is a two-factor authentication method that uses a time-based one-time "
"password algorithm."

View file

@ -21,7 +21,7 @@ msgstr ""
msgid "2FA"
msgstr "多重要素驗證"
#: src/views/preference/components/TOTP.vue:88
#: src/views/preference/components/TOTP.vue:90
msgid "2FA Settings"
msgstr "多重要素驗證設定"
@ -250,6 +250,10 @@ msgstr "CA Dir"
msgid "CADir"
msgstr "CADir"
#: src/views/preference/components/TOTP.vue:150
msgid "Can't scan? Use text key binding"
msgstr ""
#: src/components/ChatGPT/ChatGPT.vue:252
#: src/components/StdDesign/StdDataDisplay/StdBatchEdit.vue:55
#: src/components/StdDesign/StdDataDisplay/StdCurd.vue:253
@ -427,11 +431,11 @@ msgstr "認證"
msgid "Credentials"
msgstr "認證資訊"
#: src/views/preference/components/TOTP.vue:96
#: src/views/preference/components/TOTP.vue:98
msgid "Current account is enabled 2FA."
msgstr "當前帳戶已啟用多因素身份驗證。"
#: src/views/preference/components/TOTP.vue:93
#: src/views/preference/components/TOTP.vue:95
msgid "Current account is not enabled 2FA."
msgstr "當前帳戶未啟用多因素身份驗證。"
@ -708,11 +712,11 @@ msgstr "在 %{node_name} 啟用 %{conf_name} 失敗"
msgid "Enable %{conf_name} in %{node_name} successfully"
msgstr "成功在 %{node_name} 啟用 %{conf_name}"
#: src/views/preference/components/TOTP.vue:122
#: src/views/preference/components/TOTP.vue:124
msgid "Enable 2FA"
msgstr "啟用多因素身份驗證"
#: src/views/preference/components/TOTP.vue:52
#: src/views/preference/components/TOTP.vue:54
msgid "Enable 2FA successfully"
msgstr "啟用多因素身份驗證成功"
@ -922,7 +926,7 @@ msgstr ""
"如果來自某個 IP 的登錄失敗次數在禁止閾值分鐘內達到最大嘗試次數,該 IP 將被禁"
"止一段時間。"
#: src/views/preference/components/TOTP.vue:108
#: src/views/preference/components/TOTP.vue:110
msgid ""
"If you lose your mobile phone, you can use the recovery code to reset your "
"2FA."
@ -958,12 +962,12 @@ msgstr "初始化核心升級程式錯誤"
msgid "Initialing core upgrader"
msgstr "正在初始化核心升級程式"
#: src/views/preference/components/TOTP.vue:144
#: src/views/preference/components/TOTP.vue:157
msgid "Input the code from the app:"
msgstr "請輸入應用程式中的代碼:"
#: src/components/OTP/OTPAuthorization.vue:49
#: src/views/preference/components/TOTP.vue:157
#: src/views/preference/components/TOTP.vue:170
msgid "Input the recovery code:"
msgstr "輸入恢復碼:"
@ -1548,15 +1552,15 @@ msgid "Recovered Successfully"
msgstr "恢復成功"
#: src/components/OTP/OTPAuthorization.vue:56
#: src/views/preference/components/TOTP.vue:164
#: src/views/preference/components/TOTP.vue:177
msgid "Recovery"
msgstr "恢復"
#: src/views/preference/components/TOTP.vue:101
#: src/views/preference/components/TOTP.vue:103
msgid "Recovery Code"
msgstr "恢復碼"
#: src/views/preference/components/TOTP.vue:110
#: src/views/preference/components/TOTP.vue:112
msgid "Recovery Code:"
msgstr "恢復碼:"
@ -1683,7 +1687,7 @@ msgstr "請求參數錯誤"
msgid "Reset"
msgstr "重設"
#: src/views/preference/components/TOTP.vue:130
#: src/views/preference/components/TOTP.vue:132
msgid "Reset 2FA"
msgstr "重置多重因素驗證"
@ -1734,7 +1738,7 @@ msgstr "儲存成功"
msgid "Saved successfully"
msgstr "儲存成功"
#: src/views/preference/components/TOTP.vue:91
#: src/views/preference/components/TOTP.vue:93
msgid "Scan the QR code with your mobile phone to add the account to the app."
msgstr "用手機掃描二維碼將賬戶添加到應用程序中。"
@ -1742,6 +1746,10 @@ msgstr "用手機掃描二維碼將賬戶添加到應用程序中。"
msgid "SDK"
msgstr "SDK"
#: src/views/preference/components/TOTP.vue:149
msgid "Secret has been copied"
msgstr ""
#: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:155
msgid "Selector"
msgstr "選擇器"
@ -1764,8 +1772,8 @@ msgstr "傳送"
#: src/views/environment/BatchUpgrader.vue:57
#: src/views/environment/Environment.vue:15 src/views/other/Install.vue:68
#: src/views/preference/AuthSettings.vue:49
#: src/views/preference/components/TOTP.vue:42
#: src/views/preference/components/TOTP.vue:55
#: src/views/preference/components/TOTP.vue:44
#: src/views/preference/components/TOTP.vue:57
#: src/views/preference/Preference.vue:83 src/views/stream/StreamList.vue:113
#: src/views/stream/StreamList.vue:81 src/views/system/Upgrade.vue:42
msgid "Server error"
@ -1995,7 +2003,7 @@ msgstr "路徑存在,但檔案不是憑證"
msgid "The path exists, but the file is not a private key"
msgstr "路徑存在,但檔案不是金鑰"
#: src/views/preference/components/TOTP.vue:109
#: src/views/preference/components/TOTP.vue:111
msgid ""
"The recovery code is only displayed once, please save it in a safe place."
msgstr "恢復碼僅顯示一次,請將其保存在安全的地方。"
@ -2067,7 +2075,7 @@ msgstr "提示"
msgid "Title"
msgstr "標題"
#: src/views/preference/components/TOTP.vue:90
#: src/views/preference/components/TOTP.vue:92
msgid ""
"To enable it, you need to install the Google or Microsoft Authenticator app "
"on your mobile phone."
@ -2092,7 +2100,7 @@ msgstr "令牌無效"
msgid "Too many login failed attempts, please try again later"
msgstr "登錄失敗次數過多,請稍後再試"
#: src/views/preference/components/TOTP.vue:89
#: src/views/preference/components/TOTP.vue:91
msgid ""
"TOTP is a two-factor authentication method that uses a time-based one-time "
"password algorithm."

View file

@ -1,8 +1,10 @@
<script setup lang="ts">
import { message } from 'ant-design-vue'
import { CheckCircleOutlined } from '@ant-design/icons-vue'
import { UseClipboard } from '@vueuse/components'
import otp from '@/api/otp'
import OTPInput from '@/components/OTPInput/OTPInput.vue'
import { $gettext } from '@/gettext'
const status = ref(false)
const enrolling = ref(false)
@ -131,13 +133,24 @@ function reset2FA() {
</AButton>
<template v-if="enrolling">
<div class="w-64 h-64 mt-4 mb-2">
<div class="mt-4 mb-2">
<img
v-if="qrCode"
class="w-full"
class="w-64 h-64"
:src="qrCode"
alt="qr code"
>
<div class="w-64 flex justify-center">
<UseClipboard v-slot="{ copy, copied }">
<a
class="mr-2"
@click="() => copy(secret)"
>
{{ copied ? $gettext('Secret has been copied')
: $gettext('Can\'t scan? Use text key binding') }}
</a>
</UseClipboard>
</div>
</div>
<div>