Redact quick connection endpoints (#598)
* fix: redact quick connection endpoints * fix: redact host-like quick connection names --------- Co-authored-by: t8y2 <1156263951@qq.com>
This commit is contained in:
1 parent
7eca75b325
commit
87a43644de
3 files changed
+153
-4
No files matched your search
@@ -2,7 +2,12 @@
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { FilePlus2, Plus, History, Upload, Database, Search, ShieldCheck, Sparkles } from "lucide-vue-next";
|
||||
import DatabaseIcon from "@/components/icons/DatabaseIcon.vue";
|
||||
import { connectionDriverLabel, connectionIconType, connectionOptionSubtitle } from "@/lib/connectionPresentation";
|
||||
import {
|
||||
connectionDriverLabel,
|
||||
connectionIconType,
|
||||
connectionRedactedNameLabel,
|
||||
connectionRedactedOptionSubtitle,
|
||||
} from "@/lib/connectionPresentation";
|
||||
import type { ConnectionConfig } from "@/types/database";
|
||||
|
||||
defineProps<{
|
||||
@@ -64,9 +69,9 @@ const { t } = useI18n();
|
||||
<DatabaseIcon :db-type="connectionIconType(connection)" class="h-4 w-4" />
|
||||
<span class="h-5 w-1 rounded-full shrink-0" :style="{ backgroundColor: connection.color || '#9ca3af' }" />
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="truncate text-sm font-medium">{{ connection.name }}</div>
|
||||
<div class="truncate text-sm font-medium">{{ connectionRedactedNameLabel(connection) }}</div>
|
||||
<div class="truncate text-xs text-muted-foreground">
|
||||
{{ connectionOptionSubtitle(connection) || connectionDriverLabel(connection) }}
|
||||
{{ connectionRedactedOptionSubtitle(connection) || connectionDriverLabel(connection) }}
|
||||
</div>
|
||||
</div>
|
||||
<FilePlus2 class="h-4 w-4 text-muted-foreground" />
|
||||
|
||||
@@ -4,8 +4,11 @@ type ConnectionPresentationConfig = Pick<
|
||||
ConnectionConfig,
|
||||
"db_type" | "driver_profile" | "driver_label" | "host" | "port" | "database"
|
||||
>;
|
||||
type ConnectionNamePresentationConfig = ConnectionPresentationConfig & Pick<ConnectionConfig, "name">;
|
||||
|
||||
const LOCAL_DATABASE_TYPES = new Set(["sqlite", "duckdb", "access"]);
|
||||
const REDACTED_HOST_SEGMENT = "***";
|
||||
const REDACTED_PORT = "****";
|
||||
|
||||
export function connectionIconType(connection?: Pick<ConnectionConfig, "db_type" | "driver_profile">): string {
|
||||
return connection?.driver_profile || connection?.db_type || "postgres";
|
||||
@@ -24,6 +27,62 @@ export function connectionEndpointLabel(connection?: ConnectionPresentationConfi
|
||||
return connection.host || connection.database || "";
|
||||
}
|
||||
|
||||
function redactConnectionHost(host: string): string {
|
||||
const normalizedHost = host.trim();
|
||||
if (!normalizedHost) return "";
|
||||
|
||||
const unwrappedHost =
|
||||
normalizedHost.startsWith("[") && normalizedHost.endsWith("]") ? normalizedHost.slice(1, -1) : normalizedHost;
|
||||
const separator = unwrappedHost.includes(":") ? ":" : ".";
|
||||
const segments = unwrappedHost.split(separator).filter(Boolean);
|
||||
|
||||
if (segments.length >= 3) {
|
||||
return [segments[0], ...segments.slice(1, -1).map(() => REDACTED_HOST_SEGMENT), segments[segments.length - 1]].join(
|
||||
separator,
|
||||
);
|
||||
}
|
||||
|
||||
if (segments.length === 2) {
|
||||
return [segments[0], REDACTED_HOST_SEGMENT].join(separator);
|
||||
}
|
||||
|
||||
return REDACTED_HOST_SEGMENT;
|
||||
}
|
||||
|
||||
export function connectionRedactedEndpointLabel(connection?: ConnectionPresentationConfig): string {
|
||||
if (!connection) return "";
|
||||
if (LOCAL_DATABASE_TYPES.has(connection.db_type)) {
|
||||
return connectionEndpointLabel(connection);
|
||||
}
|
||||
|
||||
const redactedHost = connection.host ? redactConnectionHost(connection.host) : "";
|
||||
if (redactedHost && connection.port) {
|
||||
const endpointHost = redactedHost.includes(":") ? `[${redactedHost}]` : redactedHost;
|
||||
return `${endpointHost}:${REDACTED_PORT}`;
|
||||
}
|
||||
|
||||
return redactedHost || connection.database || "";
|
||||
}
|
||||
|
||||
export function connectionRedactedNameLabel(connection?: ConnectionNamePresentationConfig): string {
|
||||
const name = connection?.name.trim() || "";
|
||||
if (!connection || !name || LOCAL_DATABASE_TYPES.has(connection.db_type)) return name;
|
||||
|
||||
const host = connection.host.trim();
|
||||
if (!host) return name;
|
||||
|
||||
const unwrappedHost = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
|
||||
const hostNames = new Set([host, unwrappedHost]);
|
||||
if (connection.port) {
|
||||
hostNames.add(`${host}:${connection.port}`);
|
||||
if (unwrappedHost.includes(":")) {
|
||||
hostNames.add(`[${unwrappedHost}]:${connection.port}`);
|
||||
}
|
||||
}
|
||||
|
||||
return hostNames.has(name) ? connectionRedactedEndpointLabel(connection) : name;
|
||||
}
|
||||
|
||||
export function connectionUrlPlaceholder(dbType: DatabaseType): string {
|
||||
switch (dbType) {
|
||||
case "mysql":
|
||||
@@ -90,3 +149,7 @@ export function connectionUrlPlaceholder(dbType: DatabaseType): string {
|
||||
export function connectionOptionSubtitle(connection?: ConnectionPresentationConfig): string {
|
||||
return [connectionDriverLabel(connection), connectionEndpointLabel(connection)].filter(Boolean).join(" · ");
|
||||
}
|
||||
|
||||
export function connectionRedactedOptionSubtitle(connection?: ConnectionPresentationConfig): string {
|
||||
return [connectionDriverLabel(connection), connectionRedactedEndpointLabel(connection)].filter(Boolean).join(" · ");
|
||||
}
|
||||
Reference in new issue
Block a user