feat(hive): add Kerberos connection options
This commit is contained in:
1 parent
5b70626cf7
commit
2929b1c035
30 files changed
+639
-23
No files matched your search
@@ -48,6 +48,7 @@ import { isSchemaAware } from "@/lib/database/databaseFeatureSupport";
|
||||
import VisibleSchemasDialog from "@/components/sidebar/VisibleSchemasDialog.vue";
|
||||
import { oceanbaseModeConnectionPatch, oceanbaseSubModeFromConfig } from "@/lib/database/oceanbaseConnectionMode";
|
||||
import { translateBackendError } from "@/i18n/backend-errors";
|
||||
import { applyHiveKerberosSubmitConfig, hiveKerberosFormConfig, type HiveKerberosAuthMode } from "@/lib/database/hiveKerberosOptions";
|
||||
|
||||
type DbOption = { value: string; label: string };
|
||||
type DbCategory = { key: string; title: string; options: DbOption[] };
|
||||
@@ -151,6 +152,7 @@ const defaultForm = (): ConnectionForm => ({
|
||||
driver_profile: "mysql",
|
||||
driver_label: "MySQL",
|
||||
url_params: "",
|
||||
agent_java_options: [],
|
||||
host: "127.0.0.1",
|
||||
port: 3306,
|
||||
username: "root",
|
||||
@@ -378,6 +380,12 @@ const dremioConnectionUrls = ref<Record<DremioConnectionMode, string>>({
|
||||
"arrow-flight-sql": DREMIO_ARROW_FLIGHT_SQL_JDBC_URL,
|
||||
legacy: DREMIO_LEGACY_JDBC_URL,
|
||||
});
|
||||
const hiveAuthMode = ref<HiveKerberosAuthMode>("none");
|
||||
const hivePrincipal = ref("");
|
||||
const hiveKrb5ConfPath = ref("");
|
||||
const hiveJaasConfigPath = ref("");
|
||||
const hiveUseSubjectCredsOnlyFalse = ref(false);
|
||||
const hiveExtraJavaOptions = ref("");
|
||||
const dialogStep = ref<DialogStep>("select");
|
||||
const dbPickerView = ref<DbPickerView>("icon");
|
||||
const dbSearchQuery = ref("");
|
||||
@@ -775,6 +783,16 @@ function hydrateInfluxDbFields(value: unknown) {
|
||||
resetInfluxDbFields(value as Partial<InfluxDbExternalConfig>);
|
||||
}
|
||||
|
||||
function resetHiveKerberosFields(config?: Pick<ConnectionConfig, "url_params" | "agent_java_options">) {
|
||||
const kerberos = hiveKerberosFormConfig(config?.url_params, config?.agent_java_options);
|
||||
hiveAuthMode.value = kerberos.authMode;
|
||||
hivePrincipal.value = kerberos.principal;
|
||||
hiveKrb5ConfPath.value = kerberos.krb5ConfPath;
|
||||
hiveJaasConfigPath.value = kerberos.jaasConfigPath;
|
||||
hiveUseSubjectCredsOnlyFalse.value = kerberos.useSubjectCredsOnlyFalse;
|
||||
hiveExtraJavaOptions.value = kerberos.extraJavaOptions;
|
||||
}
|
||||
|
||||
function buildInfluxDbExternalConfig(): InfluxDbExternalConfig {
|
||||
if (influxDbVersion.value !== "2") return { version: "1" };
|
||||
const org = influxDbOrg.value.trim();
|
||||
@@ -1202,6 +1220,7 @@ function applyProfile(val: string, preserveConnectionFields = false) {
|
||||
form.value.port = profile.port;
|
||||
form.value.username = profile.user;
|
||||
form.value.url_params = profile.urlParams || "";
|
||||
form.value.agent_java_options = [];
|
||||
if (profile.host) {
|
||||
form.value.host = profile.host;
|
||||
}
|
||||
@@ -1258,6 +1277,7 @@ function applyProfile(val: string, preserveConnectionFields = false) {
|
||||
form.value.password = "";
|
||||
form.value.connection_string = undefined;
|
||||
}
|
||||
resetHiveKerberosFields(profile.type === "hive" ? form.value : undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1294,6 +1314,7 @@ watch(
|
||||
driver_profile: oceanbasePatch?.driver_profile || profile,
|
||||
driver_label: config.driver_label || oceanbasePatch?.driver_label || driverProfiles[profile]?.label || config.db_type,
|
||||
url_params: config.url_params || "",
|
||||
agent_java_options: config.agent_java_options || [],
|
||||
host: config.db_type === "h2" && h2FilePathFromJdbcUrl(config.connection_string) ? h2FilePathFromJdbcUrl(config.connection_string) : config.host,
|
||||
port: profile === "tdengine" && (config.port === 0 || config.port === 6030) ? 6041 : config.port,
|
||||
username: config.username,
|
||||
@@ -1346,6 +1367,7 @@ watch(
|
||||
} else {
|
||||
resetInfluxDbFields();
|
||||
}
|
||||
resetHiveKerberosFields(config.db_type === "hive" ? config : undefined);
|
||||
h2ConnectionMode.value = h2ConnectionModeForConfig(config);
|
||||
customColorInput.value = config.color || "";
|
||||
selectedTransportLayerId.value = form.value.transport_layers?.[0]?.id || null;
|
||||
@@ -1373,6 +1395,7 @@ watch(
|
||||
resetMqFields();
|
||||
resetNacosFields();
|
||||
resetInfluxDbFields();
|
||||
resetHiveKerberosFields();
|
||||
oceanbaseSubMode.value = "mysql";
|
||||
h2ConnectionMode.value = "file";
|
||||
dremioConnectionMode.value = "legacy";
|
||||
@@ -2128,6 +2151,24 @@ function connectionConfigForSubmit(id: string): ConnectionConfig {
|
||||
if (config.db_type === "manticoresearch") {
|
||||
config.url_params = "";
|
||||
}
|
||||
if (config.db_type === "hive") {
|
||||
if (hiveAuthMode.value === "kerberos" && !hivePrincipal.value.trim()) {
|
||||
throw new Error(t("connection.hiveKerberosPrincipalRequired"));
|
||||
}
|
||||
const hiveKerberos = applyHiveKerberosSubmitConfig({
|
||||
authMode: hiveAuthMode.value,
|
||||
principal: hivePrincipal.value,
|
||||
krb5ConfPath: hiveKrb5ConfPath.value,
|
||||
jaasConfigPath: hiveJaasConfigPath.value,
|
||||
useSubjectCredsOnlyFalse: hiveUseSubjectCredsOnlyFalse.value,
|
||||
extraJavaOptions: hiveExtraJavaOptions.value,
|
||||
urlParams: config.url_params,
|
||||
});
|
||||
config.url_params = hiveKerberos.urlParams;
|
||||
config.agent_java_options = hiveKerberos.agentJavaOptions;
|
||||
} else {
|
||||
config.agent_java_options = undefined;
|
||||
}
|
||||
if (config.db_type === "informix" && config.informix_server) {
|
||||
// Strip INFORMIXSERVER from url_params to avoid duplicate when dedicated field is used
|
||||
config.url_params = (config.url_params || "")
|
||||
@@ -2339,6 +2380,7 @@ function connectionConfigForSubmit(id: string): ConnectionConfig {
|
||||
config.visible_databases = Array.isArray(config.visible_databases) && config.visible_databases.length > 0 ? config.visible_databases : undefined;
|
||||
}
|
||||
if (config.visible_schemas && Object.keys(config.visible_schemas).length === 0) config.visible_schemas = undefined;
|
||||
if (config.agent_java_options && config.agent_java_options.length === 0) config.agent_java_options = undefined;
|
||||
return config as ConnectionConfig;
|
||||
}
|
||||
|
||||
@@ -3239,6 +3281,24 @@ async function browseEtcdTlsFile(target: "ca" | "cert" | "key") {
|
||||
}
|
||||
}
|
||||
|
||||
async function browseHiveKerberosFile(target: "krb5" | "jaas") {
|
||||
if (isTauriRuntime()) {
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
const selected = await open({
|
||||
title: target === "krb5" ? t("connection.hiveKrb5ConfBrowse") : t("connection.hiveJaasConfigBrowse"),
|
||||
multiple: false,
|
||||
filters: [{ name: "Config", extensions: ["conf", "ini", "properties", "*"] }],
|
||||
});
|
||||
if (selected && typeof selected === "string") {
|
||||
if (target === "krb5") {
|
||||
hiveKrb5ConfPath.value = selected;
|
||||
} else {
|
||||
hiveJaasConfigPath.value = selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function browseDbFilePath() {
|
||||
if (isTauriRuntime()) {
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
@@ -4387,6 +4447,76 @@ function openExternalUrl(url: string) {
|
||||
<Input v-model="form.database" class="col-span-3" :placeholder="databasePlaceholder" />
|
||||
</div>
|
||||
|
||||
<template v-if="form.db_type === 'hive'">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelClass">{{ t("connection.hiveAuthMode") }}</Label>
|
||||
<div class="col-span-3 grid h-8 grid-cols-2 overflow-hidden rounded-md border border-input bg-muted/30 p-0.5">
|
||||
<button type="button" class="h-7 rounded-sm px-3 text-sm transition-colors" :class="hiveAuthMode === 'none' ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'" :aria-pressed="hiveAuthMode === 'none'" @click="hiveAuthMode = 'none'">
|
||||
{{ t("connection.hiveAuthNone") }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="h-7 rounded-sm px-3 text-sm transition-colors"
|
||||
:class="hiveAuthMode === 'kerberos' ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'"
|
||||
:aria-pressed="hiveAuthMode === 'kerberos'"
|
||||
@click="hiveAuthMode = 'kerberos'"
|
||||
>
|
||||
Kerberos
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="hiveAuthMode === 'kerberos'">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("connection.hivePrincipal") }}</Label>
|
||||
<Input v-model="hivePrincipal" class="col-span-3" placeholder="hive/_HOST@EXAMPLE.COM" />
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">krb5.conf</Label>
|
||||
<div class="col-span-3 flex items-center gap-1">
|
||||
<Input v-model="hiveKrb5ConfPath" class="flex-1" placeholder="/etc/krb5.conf" />
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="outline" size="icon" class="h-9 w-9 shrink-0" @click="browseHiveKerberosFile('krb5')">
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.hiveKrb5ConfBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">JAAS</Label>
|
||||
<div class="col-span-3 flex items-center gap-1">
|
||||
<Input v-model="hiveJaasConfigPath" class="flex-1" placeholder="/etc/hive-jaas.conf" />
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="outline" size="icon" class="h-9 w-9 shrink-0" @click="browseHiveKerberosFile('jaas')">
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.hiveJaasConfigBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("connection.hiveTicketCache") }}</Label>
|
||||
<label class="col-span-3 flex items-center gap-2 cursor-pointer">
|
||||
<input type="checkbox" v-model="hiveUseSubjectCredsOnlyFalse" class="mr-0" />
|
||||
<span class="text-xs text-muted-foreground">{{ t("connection.hiveTicketCacheFallback") }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 items-start gap-4">
|
||||
<Label :class="connectionLabelTopClass">{{ t("connection.hiveJvmOptions") }}</Label>
|
||||
<textarea
|
||||
v-model="hiveExtraJavaOptions"
|
||||
class="col-span-3 min-h-16 rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
||||
:placeholder="t('connection.hiveJvmOptionsPlaceholder')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<div v-if="form.db_type === 'oracle'" class="grid grid-cols-4 items-center gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("connection.mode") }}</Label>
|
||||
<div class="col-span-3 grid h-8 grid-cols-2 overflow-hidden rounded-md border border-input bg-muted/30 p-0.5">
|
||||
|
||||
Reference in new issue
Block a user