mirror of
https://github.com/t8y2/dbx.git
synced 2026-11-01 16:28:46 +00:00
feat(db): support TLS client certificates
This commit is contained in:
@@ -29,9 +29,11 @@ import {
|
||||
FilePlus2,
|
||||
FolderOpen,
|
||||
Grid3X3,
|
||||
KeyRound,
|
||||
Link2,
|
||||
List,
|
||||
Search,
|
||||
ShieldCheck,
|
||||
} from "lucide-vue-next";
|
||||
|
||||
type DbOption = { value: string; label: string };
|
||||
@@ -573,7 +575,63 @@ const tlsCapableDatabaseTypes = new Set<DatabaseType>([
|
||||
"elasticsearch",
|
||||
]);
|
||||
const supportsTlsToggle = computed(() => tlsCapableDatabaseTypes.has(form.value.db_type));
|
||||
const supportsCaCertificatePath = computed(() => form.value.db_type === "mysql" || form.value.db_type === "clickhouse");
|
||||
const supportsCaCertificatePath = computed(() => form.value.db_type === "clickhouse");
|
||||
const bareMysqlProfiles = new Set(["doris", "starrocks", "selectdb", "oceanbase"]);
|
||||
const supportsMysqlTlsOptions = computed(
|
||||
() => form.value.db_type === "mysql" && !bareMysqlProfiles.has(selectedType.value),
|
||||
);
|
||||
const mysqlTlsMode = computed({
|
||||
get: () => mysqlTlsModeFromParams(form.value.url_params, form.value.ssl),
|
||||
set: (value: string) => {
|
||||
form.value.ssl = value !== "preferred" && value !== "disabled";
|
||||
form.value.url_params = applyMysqlTlsMode(form.value.url_params, value);
|
||||
},
|
||||
});
|
||||
const mysqlClientCertPath = computed({
|
||||
get: () => getUrlParam(form.value.url_params, "ssl-cert") || getUrlParam(form.value.url_params, "sslcert"),
|
||||
set: (value: string) => {
|
||||
let next = setUrlParam(form.value.url_params, "sslcert", "");
|
||||
form.value.url_params = setUrlParam(next, "ssl-cert", value);
|
||||
},
|
||||
});
|
||||
const mysqlClientKeyPath = computed({
|
||||
get: () => getUrlParam(form.value.url_params, "ssl-key") || getUrlParam(form.value.url_params, "sslkey"),
|
||||
set: (value: string) => {
|
||||
let next = setUrlParam(form.value.url_params, "sslkey", "");
|
||||
form.value.url_params = setUrlParam(next, "ssl-key", value);
|
||||
},
|
||||
});
|
||||
const nativePostgresTlsDatabaseTypes = new Set<DatabaseType>(["postgres", "redshift", "gaussdb", "opengauss"]);
|
||||
const supportsPostgresTlsOptions = computed(() => nativePostgresTlsDatabaseTypes.has(form.value.db_type));
|
||||
const postgresTlsMode = computed({
|
||||
get: () => {
|
||||
const value = normalizePostgresSslMode(getUrlParam(form.value.url_params, "sslmode"));
|
||||
if (value) return value;
|
||||
return form.value.ssl ? "require" : "disable";
|
||||
},
|
||||
set: (value: string) => {
|
||||
form.value.ssl = value !== "disable";
|
||||
form.value.url_params = setUrlParam(form.value.url_params, "sslmode", value === "prefer" ? "" : value);
|
||||
},
|
||||
});
|
||||
const postgresRootCertPath = computed({
|
||||
get: () => getUrlParam(form.value.url_params, "sslrootcert"),
|
||||
set: (value: string) => {
|
||||
form.value.url_params = setUrlParam(form.value.url_params, "sslrootcert", value);
|
||||
},
|
||||
});
|
||||
const postgresClientCertPath = computed({
|
||||
get: () => getUrlParam(form.value.url_params, "sslcert"),
|
||||
set: (value: string) => {
|
||||
form.value.url_params = setUrlParam(form.value.url_params, "sslcert", value);
|
||||
},
|
||||
});
|
||||
const postgresClientKeyPath = computed({
|
||||
get: () => getUrlParam(form.value.url_params, "sslkey"),
|
||||
set: (value: string) => {
|
||||
form.value.url_params = setUrlParam(form.value.url_params, "sslkey", value);
|
||||
},
|
||||
});
|
||||
const canUseSsh = computed(() => form.value.db_type !== "sqlite" && form.value.db_type !== "access");
|
||||
const canUseProxy = computed(
|
||||
() => form.value.db_type !== "sqlite" && form.value.db_type !== "duckdb" && form.value.db_type !== "access",
|
||||
@@ -712,7 +770,7 @@ function connectionConfigForSubmit(id: string): ConnectionConfig {
|
||||
config.redis_sentinel_password = undefined;
|
||||
config.redis_sentinel_tls = undefined;
|
||||
}
|
||||
if (config.db_type !== "clickhouse") {
|
||||
if (config.db_type !== "mysql" && config.db_type !== "clickhouse") {
|
||||
config.ca_cert_path = undefined;
|
||||
} else {
|
||||
config.ca_cert_path = config.ca_cert_path?.trim() || "";
|
||||
@@ -730,6 +788,92 @@ function connectionConfigForSubmit(id: string): ConnectionConfig {
|
||||
return config;
|
||||
}
|
||||
|
||||
function getUrlParam(params: string | undefined, key: string): string {
|
||||
const parsed = new URLSearchParams((params || "").trim().replace(/^\?/, ""));
|
||||
return parsed.get(key) || "";
|
||||
}
|
||||
|
||||
function setUrlParam(params: string | undefined, key: string, value: string): string {
|
||||
const parsed = new URLSearchParams((params || "").trim().replace(/^\?/, ""));
|
||||
const normalized = value.trim();
|
||||
if (normalized) {
|
||||
parsed.set(key, normalized);
|
||||
} else {
|
||||
parsed.delete(key);
|
||||
}
|
||||
return parsed.toString();
|
||||
}
|
||||
|
||||
function deleteUrlParams(params: string | undefined, keys: string[]): string {
|
||||
const parsed = new URLSearchParams((params || "").trim().replace(/^\?/, ""));
|
||||
for (const key of keys) {
|
||||
parsed.delete(key);
|
||||
}
|
||||
return parsed.toString();
|
||||
}
|
||||
|
||||
function mysqlTlsModeFromParams(params: string | undefined, ssl: boolean | undefined): string {
|
||||
const sslMode = getUrlParam(params, "ssl-mode") || getUrlParam(params, "sslmode");
|
||||
switch (sslMode.trim().toLowerCase().replace("-", "_")) {
|
||||
case "disabled":
|
||||
case "disable":
|
||||
return "disabled";
|
||||
case "preferred":
|
||||
case "prefer":
|
||||
return "preferred";
|
||||
case "required":
|
||||
case "require":
|
||||
return "required";
|
||||
case "verify_ca":
|
||||
return "verify_ca";
|
||||
case "verify_identity":
|
||||
return "verify_identity";
|
||||
}
|
||||
|
||||
if (!ssl && getUrlParam(params, "require_ssl").toLowerCase() !== "true") return "preferred";
|
||||
if (getUrlParam(params, "verify_identity").toLowerCase() === "true") return "verify_identity";
|
||||
if (getUrlParam(params, "verify_ca").toLowerCase() === "true") return "verify_ca";
|
||||
return "required";
|
||||
}
|
||||
|
||||
function applyMysqlTlsMode(params: string | undefined, mode: string): string {
|
||||
let next = deleteUrlParams(params, ["ssl-mode", "sslmode", "require_ssl", "verify_ca", "verify_identity"]);
|
||||
if (mode === "disabled") {
|
||||
return setUrlParam(next, "ssl-mode", "disabled");
|
||||
}
|
||||
if (mode === "preferred") {
|
||||
return next;
|
||||
}
|
||||
|
||||
next = setUrlParam(next, "require_ssl", "true");
|
||||
if (mode === "required") {
|
||||
next = setUrlParam(next, "verify_ca", "false");
|
||||
return setUrlParam(next, "verify_identity", "false");
|
||||
}
|
||||
if (mode === "verify_ca") {
|
||||
next = setUrlParam(next, "verify_ca", "true");
|
||||
return setUrlParam(next, "verify_identity", "false");
|
||||
}
|
||||
next = setUrlParam(next, "verify_ca", "true");
|
||||
return setUrlParam(next, "verify_identity", "true");
|
||||
}
|
||||
|
||||
function normalizePostgresSslMode(value: string): string {
|
||||
switch (value.trim().toLowerCase()) {
|
||||
case "disable":
|
||||
case "prefer":
|
||||
case "require":
|
||||
case "verify-ca":
|
||||
case "verify-full":
|
||||
return value.trim().toLowerCase();
|
||||
case "verify_identity":
|
||||
case "verify-identity":
|
||||
return "verify-full";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeRedisSentinelNodes(value: string): string {
|
||||
return value
|
||||
.split(/[\n,;]+/)
|
||||
@@ -985,6 +1129,55 @@ async function browseCaCertPath() {
|
||||
}
|
||||
}
|
||||
|
||||
async function browseMysqlTlsFile(target: "cert" | "key") {
|
||||
if (isTauriRuntime()) {
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
const selected = await open({
|
||||
title: target === "cert" ? t("connection.mysqlClientCertBrowse") : t("connection.mysqlClientKeyBrowse"),
|
||||
multiple: false,
|
||||
filters: [
|
||||
{ name: "PEM", extensions: ["pem", "crt", "cer", "key"] },
|
||||
{ name: "All Files", extensions: ["*"] },
|
||||
],
|
||||
});
|
||||
if (selected && typeof selected === "string") {
|
||||
if (target === "cert") {
|
||||
mysqlClientCertPath.value = selected;
|
||||
} else {
|
||||
mysqlClientKeyPath.value = selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function browsePostgresTlsFile(target: "root" | "cert" | "key") {
|
||||
if (isTauriRuntime()) {
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
const selected = await open({
|
||||
title:
|
||||
target === "root"
|
||||
? t("connection.postgresRootCertBrowse")
|
||||
: target === "cert"
|
||||
? t("connection.postgresClientCertBrowse")
|
||||
: t("connection.postgresClientKeyBrowse"),
|
||||
multiple: false,
|
||||
filters: [
|
||||
{ name: "PEM", extensions: ["pem", "crt", "cer", "key"] },
|
||||
{ name: "All Files", extensions: ["*"] },
|
||||
],
|
||||
});
|
||||
if (selected && typeof selected === "string") {
|
||||
if (target === "root") {
|
||||
postgresRootCertPath.value = selected;
|
||||
} else if (target === "cert") {
|
||||
postgresClientCertPath.value = selected;
|
||||
} else {
|
||||
postgresClientKeyPath.value = selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function browseDbFilePath() {
|
||||
if (isTauriRuntime()) {
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
@@ -1708,7 +1901,10 @@ function openExternalUrl(url: string) {
|
||||
|
||||
<TabsContent v-if="supportsTlsToggle" value="tls" class="m-0">
|
||||
<div class="grid gap-4 py-4 pr-2 max-h-[65vh] overflow-y-auto">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<div
|
||||
v-if="!supportsPostgresTlsOptions && !supportsMysqlTlsOptions"
|
||||
class="grid grid-cols-4 items-center gap-4"
|
||||
>
|
||||
<Label class="text-right text-xs">SSL/TLS</Label>
|
||||
<label class="col-span-3 flex items-center gap-2 cursor-pointer">
|
||||
<input type="checkbox" v-model="form.ssl" class="mr-0" />
|
||||
@@ -1716,6 +1912,232 @@ function openExternalUrl(url: string) {
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<template v-if="supportsMysqlTlsOptions">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label class="text-right text-xs">{{ t("connection.mysqlTlsMode") }}</Label>
|
||||
<Select v-model="mysqlTlsMode">
|
||||
<SelectTrigger class="col-span-3 h-9">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="preferred">{{ t("connection.mysqlTlsModePreferred") }}</SelectItem>
|
||||
<SelectItem value="disabled">{{ t("connection.mysqlTlsModeDisabled") }}</SelectItem>
|
||||
<SelectItem value="required">{{ t("connection.mysqlTlsModeRequired") }}</SelectItem>
|
||||
<SelectItem value="verify_ca">{{ t("connection.mysqlTlsModeVerifyCa") }}</SelectItem>
|
||||
<SelectItem value="verify_identity">{{
|
||||
t("connection.mysqlTlsModeVerifyIdentity")
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-4 items-start gap-4">
|
||||
<Label class="pt-2 text-right text-xs">
|
||||
<span class="inline-flex items-center justify-end gap-1">
|
||||
<ShieldCheck class="h-3.5 w-3.5" />
|
||||
{{ t("connection.caCertPath") }}
|
||||
</span>
|
||||
</Label>
|
||||
<div class="col-span-3 space-y-2">
|
||||
<div class="flex items-center gap-1">
|
||||
<Input
|
||||
v-model="form.ca_cert_path"
|
||||
class="flex-1"
|
||||
:placeholder="t('connection.caCertPathPlaceholder')"
|
||||
:disabled="mysqlTlsMode === 'preferred' || mysqlTlsMode === 'disabled'"
|
||||
/>
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class="h-9 w-9 shrink-0"
|
||||
:disabled="mysqlTlsMode === 'preferred' || mysqlTlsMode === 'disabled'"
|
||||
@click="browseCaCertPath"
|
||||
>
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.caCertPathBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<p class="text-[11px] leading-4 text-muted-foreground">
|
||||
{{ t("connection.mysqlCaCertHint") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-4 items-start gap-4">
|
||||
<Label class="pt-2 text-right text-xs">
|
||||
<span class="inline-flex items-center justify-end gap-1">
|
||||
<KeyRound class="h-3.5 w-3.5" />
|
||||
{{ t("connection.mysqlClientCert") }}
|
||||
</span>
|
||||
</Label>
|
||||
<div class="col-span-3 grid gap-2">
|
||||
<div class="flex items-center gap-1">
|
||||
<Input
|
||||
v-model="mysqlClientCertPath"
|
||||
class="flex-1"
|
||||
:placeholder="t('connection.mysqlClientCertPlaceholder')"
|
||||
:disabled="mysqlTlsMode === 'preferred' || mysqlTlsMode === 'disabled'"
|
||||
/>
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class="h-9 w-9 shrink-0"
|
||||
:disabled="mysqlTlsMode === 'preferred' || mysqlTlsMode === 'disabled'"
|
||||
@click="browseMysqlTlsFile('cert')"
|
||||
>
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.mysqlClientCertBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<Input
|
||||
v-model="mysqlClientKeyPath"
|
||||
class="flex-1"
|
||||
:placeholder="t('connection.mysqlClientKeyPlaceholder')"
|
||||
:disabled="mysqlTlsMode === 'preferred' || mysqlTlsMode === 'disabled'"
|
||||
/>
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class="h-9 w-9 shrink-0"
|
||||
:disabled="mysqlTlsMode === 'preferred' || mysqlTlsMode === 'disabled'"
|
||||
@click="browseMysqlTlsFile('key')"
|
||||
>
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.mysqlClientKeyBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<p class="text-[11px] leading-4 text-muted-foreground">
|
||||
{{ t("connection.mysqlClientCertHint") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="supportsPostgresTlsOptions">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label class="text-right text-xs">{{ t("connection.postgresSslMode") }}</Label>
|
||||
<Select v-model="postgresTlsMode">
|
||||
<SelectTrigger class="col-span-3 h-9">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="disable">{{ t("connection.postgresSslModeDisable") }}</SelectItem>
|
||||
<SelectItem value="prefer">{{ t("connection.postgresSslModePrefer") }}</SelectItem>
|
||||
<SelectItem value="require">{{ t("connection.postgresSslModeRequire") }}</SelectItem>
|
||||
<SelectItem value="verify-ca">{{ t("connection.postgresSslModeVerifyCa") }}</SelectItem>
|
||||
<SelectItem value="verify-full">{{ t("connection.postgresSslModeVerifyFull") }}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-4 items-start gap-4">
|
||||
<Label class="pt-2 text-right text-xs">
|
||||
<span class="inline-flex items-center justify-end gap-1">
|
||||
<ShieldCheck class="h-3.5 w-3.5" />
|
||||
{{ t("connection.postgresServerCert") }}
|
||||
</span>
|
||||
</Label>
|
||||
<div class="col-span-3 space-y-2">
|
||||
<div class="flex items-center gap-1">
|
||||
<Input
|
||||
v-model="postgresRootCertPath"
|
||||
class="flex-1"
|
||||
:placeholder="t('connection.postgresRootCertPlaceholder')"
|
||||
:disabled="postgresTlsMode === 'disable'"
|
||||
/>
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class="h-9 w-9 shrink-0"
|
||||
:disabled="postgresTlsMode === 'disable'"
|
||||
@click="browsePostgresTlsFile('root')"
|
||||
>
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.postgresRootCertBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<p class="text-[11px] leading-4 text-muted-foreground">
|
||||
{{ t("connection.postgresRootCertHint") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-4 items-start gap-4">
|
||||
<Label class="pt-2 text-right text-xs">
|
||||
<span class="inline-flex items-center justify-end gap-1">
|
||||
<KeyRound class="h-3.5 w-3.5" />
|
||||
{{ t("connection.postgresClientCert") }}
|
||||
</span>
|
||||
</Label>
|
||||
<div class="col-span-3 grid gap-2">
|
||||
<div class="flex items-center gap-1">
|
||||
<Input
|
||||
v-model="postgresClientCertPath"
|
||||
class="flex-1"
|
||||
:placeholder="t('connection.postgresClientCertPlaceholder')"
|
||||
:disabled="postgresTlsMode === 'disable'"
|
||||
/>
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class="h-9 w-9 shrink-0"
|
||||
:disabled="postgresTlsMode === 'disable'"
|
||||
@click="browsePostgresTlsFile('cert')"
|
||||
>
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.postgresClientCertBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<Input
|
||||
v-model="postgresClientKeyPath"
|
||||
class="flex-1"
|
||||
:placeholder="t('connection.postgresClientKeyPlaceholder')"
|
||||
:disabled="postgresTlsMode === 'disable'"
|
||||
/>
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class="h-9 w-9 shrink-0"
|
||||
:disabled="postgresTlsMode === 'disable'"
|
||||
@click="browsePostgresTlsFile('key')"
|
||||
>
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.postgresClientKeyBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<p class="text-[11px] leading-4 text-muted-foreground">
|
||||
{{ t("connection.postgresClientCertHint") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="supportsCaCertificatePath" class="grid grid-cols-4 items-center gap-4">
|
||||
<Label class="text-right text-xs">{{ t("connection.caCertPath") }}</Label>
|
||||
<div class="col-span-3 flex items-center gap-1">
|
||||
|
||||
@@ -122,6 +122,37 @@ export default {
|
||||
caCertPath: "CA Certificate",
|
||||
caCertPathPlaceholder: "Optional, e.g. ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "Browse certificate",
|
||||
mysqlTlsMode: "TLS Mode",
|
||||
mysqlTlsModePreferred: "Preferred",
|
||||
mysqlTlsModeDisabled: "Disabled",
|
||||
mysqlTlsModeRequired: "Required",
|
||||
mysqlTlsModeVerifyCa: "Verify CA",
|
||||
mysqlTlsModeVerifyIdentity: "Verify Identity",
|
||||
mysqlCaCertHint: "Required for Verify CA and Verify Identity when the server certificate uses a private CA.",
|
||||
mysqlClientCert: "Client Auth",
|
||||
mysqlClientCertPlaceholder: "/path/to/client.crt",
|
||||
mysqlClientKeyPlaceholder: "/path/to/client.key",
|
||||
mysqlClientCertHint: "Client certificate and private key must be provided together when MySQL requires mTLS.",
|
||||
mysqlClientCertBrowse: "Choose client certificate",
|
||||
mysqlClientKeyBrowse: "Choose client private key",
|
||||
postgresSslMode: "TLS Mode",
|
||||
postgresSslModeDisable: "Disable",
|
||||
postgresSslModePrefer: "Prefer",
|
||||
postgresSslModeRequire: "Require",
|
||||
postgresSslModeVerifyCa: "Verify CA",
|
||||
postgresSslModeVerifyFull: "Verify Full",
|
||||
postgresServerCert: "Server CA",
|
||||
postgresRootCertPlaceholder: "/path/to/ca.crt",
|
||||
postgresRootCertHint:
|
||||
"Use this for verify-ca or verify-full when the server certificate is signed by a private CA.",
|
||||
postgresRootCertBrowse: "Choose CA certificate",
|
||||
postgresClientCert: "Client Auth",
|
||||
postgresClientCertPlaceholder: "/path/to/client.crt",
|
||||
postgresClientKeyPlaceholder: "/path/to/client.key",
|
||||
postgresClientCertHint:
|
||||
"Client certificate and private key must be provided together when PostgreSQL requires mTLS.",
|
||||
postgresClientCertBrowse: "Choose client certificate",
|
||||
postgresClientKeyBrowse: "Choose client private key",
|
||||
connectionUrlOptional: "URL (optional)",
|
||||
connectionUrlPlaceholder: "postgresql://user:pass{'@'}host:5432/db?sslmode=require",
|
||||
parseConnectionUrl: "Parse connection URL",
|
||||
|
||||
@@ -112,6 +112,39 @@ export default {
|
||||
driverName: "Nombre del driver",
|
||||
driverNamePlaceholder: "Nombre del proveedor o entorno",
|
||||
urlParams: "Parámetros de URL",
|
||||
sslEnable: "Habilitar conexión cifrada",
|
||||
caCertPath: "Certificado CA",
|
||||
caCertPathPlaceholder: "Opcional, p. ej. ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "Buscar certificado",
|
||||
mysqlTlsMode: "Modo TLS",
|
||||
mysqlTlsModePreferred: "Preferido",
|
||||
mysqlTlsModeDisabled: "Deshabilitado",
|
||||
mysqlTlsModeRequired: "Requerido",
|
||||
mysqlTlsModeVerifyCa: "Verificar CA",
|
||||
mysqlTlsModeVerifyIdentity: "Verificar identidad",
|
||||
mysqlCaCertHint: "Requerido para Verificar CA e Identidad cuando el certificado usa una CA privada.",
|
||||
mysqlClientCert: "Autenticación cliente",
|
||||
mysqlClientCertPlaceholder: "/ruta/a/client.crt",
|
||||
mysqlClientKeyPlaceholder: "/ruta/a/client.key",
|
||||
mysqlClientCertHint: "El certificado y la clave privada deben indicarse juntos si MySQL requiere mTLS.",
|
||||
mysqlClientCertBrowse: "Elegir certificado cliente",
|
||||
mysqlClientKeyBrowse: "Elegir clave privada cliente",
|
||||
postgresSslMode: "Modo TLS",
|
||||
postgresSslModeDisable: "Deshabilitar",
|
||||
postgresSslModePrefer: "Preferir",
|
||||
postgresSslModeRequire: "Requerir",
|
||||
postgresSslModeVerifyCa: "Verificar CA",
|
||||
postgresSslModeVerifyFull: "Verificar completo",
|
||||
postgresServerCert: "CA del servidor",
|
||||
postgresRootCertPlaceholder: "/ruta/a/ca.crt",
|
||||
postgresRootCertHint: "Úsalo con verify-ca o verify-full cuando el certificado del servidor use una CA privada.",
|
||||
postgresRootCertBrowse: "Elegir certificado CA",
|
||||
postgresClientCert: "Autenticación cliente",
|
||||
postgresClientCertPlaceholder: "/ruta/a/client.crt",
|
||||
postgresClientKeyPlaceholder: "/ruta/a/client.key",
|
||||
postgresClientCertHint: "El certificado y la clave privada deben indicarse juntos si PostgreSQL requiere mTLS.",
|
||||
postgresClientCertBrowse: "Elegir certificado cliente",
|
||||
postgresClientKeyBrowse: "Elegir clave privada cliente",
|
||||
connectionUrlOptional: "URL (opcional)",
|
||||
connectionUrlPlaceholder: "postgresql://usuario:contraseña{'@'}host:5432/db?sslmode=require",
|
||||
parseConnectionUrl: "Analizar URL de conexión",
|
||||
|
||||
@@ -121,6 +121,35 @@ export default {
|
||||
caCertPath: "CA 证书",
|
||||
caCertPathPlaceholder: "可选,例如 ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "选择证书",
|
||||
mysqlTlsMode: "TLS 模式",
|
||||
mysqlTlsModePreferred: "优先使用",
|
||||
mysqlTlsModeDisabled: "禁用",
|
||||
mysqlTlsModeRequired: "必须使用",
|
||||
mysqlTlsModeVerifyCa: "验证 CA",
|
||||
mysqlTlsModeVerifyIdentity: "验证身份",
|
||||
mysqlCaCertHint: "服务端证书由私有 CA 签发时,Verify CA / Verify Identity 模式需要填写。",
|
||||
mysqlClientCert: "客户端认证",
|
||||
mysqlClientCertPlaceholder: "/path/to/client.crt",
|
||||
mysqlClientKeyPlaceholder: "/path/to/client.key",
|
||||
mysqlClientCertHint: "MySQL 要求 mTLS 时,客户端证书和私钥必须一起填写。",
|
||||
mysqlClientCertBrowse: "选择客户端证书",
|
||||
mysqlClientKeyBrowse: "选择客户端私钥",
|
||||
postgresSslMode: "TLS 模式",
|
||||
postgresSslModeDisable: "禁用",
|
||||
postgresSslModePrefer: "优先使用",
|
||||
postgresSslModeRequire: "必须使用",
|
||||
postgresSslModeVerifyCa: "验证 CA",
|
||||
postgresSslModeVerifyFull: "完整验证",
|
||||
postgresServerCert: "服务端 CA",
|
||||
postgresRootCertPlaceholder: "/path/to/ca.crt",
|
||||
postgresRootCertHint: "服务端证书由私有 CA 签发时,在 verify-ca 或 verify-full 模式下填写。",
|
||||
postgresRootCertBrowse: "选择 CA 证书",
|
||||
postgresClientCert: "客户端认证",
|
||||
postgresClientCertPlaceholder: "/path/to/client.crt",
|
||||
postgresClientKeyPlaceholder: "/path/to/client.key",
|
||||
postgresClientCertHint: "PostgreSQL 要求 mTLS 时,客户端证书和私钥必须一起填写。",
|
||||
postgresClientCertBrowse: "选择客户端证书",
|
||||
postgresClientKeyBrowse: "选择客户端私钥",
|
||||
connectionUrlOptional: "URL(可选)",
|
||||
connectionUrlPlaceholder: "postgresql://user:pass{'@'}host:5432/db?sslmode=require",
|
||||
parseConnectionUrl: "解析连接 URL",
|
||||
|
||||
Reference in New Issue
Block a user