Browse Source

Merge branch 'dev' into refactor/otp

Hintay 2 months ago
parent
commit
121287df21
40 changed files with 1084 additions and 326 deletions
  1. 28 0
      .github/workflows/sync-main-on-release.yml
  2. 22 0
      api/crypto/crypto.go
  3. 10 0
      api/crypto/router.go
  4. 2 1
      api/system/router.go
  5. 1 1
      api/user/router.go
  6. 1 0
      app/package.json
  7. 8 0
      app/pnpm-lock.yaml
  8. 1 1
      app/src/api/auth.ts
  9. 1 1
      app/src/api/install.ts
  10. 1 0
      app/src/constants/errors/crypto.ts
  11. 4 0
      app/src/constants/errors/middleware.ts
  12. 18 0
      app/src/constants/llm.ts
  13. 34 20
      app/src/language/ar/app.po
  14. 34 20
      app/src/language/en/app.po
  15. 34 20
      app/src/language/es/app.po
  16. 33 20
      app/src/language/fr_FR/app.po
  17. 102 0
      app/src/language/ko_KR/app.po
  18. 33 21
      app/src/language/messages.pot
  19. 108 0
      app/src/language/ru_RU/app.po
  20. 110 0
      app/src/language/tr_TR/app.po
  21. 102 0
      app/src/language/vi_VN/app.po
  22. 34 20
      app/src/language/zh_CN/app.po
  23. 61 57
      app/src/language/zh_TW/app.po
  24. 48 42
      app/src/lib/http/index.ts
  25. 1 1
      app/src/version.json
  26. 10 21
      app/src/views/preference/OpenAISettings.vue
  27. 11 0
      app/src/views/site/ngx_conf/config_template/ConfigTemplate.vue
  28. 7 0
      app/src/vite-env.d.ts
  29. 1 1
      gen.sh
  30. 3 3
      go.mod
  31. 6 60
      go.sum
  32. 102 0
      internal/crypto/crypto.go
  33. 1 0
      internal/crypto/errors.go
  34. 9 6
      internal/kernel/boot.go
  35. 46 0
      internal/middleware/encrypted_params.go
  36. 8 8
      internal/middleware/middleware.go
  37. 6 2
      internal/middleware/proxy_ws.go
  38. 32 0
      internal/nginx/nginx_directives.json
  39. 2 0
      router/routers.go
  40. 9 0
      template/block/vue-router-history-mode.conf

+ 28 - 0
.github/workflows/sync-main-on-release.yml

@@ -0,0 +1,28 @@
+name: Sync branch
+
+on:
+  workflow_dispatch:
+  release:
+    types: [published]
+    branches: [dev]
+
+jobs:
+  force-push-main:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+          ref: dev
+          clean: false
+
+      - name: Configure Git
+        run: |
+          git config --global user.name "github-actions[bot]"
+          git config --global user.email "github-actions[bot]@users.noreply.github.com"
+
+      - name: Force push dev to main
+        run: |
+          git fetch origin
+          git push origin dev:main --force

+ 22 - 0
api/crypto/crypto.go

@@ -0,0 +1,22 @@
+package crypto
+
+import (
+	"net/http"
+
+	"github.com/0xJacky/Nginx-UI/api"
+	"github.com/0xJacky/Nginx-UI/internal/crypto"
+	"github.com/gin-gonic/gin"
+)
+
+// GetPublicKey generates a new ED25519 key pair and registers it in the cache
+func GetPublicKey(c *gin.Context) {
+	params, err := crypto.GetCryptoParams()
+	if err != nil {
+		api.ErrHandler(c, err)
+		return
+	}
+
+	c.JSON(http.StatusOK, gin.H{
+		"public_key": params.PublicKey,
+	})
+}

+ 10 - 0
api/crypto/router.go

@@ -0,0 +1,10 @@
+package crypto
+
+import "github.com/gin-gonic/gin"
+
+func InitPublicRouter(r *gin.RouterGroup) {
+	g := r.Group("/crypto")
+	{
+		g.GET("public_key", GetPublicKey)
+	}
+}

+ 2 - 1
api/system/router.go

@@ -1,12 +1,13 @@
 package system
 package system
 
 
 import (
 import (
+	"github.com/0xJacky/Nginx-UI/internal/middleware"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 )
 )
 
 
 func InitPublicRouter(r *gin.RouterGroup) {
 func InitPublicRouter(r *gin.RouterGroup) {
 	r.GET("install", InstallLockCheck)
 	r.GET("install", InstallLockCheck)
-	r.POST("install", InstallNginxUI)
+	r.POST("install", middleware.EncryptedParams(), InstallNginxUI)
 	r.GET("translation/:code", GetTranslation)
 	r.GET("translation/:code", GetTranslation)
 }
 }
 
 

+ 1 - 1
api/user/router.go

@@ -6,7 +6,7 @@ import (
 )
 )
 
 
 func InitAuthRouter(r *gin.RouterGroup) {
 func InitAuthRouter(r *gin.RouterGroup) {
-	r.POST("/login", Login)
+	r.POST("/login", middleware.EncryptedParams(), Login)
 	r.DELETE("/logout", Logout)
 	r.DELETE("/logout", Logout)
 
 
 	r.GET("/begin_passkey_login", BeginPasskeyLogin)
 	r.GET("/begin_passkey_login", BeginPasskeyLogin)

+ 1 - 0
app/package.json

@@ -30,6 +30,7 @@
     "axios": "^1.7.9",
     "axios": "^1.7.9",
     "dayjs": "^1.11.13",
     "dayjs": "^1.11.13",
     "highlight.js": "^11.11.1",
     "highlight.js": "^11.11.1",
+    "jsencrypt": "^3.3.2",
     "lodash": "^4.17.21",
     "lodash": "^4.17.21",
     "marked": "^15.0.6",
     "marked": "^15.0.6",
     "marked-highlight": "^2.2.1",
     "marked-highlight": "^2.2.1",

+ 8 - 0
app/pnpm-lock.yaml

@@ -59,6 +59,9 @@ importers:
       highlight.js:
       highlight.js:
         specifier: ^11.11.1
         specifier: ^11.11.1
         version: 11.11.1
         version: 11.11.1
+      jsencrypt:
+        specifier: ^3.3.2
+        version: 3.3.2
       lodash:
       lodash:
         specifier: ^4.17.21
         specifier: ^4.17.21
         version: 4.17.21
         version: 4.17.21
@@ -3122,6 +3125,9 @@ packages:
     resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==}
     resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==}
     engines: {node: '>=12.0.0'}
     engines: {node: '>=12.0.0'}
 
 
+  jsencrypt@3.3.2:
+    resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==}
+
   jsesc@0.5.0:
   jsesc@0.5.0:
     resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==}
     resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==}
     hasBin: true
     hasBin: true
@@ -7904,6 +7910,8 @@ snapshots:
 
 
   jsdoc-type-pratt-parser@4.1.0: {}
   jsdoc-type-pratt-parser@4.1.0: {}
 
 
+  jsencrypt@3.3.2: {}
+
   jsesc@0.5.0: {}
   jsesc@0.5.0: {}
 
 
   jsesc@3.0.2: {}
   jsesc@3.0.2: {}

+ 1 - 1
app/src/api/auth.ts

@@ -19,7 +19,7 @@ const auth = {
       password,
       password,
       otp,
       otp,
       recovery_code: recoveryCode,
       recovery_code: recoveryCode,
-    })
+    }, { crypto: true })
   },
   },
   async casdoor_login(code?: string, state?: string) {
   async casdoor_login(code?: string, state?: string) {
     await http.post('/casdoor_callback', {
     await http.post('/casdoor_callback', {

+ 1 - 1
app/src/api/install.ts

@@ -12,7 +12,7 @@ const install = {
     return http.get('/install')
     return http.get('/install')
   },
   },
   install_nginx_ui(data: InstallRequest) {
   install_nginx_ui(data: InstallRequest) {
-    return http.post('/install', data)
+    return http.post('/install', data, { crypto: true })
   },
   },
 }
 }
 
 

+ 1 - 0
app/src/constants/errors/crypto.ts

@@ -1,4 +1,5 @@
 export default {
 export default {
   50001: () => $gettext('Plain text is empty'),
   50001: () => $gettext('Plain text is empty'),
   50002: () => $gettext('Cipher text is too short'),
   50002: () => $gettext('Cipher text is too short'),
+  40401: () => $gettext('Request timeout'),
 }
 }

+ 4 - 0
app/src/constants/errors/middleware.ts

@@ -0,0 +1,4 @@
+export default {
+  40000: () => $gettext('Invalid request format'),
+  40001: () => $gettext('Decryption failed'),
+}

+ 18 - 0
app/src/constants/llm.ts

@@ -0,0 +1,18 @@
+export const LLM_MODELS = [
+  'o3-mini',
+  'o1',
+  'deepseek-reasoner',
+  'deepseek-chat',
+  'gpt-4o-mini',
+  'gpt-4o',
+  'gpt-4',
+  'gpt-4-32k',
+  'gpt-4-turbo',
+  'gpt-3.5-turbo',
+]
+
+export const LLM_PROVIDERS = [
+  'https://api.openai.com',
+  'https://api.deepseek.com',
+  'http://localhost:11434',
+]

+ 34 - 20
app/src/language/ar/app.po

@@ -106,7 +106,7 @@ msgstr "بعد ذلك، قم بتحديث هذه الصفحة وانقر فوق
 msgid "All"
 msgid "All"
 msgstr "الكل"
 msgstr "الكل"
 
 
-#: src/views/preference/OpenAISettings.vue:44
+#: src/views/preference/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "عنوان URL الأساسي لAPI"
 msgstr "عنوان URL الأساسي لAPI"
 
 
@@ -114,15 +114,15 @@ msgstr "عنوان URL الأساسي لAPI"
 msgid "API Document"
 msgid "API Document"
 msgstr "ملف API"
 msgstr "ملف API"
 
 
-#: src/views/preference/OpenAISettings.vue:57
+#: src/views/preference/OpenAISettings.vue:46
 msgid "API Proxy"
 msgid "API Proxy"
 msgstr "وسيط API"
 msgstr "وسيط API"
 
 
-#: src/views/preference/OpenAISettings.vue:69
+#: src/views/preference/OpenAISettings.vue:58
 msgid "API Token"
 msgid "API Token"
 msgstr "رمز API"
 msgstr "رمز API"
 
 
-#: src/views/preference/OpenAISettings.vue:78
+#: src/views/preference/OpenAISettings.vue:67
 #, fuzzy
 #, fuzzy
 msgid "API Type"
 msgid "API Type"
 msgstr "رمز API"
 msgstr "رمز API"
@@ -222,7 +222,7 @@ msgstr "محاولات"
 msgid "Auth"
 msgid "Auth"
 msgstr "مصادقة"
 msgstr "مصادقة"
 
 
-#: src/components/TwoFA/Authorization.vue:121
+#: src/components/TwoFA/Authorization.vue:109
 msgid "Authenticate with a passkey"
 msgid "Authenticate with a passkey"
 msgstr "المصادقة باستخدام مفتاح المرور"
 msgstr "المصادقة باستخدام مفتاح المرور"
 
 
@@ -617,6 +617,11 @@ msgstr "قاعدة البيانات (اختياري، الافتراضي: قاع
 msgid "Days"
 msgid "Days"
 msgstr "أيام"
 msgstr "أيام"
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "وصف"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -1231,7 +1236,7 @@ msgstr "بدء ترقية النواة"
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr "أدخل الرمز من التطبيق:"
 msgstr "أدخل الرمز من التطبيق:"
 
 
-#: src/components/TwoFA/Authorization.vue:82
+#: src/components/TwoFA/Authorization.vue:72
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr "أدخل رمز الاسترداد:"
 msgstr "أدخل رمز الاسترداد:"
 
 
@@ -1274,6 +1279,11 @@ msgstr "رمز المرور أو رمز الاسترداد غير صالح"
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr "رمز 2FA أو الاسترداد غير صالح"
 msgstr "رمز 2FA أو الاسترداد غير صالح"
 
 
+#: src/constants/errors/middleware.ts:2
+#, fuzzy
+msgid "Invalid request format"
+msgstr "رمز 2FA أو الاسترداد غير صالح"
+
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
 msgid "IP"
 msgid "IP"
 msgstr "IP"
 msgstr "IP"
@@ -1321,7 +1331,7 @@ msgstr "آخر استخدام في"
 msgid "Leave blank for no change"
 msgid "Leave blank for no change"
 msgstr "اتركه فارغًا لعدم التغيير"
 msgstr "اتركه فارغًا لعدم التغيير"
 
 
-#: src/views/preference/OpenAISettings.vue:53
+#: src/views/preference/OpenAISettings.vue:41
 msgid "Leave blank for the default: https://api.openai.com/"
 msgid "Leave blank for the default: https://api.openai.com/"
 msgstr "اتركه فارغًا للإعداد الافتراضي: /https://api.openai.com"
 msgstr "اتركه فارغًا للإعداد الافتراضي: /https://api.openai.com"
 
 
@@ -1384,7 +1394,7 @@ msgstr "أماكن"
 msgid "Log"
 msgid "Log"
 msgstr "سجل"
 msgstr "سجل"
 
 
-#: src/routes/index.ts:318 src/views/other/Login.vue:222
+#: src/routes/index.ts:318 src/views/other/Login.vue:223
 msgid "Login"
 msgid "Login"
 msgstr "تسجيل الدخول"
 msgstr "تسجيل الدخول"
 
 
@@ -1462,7 +1472,7 @@ msgstr "الذاكرة والتخزين"
 msgid "Minutes"
 msgid "Minutes"
 msgstr "دقائق"
 msgstr "دقائق"
 
 
-#: src/views/preference/OpenAISettings.vue:32
+#: src/views/preference/OpenAISettings.vue:20
 msgid "Model"
 msgid "Model"
 msgstr "نموذج"
 msgstr "نموذج"
 
 
@@ -1746,7 +1756,7 @@ msgstr "متصل"
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "أوبن أي آي"
 msgstr "أوبن أي آي"
 
 
-#: src/components/TwoFA/Authorization.vue:112 src/views/other/Login.vue:231
+#: src/components/TwoFA/Authorization.vue:100 src/views/other/Login.vue:232
 msgid "Or"
 msgid "Or"
 msgstr "أو"
 msgstr "أو"
 
 
@@ -1853,7 +1863,7 @@ msgid ""
 msgstr ""
 msgstr ""
 "يرجى إدخال اسم لمفتاح المرور الذي ترغب في إنشائه ثم انقر على زر موافق أدناه."
 "يرجى إدخال اسم لمفتاح المرور الذي ترغب في إنشائه ثم انقر على زر موافق أدناه."
 
 
-#: src/components/TwoFA/Authorization.vue:70
+#: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "يرجى إدخال رمز OTP:"
 msgstr "يرجى إدخال رمز OTP:"
 
 
@@ -1992,7 +2002,7 @@ msgstr "استعادة"
 msgid "Recovered Successfully"
 msgid "Recovered Successfully"
 msgstr "تم الاسترداد بنجاح"
 msgstr "تم الاسترداد بنجاح"
 
 
-#: src/components/TwoFA/Authorization.vue:89
+#: src/components/TwoFA/Authorization.vue:79
 msgid "Recovery"
 msgid "Recovery"
 msgstr "استرداد"
 msgstr "استرداد"
 
 
@@ -2163,6 +2173,10 @@ msgstr "تجديد الشهادة بنجاح"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "تم التجديد بنجاح"
 msgstr "تم التجديد بنجاح"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "تم الطلب باستخدام عوامل خاطئة"
 msgstr "تم الطلب باستخدام عوامل خاطئة"
@@ -2340,7 +2354,7 @@ msgstr ""
 msgid "Show"
 msgid "Show"
 msgstr "عرض"
 msgstr "عرض"
 
 
-#: src/views/other/Login.vue:240
+#: src/views/other/Login.vue:241
 msgid "Sign in with a passkey"
 msgid "Sign in with a passkey"
 msgstr "تسجيل الدخول باستخدام مفتاح المرور"
 msgstr "تسجيل الدخول باستخدام مفتاح المرور"
 
 
@@ -2592,7 +2606,7 @@ msgid ""
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:23
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The model name should only contain letters, unicode, numbers, hyphens, "
 "The model name should only contain letters, unicode, numbers, hyphens, "
@@ -2647,8 +2661,8 @@ msgstr ""
 msgid "The url is invalid"
 msgid "The url is invalid"
 msgstr "عنوان URL غير صالح"
 msgstr "عنوان URL غير صالح"
 
 
-#: src/views/preference/OpenAISettings.vue:47
-#: src/views/preference/OpenAISettings.vue:60
+#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:49
 msgid "The url is invalid."
 msgid "The url is invalid."
 msgstr "عنوان URL غير صالح."
 msgstr "عنوان URL غير صالح."
 
 
@@ -2746,7 +2760,7 @@ msgstr ""
 "توجيه الطلب من السلطة إلى الخلفية، ونحتاج إلى حفظ هذا الملف وإعادة تحميل "
 "توجيه الطلب من السلطة إلى الخلفية، ونحتاج إلى حفظ هذا الملف وإعادة تحميل "
 "Nginx. هل أنت متأكد أنك تريد المتابعة؟"
 "Nginx. هل أنت متأكد أنك تريد المتابعة؟"
 
 
-#: src/views/preference/OpenAISettings.vue:48
+#: src/views/preference/OpenAISettings.vue:36
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
@@ -2757,7 +2771,7 @@ msgstr ""
 "نهاية API متوافقة مع OpenAI، لذا قم فقط بتعيين baseUrl إلىAPI المحلية الخاصة "
 "نهاية API متوافقة مع OpenAI، لذا قم فقط بتعيين baseUrl إلىAPI المحلية الخاصة "
 "بك."
 "بك."
 
 
-#: src/views/preference/OpenAISettings.vue:72
+#: src/views/preference/OpenAISettings.vue:61
 msgid "Token is not valid"
 msgid "Token is not valid"
 msgstr "الرمز غير صالح"
 msgstr "الرمز غير صالح"
 
 
@@ -2845,11 +2859,11 @@ msgstr "مدة التشغيل:"
 msgid "URL"
 msgid "URL"
 msgstr "عنوان URL"
 msgstr "عنوان URL"
 
 
-#: src/components/TwoFA/Authorization.vue:102
+#: src/components/TwoFA/Authorization.vue:121
 msgid "Use OTP"
 msgid "Use OTP"
 msgstr "استخدم كلمة المرور لمرة واحدة"
 msgstr "استخدم كلمة المرور لمرة واحدة"
 
 
-#: src/components/TwoFA/Authorization.vue:98
+#: src/components/TwoFA/Authorization.vue:117
 msgid "Use recovery code"
 msgid "Use recovery code"
 msgstr "استخدم رمز الاسترداد"
 msgstr "استخدم رمز الاسترداد"
 
 

+ 34 - 20
app/src/language/en/app.po

@@ -108,7 +108,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:44
+#: src/views/preference/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr ""
 msgstr ""
 
 
@@ -117,15 +117,15 @@ msgstr ""
 msgid "API Document"
 msgid "API Document"
 msgstr "Comments"
 msgstr "Comments"
 
 
-#: src/views/preference/OpenAISettings.vue:57
+#: src/views/preference/OpenAISettings.vue:46
 msgid "API Proxy"
 msgid "API Proxy"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:69
+#: src/views/preference/OpenAISettings.vue:58
 msgid "API Token"
 msgid "API Token"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:78
+#: src/views/preference/OpenAISettings.vue:67
 msgid "API Type"
 msgid "API Type"
 msgstr ""
 msgstr ""
 
 
@@ -233,7 +233,7 @@ msgstr ""
 msgid "Auth"
 msgid "Auth"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:121
+#: src/components/TwoFA/Authorization.vue:109
 msgid "Authenticate with a passkey"
 msgid "Authenticate with a passkey"
 msgstr ""
 msgstr ""
 
 
@@ -634,6 +634,11 @@ msgstr "Database (Optional, default: database)"
 msgid "Days"
 msgid "Days"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "Enable failed"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -1279,7 +1284,7 @@ msgstr ""
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:82
+#: src/components/TwoFA/Authorization.vue:72
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr ""
 msgstr ""
 
 
@@ -1326,6 +1331,11 @@ msgstr ""
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr "Invalid E-mail!"
 msgstr "Invalid E-mail!"
 
 
+#: src/constants/errors/middleware.ts:2
+#, fuzzy
+msgid "Invalid request format"
+msgstr "Invalid E-mail!"
+
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
 msgid "IP"
 msgid "IP"
 msgstr ""
 msgstr ""
@@ -1378,7 +1388,7 @@ msgstr "Created at"
 msgid "Leave blank for no change"
 msgid "Leave blank for no change"
 msgstr "Leave blank for no change"
 msgstr "Leave blank for no change"
 
 
-#: src/views/preference/OpenAISettings.vue:53
+#: src/views/preference/OpenAISettings.vue:41
 msgid "Leave blank for the default: https://api.openai.com/"
 msgid "Leave blank for the default: https://api.openai.com/"
 msgstr ""
 msgstr ""
 
 
@@ -1449,7 +1459,7 @@ msgstr "Locations"
 msgid "Log"
 msgid "Log"
 msgstr "Login"
 msgstr "Login"
 
 
-#: src/routes/index.ts:318 src/views/other/Login.vue:222
+#: src/routes/index.ts:318 src/views/other/Login.vue:223
 msgid "Login"
 msgid "Login"
 msgstr "Login"
 msgstr "Login"
 
 
@@ -1524,7 +1534,7 @@ msgstr "Memory and Storage"
 msgid "Minutes"
 msgid "Minutes"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:32
+#: src/views/preference/OpenAISettings.vue:20
 #, fuzzy
 #, fuzzy
 msgid "Model"
 msgid "Model"
 msgstr "Advance Mode"
 msgstr "Advance Mode"
@@ -1822,7 +1832,7 @@ msgstr ""
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:112 src/views/other/Login.vue:231
+#: src/components/TwoFA/Authorization.vue:100 src/views/other/Login.vue:232
 msgid "Or"
 msgid "Or"
 msgstr ""
 msgstr ""
 
 
@@ -1926,7 +1936,7 @@ msgid ""
 "button below."
 "button below."
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:70
+#: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr ""
 msgstr ""
 
 
@@ -2068,7 +2078,7 @@ msgstr ""
 msgid "Recovered Successfully"
 msgid "Recovered Successfully"
 msgstr "Saved successfully"
 msgstr "Saved successfully"
 
 
-#: src/components/TwoFA/Authorization.vue:89
+#: src/components/TwoFA/Authorization.vue:79
 msgid "Recovery"
 msgid "Recovery"
 msgstr ""
 msgstr ""
 
 
@@ -2260,6 +2270,10 @@ msgstr "Certificate is valid"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Enabled successfully"
 msgstr "Enabled successfully"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr ""
 msgstr ""
@@ -2442,7 +2456,7 @@ msgstr ""
 msgid "Show"
 msgid "Show"
 msgstr ""
 msgstr ""
 
 
-#: src/views/other/Login.vue:240
+#: src/views/other/Login.vue:241
 msgid "Sign in with a passkey"
 msgid "Sign in with a passkey"
 msgstr ""
 msgstr ""
 
 
@@ -2711,7 +2725,7 @@ msgid ""
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:23
 msgid ""
 msgid ""
 "The model name should only contain letters, unicode, numbers, hyphens, "
 "The model name should only contain letters, unicode, numbers, hyphens, "
 "dashes, colons, and dots."
 "dashes, colons, and dots."
@@ -2760,8 +2774,8 @@ msgstr ""
 msgid "The url is invalid"
 msgid "The url is invalid"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:47
-#: src/views/preference/OpenAISettings.vue:60
+#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:49
 msgid "The url is invalid."
 msgid "The url is invalid."
 msgstr ""
 msgstr ""
 
 
@@ -2854,14 +2868,14 @@ msgid ""
 "continue?"
 "continue?"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:48
+#: src/views/preference/OpenAISettings.vue:36
 msgid ""
 msgid ""
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "provide an OpenAI-compatible API endpoint, so just set the baseUrl to your "
 "provide an OpenAI-compatible API endpoint, so just set the baseUrl to your "
 "local API."
 "local API."
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:72
+#: src/views/preference/OpenAISettings.vue:61
 msgid "Token is not valid"
 msgid "Token is not valid"
 msgstr ""
 msgstr ""
 
 
@@ -2947,11 +2961,11 @@ msgstr "Uptime:"
 msgid "URL"
 msgid "URL"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:102
+#: src/components/TwoFA/Authorization.vue:121
 msgid "Use OTP"
 msgid "Use OTP"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:98
+#: src/components/TwoFA/Authorization.vue:117
 msgid "Use recovery code"
 msgid "Use recovery code"
 msgstr ""
 msgstr ""
 
 

+ 34 - 20
app/src/language/es/app.po

@@ -111,7 +111,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr "Todo"
 msgstr "Todo"
 
 
-#: src/views/preference/OpenAISettings.vue:44
+#: src/views/preference/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "URL Base de la API"
 msgstr "URL Base de la API"
 
 
@@ -119,15 +119,15 @@ msgstr "URL Base de la API"
 msgid "API Document"
 msgid "API Document"
 msgstr "Documento de la API"
 msgstr "Documento de la API"
 
 
-#: src/views/preference/OpenAISettings.vue:57
+#: src/views/preference/OpenAISettings.vue:46
 msgid "API Proxy"
 msgid "API Proxy"
 msgstr "Proxy de la API"
 msgstr "Proxy de la API"
 
 
-#: src/views/preference/OpenAISettings.vue:69
+#: src/views/preference/OpenAISettings.vue:58
 msgid "API Token"
 msgid "API Token"
 msgstr "Token de la API"
 msgstr "Token de la API"
 
 
-#: src/views/preference/OpenAISettings.vue:78
+#: src/views/preference/OpenAISettings.vue:67
 #, fuzzy
 #, fuzzy
 msgid "API Type"
 msgid "API Type"
 msgstr "Token de la API"
 msgstr "Token de la API"
@@ -227,7 +227,7 @@ msgstr "Intentos"
 msgid "Auth"
 msgid "Auth"
 msgstr "Autenticación"
 msgstr "Autenticación"
 
 
-#: src/components/TwoFA/Authorization.vue:121
+#: src/components/TwoFA/Authorization.vue:109
 msgid "Authenticate with a passkey"
 msgid "Authenticate with a passkey"
 msgstr "Autenticarse con una llave de acceso"
 msgstr "Autenticarse con una llave de acceso"
 
 
@@ -618,6 +618,11 @@ msgstr "Base de datos (Opcional, default: database)"
 msgid "Days"
 msgid "Days"
 msgstr "Días"
 msgstr "Días"
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "Descripción"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -1238,7 +1243,7 @@ msgstr "Inicializando la actualización del kernel"
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr "Ingrese el código de la aplicación:"
 msgstr "Ingrese el código de la aplicación:"
 
 
-#: src/components/TwoFA/Authorization.vue:82
+#: src/components/TwoFA/Authorization.vue:72
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr "Ingrese el código de recuperación:"
 msgstr "Ingrese el código de recuperación:"
 
 
@@ -1281,6 +1286,11 @@ msgstr "Código de acceso o código de recuperación inválido"
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr "Código 2FA o de recuperación inválido"
 msgstr "Código 2FA o de recuperación inválido"
 
 
+#: src/constants/errors/middleware.ts:2
+#, fuzzy
+msgid "Invalid request format"
+msgstr "Código 2FA o de recuperación inválido"
+
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
 msgid "IP"
 msgid "IP"
 msgstr "IP"
 msgstr "IP"
@@ -1329,7 +1339,7 @@ msgstr "Comprobado por última vez el"
 msgid "Leave blank for no change"
 msgid "Leave blank for no change"
 msgstr "Para no modificar dejar en blanco"
 msgstr "Para no modificar dejar en blanco"
 
 
-#: src/views/preference/OpenAISettings.vue:53
+#: src/views/preference/OpenAISettings.vue:41
 msgid "Leave blank for the default: https://api.openai.com/"
 msgid "Leave blank for the default: https://api.openai.com/"
 msgstr "Dejar en blanco para el valor predeterminado: https://api.openai.com/"
 msgstr "Dejar en blanco para el valor predeterminado: https://api.openai.com/"
 
 
@@ -1393,7 +1403,7 @@ msgstr "Ubicaciones"
 msgid "Log"
 msgid "Log"
 msgstr "Registro"
 msgstr "Registro"
 
 
-#: src/routes/index.ts:318 src/views/other/Login.vue:222
+#: src/routes/index.ts:318 src/views/other/Login.vue:223
 msgid "Login"
 msgid "Login"
 msgstr "Acceso"
 msgstr "Acceso"
 
 
@@ -1472,7 +1482,7 @@ msgstr "Memoria y almacenamiento"
 msgid "Minutes"
 msgid "Minutes"
 msgstr "Minutos"
 msgstr "Minutos"
 
 
-#: src/views/preference/OpenAISettings.vue:32
+#: src/views/preference/OpenAISettings.vue:20
 msgid "Model"
 msgid "Model"
 msgstr "Modelo"
 msgstr "Modelo"
 
 
@@ -1761,7 +1771,7 @@ msgstr "En línea"
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
 
 
-#: src/components/TwoFA/Authorization.vue:112 src/views/other/Login.vue:231
+#: src/components/TwoFA/Authorization.vue:100 src/views/other/Login.vue:232
 msgid "Or"
 msgid "Or"
 msgstr "O"
 msgstr "O"
 
 
@@ -1870,7 +1880,7 @@ msgstr ""
 "Ingrese un nombre para la llave de acceso que desea crear y a continuación "
 "Ingrese un nombre para la llave de acceso que desea crear y a continuación "
 "haga clic en el botón Aceptar."
 "haga clic en el botón Aceptar."
 
 
-#: src/components/TwoFA/Authorization.vue:70
+#: src/components/TwoFA/Authorization.vue:85
 #, fuzzy
 #, fuzzy
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "Por favor, ingrese el código 2FA:"
 msgstr "Por favor, ingrese el código 2FA:"
@@ -2024,7 +2034,7 @@ msgstr "Recuperar"
 msgid "Recovered Successfully"
 msgid "Recovered Successfully"
 msgstr "Recuperado con éxito"
 msgstr "Recuperado con éxito"
 
 
-#: src/components/TwoFA/Authorization.vue:89
+#: src/components/TwoFA/Authorization.vue:79
 msgid "Recovery"
 msgid "Recovery"
 msgstr "Recuperación"
 msgstr "Recuperación"
 
 
@@ -2203,6 +2213,10 @@ msgstr "Renovado de Certificado exitoso"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Renovado con éxito"
 msgstr "Renovado con éxito"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "Pedido con parámetros incorrectos"
 msgstr "Pedido con parámetros incorrectos"
@@ -2388,7 +2402,7 @@ msgstr ""
 msgid "Show"
 msgid "Show"
 msgstr "Mostrar"
 msgstr "Mostrar"
 
 
-#: src/views/other/Login.vue:240
+#: src/views/other/Login.vue:241
 msgid "Sign in with a passkey"
 msgid "Sign in with a passkey"
 msgstr "Iniciar sesión con una llave de acceso"
 msgstr "Iniciar sesión con una llave de acceso"
 
 
@@ -2648,7 +2662,7 @@ msgid ""
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:23
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The model name should only contain letters, unicode, numbers, hyphens, "
 "The model name should only contain letters, unicode, numbers, hyphens, "
@@ -2706,8 +2720,8 @@ msgstr ""
 msgid "The url is invalid"
 msgid "The url is invalid"
 msgstr "La URL es inválida"
 msgstr "La URL es inválida"
 
 
-#: src/views/preference/OpenAISettings.vue:47
-#: src/views/preference/OpenAISettings.vue:60
+#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:49
 msgid "The url is invalid."
 msgid "The url is invalid."
 msgstr "La URL no es válida."
 msgstr "La URL no es válida."
 
 
@@ -2814,7 +2828,7 @@ msgstr ""
 "de la autoridad al backend, y debemos guardar este archivo y volver a cargar "
 "de la autoridad al backend, y debemos guardar este archivo y volver a cargar "
 "Nginx. ¿Estás seguro de que quieres continuar?"
 "Nginx. ¿Estás seguro de que quieres continuar?"
 
 
-#: src/views/preference/OpenAISettings.vue:48
+#: src/views/preference/OpenAISettings.vue:36
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
@@ -2825,7 +2839,7 @@ msgstr ""
 "Estos proporcionan un API endpoint compatible con OpenAI, por lo que solo "
 "Estos proporcionan un API endpoint compatible con OpenAI, por lo que solo "
 "debe configurar la baseUrl en su API local."
 "debe configurar la baseUrl en su API local."
 
 
-#: src/views/preference/OpenAISettings.vue:72
+#: src/views/preference/OpenAISettings.vue:61
 msgid "Token is not valid"
 msgid "Token is not valid"
 msgstr "El token no es válido"
 msgstr "El token no es válido"
 
 
@@ -2910,11 +2924,11 @@ msgstr "Tiempo encendido:"
 msgid "URL"
 msgid "URL"
 msgstr "URL"
 msgstr "URL"
 
 
-#: src/components/TwoFA/Authorization.vue:102
+#: src/components/TwoFA/Authorization.vue:121
 msgid "Use OTP"
 msgid "Use OTP"
 msgstr "Usar OTP"
 msgstr "Usar OTP"
 
 
-#: src/components/TwoFA/Authorization.vue:98
+#: src/components/TwoFA/Authorization.vue:117
 msgid "Use recovery code"
 msgid "Use recovery code"
 msgstr "Usar código de recuperación"
 msgstr "Usar código de recuperación"
 
 

+ 33 - 20
app/src/language/fr_FR/app.po

@@ -109,7 +109,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:44
+#: src/views/preference/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "URL de base de l'API"
 msgstr "URL de base de l'API"
 
 
@@ -118,15 +118,15 @@ msgstr "URL de base de l'API"
 msgid "API Document"
 msgid "API Document"
 msgstr "Jeton d'API"
 msgstr "Jeton d'API"
 
 
-#: src/views/preference/OpenAISettings.vue:57
+#: src/views/preference/OpenAISettings.vue:46
 msgid "API Proxy"
 msgid "API Proxy"
 msgstr "Proxy d'API"
 msgstr "Proxy d'API"
 
 
-#: src/views/preference/OpenAISettings.vue:69
+#: src/views/preference/OpenAISettings.vue:58
 msgid "API Token"
 msgid "API Token"
 msgstr "Jeton d'API"
 msgstr "Jeton d'API"
 
 
-#: src/views/preference/OpenAISettings.vue:78
+#: src/views/preference/OpenAISettings.vue:67
 #, fuzzy
 #, fuzzy
 msgid "API Type"
 msgid "API Type"
 msgstr "Jeton d'API"
 msgstr "Jeton d'API"
@@ -235,7 +235,7 @@ msgstr ""
 msgid "Auth"
 msgid "Auth"
 msgstr "Autheur"
 msgstr "Autheur"
 
 
-#: src/components/TwoFA/Authorization.vue:121
+#: src/components/TwoFA/Authorization.vue:109
 msgid "Authenticate with a passkey"
 msgid "Authenticate with a passkey"
 msgstr ""
 msgstr ""
 
 
@@ -635,6 +635,11 @@ msgstr "Base de données (Facultatif, par défaut : database)"
 msgid "Days"
 msgid "Days"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "Description"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -1278,7 +1283,7 @@ msgstr "Initialisation du programme de mise à niveau du core"
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:82
+#: src/components/TwoFA/Authorization.vue:72
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr ""
 msgstr ""
 
 
@@ -1320,6 +1325,10 @@ msgstr ""
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/middleware.ts:2
+msgid "Invalid request format"
+msgstr ""
+
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
 msgid "IP"
 msgid "IP"
 msgstr ""
 msgstr ""
@@ -1371,7 +1380,7 @@ msgstr "Dernière vérification le"
 msgid "Leave blank for no change"
 msgid "Leave blank for no change"
 msgstr "Laisser vide pour aucun changement"
 msgstr "Laisser vide pour aucun changement"
 
 
-#: src/views/preference/OpenAISettings.vue:53
+#: src/views/preference/OpenAISettings.vue:41
 msgid "Leave blank for the default: https://api.openai.com/"
 msgid "Leave blank for the default: https://api.openai.com/"
 msgstr "Laissez vide pour la valeur par défaut : https://api.openai.com/"
 msgstr "Laissez vide pour la valeur par défaut : https://api.openai.com/"
 
 
@@ -1444,7 +1453,7 @@ msgstr "Localisations"
 msgid "Log"
 msgid "Log"
 msgstr "Connexion"
 msgstr "Connexion"
 
 
-#: src/routes/index.ts:318 src/views/other/Login.vue:222
+#: src/routes/index.ts:318 src/views/other/Login.vue:223
 msgid "Login"
 msgid "Login"
 msgstr "Connexion"
 msgstr "Connexion"
 
 
@@ -1519,7 +1528,7 @@ msgstr "Mémoire et stockage"
 msgid "Minutes"
 msgid "Minutes"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:32
+#: src/views/preference/OpenAISettings.vue:20
 #, fuzzy
 #, fuzzy
 msgid "Model"
 msgid "Model"
 msgstr "Mode d'exécution"
 msgstr "Mode d'exécution"
@@ -1814,7 +1823,7 @@ msgstr ""
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
 
 
-#: src/components/TwoFA/Authorization.vue:112 src/views/other/Login.vue:231
+#: src/components/TwoFA/Authorization.vue:100 src/views/other/Login.vue:232
 msgid "Or"
 msgid "Or"
 msgstr ""
 msgstr ""
 
 
@@ -1916,7 +1925,7 @@ msgid ""
 "button below."
 "button below."
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:70
+#: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr ""
 msgstr ""
 
 
@@ -2071,7 +2080,7 @@ msgstr ""
 msgid "Recovered Successfully"
 msgid "Recovered Successfully"
 msgstr "Enregistré avec succès"
 msgstr "Enregistré avec succès"
 
 
-#: src/components/TwoFA/Authorization.vue:89
+#: src/components/TwoFA/Authorization.vue:79
 msgid "Recovery"
 msgid "Recovery"
 msgstr ""
 msgstr ""
 
 
@@ -2262,6 +2271,10 @@ msgstr "Changer de certificat"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Activé avec succès"
 msgstr "Activé avec succès"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr ""
 msgstr ""
@@ -2444,7 +2457,7 @@ msgstr ""
 msgid "Show"
 msgid "Show"
 msgstr ""
 msgstr ""
 
 
-#: src/views/other/Login.vue:240
+#: src/views/other/Login.vue:241
 msgid "Sign in with a passkey"
 msgid "Sign in with a passkey"
 msgstr ""
 msgstr ""
 
 
@@ -2711,7 +2724,7 @@ msgid ""
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:23
 msgid ""
 msgid ""
 "The model name should only contain letters, unicode, numbers, hyphens, "
 "The model name should only contain letters, unicode, numbers, hyphens, "
 "dashes, colons, and dots."
 "dashes, colons, and dots."
@@ -2761,8 +2774,8 @@ msgstr ""
 msgid "The url is invalid"
 msgid "The url is invalid"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:47
-#: src/views/preference/OpenAISettings.vue:60
+#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:49
 msgid "The url is invalid."
 msgid "The url is invalid."
 msgstr ""
 msgstr ""
 
 
@@ -2861,14 +2874,14 @@ msgstr ""
 "transmettre la demande de l'autorité au backend, et nous devons enregistrer "
 "transmettre la demande de l'autorité au backend, et nous devons enregistrer "
 "ce fichier et recharger le Nginx. Êtes-vous sûr de vouloir continuer?"
 "ce fichier et recharger le Nginx. Êtes-vous sûr de vouloir continuer?"
 
 
-#: src/views/preference/OpenAISettings.vue:48
+#: src/views/preference/OpenAISettings.vue:36
 msgid ""
 msgid ""
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "provide an OpenAI-compatible API endpoint, so just set the baseUrl to your "
 "provide an OpenAI-compatible API endpoint, so just set the baseUrl to your "
 "local API."
 "local API."
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:72
+#: src/views/preference/OpenAISettings.vue:61
 msgid "Token is not valid"
 msgid "Token is not valid"
 msgstr ""
 msgstr ""
 
 
@@ -2952,11 +2965,11 @@ msgstr "Disponibilité :"
 msgid "URL"
 msgid "URL"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:102
+#: src/components/TwoFA/Authorization.vue:121
 msgid "Use OTP"
 msgid "Use OTP"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:98
+#: src/components/TwoFA/Authorization.vue:117
 msgid "Use recovery code"
 msgid "Use recovery code"
 msgstr ""
 msgstr ""
 
 

+ 102 - 0
app/src/language/ko_KR/app.po

@@ -327,6 +327,13 @@ msgstr "CA 디렉토리"
 msgid "CADir"
 msgid "CADir"
 msgstr "CA 디렉토리"
 msgstr "CA 디렉토리"
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:129
+msgid "Can't scan? Use text key binding"
+msgstr ""
+
+>>>>>>> remotes/origin/dev
 #: src/components/ChatGPT/ChatGPT.vue:356
 #: src/components/ChatGPT/ChatGPT.vue:356
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:246
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:246
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:187
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:187
@@ -579,11 +586,19 @@ msgstr "인증 정보"
 msgid "Credentials"
 msgid "Credentials"
 msgstr "인증 정보들"
 msgstr "인증 정보들"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:72
 #: src/views/preference/components/TOTP.vue:72
 msgid "Current account is enabled TOTP."
 msgid "Current account is enabled TOTP."
 msgstr ""
 msgstr ""
 
 
 #: src/views/preference/components/TOTP.vue:70
 #: src/views/preference/components/TOTP.vue:70
+=======
+#: src/views/preference/components/TOTP.vue:77
+msgid "Current account is enabled TOTP."
+msgstr ""
+
+#: src/views/preference/components/TOTP.vue:74
+>>>>>>> remotes/origin/dev
 msgid "Current account is not enabled TOTP."
 msgid "Current account is not enabled TOTP."
 msgstr ""
 msgstr ""
 
 
@@ -615,6 +630,11 @@ msgstr "데이터베이스 (선택사항, 기본값: database)"
 msgid "Days"
 msgid "Days"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "설명"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -919,7 +939,11 @@ msgstr "%{node_name}에서 %{conf_name} 활성화 실패"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 msgstr "%{node_name}에서 %{conf_name} 성공적으로 활성화됨"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:45
 #: src/views/preference/components/TOTP.vue:45
+=======
+#: src/views/preference/components/TOTP.vue:38
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Enable 2FA successfully"
 msgid "Enable 2FA successfully"
 msgstr "성공적으로 활성화"
 msgstr "성공적으로 활성화"
@@ -960,7 +984,11 @@ msgstr "성공적으로 활성화"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "TLS 활성화"
 msgstr "TLS 활성화"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:81
 #: src/views/preference/components/TOTP.vue:81
+=======
+#: src/views/preference/components/TOTP.vue:103
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Enable TOTP"
 msgid "Enable TOTP"
 msgstr "TLS 활성화"
 msgstr "TLS 활성화"
@@ -1201,6 +1229,15 @@ msgid ""
 "ban threshold minutes, the ip will be banned for a period of time."
 "ban threshold minutes, the ip will be banned for a period of time."
 msgstr ""
 msgstr ""
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:89
+msgid ""
+"If you lose your mobile phone, you can use the recovery code to reset your "
+"2FA."
+msgstr ""
+
+>>>>>>> remotes/origin/dev
 #: src/views/preference/components/AddPasskey.vue:70
 #: src/views/preference/components/AddPasskey.vue:70
 msgid "If your browser supports WebAuthn Passkey, a dialog box will appear."
 msgid "If your browser supports WebAuthn Passkey, a dialog box will appear."
 msgstr ""
 msgstr ""
@@ -1233,11 +1270,19 @@ msgstr "초기 코어 업그레이더 오류"
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr "코어 업그레이더 초기화"
 msgstr "코어 업그레이더 초기화"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:119
 #: src/views/preference/components/TOTP.vue:119
+=======
+#: src/views/preference/components/TOTP.vue:136
+>>>>>>> remotes/origin/dev
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr ""
 msgstr ""
 
 
 #: src/components/TwoFA/Authorization.vue:82
 #: src/components/TwoFA/Authorization.vue:82
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:149
+>>>>>>> remotes/origin/dev
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr ""
 msgstr ""
 
 
@@ -1284,7 +1329,15 @@ msgstr ""
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr "유효함"
 msgstr "유효함"
 
 
+<<<<<<< HEAD
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
+=======
+#: src/constants/errors/middleware.ts:2
+msgid "Invalid request format"
+msgstr ""
+
+#: src/views/preference/AuthSettings.vue:14
+>>>>>>> remotes/origin/dev
 msgid "IP"
 msgid "IP"
 msgstr ""
 msgstr ""
 
 
@@ -2037,6 +2090,7 @@ msgid "Recovered Successfully"
 msgstr "성공적으로 제거됨"
 msgstr "성공적으로 제거됨"
 
 
 #: src/components/TwoFA/Authorization.vue:89
 #: src/components/TwoFA/Authorization.vue:89
+<<<<<<< HEAD
 msgid "Recovery"
 msgid "Recovery"
 msgstr ""
 msgstr ""
 
 
@@ -2049,6 +2103,18 @@ msgstr "유효함"
 msgid ""
 msgid ""
 "Recovery codes are used to access your account when you lose access to your "
 "Recovery codes are used to access your account when you lose access to your "
 "2FA device. Each code can only be used once."
 "2FA device. Each code can only be used once."
+=======
+#: src/views/preference/components/TOTP.vue:156
+msgid "Recovery"
+msgstr ""
+
+#: src/views/preference/components/TOTP.vue:82
+msgid "Recovery Code"
+msgstr ""
+
+#: src/views/preference/components/TOTP.vue:91
+msgid "Recovery Code:"
+>>>>>>> remotes/origin/dev
 msgstr ""
 msgstr ""
 
 
 #: src/views/preference/CertSettings.vue:37
 #: src/views/preference/CertSettings.vue:37
@@ -2229,6 +2295,10 @@ msgstr "인증서 갱신 성공"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "성공적으로 갱신됨"
 msgstr "성공적으로 갱신됨"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "잘못된 매개변수로 요청됨"
 msgstr "잘못된 매개변수로 요청됨"
@@ -2237,7 +2307,11 @@ msgstr "잘못된 매개변수로 요청됨"
 msgid "Reset"
 msgid "Reset"
 msgstr "재설정"
 msgstr "재설정"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:93
 #: src/views/preference/components/TOTP.vue:93
+=======
+#: src/views/preference/components/TOTP.vue:111
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Reset 2FA"
 msgid "Reset 2FA"
 msgstr "재설정"
 msgstr "재설정"
@@ -2331,7 +2405,11 @@ msgstr "성공적으로 저장됨"
 msgid "Saved successfully"
 msgid "Saved successfully"
 msgstr "성공적으로 저장됨"
 msgstr "성공적으로 저장됨"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:69
 #: src/views/preference/components/TOTP.vue:69
+=======
+#: src/views/preference/components/TOTP.vue:72
+>>>>>>> remotes/origin/dev
 msgid "Scan the QR code with your mobile phone to add the account to the app."
 msgid "Scan the QR code with your mobile phone to add the account to the app."
 msgstr ""
 msgstr ""
 
 
@@ -2339,7 +2417,11 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr ""
 msgstr ""
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
+=======
+#: src/views/preference/components/TOTP.vue:128
+>>>>>>> remotes/origin/dev
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr ""
 msgstr ""
 
 
@@ -2705,6 +2787,14 @@ msgid ""
 "hyphens, dashes, colons, and dots."
 "hyphens, dashes, colons, and dots."
 msgstr ""
 msgstr ""
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:90
+msgid ""
+"The recovery code is only displayed once, please save it in a safe place."
+msgstr ""
+
+>>>>>>> remotes/origin/dev
 #: src/views/dashboard/Environments.vue:148
 #: src/views/dashboard/Environments.vue:148
 msgid ""
 msgid ""
 "The remote Nginx UI version is not compatible with the local Nginx UI "
 "The remote Nginx UI version is not compatible with the local Nginx UI "
@@ -2802,7 +2892,11 @@ msgstr "팁"
 msgid "Title"
 msgid "Title"
 msgstr "제목"
 msgstr "제목"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:68
 #: src/views/preference/components/TOTP.vue:68
+=======
+#: src/views/preference/components/TOTP.vue:71
+>>>>>>> remotes/origin/dev
 msgid ""
 msgid ""
 "To enable it, you need to install the Google or Microsoft Authenticator app "
 "To enable it, you need to install the Google or Microsoft Authenticator app "
 "on your mobile phone."
 "on your mobile phone."
@@ -2843,11 +2937,19 @@ msgid_plural "Total %{total} items"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:66
 #: src/views/preference/components/TOTP.vue:66
 msgid "TOTP"
 msgid "TOTP"
 msgstr ""
 msgstr ""
 
 
 #: src/views/preference/components/TOTP.vue:67
 #: src/views/preference/components/TOTP.vue:67
+=======
+#: src/views/preference/components/TOTP.vue:69
+msgid "TOTP"
+msgstr ""
+
+#: src/views/preference/components/TOTP.vue:70
+>>>>>>> remotes/origin/dev
 msgid ""
 msgid ""
 "TOTP is a two-factor authentication method that uses a time-based one-time "
 "TOTP is a two-factor authentication method that uses a time-based one-time "
 "password algorithm."
 "password algorithm."

+ 33 - 21
app/src/language/messages.pot

@@ -100,7 +100,7 @@ msgstr ""
 msgid "All"
 msgid "All"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:44
+#: src/views/preference/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr ""
 msgstr ""
 
 
@@ -108,15 +108,15 @@ msgstr ""
 msgid "API Document"
 msgid "API Document"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:57
+#: src/views/preference/OpenAISettings.vue:46
 msgid "API Proxy"
 msgid "API Proxy"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:69
+#: src/views/preference/OpenAISettings.vue:58
 msgid "API Token"
 msgid "API Token"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:78
+#: src/views/preference/OpenAISettings.vue:67
 msgid "API Type"
 msgid "API Type"
 msgstr ""
 msgstr ""
 
 
@@ -210,7 +210,7 @@ msgstr ""
 msgid "Auth"
 msgid "Auth"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:121
+#: src/components/TwoFA/Authorization.vue:109
 msgid "Authenticate with a passkey"
 msgid "Authenticate with a passkey"
 msgstr ""
 msgstr ""
 
 
@@ -592,6 +592,10 @@ msgstr ""
 msgid "Days"
 msgid "Days"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/middleware.ts:3
+msgid "Decryption failed"
+msgstr ""
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -1191,7 +1195,7 @@ msgstr ""
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:82
+#: src/components/TwoFA/Authorization.vue:72
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr ""
 msgstr ""
 
 
@@ -1233,6 +1237,10 @@ msgstr ""
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/middleware.ts:2
+msgid "Invalid request format"
+msgstr ""
+
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
 msgid "IP"
 msgid "IP"
 msgstr ""
 msgstr ""
@@ -1278,7 +1286,7 @@ msgstr ""
 msgid "Leave blank for no change"
 msgid "Leave blank for no change"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:53
+#: src/views/preference/OpenAISettings.vue:41
 msgid "Leave blank for the default: https://api.openai.com/"
 msgid "Leave blank for the default: https://api.openai.com/"
 msgstr ""
 msgstr ""
 
 
@@ -1342,7 +1350,7 @@ msgid "Log"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/index.ts:318
 #: src/routes/index.ts:318
-#: src/views/other/Login.vue:222
+#: src/views/other/Login.vue:223
 msgid "Login"
 msgid "Login"
 msgstr ""
 msgstr ""
 
 
@@ -1410,7 +1418,7 @@ msgstr ""
 msgid "Minutes"
 msgid "Minutes"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:32
+#: src/views/preference/OpenAISettings.vue:20
 msgid "Model"
 msgid "Model"
 msgstr ""
 msgstr ""
 
 
@@ -1691,8 +1699,8 @@ msgstr ""
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:112
-#: src/views/other/Login.vue:231
+#: src/components/TwoFA/Authorization.vue:100
+#: src/views/other/Login.vue:232
 msgid "Or"
 msgid "Or"
 msgstr ""
 msgstr ""
 
 
@@ -1790,7 +1798,7 @@ msgstr ""
 msgid "Please enter a name for the passkey you wish to create and click the OK button below."
 msgid "Please enter a name for the passkey you wish to create and click the OK button below."
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:70
+#: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr ""
 msgstr ""
 
 
@@ -1922,7 +1930,7 @@ msgstr ""
 msgid "Recovered Successfully"
 msgid "Recovered Successfully"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:89
+#: src/components/TwoFA/Authorization.vue:79
 msgid "Recovery"
 msgid "Recovery"
 msgstr ""
 msgstr ""
 
 
@@ -2083,6 +2091,10 @@ msgstr ""
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr ""
 msgstr ""
@@ -2253,7 +2265,7 @@ msgstr ""
 msgid "Show"
 msgid "Show"
 msgstr ""
 msgstr ""
 
 
-#: src/views/other/Login.vue:240
+#: src/views/other/Login.vue:241
 msgid "Sign in with a passkey"
 msgid "Sign in with a passkey"
 msgstr ""
 msgstr ""
 
 
@@ -2482,7 +2494,7 @@ msgstr ""
 msgid "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 msgid "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:23
 msgid "The model name should only contain letters, unicode, numbers, hyphens, dashes, colons, and dots."
 msgid "The model name should only contain letters, unicode, numbers, hyphens, dashes, colons, and dots."
 msgstr ""
 msgstr ""
 
 
@@ -2515,8 +2527,8 @@ msgstr ""
 msgid "The url is invalid"
 msgid "The url is invalid"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:47
-#: src/views/preference/OpenAISettings.vue:60
+#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:49
 msgid "The url is invalid."
 msgid "The url is invalid."
 msgstr ""
 msgstr ""
 
 
@@ -2593,11 +2605,11 @@ msgstr ""
 msgid "To make sure the certification auto-renewal can work normally, we need to add a location which can proxy the request from authority to backend, and we need to save this file and reload the Nginx. Are you sure you want to continue?"
 msgid "To make sure the certification auto-renewal can work normally, we need to add a location which can proxy the request from authority to backend, and we need to save this file and reload the Nginx. Are you sure you want to continue?"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:48
+#: src/views/preference/OpenAISettings.vue:36
 msgid "To use a local large model, deploy it with ollama, vllm or lmdeploy. They provide an OpenAI-compatible API endpoint, so just set the baseUrl to your local API."
 msgid "To use a local large model, deploy it with ollama, vllm or lmdeploy. They provide an OpenAI-compatible API endpoint, so just set the baseUrl to your local API."
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:72
+#: src/views/preference/OpenAISettings.vue:61
 msgid "Token is not valid"
 msgid "Token is not valid"
 msgstr ""
 msgstr ""
 
 
@@ -2682,11 +2694,11 @@ msgstr ""
 msgid "URL"
 msgid "URL"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:102
+#: src/components/TwoFA/Authorization.vue:121
 msgid "Use OTP"
 msgid "Use OTP"
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:98
+#: src/components/TwoFA/Authorization.vue:117
 msgid "Use recovery code"
 msgid "Use recovery code"
 msgstr ""
 msgstr ""
 
 

+ 108 - 0
app/src/language/ru_RU/app.po

@@ -330,6 +330,13 @@ msgstr "Директория корневого сертификата"
 msgid "CADir"
 msgid "CADir"
 msgstr ""
 msgstr ""
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:129
+msgid "Can't scan? Use text key binding"
+msgstr ""
+
+>>>>>>> remotes/origin/dev
 #: src/components/ChatGPT/ChatGPT.vue:356
 #: src/components/ChatGPT/ChatGPT.vue:356
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:246
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:246
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:187
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:187
@@ -579,12 +586,20 @@ msgstr "Учетные данные"
 msgid "Credentials"
 msgid "Credentials"
 msgstr "Учетные данные"
 msgstr "Учетные данные"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:72
 #: src/views/preference/components/TOTP.vue:72
+=======
+#: src/views/preference/components/TOTP.vue:77
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Current account is enabled TOTP."
 msgid "Current account is enabled TOTP."
 msgstr "Текущая учетная запись имеет включенную 2ФА."
 msgstr "Текущая учетная запись имеет включенную 2ФА."
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:70
 #: src/views/preference/components/TOTP.vue:70
+=======
+#: src/views/preference/components/TOTP.vue:74
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Current account is not enabled TOTP."
 msgid "Current account is not enabled TOTP."
 msgstr ""
 msgstr ""
@@ -619,6 +634,11 @@ msgstr "База данных (Опционально, по умолчанию:
 msgid "Days"
 msgid "Days"
 msgstr "Дни"
 msgstr "Дни"
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "Описание"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -927,7 +947,11 @@ msgstr "Включение %{conf_name} in %{node_name} нипалучилася
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 msgstr "Включение %{conf_name} in %{node_name} успешно"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:45
 #: src/views/preference/components/TOTP.vue:45
+=======
+#: src/views/preference/components/TOTP.vue:38
+>>>>>>> remotes/origin/dev
 msgid "Enable 2FA successfully"
 msgid "Enable 2FA successfully"
 msgstr "Двухфакторная аутентификация успешно включена"
 msgstr "Двухфакторная аутентификация успешно включена"
 
 
@@ -967,7 +991,11 @@ msgstr "Включено успешно"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "Включить TLS"
 msgstr "Включить TLS"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:81
 #: src/views/preference/components/TOTP.vue:81
+=======
+#: src/views/preference/components/TOTP.vue:103
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Enable TOTP"
 msgid "Enable TOTP"
 msgstr "Включить TLS"
 msgstr "Включить TLS"
@@ -1207,6 +1235,17 @@ msgstr ""
 "количества попыток в течение пороговых минут блокировки, IP будет "
 "количества попыток в течение пороговых минут блокировки, IP будет "
 "заблокирован на определенный период времени."
 "заблокирован на определенный период времени."
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:89
+msgid ""
+"If you lose your mobile phone, you can use the recovery code to reset your "
+"2FA."
+msgstr ""
+"Если вы потеряете свой мобильный телефон, вы можете использовать код "
+"восстановления для сброса 2FA."
+
+>>>>>>> remotes/origin/dev
 #: src/views/preference/components/AddPasskey.vue:70
 #: src/views/preference/components/AddPasskey.vue:70
 msgid "If your browser supports WebAuthn Passkey, a dialog box will appear."
 msgid "If your browser supports WebAuthn Passkey, a dialog box will appear."
 msgstr ""
 msgstr ""
@@ -1241,11 +1280,19 @@ msgstr "Ошибка первоначального обновления ядр
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr "Инициализация программы обновления ядра"
 msgstr "Инициализация программы обновления ядра"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:119
 #: src/views/preference/components/TOTP.vue:119
+=======
+#: src/views/preference/components/TOTP.vue:136
+>>>>>>> remotes/origin/dev
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr "Введите код из приложения:"
 msgstr "Введите код из приложения:"
 
 
 #: src/components/TwoFA/Authorization.vue:82
 #: src/components/TwoFA/Authorization.vue:82
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:149
+>>>>>>> remotes/origin/dev
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr "Введите код восстановления:"
 msgstr "Введите код восстановления:"
 
 
@@ -1288,7 +1335,16 @@ msgstr "Неверный пароль или код восстановления
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr "Неверный 2FA или код восстановления"
 msgstr "Неверный 2FA или код восстановления"
 
 
+<<<<<<< HEAD
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
+=======
+#: src/constants/errors/middleware.ts:2
+#, fuzzy
+msgid "Invalid request format"
+msgstr "Неверный 2FA или код восстановления"
+
+#: src/views/preference/AuthSettings.vue:14
+>>>>>>> remotes/origin/dev
 msgid "IP"
 msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
@@ -2023,6 +2079,7 @@ msgid "Recovered Successfully"
 msgstr "Восстановлено успешно"
 msgstr "Восстановлено успешно"
 
 
 #: src/components/TwoFA/Authorization.vue:89
 #: src/components/TwoFA/Authorization.vue:89
+<<<<<<< HEAD
 msgid "Recovery"
 msgid "Recovery"
 msgstr "Восстановление"
 msgstr "Восстановление"
 
 
@@ -2036,6 +2093,19 @@ msgid ""
 "Recovery codes are used to access your account when you lose access to your "
 "Recovery codes are used to access your account when you lose access to your "
 "2FA device. Each code can only be used once."
 "2FA device. Each code can only be used once."
 msgstr ""
 msgstr ""
+=======
+#: src/views/preference/components/TOTP.vue:156
+msgid "Recovery"
+msgstr "Восстановление"
+
+#: src/views/preference/components/TOTP.vue:82
+msgid "Recovery Code"
+msgstr "Код восстановления"
+
+#: src/views/preference/components/TOTP.vue:91
+msgid "Recovery Code:"
+msgstr "Код восстановления:"
+>>>>>>> remotes/origin/dev
 
 
 #: src/views/preference/CertSettings.vue:37
 #: src/views/preference/CertSettings.vue:37
 msgid "Recursive Nameservers"
 msgid "Recursive Nameservers"
@@ -2200,6 +2270,10 @@ msgstr "Успешное обновление сертификата"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Успешно обновлено"
 msgstr "Успешно обновлено"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "Запрос с неправильными параметрами"
 msgstr "Запрос с неправильными параметрами"
@@ -2208,7 +2282,11 @@ msgstr "Запрос с неправильными параметрами"
 msgid "Reset"
 msgid "Reset"
 msgstr "Сброс"
 msgstr "Сброс"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:93
 #: src/views/preference/components/TOTP.vue:93
+=======
+#: src/views/preference/components/TOTP.vue:111
+>>>>>>> remotes/origin/dev
 msgid "Reset 2FA"
 msgid "Reset 2FA"
 msgstr "Сброс 2FA"
 msgstr "Сброс 2FA"
 
 
@@ -2301,7 +2379,11 @@ msgstr "Сохранено успешно"
 msgid "Saved successfully"
 msgid "Saved successfully"
 msgstr "Успешно сохранено"
 msgstr "Успешно сохранено"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:69
 #: src/views/preference/components/TOTP.vue:69
+=======
+#: src/views/preference/components/TOTP.vue:72
+>>>>>>> remotes/origin/dev
 msgid "Scan the QR code with your mobile phone to add the account to the app."
 msgid "Scan the QR code with your mobile phone to add the account to the app."
 msgstr ""
 msgstr ""
 "Отсканируйте QR-код с помощью мобильного телефона, чтобы добавить учетную "
 "Отсканируйте QR-код с помощью мобильного телефона, чтобы добавить учетную "
@@ -2311,7 +2393,11 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr "SDK"
 msgstr "SDK"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
+=======
+#: src/views/preference/components/TOTP.vue:128
+>>>>>>> remotes/origin/dev
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr ""
 msgstr ""
 
 
@@ -2681,6 +2767,16 @@ msgstr ""
 "Имя сервера должно содержать только буквы, юникод, цифры, дефисы, тире и "
 "Имя сервера должно содержать только буквы, юникод, цифры, дефисы, тире и "
 "точки."
 "точки."
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:90
+msgid ""
+"The recovery code is only displayed once, please save it in a safe place."
+msgstr ""
+"Код восстановления отображается только один раз, пожалуйста, сохраните его в "
+"безопасном месте."
+
+>>>>>>> remotes/origin/dev
 #: src/views/dashboard/Environments.vue:148
 #: src/views/dashboard/Environments.vue:148
 msgid ""
 msgid ""
 "The remote Nginx UI version is not compatible with the local Nginx UI "
 "The remote Nginx UI version is not compatible with the local Nginx UI "
@@ -2782,7 +2878,11 @@ msgstr "Советы"
 msgid "Title"
 msgid "Title"
 msgstr "Заголовок"
 msgstr "Заголовок"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:68
 #: src/views/preference/components/TOTP.vue:68
+=======
+#: src/views/preference/components/TOTP.vue:71
+>>>>>>> remotes/origin/dev
 msgid ""
 msgid ""
 "To enable it, you need to install the Google or Microsoft Authenticator app "
 "To enable it, you need to install the Google or Microsoft Authenticator app "
 "on your mobile phone."
 "on your mobile phone."
@@ -2826,11 +2926,19 @@ msgid_plural "Total %{total} items"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:66
 #: src/views/preference/components/TOTP.vue:66
 msgid "TOTP"
 msgid "TOTP"
 msgstr ""
 msgstr ""
 
 
 #: src/views/preference/components/TOTP.vue:67
 #: src/views/preference/components/TOTP.vue:67
+=======
+#: src/views/preference/components/TOTP.vue:69
+msgid "TOTP"
+msgstr ""
+
+#: src/views/preference/components/TOTP.vue:70
+>>>>>>> remotes/origin/dev
 msgid ""
 msgid ""
 "TOTP is a two-factor authentication method that uses a time-based one-time "
 "TOTP is a two-factor authentication method that uses a time-based one-time "
 "password algorithm."
 "password algorithm."

+ 110 - 0
app/src/language/tr_TR/app.po

@@ -325,6 +325,13 @@ msgstr "CA Dizini"
 msgid "CADir"
 msgid "CADir"
 msgstr "CADizini"
 msgstr "CADizini"
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:129
+msgid "Can't scan? Use text key binding"
+msgstr "Tarayamıyor musunuz? Metin anahtar bağlamasını kullanın"
+
+>>>>>>> remotes/origin/dev
 #: src/components/ChatGPT/ChatGPT.vue:356
 #: src/components/ChatGPT/ChatGPT.vue:356
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:246
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:246
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:187
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:187
@@ -573,11 +580,19 @@ msgstr "Kimlik bilgisi"
 msgid "Credentials"
 msgid "Credentials"
 msgstr "Kimlik bilgileri"
 msgstr "Kimlik bilgileri"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:72
 #: src/views/preference/components/TOTP.vue:72
 msgid "Current account is enabled TOTP."
 msgid "Current account is enabled TOTP."
 msgstr "Mevcut hesap için TOTP etkinleştirildi."
 msgstr "Mevcut hesap için TOTP etkinleştirildi."
 
 
 #: src/views/preference/components/TOTP.vue:70
 #: src/views/preference/components/TOTP.vue:70
+=======
+#: src/views/preference/components/TOTP.vue:77
+msgid "Current account is enabled TOTP."
+msgstr "Mevcut hesap için TOTP etkinleştirildi."
+
+#: src/views/preference/components/TOTP.vue:74
+>>>>>>> remotes/origin/dev
 msgid "Current account is not enabled TOTP."
 msgid "Current account is not enabled TOTP."
 msgstr "Mevcut hesap için TOTP etkin değil."
 msgstr "Mevcut hesap için TOTP etkin değil."
 
 
@@ -610,6 +625,11 @@ msgstr "Veritabanı (İsteğe bağlı, varsayılan: database)"
 msgid "Days"
 msgid "Days"
 msgstr "Günler"
 msgstr "Günler"
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "Açıklama"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -925,7 +945,11 @@ msgstr ""
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "%{conf_name} yapılandırmasını %{node_name} düğümünde etkinleştirme başarılı "
 "oldu"
 "oldu"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:45
 #: src/views/preference/components/TOTP.vue:45
+=======
+#: src/views/preference/components/TOTP.vue:38
+>>>>>>> remotes/origin/dev
 msgid "Enable 2FA successfully"
 msgid "Enable 2FA successfully"
 msgstr "2FA'yı başarıyla etkinleştirildi"
 msgstr "2FA'yı başarıyla etkinleştirildi"
 
 
@@ -969,7 +993,11 @@ msgstr "Başarıyla etkinleştirildi"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "TLS'yi Etkinleştir"
 msgstr "TLS'yi Etkinleştir"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:81
 #: src/views/preference/components/TOTP.vue:81
+=======
+#: src/views/preference/components/TOTP.vue:103
+>>>>>>> remotes/origin/dev
 msgid "Enable TOTP"
 msgid "Enable TOTP"
 msgstr "TOTP'yi Etkinleştir"
 msgstr "TOTP'yi Etkinleştir"
 
 
@@ -1208,6 +1236,17 @@ msgstr ""
 "yasaklama eşiği dakikaları içinde maksimum deneme sayısına ulaşırsa, IP "
 "yasaklama eşiği dakikaları içinde maksimum deneme sayısına ulaşırsa, IP "
 "adresi belirli bir süre için yasaklanacaktır."
 "adresi belirli bir süre için yasaklanacaktır."
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:89
+msgid ""
+"If you lose your mobile phone, you can use the recovery code to reset your "
+"2FA."
+msgstr ""
+"Cep telefonunuzu kaybederseniz, 2FA'nızı sıfırlamak için kurtarma kodunu "
+"kullanabilirsiniz."
+
+>>>>>>> remotes/origin/dev
 #: src/views/preference/components/AddPasskey.vue:70
 #: src/views/preference/components/AddPasskey.vue:70
 msgid "If your browser supports WebAuthn Passkey, a dialog box will appear."
 msgid "If your browser supports WebAuthn Passkey, a dialog box will appear."
 msgstr ""
 msgstr ""
@@ -1243,11 +1282,19 @@ msgstr "İlk çekirdek yükseltici hatası"
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr "Çekirdek yükseltici başlatılıyor"
 msgstr "Çekirdek yükseltici başlatılıyor"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:119
 #: src/views/preference/components/TOTP.vue:119
+=======
+#: src/views/preference/components/TOTP.vue:136
+>>>>>>> remotes/origin/dev
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr "Uygulamadan kodu girin:"
 msgstr "Uygulamadan kodu girin:"
 
 
 #: src/components/TwoFA/Authorization.vue:82
 #: src/components/TwoFA/Authorization.vue:82
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:149
+>>>>>>> remotes/origin/dev
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr "Kurtarma kodunu girin:"
 msgstr "Kurtarma kodunu girin:"
 
 
@@ -1290,7 +1337,16 @@ msgstr "Geçersiz parola veya kurtarma kodu"
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr "Geçersiz 2FA veya kurtarma kodu"
 msgstr "Geçersiz 2FA veya kurtarma kodu"
 
 
+<<<<<<< HEAD
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
+=======
+#: src/constants/errors/middleware.ts:2
+#, fuzzy
+msgid "Invalid request format"
+msgstr "Geçersiz 2FA veya kurtarma kodu"
+
+#: src/views/preference/AuthSettings.vue:14
+>>>>>>> remotes/origin/dev
 msgid "IP"
 msgid "IP"
 msgstr "IP"
 msgstr "IP"
 
 
@@ -2119,20 +2175,35 @@ msgid "Recovered Successfully"
 msgstr "Başarıyla Kurtarıldı"
 msgstr "Başarıyla Kurtarıldı"
 
 
 #: src/components/TwoFA/Authorization.vue:89
 #: src/components/TwoFA/Authorization.vue:89
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:156
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Recovery"
 msgid "Recovery"
 msgstr "Kurtarma"
 msgstr "Kurtarma"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/RecoveryCodes.vue:68
 #: src/views/preference/components/RecoveryCodes.vue:68
+=======
+#: src/views/preference/components/TOTP.vue:82
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Recovery Codes"
 msgid "Recovery Codes"
 msgstr "Kurtarma Kodu"
 msgstr "Kurtarma Kodu"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/RecoveryCodes.vue:73
 #: src/views/preference/components/RecoveryCodes.vue:73
 msgid ""
 msgid ""
 "Recovery codes are used to access your account when you lose access to your "
 "Recovery codes are used to access your account when you lose access to your "
 "2FA device. Each code can only be used once."
 "2FA device. Each code can only be used once."
 msgstr ""
 msgstr ""
+=======
+#: src/views/preference/components/TOTP.vue:91
+#, fuzzy
+msgid "Recovery Code:"
+msgstr "Kurtarma Kodu:"
+>>>>>>> remotes/origin/dev
 
 
 #: src/views/preference/CertSettings.vue:37
 #: src/views/preference/CertSettings.vue:37
 #, fuzzy
 #, fuzzy
@@ -2328,6 +2399,10 @@ msgstr "Sertifika Yenileme Başarısı"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Başarıyla yenileyin"
 msgstr "Başarıyla yenileyin"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 #, fuzzy
 #, fuzzy
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
@@ -2338,7 +2413,11 @@ msgstr "Yanlış parametrelerle talep edildi"
 msgid "Reset"
 msgid "Reset"
 msgstr "Sıfırla"
 msgstr "Sıfırla"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:93
 #: src/views/preference/components/TOTP.vue:93
+=======
+#: src/views/preference/components/TOTP.vue:111
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Reset 2FA"
 msgid "Reset 2FA"
 msgstr "2FA'yı Sıfırla"
 msgstr "2FA'yı Sıfırla"
@@ -2441,7 +2520,11 @@ msgstr "Başarıyla kaydedin"
 msgid "Saved successfully"
 msgid "Saved successfully"
 msgstr "Başarıyla Kaydedildi"
 msgstr "Başarıyla Kaydedildi"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:69
 #: src/views/preference/components/TOTP.vue:69
+=======
+#: src/views/preference/components/TOTP.vue:72
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Scan the QR code with your mobile phone to add the account to the app."
 msgid "Scan the QR code with your mobile phone to add the account to the app."
 msgstr "Hesabı uygulamaya eklemek için QR kodunu cep telefonunuzla tarayın."
 msgstr "Hesabı uygulamaya eklemek için QR kodunu cep telefonunuzla tarayın."
@@ -2451,7 +2534,11 @@ msgstr "Hesabı uygulamaya eklemek için QR kodunu cep telefonunuzla tarayın."
 msgid "SDK"
 msgid "SDK"
 msgstr "SDK"
 msgstr "SDK"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
+=======
+#: src/views/preference/components/TOTP.vue:128
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr "Sır kopyalandı"
 msgstr "Sır kopyalandı"
@@ -2867,6 +2954,17 @@ msgstr ""
 "Sunucu adı yalnızca harf, unicode, sayı, kısa çizgi, tire ve nokta "
 "Sunucu adı yalnızca harf, unicode, sayı, kısa çizgi, tire ve nokta "
 "içermelidir."
 "içermelidir."
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:90
+#, fuzzy
+msgid ""
+"The recovery code is only displayed once, please save it in a safe place."
+msgstr ""
+"Kurtarma kodu yalnızca bir kez görüntülenir, lütfen güvenli bir yere "
+"kaydedin."
+
+>>>>>>> remotes/origin/dev
 #: src/views/dashboard/Environments.vue:148
 #: src/views/dashboard/Environments.vue:148
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
@@ -2979,7 +3077,11 @@ msgstr "İpuçları"
 msgid "Title"
 msgid "Title"
 msgstr "Başlık"
 msgstr "Başlık"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:68
 #: src/views/preference/components/TOTP.vue:68
+=======
+#: src/views/preference/components/TOTP.vue:71
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "To enable it, you need to install the Google or Microsoft Authenticator app "
 "To enable it, you need to install the Google or Microsoft Authenticator app "
@@ -3034,12 +3136,20 @@ msgid_plural "Total %{total} items"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:66
 #: src/views/preference/components/TOTP.vue:66
+=======
+#: src/views/preference/components/TOTP.vue:69
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "TOTP"
 msgid "TOTP"
 msgstr "TOTP"
 msgstr "TOTP"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:67
 #: src/views/preference/components/TOTP.vue:67
+=======
+#: src/views/preference/components/TOTP.vue:70
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "TOTP is a two-factor authentication method that uses a time-based one-time "
 "TOTP is a two-factor authentication method that uses a time-based one-time "

+ 102 - 0
app/src/language/vi_VN/app.po

@@ -342,6 +342,13 @@ msgstr ""
 msgid "CADir"
 msgid "CADir"
 msgstr ""
 msgstr ""
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:129
+msgid "Can't scan? Use text key binding"
+msgstr ""
+
+>>>>>>> remotes/origin/dev
 #: src/components/ChatGPT/ChatGPT.vue:356
 #: src/components/ChatGPT/ChatGPT.vue:356
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:246
 #: src/components/StdDesign/StdDataDisplay/StdCurd.vue:246
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:187
 #: src/components/StdDesign/StdDataEntry/components/StdSelector.vue:187
@@ -603,11 +610,19 @@ msgstr "Chứng chỉ"
 msgid "Credentials"
 msgid "Credentials"
 msgstr "Chứng chỉ"
 msgstr "Chứng chỉ"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:72
 #: src/views/preference/components/TOTP.vue:72
 msgid "Current account is enabled TOTP."
 msgid "Current account is enabled TOTP."
 msgstr ""
 msgstr ""
 
 
 #: src/views/preference/components/TOTP.vue:70
 #: src/views/preference/components/TOTP.vue:70
+=======
+#: src/views/preference/components/TOTP.vue:77
+msgid "Current account is enabled TOTP."
+msgstr ""
+
+#: src/views/preference/components/TOTP.vue:74
+>>>>>>> remotes/origin/dev
 msgid "Current account is not enabled TOTP."
 msgid "Current account is not enabled TOTP."
 msgstr ""
 msgstr ""
 
 
@@ -639,6 +654,11 @@ msgstr "Tên cơ sở dữ liệu (Tuỳ chọn, Mặc định là: database)"
 msgid "Days"
 msgid "Days"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "Mô tả"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -961,7 +981,11 @@ msgstr "Không thể bật %{conf_name} trên %{node_name}"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgid "Enable %{conf_name} in %{node_name} successfully"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 msgstr "Đã bật %{conf_name} trên %{node_name}"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:45
 #: src/views/preference/components/TOTP.vue:45
+=======
+#: src/views/preference/components/TOTP.vue:38
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Enable 2FA successfully"
 msgid "Enable 2FA successfully"
 msgstr "Đã bật"
 msgstr "Đã bật"
@@ -1003,7 +1027,11 @@ msgstr "Đã bật"
 msgid "Enable TLS"
 msgid "Enable TLS"
 msgstr "Bật TLS"
 msgstr "Bật TLS"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:81
 #: src/views/preference/components/TOTP.vue:81
+=======
+#: src/views/preference/components/TOTP.vue:103
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Enable TOTP"
 msgid "Enable TOTP"
 msgstr "Bật TLS"
 msgstr "Bật TLS"
@@ -1247,6 +1275,15 @@ msgid ""
 "ban threshold minutes, the ip will be banned for a period of time."
 "ban threshold minutes, the ip will be banned for a period of time."
 msgstr ""
 msgstr ""
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:89
+msgid ""
+"If you lose your mobile phone, you can use the recovery code to reset your "
+"2FA."
+msgstr ""
+
+>>>>>>> remotes/origin/dev
 #: src/views/preference/components/AddPasskey.vue:70
 #: src/views/preference/components/AddPasskey.vue:70
 msgid "If your browser supports WebAuthn Passkey, a dialog box will appear."
 msgid "If your browser supports WebAuthn Passkey, a dialog box will appear."
 msgstr ""
 msgstr ""
@@ -1280,11 +1317,19 @@ msgstr "Không thể khởi tạo trình nâng cấp"
 msgid "Initialing core upgrader"
 msgid "Initialing core upgrader"
 msgstr "Đang khởi tạo trình nâng cấp"
 msgstr "Đang khởi tạo trình nâng cấp"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:119
 #: src/views/preference/components/TOTP.vue:119
+=======
+#: src/views/preference/components/TOTP.vue:136
+>>>>>>> remotes/origin/dev
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr ""
 msgstr ""
 
 
 #: src/components/TwoFA/Authorization.vue:82
 #: src/components/TwoFA/Authorization.vue:82
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:149
+>>>>>>> remotes/origin/dev
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr ""
 msgstr ""
 
 
@@ -1331,7 +1376,15 @@ msgstr ""
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr "Hợp lệ"
 msgstr "Hợp lệ"
 
 
+<<<<<<< HEAD
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
+=======
+#: src/constants/errors/middleware.ts:2
+msgid "Invalid request format"
+msgstr ""
+
+#: src/views/preference/AuthSettings.vue:14
+>>>>>>> remotes/origin/dev
 msgid "IP"
 msgid "IP"
 msgstr ""
 msgstr ""
 
 
@@ -2080,6 +2133,7 @@ msgid "Recovered Successfully"
 msgstr "Xoá thành công"
 msgstr "Xoá thành công"
 
 
 #: src/components/TwoFA/Authorization.vue:89
 #: src/components/TwoFA/Authorization.vue:89
+<<<<<<< HEAD
 msgid "Recovery"
 msgid "Recovery"
 msgstr ""
 msgstr ""
 
 
@@ -2092,6 +2146,18 @@ msgstr "Hợp lệ"
 msgid ""
 msgid ""
 "Recovery codes are used to access your account when you lose access to your "
 "Recovery codes are used to access your account when you lose access to your "
 "2FA device. Each code can only be used once."
 "2FA device. Each code can only be used once."
+=======
+#: src/views/preference/components/TOTP.vue:156
+msgid "Recovery"
+msgstr ""
+
+#: src/views/preference/components/TOTP.vue:82
+msgid "Recovery Code"
+msgstr ""
+
+#: src/views/preference/components/TOTP.vue:91
+msgid "Recovery Code:"
+>>>>>>> remotes/origin/dev
 msgstr ""
 msgstr ""
 
 
 #: src/views/preference/CertSettings.vue:37
 #: src/views/preference/CertSettings.vue:37
@@ -2272,6 +2338,10 @@ msgstr "Gia hạn chứng chỉ SSL thành công"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "Gia hạn chứng chỉ SSL"
 msgstr "Gia hạn chứng chỉ SSL"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "Yêu cầu có chứa tham số sai"
 msgstr "Yêu cầu có chứa tham số sai"
@@ -2280,7 +2350,11 @@ msgstr "Yêu cầu có chứa tham số sai"
 msgid "Reset"
 msgid "Reset"
 msgstr "Đặt lại"
 msgstr "Đặt lại"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:93
 #: src/views/preference/components/TOTP.vue:93
+=======
+#: src/views/preference/components/TOTP.vue:111
+>>>>>>> remotes/origin/dev
 #, fuzzy
 #, fuzzy
 msgid "Reset 2FA"
 msgid "Reset 2FA"
 msgstr "Đặt lại"
 msgstr "Đặt lại"
@@ -2374,7 +2448,11 @@ msgstr "Lưu thành công"
 msgid "Saved successfully"
 msgid "Saved successfully"
 msgstr "Lưu thành công"
 msgstr "Lưu thành công"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:69
 #: src/views/preference/components/TOTP.vue:69
+=======
+#: src/views/preference/components/TOTP.vue:72
+>>>>>>> remotes/origin/dev
 msgid "Scan the QR code with your mobile phone to add the account to the app."
 msgid "Scan the QR code with your mobile phone to add the account to the app."
 msgstr ""
 msgstr ""
 
 
@@ -2382,7 +2460,11 @@ msgstr ""
 msgid "SDK"
 msgid "SDK"
 msgstr ""
 msgstr ""
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:109
 #: src/views/preference/components/TOTP.vue:109
+=======
+#: src/views/preference/components/TOTP.vue:128
+>>>>>>> remotes/origin/dev
 msgid "Secret has been copied"
 msgid "Secret has been copied"
 msgstr ""
 msgstr ""
 
 
@@ -2748,6 +2830,14 @@ msgid ""
 "hyphens, dashes, colons, and dots."
 "hyphens, dashes, colons, and dots."
 msgstr ""
 msgstr ""
 
 
+<<<<<<< HEAD
+=======
+#: src/views/preference/components/TOTP.vue:90
+msgid ""
+"The recovery code is only displayed once, please save it in a safe place."
+msgstr ""
+
+>>>>>>> remotes/origin/dev
 #: src/views/dashboard/Environments.vue:148
 #: src/views/dashboard/Environments.vue:148
 msgid ""
 msgid ""
 "The remote Nginx UI version is not compatible with the local Nginx UI "
 "The remote Nginx UI version is not compatible with the local Nginx UI "
@@ -2842,7 +2932,11 @@ msgstr ""
 msgid "Title"
 msgid "Title"
 msgstr "Tiêu đề"
 msgstr "Tiêu đề"
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:68
 #: src/views/preference/components/TOTP.vue:68
+=======
+#: src/views/preference/components/TOTP.vue:71
+>>>>>>> remotes/origin/dev
 msgid ""
 msgid ""
 "To enable it, you need to install the Google or Microsoft Authenticator app "
 "To enable it, you need to install the Google or Microsoft Authenticator app "
 "on your mobile phone."
 "on your mobile phone."
@@ -2884,11 +2978,19 @@ msgid_plural "Total %{total} items"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
+<<<<<<< HEAD
 #: src/views/preference/components/TOTP.vue:66
 #: src/views/preference/components/TOTP.vue:66
 msgid "TOTP"
 msgid "TOTP"
 msgstr ""
 msgstr ""
 
 
 #: src/views/preference/components/TOTP.vue:67
 #: src/views/preference/components/TOTP.vue:67
+=======
+#: src/views/preference/components/TOTP.vue:69
+msgid "TOTP"
+msgstr ""
+
+#: src/views/preference/components/TOTP.vue:70
+>>>>>>> remotes/origin/dev
 msgid ""
 msgid ""
 "TOTP is a two-factor authentication method that uses a time-based one-time "
 "TOTP is a two-factor authentication method that uses a time-based one-time "
 "password algorithm."
 "password algorithm."

+ 34 - 20
app/src/language/zh_CN/app.po

@@ -106,7 +106,7 @@ msgstr "然后,刷新此页面并再次点击添加 Passkey。"
 msgid "All"
 msgid "All"
 msgstr "全部"
 msgstr "全部"
 
 
-#: src/views/preference/OpenAISettings.vue:44
+#: src/views/preference/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "API 地址"
 msgstr "API 地址"
 
 
@@ -114,15 +114,15 @@ msgstr "API 地址"
 msgid "API Document"
 msgid "API Document"
 msgstr "API 文档"
 msgstr "API 文档"
 
 
-#: src/views/preference/OpenAISettings.vue:57
+#: src/views/preference/OpenAISettings.vue:46
 msgid "API Proxy"
 msgid "API Proxy"
 msgstr "API 代理"
 msgstr "API 代理"
 
 
-#: src/views/preference/OpenAISettings.vue:69
+#: src/views/preference/OpenAISettings.vue:58
 msgid "API Token"
 msgid "API Token"
 msgstr "API Token"
 msgstr "API Token"
 
 
-#: src/views/preference/OpenAISettings.vue:78
+#: src/views/preference/OpenAISettings.vue:67
 msgid "API Type"
 msgid "API Type"
 msgstr "API 类型"
 msgstr "API 类型"
 
 
@@ -216,7 +216,7 @@ msgstr "尝试次数"
 msgid "Auth"
 msgid "Auth"
 msgstr "认证"
 msgstr "认证"
 
 
-#: src/components/TwoFA/Authorization.vue:121
+#: src/components/TwoFA/Authorization.vue:109
 msgid "Authenticate with a passkey"
 msgid "Authenticate with a passkey"
 msgstr "通过 Passkey 认证"
 msgstr "通过 Passkey 认证"
 
 
@@ -596,6 +596,11 @@ msgstr "数据库 (可选,默认: database)"
 msgid "Days"
 msgid "Days"
 msgstr "天"
 msgstr "天"
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "描述"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -1191,7 +1196,7 @@ msgstr "初始化核心升级器"
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr "输入应用程序中的代码:"
 msgstr "输入应用程序中的代码:"
 
 
-#: src/components/TwoFA/Authorization.vue:82
+#: src/components/TwoFA/Authorization.vue:72
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr "输入恢复代码:"
 msgstr "输入恢复代码:"
 
 
@@ -1232,6 +1237,11 @@ msgstr "二次验证码或恢复代码无效"
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr "无效的恢复代码"
 msgstr "无效的恢复代码"
 
 
+#: src/constants/errors/middleware.ts:2
+#, fuzzy
+msgid "Invalid request format"
+msgstr "无效的恢复代码"
+
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
 msgid "IP"
 msgid "IP"
 msgstr "IP"
 msgstr "IP"
@@ -1280,7 +1290,7 @@ msgstr "上次使用"
 msgid "Leave blank for no change"
 msgid "Leave blank for no change"
 msgstr "留空表示不修改"
 msgstr "留空表示不修改"
 
 
-#: src/views/preference/OpenAISettings.vue:53
+#: src/views/preference/OpenAISettings.vue:41
 msgid "Leave blank for the default: https://api.openai.com/"
 msgid "Leave blank for the default: https://api.openai.com/"
 msgstr "留空为默认:https://api.openai.com/"
 msgstr "留空为默认:https://api.openai.com/"
 
 
@@ -1343,7 +1353,7 @@ msgstr "Locations"
 msgid "Log"
 msgid "Log"
 msgstr "日志"
 msgstr "日志"
 
 
-#: src/routes/index.ts:318 src/views/other/Login.vue:222
+#: src/routes/index.ts:318 src/views/other/Login.vue:223
 msgid "Login"
 msgid "Login"
 msgstr "登录"
 msgstr "登录"
 
 
@@ -1419,7 +1429,7 @@ msgstr "内存与存储"
 msgid "Minutes"
 msgid "Minutes"
 msgstr "分钟"
 msgstr "分钟"
 
 
-#: src/views/preference/OpenAISettings.vue:32
+#: src/views/preference/OpenAISettings.vue:20
 msgid "Model"
 msgid "Model"
 msgstr "模型"
 msgstr "模型"
 
 
@@ -1699,7 +1709,7 @@ msgstr "在线"
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
 
 
-#: src/components/TwoFA/Authorization.vue:112 src/views/other/Login.vue:231
+#: src/components/TwoFA/Authorization.vue:100 src/views/other/Login.vue:232
 msgid "Or"
 msgid "Or"
 msgstr "或"
 msgstr "或"
 
 
@@ -1802,7 +1812,7 @@ msgid ""
 "button below."
 "button below."
 msgstr "请为您要创建的 Passkey 输入一个名称,然后单击下面的 \"确定 \"按钮。"
 msgstr "请为您要创建的 Passkey 输入一个名称,然后单击下面的 \"确定 \"按钮。"
 
 
-#: src/components/TwoFA/Authorization.vue:70
+#: src/components/TwoFA/Authorization.vue:85
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "请输入 OTP:"
 msgstr "请输入 OTP:"
 
 
@@ -1941,7 +1951,7 @@ msgstr "恢复"
 msgid "Recovered Successfully"
 msgid "Recovered Successfully"
 msgstr "恢复成功"
 msgstr "恢复成功"
 
 
-#: src/components/TwoFA/Authorization.vue:89
+#: src/components/TwoFA/Authorization.vue:79
 msgid "Recovery"
 msgid "Recovery"
 msgstr "恢复"
 msgstr "恢复"
 
 
@@ -2110,6 +2120,10 @@ msgstr "证书续期成功"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "更新成功"
 msgstr "更新成功"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr "请求超时"
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "请求参数错误"
 msgstr "请求参数错误"
@@ -2288,7 +2302,7 @@ msgstr ""
 msgid "Show"
 msgid "Show"
 msgstr "显示"
 msgstr "显示"
 
 
-#: src/views/other/Login.vue:240
+#: src/views/other/Login.vue:241
 msgid "Sign in with a passkey"
 msgid "Sign in with a passkey"
 msgstr "使用 Passkey 登录"
 msgstr "使用 Passkey 登录"
 
 
@@ -2530,7 +2544,7 @@ msgid ""
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 msgstr "日志路径不在 settings.NginxSettings.LogDirWhiteList 中的路径之下"
 msgstr "日志路径不在 settings.NginxSettings.LogDirWhiteList 中的路径之下"
 
 
-#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:23
 msgid ""
 msgid ""
 "The model name should only contain letters, unicode, numbers, hyphens, "
 "The model name should only contain letters, unicode, numbers, hyphens, "
 "dashes, colons, and dots."
 "dashes, colons, and dots."
@@ -2576,8 +2590,8 @@ msgstr "当前配置中的 server_name 必须是获取证书所需的域名,
 msgid "The url is invalid"
 msgid "The url is invalid"
 msgstr "URL无效"
 msgstr "URL无效"
 
 
-#: src/views/preference/OpenAISettings.vue:47
-#: src/views/preference/OpenAISettings.vue:60
+#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:49
 msgid "The url is invalid."
 msgid "The url is invalid."
 msgstr "URL 无效."
 msgstr "URL 无效."
 
 
@@ -2675,7 +2689,7 @@ msgstr ""
 "为了确保认证自动更新能够正常工作,我们需要添加一个能够代理从权威机构到后端的"
 "为了确保认证自动更新能够正常工作,我们需要添加一个能够代理从权威机构到后端的"
 "请求的 Location,并且我们需要保存这个文件并重新加载Nginx。你确定要继续吗?"
 "请求的 Location,并且我们需要保存这个文件并重新加载Nginx。你确定要继续吗?"
 
 
-#: src/views/preference/OpenAISettings.vue:48
+#: src/views/preference/OpenAISettings.vue:36
 msgid ""
 msgid ""
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "provide an OpenAI-compatible API endpoint, so just set the baseUrl to your "
 "provide an OpenAI-compatible API endpoint, so just set the baseUrl to your "
@@ -2684,7 +2698,7 @@ msgstr ""
 "要使用本地大型模型,可使用 ollama、vllm 或 lmdeploy 进行部署。它们提供了与 "
 "要使用本地大型模型,可使用 ollama、vllm 或 lmdeploy 进行部署。它们提供了与 "
 "OpenAI 兼容的 API 端点,因此只需将 baseUrl 设置为本地 API 即可。"
 "OpenAI 兼容的 API 端点,因此只需将 baseUrl 设置为本地 API 即可。"
 
 
-#: src/views/preference/OpenAISettings.vue:72
+#: src/views/preference/OpenAISettings.vue:61
 msgid "Token is not valid"
 msgid "Token is not valid"
 msgstr "Token 无效"
 msgstr "Token 无效"
 
 
@@ -2765,11 +2779,11 @@ msgstr "运行时间:"
 msgid "URL"
 msgid "URL"
 msgstr "URL"
 msgstr "URL"
 
 
-#: src/components/TwoFA/Authorization.vue:102
+#: src/components/TwoFA/Authorization.vue:121
 msgid "Use OTP"
 msgid "Use OTP"
 msgstr "使用二步验证码"
 msgstr "使用二步验证码"
 
 
-#: src/components/TwoFA/Authorization.vue:98
+#: src/components/TwoFA/Authorization.vue:117
 msgid "Use recovery code"
 msgid "Use recovery code"
 msgstr "使用恢复代码"
 msgstr "使用恢复代码"
 
 

+ 61 - 57
app/src/language/zh_TW/app.po

@@ -2,25 +2,26 @@
 # Hintay Lin <hintay@me.com>, 2024.
 # Hintay Lin <hintay@me.com>, 2024.
 # Weblate <noreply-mt-weblate@weblate.org>, 2024.
 # Weblate <noreply-mt-weblate@weblate.org>, 2024.
 # "Xaver Y.R. Chen" <yrchen@atcity.org>, 2025.
 # "Xaver Y.R. Chen" <yrchen@atcity.org>, 2025.
+# 0xJacky <me@jackyu.cn>, 2025.
 msgid ""
 msgid ""
 msgstr ""
 msgstr ""
 "Project-Id-Version: \n"
 "Project-Id-Version: \n"
 "POT-Creation-Date: \n"
 "POT-Creation-Date: \n"
-"PO-Revision-Date: 2025-02-01 18:25+0000\n"
-"Last-Translator: \"Xaver Y.R. Chen\" <yrchen@atcity.org>\n"
-"Language-Team: Chinese (Traditional) <https://weblate.nginxui.com/projects/"
-"nginx-ui/frontend/zh_Hant/>\n"
+"PO-Revision-Date: 2025-02-08 18:25+0000\n"
+"Last-Translator: 0xJacky <me@jackyu.cn>\n"
+"Language-Team: Chinese (Traditional Han script) <https://weblate.nginxui.com/"
+"projects/nginx-ui/frontend/zh_Hant/>\n"
 "Language: zh_TW\n"
 "Language: zh_TW\n"
 "MIME-Version: 1.0\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 5.6.2\n"
+"X-Generator: Weblate 5.9.2\n"
 "Generated-By: easygettext\n"
 "Generated-By: easygettext\n"
 
 
 #: src/views/user/userColumns.tsx:32
 #: src/views/user/userColumns.tsx:32
 msgid "2FA"
 msgid "2FA"
-msgstr "多重要素驗證"
+msgstr "雙因素驗證"
 
 
 #: src/views/preference/AuthSettings.vue:70
 #: src/views/preference/AuthSettings.vue:70
 msgid "2FA Settings"
 msgid "2FA Settings"
@@ -32,7 +33,7 @@ msgstr "關於"
 
 
 #: src/routes/index.ts:210 src/views/site/ngx_conf/LogEntry.vue:75
 #: src/routes/index.ts:210 src/views/site/ngx_conf/LogEntry.vue:75
 msgid "Access Logs"
 msgid "Access Logs"
-msgstr "存取日誌"
+msgstr "訪問日誌"
 
 
 #: src/routes/index.ts:148 src/views/certificate/ACMEUser.vue:113
 #: src/routes/index.ts:148 src/views/certificate/ACMEUser.vue:113
 #: src/views/certificate/ACMEUserSelector.vue:85
 #: src/views/certificate/ACMEUserSelector.vue:85
@@ -111,7 +112,7 @@ msgstr "然後,重新整理此頁面並再次點選新增通行密鑰。"
 msgid "All"
 msgid "All"
 msgstr "全部"
 msgstr "全部"
 
 
-#: src/views/preference/OpenAISettings.vue:44
+#: src/views/preference/OpenAISettings.vue:32
 msgid "API Base Url"
 msgid "API Base Url"
 msgstr "API 基礎網址"
 msgstr "API 基礎網址"
 
 
@@ -119,27 +120,25 @@ msgstr "API 基礎網址"
 msgid "API Document"
 msgid "API Document"
 msgstr "API 文件"
 msgstr "API 文件"
 
 
-#: src/views/preference/OpenAISettings.vue:57
+#: src/views/preference/OpenAISettings.vue:46
 msgid "API Proxy"
 msgid "API Proxy"
 msgstr "API 代理"
 msgstr "API 代理"
 
 
-#: src/views/preference/OpenAISettings.vue:69
+#: src/views/preference/OpenAISettings.vue:58
 msgid "API Token"
 msgid "API Token"
 msgstr "API Token"
 msgstr "API Token"
 
 
-#: src/views/preference/OpenAISettings.vue:78
-#, fuzzy
+#: src/views/preference/OpenAISettings.vue:67
 msgid "API Type"
 msgid "API Type"
-msgstr "API Token"
+msgstr "API 類型"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:103
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:103
 msgid "Apply"
 msgid "Apply"
 msgstr "套用"
 msgstr "套用"
 
 
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:67
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:67
-#, fuzzy
 msgid "Apply bulk action successfully"
 msgid "Apply bulk action successfully"
-msgstr "複製成功"
+msgstr "批量操作成功應用"
 
 
 #: src/views/system/Upgrade.vue:176
 #: src/views/system/Upgrade.vue:176
 msgid "Arch"
 msgid "Arch"
@@ -227,7 +226,7 @@ msgstr "嘗試次數"
 msgid "Auth"
 msgid "Auth"
 msgstr "身份驗證"
 msgstr "身份驗證"
 
 
-#: src/components/TwoFA/Authorization.vue:121
+#: src/components/TwoFA/Authorization.vue:109
 msgid "Authenticate with a passkey"
 msgid "Authenticate with a passkey"
 msgstr "使用通行密鑰認證"
 msgstr "使用通行密鑰認證"
 
 
@@ -522,7 +521,6 @@ msgid "Copy"
 msgstr "複製"
 msgstr "複製"
 
 
 #: src/views/preference/components/RecoveryCodes.vue:121
 #: src/views/preference/components/RecoveryCodes.vue:121
-#, fuzzy
 msgid "Copy Codes"
 msgid "Copy Codes"
 msgstr "恢復碼"
 msgstr "恢復碼"
 
 
@@ -615,6 +613,11 @@ msgstr "資料庫 (可選,預設: database)"
 msgid "Days"
 msgid "Days"
 msgstr "天"
 msgstr "天"
 
 
+#: src/constants/errors/middleware.ts:3
+#, fuzzy
+msgid "Decryption failed"
+msgstr "描述"
+
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdBulkActions.vue:21
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/components/StdDesign/StdDataDisplay/StdTable.vue:519
 #: src/views/site/ngx_conf/NgxServer.vue:110
 #: src/views/site/ngx_conf/NgxServer.vue:110
@@ -691,9 +694,8 @@ msgid "Directive"
 msgstr "指令"
 msgstr "指令"
 
 
 #: src/constants/errors/nginx_log.ts:6
 #: src/constants/errors/nginx_log.ts:6
-#, fuzzy
 msgid "Directive params is empty"
 msgid "Directive params is empty"
-msgstr "檔名空白"
+msgstr ""
 
 
 #: src/constants/errors/nginx_log.ts:5
 #: src/constants/errors/nginx_log.ts:5
 msgid "Directive.Params neither access_log nor error_log"
 msgid "Directive.Params neither access_log nor error_log"
@@ -1049,9 +1051,8 @@ msgid "Failed to get certificate information"
 msgstr "取得憑證資訊失敗"
 msgstr "取得憑證資訊失敗"
 
 
 #: src/constants/errors/self_check.ts:4
 #: src/constants/errors/self_check.ts:4
-#, fuzzy
 msgid "Failed to parse nginx.conf"
 msgid "Failed to parse nginx.conf"
-msgstr "讀取 nginx.conf 失敗"
+msgstr ""
 
 
 #: src/constants/errors/self_check.ts:3
 #: src/constants/errors/self_check.ts:3
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
@@ -1228,7 +1229,7 @@ msgstr "正在初始化核心升級程式"
 msgid "Input the code from the app:"
 msgid "Input the code from the app:"
 msgstr "請輸入應用程式中的代碼:"
 msgstr "請輸入應用程式中的代碼:"
 
 
-#: src/components/TwoFA/Authorization.vue:82
+#: src/components/TwoFA/Authorization.vue:72
 msgid "Input the recovery code:"
 msgid "Input the recovery code:"
 msgstr "輸入恢復碼:"
 msgstr "輸入恢復碼:"
 
 
@@ -1271,6 +1272,11 @@ msgstr "無效的密碼或恢復碼"
 msgid "Invalid recovery code"
 msgid "Invalid recovery code"
 msgstr "無效的多重因素驗證或恢復碼"
 msgstr "無效的多重因素驗證或恢復碼"
 
 
+#: src/constants/errors/middleware.ts:2
+#, fuzzy
+msgid "Invalid request format"
+msgstr "無效的多重因素驗證或恢復碼"
+
 #: src/views/preference/AuthSettings.vue:18
 #: src/views/preference/AuthSettings.vue:18
 msgid "IP"
 msgid "IP"
 msgstr "IP"
 msgstr "IP"
@@ -1319,7 +1325,7 @@ msgstr "上次檢查時間"
 msgid "Leave blank for no change"
 msgid "Leave blank for no change"
 msgstr "留空表示不修改"
 msgstr "留空表示不修改"
 
 
-#: src/views/preference/OpenAISettings.vue:53
+#: src/views/preference/OpenAISettings.vue:41
 msgid "Leave blank for the default: https://api.openai.com/"
 msgid "Leave blank for the default: https://api.openai.com/"
 msgstr "預設留空:https://api.openai.com/"
 msgstr "預設留空:https://api.openai.com/"
 
 
@@ -1384,7 +1390,7 @@ msgstr "Locations"
 msgid "Log"
 msgid "Log"
 msgstr "日誌"
 msgstr "日誌"
 
 
-#: src/routes/index.ts:318 src/views/other/Login.vue:222
+#: src/routes/index.ts:318 src/views/other/Login.vue:223
 msgid "Login"
 msgid "Login"
 msgstr "登入"
 msgstr "登入"
 
 
@@ -1459,7 +1465,7 @@ msgstr "記憶體與儲存"
 msgid "Minutes"
 msgid "Minutes"
 msgstr "分鐘"
 msgstr "分鐘"
 
 
-#: src/views/preference/OpenAISettings.vue:32
+#: src/views/preference/OpenAISettings.vue:20
 msgid "Model"
 msgid "Model"
 msgstr "模型"
 msgstr "模型"
 
 
@@ -1598,9 +1604,8 @@ msgid "Nginx Log"
 msgstr "Nginx 日誌"
 msgstr "Nginx 日誌"
 
 
 #: src/views/preference/NginxSettings.vue:18
 #: src/views/preference/NginxSettings.vue:18
-#, fuzzy
 msgid "Nginx Log Directory Whitelist"
 msgid "Nginx Log Directory Whitelist"
-msgstr "Nginx 設定解析錯誤"
+msgstr ""
 
 
 #: src/views/preference/NginxSettings.vue:27
 #: src/views/preference/NginxSettings.vue:27
 #, fuzzy
 #, fuzzy
@@ -1608,9 +1613,8 @@ msgid "Nginx PID Path"
 msgstr "Nginx 錯誤日誌路徑"
 msgstr "Nginx 錯誤日誌路徑"
 
 
 #: src/views/preference/NginxSettings.vue:30
 #: src/views/preference/NginxSettings.vue:30
-#, fuzzy
 msgid "Nginx Reload Command"
 msgid "Nginx Reload Command"
-msgstr "終端機啟動指令"
+msgstr ""
 
 
 #: src/components/NginxControl/NginxControl.vue:26
 #: src/components/NginxControl/NginxControl.vue:26
 msgid "Nginx reloaded successfully"
 msgid "Nginx reloaded successfully"
@@ -1745,7 +1749,7 @@ msgstr "線上"
 msgid "OpenAI"
 msgid "OpenAI"
 msgstr "OpenAI"
 msgstr "OpenAI"
 
 
-#: src/components/TwoFA/Authorization.vue:112 src/views/other/Login.vue:231
+#: src/components/TwoFA/Authorization.vue:100 src/views/other/Login.vue:232
 msgid "Or"
 msgid "Or"
 msgstr "或"
 msgstr "或"
 
 
@@ -1819,9 +1823,8 @@ msgid "Path"
 msgstr "路徑"
 msgstr "路徑"
 
 
 #: src/constants/errors/cert.ts:7 src/constants/errors/config.ts:2
 #: src/constants/errors/cert.ts:7 src/constants/errors/config.ts:2
-#, fuzzy
 msgid "Path: {0} is not under the nginx conf dir: {1}"
 msgid "Path: {0} is not under the nginx conf dir: {1}"
-msgstr "簽章路徑不在 Nginx 設定檔資料夾下"
+msgstr ""
 
 
 #: src/constants/errors/cert.ts:6
 #: src/constants/errors/cert.ts:6
 msgid "Payload resource is nil"
 msgid "Payload resource is nil"
@@ -1840,9 +1843,8 @@ msgid "Performing core upgrade"
 msgstr "正在執行核心升級"
 msgstr "正在執行核心升級"
 
 
 #: src/constants/errors/crypto.ts:2
 #: src/constants/errors/crypto.ts:2
-#, fuzzy
 msgid "Plain text is empty"
 msgid "Plain text is empty"
-msgstr "檔名空白"
+msgstr ""
 
 
 #: src/views/preference/components/AddPasskey.vue:69
 #: src/views/preference/components/AddPasskey.vue:69
 msgid ""
 msgid ""
@@ -1850,7 +1852,7 @@ msgid ""
 "button below."
 "button below."
 msgstr ""
 msgstr ""
 
 
-#: src/components/TwoFA/Authorization.vue:70
+#: src/components/TwoFA/Authorization.vue:85
 #, fuzzy
 #, fuzzy
 msgid "Please enter the OTP code:"
 msgid "Please enter the OTP code:"
 msgstr "請輸入多重因素驗證碼:"
 msgstr "請輸入多重因素驗證碼:"
@@ -1995,7 +1997,7 @@ msgstr "恢復"
 msgid "Recovered Successfully"
 msgid "Recovered Successfully"
 msgstr "恢復成功"
 msgstr "恢復成功"
 
 
-#: src/components/TwoFA/Authorization.vue:89
+#: src/components/TwoFA/Authorization.vue:79
 msgid "Recovery"
 msgid "Recovery"
 msgstr "恢復"
 msgstr "恢復"
 
 
@@ -2172,6 +2174,10 @@ msgstr "更新憑證成功"
 msgid "Renew successfully"
 msgid "Renew successfully"
 msgstr "更新成功"
 msgstr "更新成功"
 
 
+#: src/constants/errors/crypto.ts:4
+msgid "Request timeout"
+msgstr ""
+
 #: src/language/constants.ts:32
 #: src/language/constants.ts:32
 msgid "Requested with wrong parameters"
 msgid "Requested with wrong parameters"
 msgstr "請求參數錯誤"
 msgstr "請求參數錯誤"
@@ -2351,19 +2357,17 @@ msgstr ""
 msgid "Show"
 msgid "Show"
 msgstr "顯示"
 msgstr "顯示"
 
 
-#: src/views/other/Login.vue:240
-#, fuzzy
+#: src/views/other/Login.vue:241
 msgid "Sign in with a passkey"
 msgid "Sign in with a passkey"
-msgstr "使用通行密鑰認證"
+msgstr ""
 
 
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:65
 #: src/views/site/ngx_conf/directive/DirectiveAdd.vue:65
 msgid "Single Directive"
 msgid "Single Directive"
 msgstr "單一指令"
 msgstr "單一指令"
 
 
 #: src/routes/index.ts:71 src/views/site/site_category/SiteCategory.vue:10
 #: src/routes/index.ts:71 src/views/site/site_category/SiteCategory.vue:10
-#, fuzzy
 msgid "Site Categories"
 msgid "Site Categories"
-msgstr "類別"
+msgstr ""
 
 
 #: src/constants/errors/site.ts:4
 #: src/constants/errors/site.ts:4
 #, fuzzy
 #, fuzzy
@@ -2389,14 +2393,12 @@ msgid "Sites List"
 msgstr "網站列表"
 msgstr "網站列表"
 
 
 #: src/constants/errors/self_check.ts:10
 #: src/constants/errors/self_check.ts:10
-#, fuzzy
 msgid "Sites-available directory not exist"
 msgid "Sites-available directory not exist"
-msgstr "目錄"
+msgstr ""
 
 
 #: src/constants/errors/self_check.ts:11
 #: src/constants/errors/self_check.ts:11
-#, fuzzy
 msgid "Sites-enabled directory not exist"
 msgid "Sites-enabled directory not exist"
-msgstr "目錄"
+msgstr ""
 
 
 #: src/views/certificate/CertificateEditor.vue:211
 #: src/views/certificate/CertificateEditor.vue:211
 msgid "SSL Certificate Content"
 msgid "SSL Certificate Content"
@@ -2446,9 +2448,8 @@ msgid "Streams Directory"
 msgstr "目錄"
 msgstr "目錄"
 
 
 #: src/constants/errors/self_check.ts:12
 #: src/constants/errors/self_check.ts:12
-#, fuzzy
 msgid "Streams-available directory not exist"
 msgid "Streams-available directory not exist"
-msgstr "目錄"
+msgstr ""
 
 
 #: src/constants/errors/self_check.ts:13
 #: src/constants/errors/self_check.ts:13
 #, fuzzy
 #, fuzzy
@@ -2604,7 +2605,7 @@ msgid ""
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 "The log path is not under the paths in settings.NginxSettings.LogDirWhiteList"
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:23
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 "The model name should only contain letters, unicode, numbers, hyphens, "
 "The model name should only contain letters, unicode, numbers, hyphens, "
@@ -2653,8 +2654,8 @@ msgstr "當前配置中的 server_name 必須是您需要獲取憑證的網域
 msgid "The url is invalid"
 msgid "The url is invalid"
 msgstr "網址無效"
 msgstr "網址無效"
 
 
-#: src/views/preference/OpenAISettings.vue:47
-#: src/views/preference/OpenAISettings.vue:60
+#: src/views/preference/OpenAISettings.vue:35
+#: src/views/preference/OpenAISettings.vue:49
 msgid "The url is invalid."
 msgid "The url is invalid."
 msgstr "網址無效。"
 msgstr "網址無效。"
 
 
@@ -2751,14 +2752,14 @@ msgstr ""
 "為了確保憑證自動續期能夠正常運作,我們需要新增一個 Location 來代理從授權後端"
 "為了確保憑證自動續期能夠正常運作,我們需要新增一個 Location 來代理從授權後端"
 "的請求,我們需要儲存這個檔案並重新載入 Nginx。你確定你要繼續嗎?"
 "的請求,我們需要儲存這個檔案並重新載入 Nginx。你確定你要繼續嗎?"
 
 
-#: src/views/preference/OpenAISettings.vue:48
+#: src/views/preference/OpenAISettings.vue:36
 msgid ""
 msgid ""
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "To use a local large model, deploy it with ollama, vllm or lmdeploy. They "
 "provide an OpenAI-compatible API endpoint, so just set the baseUrl to your "
 "provide an OpenAI-compatible API endpoint, so just set the baseUrl to your "
 "local API."
 "local API."
 msgstr ""
 msgstr ""
 
 
-#: src/views/preference/OpenAISettings.vue:72
+#: src/views/preference/OpenAISettings.vue:61
 msgid "Token is not valid"
 msgid "Token is not valid"
 msgstr "令牌無效"
 msgstr "令牌無效"
 
 
@@ -2840,11 +2841,11 @@ msgstr "運作時間:"
 msgid "URL"
 msgid "URL"
 msgstr "URL"
 msgstr "URL"
 
 
-#: src/components/TwoFA/Authorization.vue:102
+#: src/components/TwoFA/Authorization.vue:121
 msgid "Use OTP"
 msgid "Use OTP"
 msgstr "使用一次性密碼"
 msgstr "使用一次性密碼"
 
 
-#: src/components/TwoFA/Authorization.vue:98
+#: src/components/TwoFA/Authorization.vue:117
 msgid "Use recovery code"
 msgid "Use recovery code"
 msgstr "使用恢復碼"
 msgstr "使用恢復碼"
 
 
@@ -2994,8 +2995,9 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/preference/components/RecoveryCodes.vue:94
 #: src/views/preference/components/RecoveryCodes.vue:94
+#, fuzzy
 msgid "You have not generated recovery codes yet."
 msgid "You have not generated recovery codes yet."
-msgstr ""
+msgstr "您確定要恢復此項目嗎?"
 
 
 #: src/views/preference/components/RecoveryCodes.vue:91
 #: src/views/preference/components/RecoveryCodes.vue:91
 msgid ""
 msgid ""
@@ -3009,9 +3011,8 @@ msgid "Your old codes won't work anymore."
 msgstr ""
 msgstr ""
 
 
 #: src/views/preference/components/Passkey.vue:75
 #: src/views/preference/components/Passkey.vue:75
-#, fuzzy
 msgid "Your passkeys"
 msgid "Your passkeys"
-msgstr "新增通行密鑰"
+msgstr ""
 
 
 #~ msgid ""
 #~ msgid ""
 #~ "If you lose your mobile phone, you can use the recovery code to reset "
 #~ "If you lose your mobile phone, you can use the recovery code to reset "
@@ -3164,6 +3165,9 @@ msgstr "新增通行密鑰"
 #~ msgid "404 Not Found"
 #~ msgid "404 Not Found"
 #~ msgstr "404 未找到頁面"
 #~ msgstr "404 未找到頁面"
 
 
+#~ msgid "Are you sure you want to restore?"
+#~ msgstr "您確定要恢復?"
+
 #~ msgid "Destroy"
 #~ msgid "Destroy"
 #~ msgstr "刪除"
 #~ msgstr "刪除"
 
 

+ 48 - 42
app/src/lib/http/index.ts

@@ -5,6 +5,7 @@ import { useSettingsStore, useUserStore } from '@/pinia'
 import router from '@/routes'
 import router from '@/routes'
 import { message } from 'ant-design-vue'
 import { message } from 'ant-design-vue'
 import axios from 'axios'
 import axios from 'axios'
+import JSEncrypt from 'jsencrypt'
 import { storeToRefs } from 'pinia'
 import { storeToRefs } from 'pinia'
 import 'nprogress/nprogress.css'
 import 'nprogress/nprogress.css'
 
 
@@ -33,16 +34,35 @@ const instance = axios.create({
   baseURL: import.meta.env.VITE_API_ROOT,
   baseURL: import.meta.env.VITE_API_ROOT,
   timeout: 50000,
   timeout: 50000,
   headers: { 'Content-Type': 'application/json' },
   headers: { 'Content-Type': 'application/json' },
-  transformRequest: [function (data, headers) {
-    if (!(headers) || headers['Content-Type'] === 'multipart/form-data;charset=UTF-8')
-      return data
-    else
-      headers['Content-Type'] = 'application/json'
-
-    return JSON.stringify(data)
-  }],
 })
 })
 
 
+const http = {
+  get(url: string, config: AxiosRequestConfig = {}) {
+    // eslint-disable-next-line ts/no-explicit-any
+    return instance.get<any, any>(url, config)
+  },
+  // eslint-disable-next-line ts/no-explicit-any
+  post(url: string, data: any = undefined, config: AxiosRequestConfig = {}) {
+    // eslint-disable-next-line ts/no-explicit-any
+    return instance.post<any, any>(url, data, config)
+  },
+  // eslint-disable-next-line ts/no-explicit-any
+  put(url: string, data: any = undefined, config: AxiosRequestConfig = {}) {
+    // eslint-disable-next-line ts/no-explicit-any
+    return instance.put<any, any>(url, data, config)
+  },
+  delete(url: string, config: AxiosRequestConfig = {}) {
+    // eslint-disable-next-line ts/no-explicit-any
+    return instance.delete<any, any>(url, config)
+  },
+  patch(url: string, config: AxiosRequestConfig = {}) {
+    // eslint-disable-next-line ts/no-explicit-any
+    return instance.patch<any, any>(url, config)
+  },
+}
+
+export default http
+
 const nprogress = useNProgress()
 const nprogress = useNProgress()
 
 
 // Add new dedupe utility at the top
 // Add new dedupe utility at the top
@@ -65,23 +85,36 @@ function useMessageDedupe(interval = 5000): MessageDedupe {
 }
 }
 
 
 instance.interceptors.request.use(
 instance.interceptors.request.use(
-  config => {
+  async config => {
     nprogress.start()
     nprogress.start()
     if (token.value) {
     if (token.value) {
-      // eslint-disable-next-line ts/no-explicit-any
-      (config.headers as any).Authorization = token.value
+      config.headers.Authorization = token.value
     }
     }
 
 
     if (settings.environment.id) {
     if (settings.environment.id) {
-      // eslint-disable-next-line ts/no-explicit-any
-      (config.headers as any)['X-Node-ID'] = settings.environment.id
+      config.headers['X-Node-ID'] = settings.environment.id
     }
     }
 
 
     if (secureSessionId.value) {
     if (secureSessionId.value) {
-      // eslint-disable-next-line ts/no-explicit-any
-      (config.headers as any)['X-Secure-Session-ID'] = secureSessionId.value
+      config.headers['X-Secure-Session-ID'] = secureSessionId.value
     }
     }
 
 
+    if (config.headers?.['Content-Type'] !== 'multipart/form-data;charset=UTF-8') {
+      config.headers['Content-Type'] = 'application/json'
+
+      if (config.crypto) {
+        const cryptoParams = await http.get('/crypto/public_key')
+        const { public_key } = await cryptoParams
+
+        // Encrypt data with RSA public key
+        const encrypt = new JSEncrypt()
+        encrypt.setPublicKey(public_key)
+
+        config.data = JSON.stringify({
+          encrypted_params: encrypt.encrypt(JSON.stringify(config.data)),
+        })
+      }
+    }
     return config
     return config
   },
   },
   err => {
   err => {
@@ -154,30 +187,3 @@ instance.interceptors.response.use(
     return Promise.reject(error.response.data)
     return Promise.reject(error.response.data)
   },
   },
 )
 )
-
-const http = {
-  get(url: string, config: AxiosRequestConfig = {}) {
-    // eslint-disable-next-line ts/no-explicit-any
-    return instance.get<any, any>(url, config)
-  },
-  // eslint-disable-next-line ts/no-explicit-any
-  post(url: string, data: any = undefined, config: AxiosRequestConfig = {}) {
-    // eslint-disable-next-line ts/no-explicit-any
-    return instance.post<any, any>(url, data, config)
-  },
-  // eslint-disable-next-line ts/no-explicit-any
-  put(url: string, data: any = undefined, config: AxiosRequestConfig = {}) {
-    // eslint-disable-next-line ts/no-explicit-any
-    return instance.put<any, any>(url, data, config)
-  },
-  delete(url: string, config: AxiosRequestConfig = {}) {
-    // eslint-disable-next-line ts/no-explicit-any
-    return instance.delete<any, any>(url, config)
-  },
-  patch(url: string, config: AxiosRequestConfig = {}) {
-    // eslint-disable-next-line ts/no-explicit-any
-    return instance.patch<any, any>(url, config)
-  },
-}
-
-export default http

+ 1 - 1
app/src/version.json

@@ -1 +1 @@
-{"version":"2.0.0-rc.1","build_id":7,"total_build":381}
+{"version":"2.0.0-rc.1","build_id":8,"total_build":382}

+ 10 - 21
app/src/views/preference/OpenAISettings.vue

@@ -1,29 +1,17 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import type { Settings } from '@/api/settings'
 import type { Settings } from '@/api/settings'
+import { LLM_MODELS, LLM_PROVIDERS } from '@/constants/llm'
 
 
 const data: Settings = inject('data')!
 const data: Settings = inject('data')!
 const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>>
 const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>>
 
 
-const models = shallowRef([
-  {
-    value: 'gpt-4o-mini',
-  },
-  {
-    value: 'gpt-4o',
-  },
-  {
-    value: 'gpt-4-1106-preview',
-  },
-  {
-    value: 'gpt-4',
-  },
-  {
-    value: 'gpt-4-32k',
-  },
-  {
-    value: 'gpt-3.5-turbo',
-  },
-])
+const models = LLM_MODELS.map(model => ({
+  value: model,
+}))
+
+const providers = LLM_PROVIDERS.map(provider => ({
+  value: provider,
+}))
 </script>
 </script>
 
 
 <template>
 <template>
@@ -48,9 +36,10 @@ const models = shallowRef([
         : $gettext('To use a local large model, deploy it with ollama, vllm or lmdeploy. '
         : $gettext('To use a local large model, deploy it with ollama, vllm or lmdeploy. '
           + 'They provide an OpenAI-compatible API endpoint, so just set the baseUrl to your local API.')"
           + 'They provide an OpenAI-compatible API endpoint, so just set the baseUrl to your local API.')"
     >
     >
-      <AInput
+      <AAutoComplete
         v-model:value="data.openai.base_url"
         v-model:value="data.openai.base_url"
         :placeholder="$gettext('Leave blank for the default: https://api.openai.com/')"
         :placeholder="$gettext('Leave blank for the default: https://api.openai.com/')"
+        :options="providers"
       />
       />
     </AFormItem>
     </AFormItem>
     <AFormItem
     <AFormItem

+ 11 - 0
app/src/views/site/ngx_conf/config_template/ConfigTemplate.vue

@@ -149,4 +149,15 @@ provide('ngx_directives', ngx_directives)
   overflow-y: scroll;
   overflow-y: scroll;
   overflow-x: hidden;
   overflow-x: hidden;
 }
 }
+
+:deep(.ant-col) {
+  height: calc(100% - 16px);
+  .ant-list-item {
+    height: 100%;
+
+    .ant-card {
+      height: 100%;
+    }
+  }
+}
 </style>
 </style>

+ 7 - 0
app/src/vite-env.d.ts

@@ -27,3 +27,10 @@ declare module '@vue/runtime-core' {
     }, disableHtmlEscaping?: boolean) => string
     }, disableHtmlEscaping?: boolean) => string
   }
   }
 }
 }
+
+declare module 'axios' {
+  interface AxiosRequestConfig {
+    crypto?: boolean
+    skipErrHandling?: boolean
+  }
+}

+ 1 - 1
gen.sh

@@ -4,7 +4,7 @@ go run generate.go -config ../../app.ini
 popd || exit
 popd || exit
 
 
 # generate error definitions
 # generate error definitions
-go run cmd/errdef/generate.go . ts ./app/src/constants/errors
+go run cmd/errdef/generate.go -project . -type ts -output ./app/src/constants/errors -ignore-dirs .devcontainer,app,.github
 
 
 # parse nginx directive indexs
 # parse nginx directive indexs
 go run cmd/ngx_dir_index/ngx_dir_index.go ./internal/nginx/nginx_directives.json
 go run cmd/ngx_dir_index/ngx_dir_index.go ./internal/nginx/nginx_directives.json

+ 3 - 3
go.mod

@@ -35,7 +35,7 @@ require (
 	github.com/spf13/cast v1.7.1
 	github.com/spf13/cast v1.7.1
 	github.com/stretchr/testify v1.10.0
 	github.com/stretchr/testify v1.10.0
 	github.com/tufanbarisyildirim/gonginx v0.0.0-20250120210832-12a9c7ae0c8a
 	github.com/tufanbarisyildirim/gonginx v0.0.0-20250120210832-12a9c7ae0c8a
-	github.com/uozi-tech/cosy v1.14.3
+	github.com/uozi-tech/cosy v1.14.4
 	github.com/uozi-tech/cosy-driver-sqlite v0.2.1
 	github.com/uozi-tech/cosy-driver-sqlite v0.2.1
 	github.com/urfave/cli/v3 v3.0.0-beta1
 	github.com/urfave/cli/v3 v3.0.0-beta1
 	golang.org/x/crypto v0.32.0
 	golang.org/x/crypto v0.32.0
@@ -256,7 +256,7 @@ require (
 	go.uber.org/ratelimit v0.3.1 // indirect
 	go.uber.org/ratelimit v0.3.1 // indirect
 	go.uber.org/zap v1.27.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
 	golang.org/x/arch v0.14.0 // indirect
 	golang.org/x/arch v0.14.0 // indirect
-	golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c // indirect
+	golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 // indirect
 	golang.org/x/mod v0.23.0 // indirect
 	golang.org/x/mod v0.23.0 // indirect
 	golang.org/x/oauth2 v0.26.0 // indirect
 	golang.org/x/oauth2 v0.26.0 // indirect
 	golang.org/x/sync v0.11.0 // indirect
 	golang.org/x/sync v0.11.0 // indirect
@@ -269,7 +269,7 @@ require (
 	google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 // indirect
 	google.golang.org/grpc v1.70.0 // indirect
 	google.golang.org/grpc v1.70.0 // indirect
-	google.golang.org/protobuf v1.36.4 // indirect
+	google.golang.org/protobuf v1.36.5 // indirect
 	gopkg.in/fsnotify.v1 v1.4.7 // indirect
 	gopkg.in/fsnotify.v1 v1.4.7 // indirect
 	gopkg.in/guregu/null.v4 v4.0.0 // indirect
 	gopkg.in/guregu/null.v4 v4.0.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect

+ 6 - 60
go.sum

@@ -712,28 +712,16 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
 github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
 github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
 github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
 github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
 github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
 github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
-github.com/aws/aws-sdk-go-v2 v1.35.0 h1:jTPxEJyzjSuuz0wB+302hr8Eu9KUI+Zv8zlujMGJpVI=
-github.com/aws/aws-sdk-go-v2 v1.35.0/go.mod h1:JgstGg0JjWU1KpVJjD5H0y0yyAIpSdKEq556EI6yOOM=
 github.com/aws/aws-sdk-go-v2 v1.36.0 h1:b1wM5CcE65Ujwn565qcwgtOTT1aT4ADOHHgglKjG7fk=
 github.com/aws/aws-sdk-go-v2 v1.36.0 h1:b1wM5CcE65Ujwn565qcwgtOTT1aT4ADOHHgglKjG7fk=
 github.com/aws/aws-sdk-go-v2 v1.36.0/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM=
 github.com/aws/aws-sdk-go-v2 v1.36.0/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM=
-github.com/aws/aws-sdk-go-v2/config v1.29.3 h1:a5Ucjxe6iV+LHEBmYA9w40rT5aGxWybx/4l/O/fvJlE=
-github.com/aws/aws-sdk-go-v2/config v1.29.3/go.mod h1:pt9z1x12zDiDb4iFLrxoeAKLVCU/Gp9DL/5BnwlY77o=
 github.com/aws/aws-sdk-go-v2/config v1.29.5 h1:4lS2IB+wwkj5J43Tq/AwvnscBerBJtQQ6YS7puzCI1k=
 github.com/aws/aws-sdk-go-v2/config v1.29.5 h1:4lS2IB+wwkj5J43Tq/AwvnscBerBJtQQ6YS7puzCI1k=
 github.com/aws/aws-sdk-go-v2/config v1.29.5/go.mod h1:SNzldMlDVbN6nWxM7XsUiNXPSa1LWlqiXtvh/1PrJGg=
 github.com/aws/aws-sdk-go-v2/config v1.29.5/go.mod h1:SNzldMlDVbN6nWxM7XsUiNXPSa1LWlqiXtvh/1PrJGg=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.56 h1:JKMBreKudV+ozx6rZJLvEtiexv48aEdhdC7mXUw9MLs=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.56/go.mod h1:S3xRjIHD8HHFgMTz4L56q/7IldfNtGL9JjH/vP3U6DA=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.58 h1:/d7FUpAPU8Lf2KUdjniQvfNdlMID0Sd9pS23FJ3SS9Y=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.58 h1:/d7FUpAPU8Lf2KUdjniQvfNdlMID0Sd9pS23FJ3SS9Y=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.58/go.mod h1:aVYW33Ow10CyMQGFgC0ptMRIqJWvJ4nxZb0sUiuQT/A=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.58/go.mod h1:aVYW33Ow10CyMQGFgC0ptMRIqJWvJ4nxZb0sUiuQT/A=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.26 h1:XMBqBEuZLf8yxtH+mU/uUDyQbN4iD/xv9h6he2+lzhw=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.26/go.mod h1:d0+wQ/3CYGPuHEfBTPpQdfUX7gjk0/Lxs5Q6KzdEGY8=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27 h1:7lOW8NUwE9UZekS1DYoiPdVAqZ6A+LheHWb+mHbNOq8=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27 h1:7lOW8NUwE9UZekS1DYoiPdVAqZ6A+LheHWb+mHbNOq8=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27/go.mod h1:w1BASFIPOPUae7AgaH4SbjNbfdkxuggLyGfNFTn8ITY=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27/go.mod h1:w1BASFIPOPUae7AgaH4SbjNbfdkxuggLyGfNFTn8ITY=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.30 h1:+7AzSGNhHoY53di13lvztf9Dyd/9ofzoYGBllkWp3a0=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.30/go.mod h1:Jxd/FrCny99yURiQiMywgXvBhd7tmgdv6KdlUTNzMSo=
 github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31 h1:lWm9ucLSRFiI4dQQafLrEOmEDGry3Swrz0BIRdiHJqQ=
 github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31 h1:lWm9ucLSRFiI4dQQafLrEOmEDGry3Swrz0BIRdiHJqQ=
 github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31/go.mod h1:Huu6GG0YTfbPphQkDSo4dEGmQRTKb9k9G7RdtyQWxuI=
 github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31/go.mod h1:Huu6GG0YTfbPphQkDSo4dEGmQRTKb9k9G7RdtyQWxuI=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.30 h1:Ex06eY6I5rO7IX0HalGfa5nGjpBoOsS1Qm3xfjkuszs=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.30/go.mod h1:AvyEMA9QcX59kFhVizBpIBpEMThUTXssuJe+emBdcGM=
 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31 h1:ACxDklUKKXb48+eg5ROZXi1vDgfMyfIA/WyvqHcHI0o=
 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31 h1:ACxDklUKKXb48+eg5ROZXi1vDgfMyfIA/WyvqHcHI0o=
 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31/go.mod h1:yadnfsDwqXeVaohbGc/RaD287PuyRw2wugkh5ZL2J6k=
 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31/go.mod h1:yadnfsDwqXeVaohbGc/RaD287PuyRw2wugkh5ZL2J6k=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 h1:Pg9URiobXy85kgFev3og2CuOZ8JZUBENF+dcgWBaYNk=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 h1:Pg9URiobXy85kgFev3og2CuOZ8JZUBENF+dcgWBaYNk=
@@ -741,28 +729,16 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2/go.mod h1:FbtygfRFze9usAadmnGJN
 github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
 github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.11 h1:5JKQ2J3BBW4ovy6A/5Lwx9SpA6IzgH8jB3bquGZ1NUw=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.11/go.mod h1:VShCk7rfCzK/b9U1aSkzLwcOoaDlYna16482QqEavis=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 h1:O+8vD2rGjfihBewr5bT+QUfYUHIxCVgG61LHoT59shM=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 h1:O+8vD2rGjfihBewr5bT+QUfYUHIxCVgG61LHoT59shM=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12/go.mod h1:usVdWJaosa66NMvmCrr08NcWDBRv4E6+YFG2pUdw1Lk=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12/go.mod h1:usVdWJaosa66NMvmCrr08NcWDBRv4E6+YFG2pUdw1Lk=
-github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.13 h1:yukUijkcclShNo3QXry+udZDyDQOy8siCjqNfpRKuf8=
-github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.13/go.mod h1:Ka+a4bm2nmtvk+Ql1K2Bmr7MrJCs8qz4UDmaLQs1daY=
 github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.14 h1:GH3vnPsdH2sTkZRBPnAeMqwkJXdwPNrEh9nI+DEdD0o=
 github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.14 h1:GH3vnPsdH2sTkZRBPnAeMqwkJXdwPNrEh9nI+DEdD0o=
 github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.14/go.mod h1:fHFrxpH3kA2iK2NBg/jj3jxgVVfNS7WaKYC5axxr/PY=
 github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.14/go.mod h1:fHFrxpH3kA2iK2NBg/jj3jxgVVfNS7WaKYC5axxr/PY=
-github.com/aws/aws-sdk-go-v2/service/route53 v1.48.4 h1:qajhoD/ElVskbXAJfgljClGj7DGME0uoDGUMVjFTkNs=
-github.com/aws/aws-sdk-go-v2/service/route53 v1.48.4/go.mod h1:kDfNqSNtcqB8aNUJClykJ+xLILNoYAaUIo72A2uR73Y=
 github.com/aws/aws-sdk-go-v2/service/route53 v1.48.6 h1:O7L9iEodiF07vJoXShMrw2XyeAqZhLUIXqWEitCq6EE=
 github.com/aws/aws-sdk-go-v2/service/route53 v1.48.6 h1:O7L9iEodiF07vJoXShMrw2XyeAqZhLUIXqWEitCq6EE=
 github.com/aws/aws-sdk-go-v2/service/route53 v1.48.6/go.mod h1:E93uWfli9RToQzVA7+bYnynKOFcYOhNWqhY1hWSMZRc=
 github.com/aws/aws-sdk-go-v2/service/route53 v1.48.6/go.mod h1:E93uWfli9RToQzVA7+bYnynKOFcYOhNWqhY1hWSMZRc=
-github.com/aws/aws-sdk-go-v2/service/sso v1.24.13 h1:q4pOAKxypbFoUJzOpgo939bF50qb4DgYshiDfcsdN0M=
-github.com/aws/aws-sdk-go-v2/service/sso v1.24.13/go.mod h1:G/0PTg7+vQT42ictQGjJhixzTcVZtHFvrN/OeTXrRfQ=
 github.com/aws/aws-sdk-go-v2/service/sso v1.24.14 h1:c5WJ3iHz7rLIgArznb3JCSQT3uUMiz9DLZhIX+1G8ok=
 github.com/aws/aws-sdk-go-v2/service/sso v1.24.14 h1:c5WJ3iHz7rLIgArznb3JCSQT3uUMiz9DLZhIX+1G8ok=
 github.com/aws/aws-sdk-go-v2/service/sso v1.24.14/go.mod h1:+JJQTxB6N4niArC14YNtxcQtwEqzS3o9Z32n7q33Rfs=
 github.com/aws/aws-sdk-go-v2/service/sso v1.24.14/go.mod h1:+JJQTxB6N4niArC14YNtxcQtwEqzS3o9Z32n7q33Rfs=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.12 h1:4sGSGshSSfO1vrcXruPick3ioSf8nhhD6nuB2ni37P4=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.12/go.mod h1:NHpu/pLOelViA4qxkAFH10VLqh+XeLhZfXDaFyMVgSs=
 github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13 h1:f1L/JtUkVODD+k1+IiSJUUv8A++2qVr+Xvb3xWXETMU=
 github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13 h1:f1L/JtUkVODD+k1+IiSJUUv8A++2qVr+Xvb3xWXETMU=
 github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13/go.mod h1:tvqlFoja8/s0o+UruA1Nrezo/df0PzdunMDDurUfg6U=
 github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13/go.mod h1:tvqlFoja8/s0o+UruA1Nrezo/df0PzdunMDDurUfg6U=
-github.com/aws/aws-sdk-go-v2/service/sts v1.33.11 h1:RIXOjp7Dp4siCYJRwBHUcBdVgOWflSJGlq4ZhMI5Ta0=
-github.com/aws/aws-sdk-go-v2/service/sts v1.33.11/go.mod h1:ZR17k9bPKPR8u0IkyA6xVsjr56doNQ4ZB1fs7abYBfE=
 github.com/aws/aws-sdk-go-v2/service/sts v1.33.13 h1:3LXNnmtH3TURctC23hnC0p/39Q5gre3FI7BNOiDcVWc=
 github.com/aws/aws-sdk-go-v2/service/sts v1.33.13 h1:3LXNnmtH3TURctC23hnC0p/39Q5gre3FI7BNOiDcVWc=
 github.com/aws/aws-sdk-go-v2/service/sts v1.33.13/go.mod h1:7Yn+p66q/jt38qMoVfNvjbm3D89mGBnkwDcijgtih8w=
 github.com/aws/aws-sdk-go-v2/service/sts v1.33.13/go.mod h1:7Yn+p66q/jt38qMoVfNvjbm3D89mGBnkwDcijgtih8w=
 github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
 github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
@@ -1558,8 +1534,6 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
 github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
 github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
-github.com/oracle/oci-go-sdk/v65 v65.82.0 h1:42fSqE847E95ICfVPcKhRmzkvM6tucwbPdUMQydfWGc=
-github.com/oracle/oci-go-sdk/v65 v65.82.0/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0=
 github.com/oracle/oci-go-sdk/v65 v65.83.0 h1:KFI0oyyCTPmgevHF+QlN02Zdf23Jx1p1X+4KPyH14H8=
 github.com/oracle/oci-go-sdk/v65 v65.83.0 h1:KFI0oyyCTPmgevHF+QlN02Zdf23Jx1p1X+4KPyH14H8=
 github.com/oracle/oci-go-sdk/v65 v65.83.0/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0=
 github.com/oracle/oci-go-sdk/v65 v65.83.0/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0=
 github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI=
 github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI=
@@ -1678,8 +1652,6 @@ github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd
 github.com/sashabaranov/go-openai v1.36.1 h1:EVfRXwIlW2rUzpx6vR+aeIKCK/xylSrVYAx1TMTSX3g=
 github.com/sashabaranov/go-openai v1.36.1 h1:EVfRXwIlW2rUzpx6vR+aeIKCK/xylSrVYAx1TMTSX3g=
 github.com/sashabaranov/go-openai v1.36.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
 github.com/sashabaranov/go-openai v1.36.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
-github.com/scaleway/scaleway-sdk-go v1.0.0-beta.31 h1:Fj7jPyu9TQjqfXcLylINK5PANSzOWXIX4QtGmfp67AY=
-github.com/scaleway/scaleway-sdk-go v1.0.0-beta.31/go.mod h1:kzh+BSAvpoyHHdHBCDhmSWtBc1NbLMZ2lWHqnBoxFks=
 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32 h1:4+LP7qmsLSGbmc66m1s5dKRMBwztRppfxFKlYqYte/c=
 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32 h1:4+LP7qmsLSGbmc66m1s5dKRMBwztRppfxFKlYqYte/c=
 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32/go.mod h1:kzh+BSAvpoyHHdHBCDhmSWtBc1NbLMZ2lWHqnBoxFks=
 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32/go.mod h1:kzh+BSAvpoyHHdHBCDhmSWtBc1NbLMZ2lWHqnBoxFks=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@@ -1687,8 +1659,6 @@ github.com/selectel/domains-go v1.1.0 h1:futG50J43ALLKQAnZk9H9yOtLGnSUh7c5hSvuC5
 github.com/selectel/domains-go v1.1.0/go.mod h1:SugRKfq4sTpnOHquslCpzda72wV8u0cMBHx0C0l+bzA=
 github.com/selectel/domains-go v1.1.0/go.mod h1:SugRKfq4sTpnOHquslCpzda72wV8u0cMBHx0C0l+bzA=
 github.com/selectel/go-selvpcclient/v3 v3.2.1 h1:ny6WIAMiHzKxOgOEnwcWE79wIQij1AHHylzPA41MXCw=
 github.com/selectel/go-selvpcclient/v3 v3.2.1 h1:ny6WIAMiHzKxOgOEnwcWE79wIQij1AHHylzPA41MXCw=
 github.com/selectel/go-selvpcclient/v3 v3.2.1/go.mod h1:3EfSf8aEWyhspOGbvZ6mvnFg7JN5uckxNyBFPGWsXNQ=
 github.com/selectel/go-selvpcclient/v3 v3.2.1/go.mod h1:3EfSf8aEWyhspOGbvZ6mvnFg7JN5uckxNyBFPGWsXNQ=
-github.com/shirou/gopsutil/v4 v4.24.12 h1:qvePBOk20e0IKA1QXrIIU+jmk+zEiYVVx06WjBRlZo4=
-github.com/shirou/gopsutil/v4 v4.24.12/go.mod h1:DCtMPAad2XceTeIAbGyVfycbYQNBGk2P8cvDi7/VN9o=
 github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs=
 github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs=
 github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI=
 github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI=
 github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
 github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
@@ -1780,12 +1750,8 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
 github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
-github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1090 h1:0fZ+FZE7ZvqxGdYbtQW8OyPXGD1qGPmg4wT+Tjkv+1s=
-github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1090/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1091 h1:RxogX8ZCPBmZ6PY7DjnWnwGRkAkYEEinT5WNNxbLVeo=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1091 h1:RxogX8ZCPBmZ6PY7DjnWnwGRkAkYEEinT5WNNxbLVeo=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1091/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1091/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
-github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1090 h1:8AXFluT9RV4EeWC7kfJUWjnFQlIJ4pBVC/+Qtqgg0hM=
-github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1090/go.mod h1:/XMAs17Sih+pqp/Pxy0WpmdZE/CychzXEnW/tTrCujk=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1091 h1:36WwNgrtoGKszQovUj3+0CjNsM1gMQ3a5lvZx2bkjng=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1091 h1:36WwNgrtoGKszQovUj3+0CjNsM1gMQ3a5lvZx2bkjng=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1091/go.mod h1:cWRGvOUnMQMky4oliMX1dXT6Z4CbsSGOIxaUcrD5Zvw=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1091/go.mod h1:cWRGvOUnMQMky4oliMX1dXT6Z4CbsSGOIxaUcrD5Zvw=
 github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
 github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
@@ -1812,12 +1778,12 @@ github.com/ultradns/ultradns-go-sdk v1.8.0-20241010134910-243eeec h1:2s/ghQ8wKE+
 github.com/ultradns/ultradns-go-sdk v1.8.0-20241010134910-243eeec/go.mod h1:BZr7Qs3ku1ckpqed8tCRSqTlp8NAeZfAVpfx4OzXMss=
 github.com/ultradns/ultradns-go-sdk v1.8.0-20241010134910-243eeec/go.mod h1:BZr7Qs3ku1ckpqed8tCRSqTlp8NAeZfAVpfx4OzXMss=
 github.com/uozi-tech/cosy v1.14.3 h1:YDleGHghw5Dtd8H7Fy0Iq0caXfxmhk7Zt6tJBONjq5Q=
 github.com/uozi-tech/cosy v1.14.3 h1:YDleGHghw5Dtd8H7Fy0Iq0caXfxmhk7Zt6tJBONjq5Q=
 github.com/uozi-tech/cosy v1.14.3/go.mod h1:DSKLtoVaGLUlJ8KiQ1vWEsnv85epRrAAMXSijuq+asM=
 github.com/uozi-tech/cosy v1.14.3/go.mod h1:DSKLtoVaGLUlJ8KiQ1vWEsnv85epRrAAMXSijuq+asM=
+github.com/uozi-tech/cosy v1.14.4 h1:9X9CzxYjTg9DRQKgBjYvDNOAYYFclOXYYq518nO4vr0=
+github.com/uozi-tech/cosy v1.14.4/go.mod h1:DSKLtoVaGLUlJ8KiQ1vWEsnv85epRrAAMXSijuq+asM=
 github.com/uozi-tech/cosy-driver-mysql v0.2.2 h1:22S/XNIvuaKGqxQPsYPXN8TZ8hHjCQdcJKVQ83Vzxoo=
 github.com/uozi-tech/cosy-driver-mysql v0.2.2 h1:22S/XNIvuaKGqxQPsYPXN8TZ8hHjCQdcJKVQ83Vzxoo=
 github.com/uozi-tech/cosy-driver-mysql v0.2.2/go.mod h1:EZnRIbSj1V5U0gEeTobrXai/d1SV11lkl4zP9NFEmyE=
 github.com/uozi-tech/cosy-driver-mysql v0.2.2/go.mod h1:EZnRIbSj1V5U0gEeTobrXai/d1SV11lkl4zP9NFEmyE=
 github.com/uozi-tech/cosy-driver-postgres v0.2.1 h1:OICakGuT+omva6QOJCxTJ5Lfr7CGXLmk/zD+aS51Z2o=
 github.com/uozi-tech/cosy-driver-postgres v0.2.1 h1:OICakGuT+omva6QOJCxTJ5Lfr7CGXLmk/zD+aS51Z2o=
 github.com/uozi-tech/cosy-driver-postgres v0.2.1/go.mod h1:eAy1A89yHbAEfjkhNAifaJQk172NqrNoRyRtFcZc9Go=
 github.com/uozi-tech/cosy-driver-postgres v0.2.1/go.mod h1:eAy1A89yHbAEfjkhNAifaJQk172NqrNoRyRtFcZc9Go=
-github.com/uozi-tech/cosy-driver-sqlite v0.2.0 h1:eTpIMyGoFUK4JcaiKfJHD5AyiM6vtCwN98c7Bz5n25o=
-github.com/uozi-tech/cosy-driver-sqlite v0.2.0/go.mod h1:87a6mzn5IuEtIR4z7U4Ey8eKLGfNEOSkv7kPQlbNQgM=
 github.com/uozi-tech/cosy-driver-sqlite v0.2.1 h1:W+Z4pY25PSJCeReqroG7LIBeffsqotbpHzgqSMqZDIM=
 github.com/uozi-tech/cosy-driver-sqlite v0.2.1 h1:W+Z4pY25PSJCeReqroG7LIBeffsqotbpHzgqSMqZDIM=
 github.com/uozi-tech/cosy-driver-sqlite v0.2.1/go.mod h1:2ya7Z5P3HzFi1ktfL8gvwaAGx0DDV0bmWxNSNpaLlwo=
 github.com/uozi-tech/cosy-driver-sqlite v0.2.1/go.mod h1:2ya7Z5P3HzFi1ktfL8gvwaAGx0DDV0bmWxNSNpaLlwo=
 github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
 github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
@@ -1840,12 +1806,8 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2
 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
-github.com/yandex-cloud/go-genproto v0.0.0-20250127124313-5be1a2cc06d4 h1:3N8k0k2YikzqQUUAFqPhbhiLEodQrRKIvlsUuJ09DYo=
-github.com/yandex-cloud/go-genproto v0.0.0-20250127124313-5be1a2cc06d4/go.mod h1:0LDD/IZLIUIV4iPH+YcF+jysO3jkSvADFGm4dCAuwQo=
 github.com/yandex-cloud/go-genproto v0.0.0-20250203115010-0bcba64c41f6 h1:CHYGew+KO1JaK5sx/N2ApgVCTGCKvfSl0sSPplTyCog=
 github.com/yandex-cloud/go-genproto v0.0.0-20250203115010-0bcba64c41f6 h1:CHYGew+KO1JaK5sx/N2ApgVCTGCKvfSl0sSPplTyCog=
 github.com/yandex-cloud/go-genproto v0.0.0-20250203115010-0bcba64c41f6/go.mod h1:0LDD/IZLIUIV4iPH+YcF+jysO3jkSvADFGm4dCAuwQo=
 github.com/yandex-cloud/go-genproto v0.0.0-20250203115010-0bcba64c41f6/go.mod h1:0LDD/IZLIUIV4iPH+YcF+jysO3jkSvADFGm4dCAuwQo=
-github.com/yandex-cloud/go-sdk v0.0.0-20250127132311-016f84adc072 h1:s2wfllm5Z32Sl1TktCxHXMKJ9yQXpdFUuN5CFA/8qJY=
-github.com/yandex-cloud/go-sdk v0.0.0-20250127132311-016f84adc072/go.mod h1:/7UdvQNU5/ISIOPHcj0S4lUcp/KejW2LJQhZGt9tdMU=
 github.com/yandex-cloud/go-sdk v0.0.0-20250203123950-24786ecffd92 h1:UTcY1921ZXBABB5JpSWxccyZaCjMuSbniyifW6nmLZ4=
 github.com/yandex-cloud/go-sdk v0.0.0-20250203123950-24786ecffd92 h1:UTcY1921ZXBABB5JpSWxccyZaCjMuSbniyifW6nmLZ4=
 github.com/yandex-cloud/go-sdk v0.0.0-20250203123950-24786ecffd92/go.mod h1:MQm5WxsYpQRdUklz2C8q3uDhuIaDzzV7seLErAILLBE=
 github.com/yandex-cloud/go-sdk v0.0.0-20250203123950-24786ecffd92/go.mod h1:MQm5WxsYpQRdUklz2C8q3uDhuIaDzzV7seLErAILLBE=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
@@ -1931,8 +1893,6 @@ go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
 go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
 go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
 go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
 go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
 go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
-golang.org/x/arch v0.13.0 h1:KCkqVVV1kGg0X87TFysjCJ8MxtZEIU4Ja/yXGeoECdA=
-golang.org/x/arch v0.13.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
 golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4=
 golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4=
 golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
 golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -1991,6 +1951,8 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk
 golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
 golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
 golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c h1:KL/ZBHXgKGVmuZBZ01Lt57yE5ws8ZPSkkihmEyq7FXc=
 golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c h1:KL/ZBHXgKGVmuZBZ01Lt57yE5ws8ZPSkkihmEyq7FXc=
 golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
 golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
+golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 h1:qNgPs5exUA+G0C96DrPwNrvLSj7GT/9D+3WMWUcUg34=
+golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
 golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
 golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -2033,8 +1995,6 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
-golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
 golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
 golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
 golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
 golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -2147,8 +2107,6 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec
 golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
 golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
 golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
 golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
 golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
 golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
-golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
-golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
 golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
 golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -2167,8 +2125,6 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
-golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
 golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
 golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -2293,8 +2249,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
-golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
 golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
 golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@@ -2335,8 +2289,6 @@ golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
-golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
 golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
 golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
 golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2347,8 +2299,6 @@ golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxb
 golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
-golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
 golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
 golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -2645,16 +2595,10 @@ google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOl
 google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
 google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
 google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
 google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
 google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
 google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
-google.golang.org/genproto v0.0.0-20250127172529-29210b9bc287 h1:WoUI1G0DQ648FKvSl756SKxHQR/bI+y4HyyIQfxMWI8=
-google.golang.org/genproto v0.0.0-20250127172529-29210b9bc287/go.mod h1:wkQ2Aj/xvshAUDtO/JHvu9y+AaN9cqs28QuSVSHtZSY=
 google.golang.org/genproto v0.0.0-20250204164813-702378808489 h1:nQcbCCOg2h2CQ0yA8SY3AHqriNKDvsetuq9mE/HFjtc=
 google.golang.org/genproto v0.0.0-20250204164813-702378808489 h1:nQcbCCOg2h2CQ0yA8SY3AHqriNKDvsetuq9mE/HFjtc=
 google.golang.org/genproto v0.0.0-20250204164813-702378808489/go.mod h1:wkQ2Aj/xvshAUDtO/JHvu9y+AaN9cqs28QuSVSHtZSY=
 google.golang.org/genproto v0.0.0-20250204164813-702378808489/go.mod h1:wkQ2Aj/xvshAUDtO/JHvu9y+AaN9cqs28QuSVSHtZSY=
-google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287 h1:A2ni10G3UlplFrWdCDJTl7D7mJ7GSRm37S+PDimaKRw=
-google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
 google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o=
 google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o=
 google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
 google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287 h1:J1H9f+LEdWAfHcez/4cvaVBox7cOYT+IU6rgqj5x++8=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 h1:5bKytslY8ViY0Cj/ewmRtrWHW64bNF03cAatUUFCdFI=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 h1:5bKytslY8ViY0Cj/ewmRtrWHW64bNF03cAatUUFCdFI=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -2721,6 +2665,8 @@ google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
 google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
 google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
 google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

+ 102 - 0
internal/crypto/crypto.go

@@ -0,0 +1,102 @@
+package crypto
+
+import (
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/base64"
+	"encoding/json"
+	"encoding/pem"
+	"fmt"
+	"time"
+
+	"github.com/0xJacky/Nginx-UI/internal/cache"
+	"github.com/uozi-tech/cosy/logger"
+)
+
+const (
+	CacheKey = "crypto"
+	timeout  = 10 * time.Minute
+)
+
+type Params struct {
+	PrivateKey string `json:"-"`
+	PublicKey  string `json:"public_key"`
+}
+
+// GenerateRSAKeyPair generates a new RSA key pair
+func GenerateRSAKeyPair() (privateKeyPEM, publicKeyPEM []byte, err error) {
+	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		return nil, nil, err
+	}
+	privateKeyPEM = pem.EncodeToMemory(&pem.Block{
+		Type:  "RSA PRIVATE KEY",
+		Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
+	})
+	publicKeyPEM = pem.EncodeToMemory(&pem.Block{
+		Type:  "RSA PUBLIC KEY",
+		Bytes: x509.MarshalPKCS1PublicKey(&privateKey.PublicKey),
+	})
+	return
+}
+
+// GetCryptoParams registers a new key pair in the cache if it doesn't exist
+// otherwise, it returns the existing nonce and public key
+func GetCryptoParams() (params *Params, err error) {
+	// Check if the key pair exists in then cache
+	if value, ok := cache.Get(CacheKey); ok {
+		return value.(*Params), nil
+	}
+	// Generate a nonce = hash(publicKey)
+	privateKeyPEM, publicKeyPEM, err := GenerateRSAKeyPair()
+	if err != nil {
+		return nil, err
+	}
+	params = &Params{
+		PrivateKey: string(privateKeyPEM),
+		PublicKey:  string(publicKeyPEM),
+	}
+	cache.Set(CacheKey, params, timeout)
+	return
+}
+
+// Decrypt decrypts the data with the private key (nonce, paramEncrypted)
+func Decrypt(paramEncrypted string) (data map[string]interface{}, err error) {
+	// Get crypto params from cache
+	value, ok := cache.Get(CacheKey)
+	if !ok {
+		return nil, ErrTimeout
+	}
+
+	params := value.(*Params)
+	block, _ := pem.Decode([]byte(params.PrivateKey))
+	if block == nil {
+		return nil, fmt.Errorf("failed to decode PEM block containing private key")
+	}
+
+	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+	if err != nil {
+		logger.Errorf("failed to parse private key: %v", err)
+		return nil, err
+	}
+
+	paramEncryptedDecoded, err := base64.StdEncoding.DecodeString(paramEncrypted)
+	if err != nil {
+		logger.Errorf("base64 decode error: %v", err)
+		return nil, err
+	}
+
+	decrypted, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, paramEncryptedDecoded)
+	if err != nil {
+		logger.Errorf("decryption failed: %v", err)
+		return nil, err
+	}
+
+	err = json.Unmarshal(decrypted, &data)
+	if err != nil {
+		return nil, err
+	}
+
+	return
+}

+ 1 - 0
internal/crypto/errors.go

@@ -6,4 +6,5 @@ var (
 	e                     = cosy.NewErrorScope("crypto")
 	e                     = cosy.NewErrorScope("crypto")
 	ErrPlainTextEmpty     = e.New(50001, "plain text is empty")
 	ErrPlainTextEmpty     = e.New(50001, "plain text is empty")
 	ErrCipherTextTooShort = e.New(50002, "cipher text is too short")
 	ErrCipherTextTooShort = e.New(50002, "cipher text is too short")
+	ErrTimeout            = e.New(40401, "request timeout")
 )
 )

+ 9 - 6
internal/kernel/boot.go

@@ -3,6 +3,10 @@ package kernel
 import (
 import (
 	"crypto/rand"
 	"crypto/rand"
 	"encoding/hex"
 	"encoding/hex"
+	"mime"
+	"path"
+	"runtime"
+
 	"github.com/0xJacky/Nginx-UI/internal/analytic"
 	"github.com/0xJacky/Nginx-UI/internal/analytic"
 	"github.com/0xJacky/Nginx-UI/internal/cache"
 	"github.com/0xJacky/Nginx-UI/internal/cache"
 	"github.com/0xJacky/Nginx-UI/internal/cert"
 	"github.com/0xJacky/Nginx-UI/internal/cert"
@@ -17,10 +21,8 @@ import (
 	"github.com/uozi-tech/cosy"
 	"github.com/uozi-tech/cosy"
 	sqlite "github.com/uozi-tech/cosy-driver-sqlite"
 	sqlite "github.com/uozi-tech/cosy-driver-sqlite"
 	"github.com/uozi-tech/cosy/logger"
 	"github.com/uozi-tech/cosy/logger"
+	cModel "github.com/uozi-tech/cosy/model"
 	cSettings "github.com/uozi-tech/cosy/settings"
 	cSettings "github.com/uozi-tech/cosy/settings"
-	"mime"
-	"path"
-	"runtime"
 )
 )
 
 
 func Boot() {
 func Boot() {
@@ -73,12 +75,13 @@ func recovery() {
 }
 }
 
 
 func InitDatabase() {
 func InitDatabase() {
+	cModel.ResolvedModels()
 	// Skip install
 	// Skip install
 	if settings.NodeSettings.SkipInstallation {
 	if settings.NodeSettings.SkipInstallation {
 		skipInstall()
 		skipInstall()
 	}
 	}
 
 
-	if "" != cSettings.AppSettings.JwtSecret {
+	if cSettings.AppSettings.JwtSecret != "" {
 		db := cosy.InitDB(sqlite.Open(path.Dir(cSettings.ConfPath), settings.DatabaseSettings))
 		db := cosy.InitDB(sqlite.Open(path.Dir(cSettings.ConfPath), settings.DatabaseSettings))
 		model.Use(db)
 		model.Use(db)
 		query.Init(db)
 		query.Init(db)
@@ -88,7 +91,7 @@ func InitDatabase() {
 }
 }
 
 
 func InitNodeSecret() {
 func InitNodeSecret() {
-	if "" == settings.NodeSettings.Secret {
+	if settings.NodeSettings.Secret == "" {
 		logger.Info("Secret is empty, generating...")
 		logger.Info("Secret is empty, generating...")
 		uuidStr := uuid.New().String()
 		uuidStr := uuid.New().String()
 		settings.NodeSettings.Secret = uuidStr
 		settings.NodeSettings.Secret = uuidStr
@@ -102,7 +105,7 @@ func InitNodeSecret() {
 }
 }
 
 
 func InitCryptoSecret() {
 func InitCryptoSecret() {
-	if "" == settings.CryptoSettings.Secret {
+	if settings.CryptoSettings.Secret == "" {
 		logger.Info("Secret is empty, generating...")
 		logger.Info("Secret is empty, generating...")
 
 
 		key := make([]byte, 32)
 		key := make([]byte, 32)

+ 46 - 0
internal/middleware/encrypted_params.go

@@ -0,0 +1,46 @@
+package middleware
+
+import (
+	"bytes"
+	"encoding/json"
+	"io"
+	"net/http"
+
+	"github.com/0xJacky/Nginx-UI/internal/crypto"
+	"github.com/gin-gonic/gin"
+	"github.com/uozi-tech/cosy"
+)
+
+var (
+	e                       = cosy.NewErrorScope("middleware")
+	ErrInvalidRequestFormat = e.New(40000, "invalid request format")
+	ErrDecryptionFailed     = e.New(40001, "decryption failed")
+)
+
+func EncryptedParams() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		// read the encrypted payload
+		var encryptedReq struct {
+			EncryptedParams string `json:"encrypted_params"`
+		}
+
+		if err := c.ShouldBindJSON(&encryptedReq); err != nil {
+			c.AbortWithStatusJSON(http.StatusBadRequest, ErrInvalidRequestFormat)
+			return
+		}
+
+		// decrypt the parameters
+		decryptedData, err := crypto.Decrypt(encryptedReq.EncryptedParams)
+		if err != nil {
+			c.AbortWithStatusJSON(http.StatusBadRequest, ErrDecryptionFailed)
+			return
+		}
+
+		// replace request body with decrypted data
+		newBody, _ := json.Marshal(decryptedData)
+		c.Request.Body = io.NopCloser(bytes.NewReader(newBody))
+		c.Request.ContentLength = int64(len(newBody))
+
+		c.Next()
+	}
+}

+ 8 - 8
internal/middleware/middleware.go

@@ -53,16 +53,16 @@ func AuthRequired() gin.HandlerFunc {
 			c.Set("ProxyNodeID", xNodeID)
 			c.Set("ProxyNodeID", xNodeID)
 		}
 		}
 
 
+		if token := c.GetHeader("X-Node-Secret"); token != "" && token == settings.NodeSettings.Secret {
+			c.Set("Secret", token)
+			c.Next()
+			return
+		}
+
 		token := getToken(c)
 		token := getToken(c)
 		if token == "" {
 		if token == "" {
-			if token = c.GetHeader("X-Node-Secret"); token != "" && token == settings.NodeSettings.Secret {
-				c.Set("Secret", token)
-				c.Next()
-				return
-			} else {
-				abortWithAuthFailure()
-				return
-			}
+			abortWithAuthFailure()
+			return
 		}
 		}
 
 
 		u, ok := user.GetTokenUser(token)
 		u, ok := user.GetTokenUser(token)

+ 6 - 2
internal/middleware/proxy_ws.go

@@ -1,12 +1,13 @@
 package middleware
 package middleware
 
 
 import (
 import (
+	"net/http"
+
 	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/pretty66/websocketproxy"
 	"github.com/pretty66/websocketproxy"
 	"github.com/spf13/cast"
 	"github.com/spf13/cast"
 	"github.com/uozi-tech/cosy/logger"
 	"github.com/uozi-tech/cosy/logger"
-	"net/http"
 )
 )
 
 
 func ProxyWs() gin.HandlerFunc {
 func ProxyWs() gin.HandlerFunc {
@@ -26,7 +27,6 @@ func ProxyWs() gin.HandlerFunc {
 
 
 		env := query.Environment
 		env := query.Environment
 		environment, err := env.Where(env.ID.Eq(id)).First()
 		environment, err := env.Where(env.ID.Eq(id)).First()
-
 		if err != nil {
 		if err != nil {
 			logger.Error(err)
 			logger.Error(err)
 			return
 			return
@@ -43,6 +43,10 @@ func ProxyWs() gin.HandlerFunc {
 
 
 		wp, err := websocketproxy.NewProxy(decodedUri, func(r *http.Request) error {
 		wp, err := websocketproxy.NewProxy(decodedUri, func(r *http.Request) error {
 			r.Header.Set("X-Node-Secret", environment.Token)
 			r.Header.Set("X-Node-Secret", environment.Token)
+			r.Header.Del("X-Node-ID")
+			queryValues := r.URL.Query()
+			queryValues.Del("x_node_id")
+			r.URL.RawQuery = queryValues.Encode()
 			return nil
 			return nil
 		})
 		})
 
 

+ 32 - 0
internal/nginx/nginx_directives.json

@@ -741,6 +741,11 @@
       "https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_ssl_certificate"
       "https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_ssl_certificate"
     ]
     ]
   },
   },
+  "grpc_ssl_certificate_cache": {
+    "links": [
+      "https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_ssl_certificate_cache"
+    ]
+  },
   "grpc_ssl_certificate_key": {
   "grpc_ssl_certificate_key": {
     "links": [
     "links": [
       "https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_ssl_certificate_key"
       "https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_ssl_certificate_key"
@@ -1241,6 +1246,11 @@
       "https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_disable"
       "https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_disable"
     ]
     ]
   },
   },
+  "keepalive_min_timeout": {
+    "links": [
+      "https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_min_timeout"
+    ]
+  },
   "keepalive_requests": {
   "keepalive_requests": {
     "links": [
     "links": [
       "https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_requests",
       "https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_requests",
@@ -2100,6 +2110,12 @@
       "https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_ssl_certificate"
       "https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_ssl_certificate"
     ]
     ]
   },
   },
+  "proxy_ssl_certificate_cache": {
+    "links": [
+      "https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate_cache",
+      "https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_ssl_certificate_cache"
+    ]
+  },
   "proxy_ssl_certificate_key": {
   "proxy_ssl_certificate_key": {
     "links": [
     "links": [
       "https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate_key",
       "https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificate_key",
@@ -2750,6 +2766,12 @@
       "https://nginx.org/en/docs/stream/ngx_stream_ssl_module.html#ssl_certificate"
       "https://nginx.org/en/docs/stream/ngx_stream_ssl_module.html#ssl_certificate"
     ]
     ]
   },
   },
+  "ssl_certificate_cache": {
+    "links": [
+      "https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate_cache",
+      "https://nginx.org/en/docs/stream/ngx_stream_ssl_module.html#ssl_certificate_cache"
+    ]
+  },
   "ssl_certificate_key": {
   "ssl_certificate_key": {
     "links": [
     "links": [
       "https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate_key",
       "https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate_key",
@@ -2821,6 +2843,11 @@
       "https://nginx.org/en/docs/stream/ngx_stream_ssl_module.html#ssl_key_log"
       "https://nginx.org/en/docs/stream/ngx_stream_ssl_module.html#ssl_key_log"
     ]
     ]
   },
   },
+  "ssl_object_cache_inheritable": {
+    "links": [
+      "https://nginx.org/en/docs/ngx_core_module.html#ssl_object_cache_inheritable"
+    ]
+  },
   "ssl_ocsp": {
   "ssl_ocsp": {
     "links": [
     "links": [
       "https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ocsp",
       "https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ocsp",
@@ -3374,6 +3401,11 @@
       "https://nginx.org/en/docs/http/ngx_http_uwsgi_module.html#uwsgi_ssl_certificate"
       "https://nginx.org/en/docs/http/ngx_http_uwsgi_module.html#uwsgi_ssl_certificate"
     ]
     ]
   },
   },
+  "uwsgi_ssl_certificate_cache": {
+    "links": [
+      "https://nginx.org/en/docs/http/ngx_http_uwsgi_module.html#uwsgi_ssl_certificate_cache"
+    ]
+  },
   "uwsgi_ssl_certificate_key": {
   "uwsgi_ssl_certificate_key": {
     "links": [
     "links": [
       "https://nginx.org/en/docs/http/ngx_http_uwsgi_module.html#uwsgi_ssl_certificate_key"
       "https://nginx.org/en/docs/http/ngx_http_uwsgi_module.html#uwsgi_ssl_certificate_key"

+ 2 - 0
router/routers.go

@@ -15,6 +15,7 @@ import (
 	"github.com/0xJacky/Nginx-UI/api/openai"
 	"github.com/0xJacky/Nginx-UI/api/openai"
 	"github.com/0xJacky/Nginx-UI/api/public"
 	"github.com/0xJacky/Nginx-UI/api/public"
 	"github.com/0xJacky/Nginx-UI/api/settings"
 	"github.com/0xJacky/Nginx-UI/api/settings"
+	"github.com/0xJacky/Nginx-UI/api/crypto"
 	"github.com/0xJacky/Nginx-UI/api/sites"
 	"github.com/0xJacky/Nginx-UI/api/sites"
 	"github.com/0xJacky/Nginx-UI/api/streams"
 	"github.com/0xJacky/Nginx-UI/api/streams"
 	"github.com/0xJacky/Nginx-UI/api/system"
 	"github.com/0xJacky/Nginx-UI/api/system"
@@ -42,6 +43,7 @@ func InitRouter() {
 	root := r.Group("/api")
 	root := r.Group("/api")
 	{
 	{
 		public.InitRouter(root)
 		public.InitRouter(root)
+		crypto.InitPublicRouter(root)
 		system.InitPublicRouter(root)
 		system.InitPublicRouter(root)
 		user.InitAuthRouter(root)
 		user.InitAuthRouter(root)
 
 

+ 9 - 0
template/block/vue-router-history-mode.conf

@@ -0,0 +1,9 @@
+# Nginx UI Template Start
+name = "Vue History Router"
+author = "@0xJacky"
+description = { en = "Vue Router History Mode Config", zh_CN = "Vue Router History 模式配置", zh_TW = "Vue Router History 模式配置" }
+# Nginx UI Template End
+
+location / {
+  try_files $uri $uri/ /index.html;
+}