From 60c54827aa106e499ad4d632d5e200f5cc192745 Mon Sep 17 00:00:00 2001 From: Nikan Zeyaei <72458440+NikanZeyaei@users.noreply.github.com> Date: Sun, 28 Jun 2026 19:40:38 +0330 Subject: [PATCH] feat: ldap skip tls verify (#5637) * feat(ldap): add InsecureSkipVerify field and tlsConfig helper Extract the inline TLS config at both LDAPS dial sites (FetchVlessFlags, AuthenticateUser) into a tlsConfig(cfg) helper, and add a new Config.InsecureSkipVerify bool that flows through to tls.Config.InsecureSkipVerify. This unblocks enterprise environments (e.g. Microsoft AD CS with internal CAs) where the server certificate chain cannot be imported into the system trust store. Behavior is identical when InsecureSkipVerify is false (the default) - pure refactor + plumbing. The helper is unit-testable without a live server, which is why it is extracted. Closes https://github.com/MHSanaei/3x-ui/issues/5538 * feat(settings): add LdapInsecureSkipVerify setting Plumb the new LDAP skip-TLS-verify toggle through the settings stack: - AllSetting struct field (json/form tag: ldapInsecureSkipVerify) - defaultValueMap default ("false") - GetLdapInsecureSkipVerify() getter - ldap_sync_job wiring into ldaputil.Config (FetchVlessFlags path) - panel/user.go wiring into ldaputil.Config (AuthenticateUser path; the original issue's file list missed this) Persistence is handled by UpdateAllSetting's reflect loop, matching the existing pattern used by ldapUseTLS (no explicit setter). Closes https://github.com/MHSanaei/3x-ui/issues/5538 * feat(ui): add Skip TLS verification switch in LDAP settings Wire the new ldapInsecureSkipVerify setting into the hand-written frontend model and Zod schema, and render it as a new Switch in GeneralTab right under "Use TLS (LDAPS)". The switch is disabled when TLS is off (the setting is meaningless without LDAPS) and shows an insecure-warning description to make the security implication visible to operators. Also adds a Vitest round-trip test pinning schema acceptance and model default-to-false behavior. Closes https://github.com/MHSanaei/3x-ui/issues/5538 * chore(i18n): add Skip TLS verification strings to all locales Add pages.settings.ldap.skipTlsVerify and skipTlsVerifyDesc to all 13 backend-served translation files, matching the existing repo convention of keeping LDAP keys present in every locale (en-US, fa-IR, ru-RU, zh-CN, zh-TW, pt-BR, ar-EG, uk-UA, id-ID, tr-TR, vi-VN, ja-JP, es-ES). No translation-parity test exists in CI, but every other LDAP key is replicated across all files, so this keeps the invariant intact. Closes https://github.com/MHSanaei/3x-ui/issues/5538 * chore(codegen): regenerate frontend artifacts Regenerate frontend/src/generated/{zod,types,schemas,examples}.ts and frontend/public/openapi.json via `npm run gen` to reflect the new ldapInsecureSkipVerify field. The codegen CI job runs `git diff --exit-code` on these files; failing to commit them would break the build. Closes https://github.com/MHSanaei/3x-ui/issues/5538 --- frontend/public/openapi.json | 8 ++++ frontend/src/generated/examples.ts | 2 + frontend/src/generated/schemas.ts | 8 ++++ frontend/src/generated/types.ts | 2 + frontend/src/generated/zod.ts | 2 + frontend/src/models/setting.ts | 1 + frontend/src/pages/settings/GeneralTab.tsx | 11 +++++ frontend/src/schemas/setting.ts | 1 + .../src/test/setting-ldap-skip-verify.test.ts | 20 +++++++++ internal/util/ldap/ldap.go | 35 ++++++++------- internal/util/ldap/ldap_test.go | 22 +++++++++ internal/web/entity/entity.go | 23 +++++----- internal/web/job/ldap_sync_job.go | 23 +++++----- internal/web/service/panel/user.go | 18 ++++---- internal/web/service/setting.go | 45 ++++++++++--------- internal/web/translation/ar-EG.json | 2 + internal/web/translation/en-US.json | 2 + internal/web/translation/es-ES.json | 2 + internal/web/translation/fa-IR.json | 2 + internal/web/translation/id-ID.json | 2 + internal/web/translation/ja-JP.json | 2 + internal/web/translation/pt-BR.json | 2 + internal/web/translation/ru-RU.json | 2 + internal/web/translation/tr-TR.json | 2 + internal/web/translation/uk-UA.json | 2 + internal/web/translation/vi-VN.json | 2 + internal/web/translation/zh-CN.json | 2 + internal/web/translation/zh-TW.json | 2 + 28 files changed, 180 insertions(+), 67 deletions(-) create mode 100644 frontend/src/test/setting-ldap-skip-verify.test.ts create mode 100644 internal/util/ldap/ldap_test.go diff --git a/frontend/public/openapi.json b/frontend/public/openapi.json index 903ee14af..fa64351ea 100644 --- a/frontend/public/openapi.json +++ b/frontend/public/openapi.json @@ -84,6 +84,9 @@ "ldapInboundTags": { "type": "string" }, + "ldapInsecureSkipVerify": { + "type": "boolean" + }, "ldapInvertFlag": { "type": "boolean" }, @@ -429,6 +432,7 @@ "ldapFlagField", "ldapHost", "ldapInboundTags", + "ldapInsecureSkipVerify", "ldapInvertFlag", "ldapPassword", "ldapPort", @@ -589,6 +593,9 @@ "ldapInboundTags": { "type": "string" }, + "ldapInsecureSkipVerify": { + "type": "boolean" + }, "ldapInvertFlag": { "type": "boolean" }, @@ -941,6 +948,7 @@ "ldapFlagField", "ldapHost", "ldapInboundTags", + "ldapInsecureSkipVerify", "ldapInvertFlag", "ldapPassword", "ldapPort", diff --git a/frontend/src/generated/examples.ts b/frontend/src/generated/examples.ts index f067a8ab4..24eb26370 100644 --- a/frontend/src/generated/examples.ts +++ b/frontend/src/generated/examples.ts @@ -16,6 +16,7 @@ export const EXAMPLES: Record = { "ldapFlagField": "", "ldapHost": "", "ldapInboundTags": "", + "ldapInsecureSkipVerify": false, "ldapInvertFlag": false, "ldapPassword": "", "ldapPort": 0, @@ -118,6 +119,7 @@ export const EXAMPLES: Record = { "ldapFlagField": "", "ldapHost": "", "ldapInboundTags": "", + "ldapInsecureSkipVerify": false, "ldapInvertFlag": false, "ldapPassword": "", "ldapPort": 0, diff --git a/frontend/src/generated/schemas.ts b/frontend/src/generated/schemas.ts index b2a11819a..ac28804f9 100644 --- a/frontend/src/generated/schemas.ts +++ b/frontend/src/generated/schemas.ts @@ -58,6 +58,9 @@ export const SCHEMAS: Record = { "ldapInboundTags": { "type": "string" }, + "ldapInsecureSkipVerify": { + "type": "boolean" + }, "ldapInvertFlag": { "type": "boolean" }, @@ -403,6 +406,7 @@ export const SCHEMAS: Record = { "ldapFlagField", "ldapHost", "ldapInboundTags", + "ldapInsecureSkipVerify", "ldapInvertFlag", "ldapPassword", "ldapPort", @@ -563,6 +567,9 @@ export const SCHEMAS: Record = { "ldapInboundTags": { "type": "string" }, + "ldapInsecureSkipVerify": { + "type": "boolean" + }, "ldapInvertFlag": { "type": "boolean" }, @@ -915,6 +922,7 @@ export const SCHEMAS: Record = { "ldapFlagField", "ldapHost", "ldapInboundTags", + "ldapInsecureSkipVerify", "ldapInvertFlag", "ldapPassword", "ldapPort", diff --git a/frontend/src/generated/types.ts b/frontend/src/generated/types.ts index 5909724f8..87bdb7827 100644 --- a/frontend/src/generated/types.ts +++ b/frontend/src/generated/types.ts @@ -22,6 +22,7 @@ export interface AllSetting { ldapFlagField: string; ldapHost: string; ldapInboundTags: string; + ldapInsecureSkipVerify: boolean; ldapInvertFlag: boolean; ldapPassword: string; ldapPort: number; @@ -125,6 +126,7 @@ export interface AllSettingView { ldapFlagField: string; ldapHost: string; ldapInboundTags: string; + ldapInsecureSkipVerify: boolean; ldapInvertFlag: boolean; ldapPassword: string; ldapPort: number; diff --git a/frontend/src/generated/zod.ts b/frontend/src/generated/zod.ts index 8e7516055..6cc9a8434 100644 --- a/frontend/src/generated/zod.ts +++ b/frontend/src/generated/zod.ts @@ -34,6 +34,7 @@ export const AllSettingSchema = z.object({ ldapFlagField: z.string(), ldapHost: z.string(), ldapInboundTags: z.string(), + ldapInsecureSkipVerify: z.boolean(), ldapInvertFlag: z.boolean(), ldapPassword: z.string(), ldapPort: z.number().int().min(0).max(65535), @@ -138,6 +139,7 @@ export const AllSettingViewSchema = z.object({ ldapFlagField: z.string(), ldapHost: z.string(), ldapInboundTags: z.string(), + ldapInsecureSkipVerify: z.boolean(), ldapInvertFlag: z.boolean(), ldapPassword: z.string(), ldapPort: z.number().int().min(0).max(65535), diff --git a/frontend/src/models/setting.ts b/frontend/src/models/setting.ts index bf498fc21..739fb78c5 100644 --- a/frontend/src/models/setting.ts +++ b/frontend/src/models/setting.ts @@ -68,6 +68,7 @@ export class AllSetting { ldapHost = ''; ldapPort = 389; ldapUseTLS = false; + ldapInsecureSkipVerify = false; ldapBindDN = ''; ldapPassword = ''; ldapBaseDN = ''; diff --git a/frontend/src/pages/settings/GeneralTab.tsx b/frontend/src/pages/settings/GeneralTab.tsx index 765d04af3..b40ab935f 100644 --- a/frontend/src/pages/settings/GeneralTab.tsx +++ b/frontend/src/pages/settings/GeneralTab.tsx @@ -312,6 +312,17 @@ export default function GeneralTab({ allSetting, updateSetting }: GeneralTabProp updateSetting({ ldapUseTLS: v })} /> + + updateSetting({ ldapInsecureSkipVerify: v })} + /> + updateSetting({ ldapBindDN: e.target.value })} /> diff --git a/frontend/src/schemas/setting.ts b/frontend/src/schemas/setting.ts index ffb77e921..e7d39ba86 100644 --- a/frontend/src/schemas/setting.ts +++ b/frontend/src/schemas/setting.ts @@ -69,6 +69,7 @@ export const AllSettingSchema = z.object({ ldapHost: z.string().optional(), ldapPort: port.optional(), ldapUseTLS: z.boolean().optional(), + ldapInsecureSkipVerify: z.boolean().optional(), ldapBindDN: z.string().optional(), ldapPassword: z.string().optional(), ldapBaseDN: z.string().optional(), diff --git a/frontend/src/test/setting-ldap-skip-verify.test.ts b/frontend/src/test/setting-ldap-skip-verify.test.ts new file mode 100644 index 000000000..8ce524802 --- /dev/null +++ b/frontend/src/test/setting-ldap-skip-verify.test.ts @@ -0,0 +1,20 @@ +import { describe, it, expect } from 'vitest'; +import { AllSettingSchema } from '@/schemas/setting'; +import { AllSetting } from '@/models/setting'; + +describe('ldapInsecureSkipVerify', () => { + it('parses through the Zod schema', () => { + const r = AllSettingSchema.safeParse({ ldapInsecureSkipVerify: true }); + expect(r.success).toBe(true); + expect(r.success && r.data.ldapInsecureSkipVerify).toBe(true); + }); + + it('rejects non-boolean values', () => { + expect(AllSettingSchema.safeParse({ ldapInsecureSkipVerify: 'yes' }).success).toBe(false); + }); + + it('defaults to false on the model and clones from payload', () => { + expect(new AllSetting().ldapInsecureSkipVerify).toBe(false); + expect(new AllSetting({ ldapInsecureSkipVerify: true }).ldapInsecureSkipVerify).toBe(true); + }); +}); diff --git a/internal/util/ldap/ldap.go b/internal/util/ldap/ldap.go index 4d5bdbb75..e5a023de3 100644 --- a/internal/util/ldap/ldap.go +++ b/internal/util/ldap/ldap.go @@ -9,17 +9,22 @@ import ( ) type Config struct { - Host string - Port int - UseTLS bool - BindDN string - Password string - BaseDN string - UserFilter string - UserAttr string - FlagField string - TruthyVals []string - Invert bool + Host string + Port int + UseTLS bool + InsecureSkipVerify bool + BindDN string + Password string + BaseDN string + UserFilter string + UserAttr string + FlagField string + TruthyVals []string + Invert bool +} + +func tlsConfig(cfg Config) *tls.Config { + return &tls.Config{InsecureSkipVerify: cfg.InsecureSkipVerify} } // FetchVlessFlags returns map[email]enabled @@ -35,9 +40,7 @@ func FetchVlessFlags(cfg Config) (map[string]bool, error) { var opts []ldap.DialOpt if cfg.UseTLS { - opts = append(opts, ldap.DialWithTLSConfig(&tls.Config{ - InsecureSkipVerify: false, - })) + opts = append(opts, ldap.DialWithTLSConfig(tlsConfig(cfg))) } conn, err := ldap.DialURL(ldapURL, opts...) @@ -105,9 +108,7 @@ func AuthenticateUser(cfg Config, username, password string) (bool, error) { var opts []ldap.DialOpt if cfg.UseTLS { - opts = append(opts, ldap.DialWithTLSConfig(&tls.Config{ - InsecureSkipVerify: false, - })) + opts = append(opts, ldap.DialWithTLSConfig(tlsConfig(cfg))) } conn, err := ldap.DialURL(ldapURL, opts...) diff --git a/internal/util/ldap/ldap_test.go b/internal/util/ldap/ldap_test.go new file mode 100644 index 000000000..360d1b588 --- /dev/null +++ b/internal/util/ldap/ldap_test.go @@ -0,0 +1,22 @@ +package ldaputil + +import "testing" + +func TestTLSConfig_InsecureSkipVerifyPropagates(t *testing.T) { + cases := []struct { + name string + skip bool + want bool + }{ + {"default verifies", false, false}, + {"skip flows through", true, true}, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + got := tlsConfig(Config{InsecureSkipVerify: c.skip}) + if got.InsecureSkipVerify != c.want { + t.Fatalf("InsecureSkipVerify = %v, want %v", got.InsecureSkipVerify, c.want) + } + }) + } +} diff --git a/internal/web/entity/entity.go b/internal/web/entity/entity.go index 836dba6d2..4a8f9af48 100644 --- a/internal/web/entity/entity.go +++ b/internal/web/entity/entity.go @@ -105,17 +105,18 @@ type AllSetting struct { SubHideSettings bool `json:"subHideSettings" form:"subHideSettings"` // Hide server settings in happ subscription (Only for Happ) // LDAP settings - LdapEnable bool `json:"ldapEnable" form:"ldapEnable"` - LdapHost string `json:"ldapHost" form:"ldapHost"` - LdapPort int `json:"ldapPort" form:"ldapPort" validate:"gte=0,lte=65535"` - LdapUseTLS bool `json:"ldapUseTLS" form:"ldapUseTLS"` - LdapBindDN string `json:"ldapBindDN" form:"ldapBindDN"` - LdapPassword string `json:"ldapPassword" form:"ldapPassword"` - LdapBaseDN string `json:"ldapBaseDN" form:"ldapBaseDN"` - LdapUserFilter string `json:"ldapUserFilter" form:"ldapUserFilter"` - LdapUserAttr string `json:"ldapUserAttr" form:"ldapUserAttr"` // e.g., mail or uid - LdapVlessField string `json:"ldapVlessField" form:"ldapVlessField"` - LdapSyncCron string `json:"ldapSyncCron" form:"ldapSyncCron"` + LdapEnable bool `json:"ldapEnable" form:"ldapEnable"` + LdapHost string `json:"ldapHost" form:"ldapHost"` + LdapPort int `json:"ldapPort" form:"ldapPort" validate:"gte=0,lte=65535"` + LdapUseTLS bool `json:"ldapUseTLS" form:"ldapUseTLS"` + LdapInsecureSkipVerify bool `json:"ldapInsecureSkipVerify" form:"ldapInsecureSkipVerify"` + LdapBindDN string `json:"ldapBindDN" form:"ldapBindDN"` + LdapPassword string `json:"ldapPassword" form:"ldapPassword"` + LdapBaseDN string `json:"ldapBaseDN" form:"ldapBaseDN"` + LdapUserFilter string `json:"ldapUserFilter" form:"ldapUserFilter"` + LdapUserAttr string `json:"ldapUserAttr" form:"ldapUserAttr"` // e.g., mail or uid + LdapVlessField string `json:"ldapVlessField" form:"ldapVlessField"` + LdapSyncCron string `json:"ldapSyncCron" form:"ldapSyncCron"` // Generic flag configuration LdapFlagField string `json:"ldapFlagField" form:"ldapFlagField"` LdapTruthyValues string `json:"ldapTruthyValues" form:"ldapTruthyValues"` diff --git a/internal/web/job/ldap_sync_job.go b/internal/web/job/ldap_sync_job.go index 42732e0d4..d1c5ed548 100644 --- a/internal/web/job/ldap_sync_job.go +++ b/internal/web/job/ldap_sync_job.go @@ -69,17 +69,18 @@ func (j *LdapSyncJob) Run() { // --- LDAP fetch --- cfg := ldaputil.Config{ - Host: mustGetString(j.settingService.GetLdapHost), - Port: mustGetInt(j.settingService.GetLdapPort), - UseTLS: mustGetBool(j.settingService.GetLdapUseTLS), - BindDN: mustGetString(j.settingService.GetLdapBindDN), - Password: mustGetString(j.settingService.GetLdapPassword), - BaseDN: mustGetString(j.settingService.GetLdapBaseDN), - UserFilter: mustGetString(j.settingService.GetLdapUserFilter), - UserAttr: mustGetString(j.settingService.GetLdapUserAttr), - FlagField: mustGetStringOr(j.settingService.GetLdapFlagField, mustGetString(j.settingService.GetLdapVlessField)), - TruthyVals: splitCsv(mustGetString(j.settingService.GetLdapTruthyValues)), - Invert: mustGetBool(j.settingService.GetLdapInvertFlag), + Host: mustGetString(j.settingService.GetLdapHost), + Port: mustGetInt(j.settingService.GetLdapPort), + UseTLS: mustGetBool(j.settingService.GetLdapUseTLS), + InsecureSkipVerify: mustGetBool(j.settingService.GetLdapInsecureSkipVerify), + BindDN: mustGetString(j.settingService.GetLdapBindDN), + Password: mustGetString(j.settingService.GetLdapPassword), + BaseDN: mustGetString(j.settingService.GetLdapBaseDN), + UserFilter: mustGetString(j.settingService.GetLdapUserFilter), + UserAttr: mustGetString(j.settingService.GetLdapUserAttr), + FlagField: mustGetStringOr(j.settingService.GetLdapFlagField, mustGetString(j.settingService.GetLdapVlessField)), + TruthyVals: splitCsv(mustGetString(j.settingService.GetLdapTruthyValues)), + Invert: mustGetBool(j.settingService.GetLdapInvertFlag), } flags, err := ldaputil.FetchVlessFlags(cfg) diff --git a/internal/web/service/panel/user.go b/internal/web/service/panel/user.go index fa058a2ee..a11402187 100644 --- a/internal/web/service/panel/user.go +++ b/internal/web/service/panel/user.go @@ -60,6 +60,7 @@ func (s *UserService) CheckUser(username string, password string, twoFactorCode host, _ := s.settingService.GetLdapHost() port, _ := s.settingService.GetLdapPort() useTLS, _ := s.settingService.GetLdapUseTLS() + skipVerify, _ := s.settingService.GetLdapInsecureSkipVerify() bindDN, _ := s.settingService.GetLdapBindDN() ldapPass, _ := s.settingService.GetLdapPassword() baseDN, _ := s.settingService.GetLdapBaseDN() @@ -67,14 +68,15 @@ func (s *UserService) CheckUser(username string, password string, twoFactorCode userAttr, _ := s.settingService.GetLdapUserAttr() cfg := ldaputil.Config{ - Host: host, - Port: port, - UseTLS: useTLS, - BindDN: bindDN, - Password: ldapPass, - BaseDN: baseDN, - UserFilter: userFilter, - UserAttr: userAttr, + Host: host, + Port: port, + UseTLS: useTLS, + InsecureSkipVerify: skipVerify, + BindDN: bindDN, + Password: ldapPass, + BaseDN: baseDN, + UserFilter: userFilter, + UserAttr: userAttr, } ok, err := ldaputil.AuthenticateUser(cfg, username, password) if err != nil || !ok { diff --git a/internal/web/service/setting.go b/internal/web/service/setting.go index ca74295b4..d3eedea17 100644 --- a/internal/web/service/setting.go +++ b/internal/web/service/setting.go @@ -114,26 +114,27 @@ var defaultValueMap = map[string]string{ "devChannelEnable": "false", // LDAP defaults - "ldapEnable": "false", - "ldapHost": "", - "ldapPort": "389", - "ldapUseTLS": "false", - "ldapBindDN": "", - "ldapPassword": "", - "ldapBaseDN": "", - "ldapUserFilter": "(objectClass=person)", - "ldapUserAttr": "mail", - "ldapVlessField": "vless_enabled", - "ldapSyncCron": "@every 1m", - "ldapFlagField": "", - "ldapTruthyValues": "true,1,yes,on", - "ldapInvertFlag": "false", - "ldapInboundTags": "", - "ldapAutoCreate": "false", - "ldapAutoDelete": "false", - "ldapDefaultTotalGB": "0", - "ldapDefaultExpiryDays": "0", - "ldapDefaultLimitIP": "0", + "ldapEnable": "false", + "ldapHost": "", + "ldapPort": "389", + "ldapUseTLS": "false", + "ldapInsecureSkipVerify": "false", + "ldapBindDN": "", + "ldapPassword": "", + "ldapBaseDN": "", + "ldapUserFilter": "(objectClass=person)", + "ldapUserAttr": "mail", + "ldapVlessField": "vless_enabled", + "ldapSyncCron": "@every 1m", + "ldapFlagField": "", + "ldapTruthyValues": "true,1,yes,on", + "ldapInvertFlag": "false", + "ldapInboundTags": "", + "ldapAutoCreate": "false", + "ldapAutoDelete": "false", + "ldapDefaultTotalGB": "0", + "ldapDefaultExpiryDays": "0", + "ldapDefaultLimitIP": "0", // Event bus — per-subscriber event filtering (empty = all disabled) "tgEnabledEvents": "login.attempt,cpu.high", @@ -922,6 +923,10 @@ func (s *SettingService) GetLdapUseTLS() (bool, error) { return s.getBool("ldapUseTLS") } +func (s *SettingService) GetLdapInsecureSkipVerify() (bool, error) { + return s.getBool("ldapInsecureSkipVerify") +} + func (s *SettingService) GetLdapBindDN() (string, error) { return s.getString("ldapBindDN") } diff --git a/internal/web/translation/ar-EG.json b/internal/web/translation/ar-EG.json index 65a28a2b0..7d9bc567e 100644 --- a/internal/web/translation/ar-EG.json +++ b/internal/web/translation/ar-EG.json @@ -1220,6 +1220,8 @@ "host": "مضيف LDAP", "port": "منفذ LDAP", "useTls": "استخدام TLS (LDAPS)", + "skipTlsVerify": "تخطي التحقق من شهادة TLS", + "skipTlsVerifyDesc": "غير آمن — يعطل التحقق من شهادة الخادم. استخدم فقط مع CA الداخلية/غير الموثوقة.", "bindDn": "Bind DN", "passwordConfigured": "مهيأة؛ اترك فارغاً للاحتفاظ بكلمة المرور الحالية.", "passwordUnconfigured": "غير مهيأة.", diff --git a/internal/web/translation/en-US.json b/internal/web/translation/en-US.json index 90dc3f736..ea1fd4538 100644 --- a/internal/web/translation/en-US.json +++ b/internal/web/translation/en-US.json @@ -1341,6 +1341,8 @@ "host": "LDAP host", "port": "LDAP port", "useTls": "Use TLS (LDAPS)", + "skipTlsVerify": "Skip TLS certificate verification", + "skipTlsVerifyDesc": "Insecure — disables server certificate validation. Use only with internal/untrusted CAs.", "bindDn": "Bind DN", "passwordConfigured": "Configured; leave blank to keep current password.", "passwordUnconfigured": "Not configured.", diff --git a/internal/web/translation/es-ES.json b/internal/web/translation/es-ES.json index dd7faae2d..53c922c13 100644 --- a/internal/web/translation/es-ES.json +++ b/internal/web/translation/es-ES.json @@ -1220,6 +1220,8 @@ "host": "Host LDAP", "port": "Puerto LDAP", "useTls": "Usar TLS (LDAPS)", + "skipTlsVerify": "Omitir verificación de certificado TLS", + "skipTlsVerifyDesc": "Inseguro — desactiva la validación del certificado del servidor. Usar solo con CA internos/no confiables.", "bindDn": "Bind DN", "passwordConfigured": "Configurada; deja en blanco para mantener la contraseña actual.", "passwordUnconfigured": "No configurada.", diff --git a/internal/web/translation/fa-IR.json b/internal/web/translation/fa-IR.json index 4ee445b3b..0d5235275 100644 --- a/internal/web/translation/fa-IR.json +++ b/internal/web/translation/fa-IR.json @@ -1222,6 +1222,8 @@ "host": "میزبان LDAP", "port": "پورت LDAP", "useTls": "استفاده از TLS (LDAPS)", + "skipTlsVerify": "رد کردن تأیید گواهی TLS", + "skipTlsVerifyDesc": "ناامن — اعتبارسنجی گواهی سرور را غیرفعال می‌کند. فقط برای CAهای داخلی/غیرمعتبر استفاده کنید.", "bindDn": "Bind DN", "passwordConfigured": "تنظیم‌شده؛ برای حفظ رمز فعلی خالی بگذارید.", "passwordUnconfigured": "تنظیم نشده.", diff --git a/internal/web/translation/id-ID.json b/internal/web/translation/id-ID.json index 9c0a273cb..dbfb1d1a2 100644 --- a/internal/web/translation/id-ID.json +++ b/internal/web/translation/id-ID.json @@ -1220,6 +1220,8 @@ "host": "LDAP host", "port": "Port LDAP", "useTls": "Gunakan TLS (LDAPS)", + "skipTlsVerify": "Lewati verifikasi sertifikat TLS", + "skipTlsVerifyDesc": "Tidak aman — menonaktifkan validasi sertifikat server. Gunakan hanya dengan CA internal/tidak terpercaya.", "bindDn": "Bind DN", "passwordConfigured": "Terkonfigurasi; biarkan kosong untuk mempertahankan kata sandi saat ini.", "passwordUnconfigured": "Tidak terkonfigurasi.", diff --git a/internal/web/translation/ja-JP.json b/internal/web/translation/ja-JP.json index 59f45bc68..9161b09d0 100644 --- a/internal/web/translation/ja-JP.json +++ b/internal/web/translation/ja-JP.json @@ -1220,6 +1220,8 @@ "host": "LDAP host", "port": "LDAP ポート", "useTls": "TLS (LDAPS) を使用", + "skipTlsVerify": "TLS 証明書の検証をスキップ", + "skipTlsVerifyDesc": "安全ではありません — サーバー証明書の検証を無効化します。内部/信頼できない CA でのみ使用してください。", "bindDn": "Bind DN", "passwordConfigured": "設定済み;現在のパスワードを保持するには空のままにします。", "passwordUnconfigured": "未設定。", diff --git a/internal/web/translation/pt-BR.json b/internal/web/translation/pt-BR.json index 379cb2b36..95c5ca19a 100644 --- a/internal/web/translation/pt-BR.json +++ b/internal/web/translation/pt-BR.json @@ -1220,6 +1220,8 @@ "host": "Host LDAP", "port": "Porta LDAP", "useTls": "Usar TLS (LDAPS)", + "skipTlsVerify": "Pular verificação de certificado TLS", + "skipTlsVerifyDesc": "Inseguro — desativa a validação do certificado do servidor. Use apenas com CAs internos/não confiáveis.", "bindDn": "Bind DN", "passwordConfigured": "Configurada; deixe em branco para manter a senha atual.", "passwordUnconfigured": "Não configurada.", diff --git a/internal/web/translation/ru-RU.json b/internal/web/translation/ru-RU.json index 364d785e6..f416e1a6d 100644 --- a/internal/web/translation/ru-RU.json +++ b/internal/web/translation/ru-RU.json @@ -1220,6 +1220,8 @@ "host": "LDAP-хост", "port": "Порт LDAP", "useTls": "Использовать TLS (LDAPS)", + "skipTlsVerify": "Пропустить проверку сертификата TLS", + "skipTlsVerifyDesc": "Небезопасно — отключает проверку сертификата сервера. Используйте только с внутренними/недоверенными CA.", "bindDn": "Bind DN", "passwordConfigured": "Настроено; оставьте пустым, чтобы сохранить текущий пароль.", "passwordUnconfigured": "Не настроено.", diff --git a/internal/web/translation/tr-TR.json b/internal/web/translation/tr-TR.json index c1232eae9..3238df07d 100644 --- a/internal/web/translation/tr-TR.json +++ b/internal/web/translation/tr-TR.json @@ -1220,6 +1220,8 @@ "host": "LDAP host", "port": "LDAP port", "useTls": "TLS kullan (LDAPS)", + "skipTlsVerify": "TLS sertifika doğrulamasını atla", + "skipTlsVerifyDesc": "Güvenli değil — sunucu sertifika doğrulamasını devre dışı bırakır. Yalnızca dahili/güvenilmeyen CA'larla kullanın.", "bindDn": "Bind DN", "passwordConfigured": "Yapılandırıldı; mevcut parolayı korumak için boş bırakın.", "passwordUnconfigured": "Yapılandırılmadı.", diff --git a/internal/web/translation/uk-UA.json b/internal/web/translation/uk-UA.json index 14701131c..9bd48b947 100644 --- a/internal/web/translation/uk-UA.json +++ b/internal/web/translation/uk-UA.json @@ -1220,6 +1220,8 @@ "host": "LDAP-хост", "port": "Порт LDAP", "useTls": "Використовувати TLS (LDAPS)", + "skipTlsVerify": "Пропустити перевірку сертифіката TLS", + "skipTlsVerifyDesc": "Небезпечно — вимикає перевірку сертифіката сервера. Використовуйте лише з внутрішніми/ненадійними CA.", "bindDn": "Bind DN", "passwordConfigured": "Налаштовано; залиште порожнім для збереження поточного паролю.", "passwordUnconfigured": "Не налаштовано.", diff --git a/internal/web/translation/vi-VN.json b/internal/web/translation/vi-VN.json index 29228b0e1..85bb5a594 100644 --- a/internal/web/translation/vi-VN.json +++ b/internal/web/translation/vi-VN.json @@ -1220,6 +1220,8 @@ "host": "LDAP host", "port": "Cổng LDAP", "useTls": "Dùng TLS (LDAPS)", + "skipTlsVerify": "Bỏ qua xác minh chứng chỉ TLS", + "skipTlsVerifyDesc": "Không an toàn — tắt xác thực chứng chỉ máy chủ. Chỉ dùng với CA nội bộ/không đáng tin.", "bindDn": "Bind DN", "passwordConfigured": "Đã cấu hình; để trống để giữ mật khẩu hiện tại.", "passwordUnconfigured": "Chưa cấu hình.", diff --git a/internal/web/translation/zh-CN.json b/internal/web/translation/zh-CN.json index d6b4021ba..2afcfdb3e 100644 --- a/internal/web/translation/zh-CN.json +++ b/internal/web/translation/zh-CN.json @@ -1220,6 +1220,8 @@ "host": "LDAP host", "port": "LDAP 端口", "useTls": "使用 TLS (LDAPS)", + "skipTlsVerify": "跳过 TLS 证书验证", + "skipTlsVerifyDesc": "不安全 — 禁用服务器证书验证。仅用于内部/不受信任的 CA。", "bindDn": "Bind DN", "passwordConfigured": "已配置;留空以保留当前密码。", "passwordUnconfigured": "未配置。", diff --git a/internal/web/translation/zh-TW.json b/internal/web/translation/zh-TW.json index bffc6f087..401d1d86e 100644 --- a/internal/web/translation/zh-TW.json +++ b/internal/web/translation/zh-TW.json @@ -1220,6 +1220,8 @@ "host": "LDAP host", "port": "LDAP 連接埠", "useTls": "使用 TLS (LDAPS)", + "skipTlsVerify": "略過 TLS 憑證驗證", + "skipTlsVerifyDesc": "不安全 — 停用伺服器憑證驗證。僅用於內部/不受信任的 CA。", "bindDn": "Bind DN", "passwordConfigured": "已設定;留空以保留目前密碼。", "passwordUnconfigured": "未設定。",