feat: store rdp, vnc and telnet logins in a generic per-protocol table

This commit is contained in:
LukeGus committed 2026-09-29 12:33:09 -05:00
1 parent e0c30a4e6f
commit bba06f7ff6
107 files changed
+18750 -1224

No files matched your search

+4 -51
View File
@@ -1,55 +1,8 @@
export const AUTH_OVERRIDE_PROTOCOLS = ["ssh", "rdp", "vnc", "telnet"] as const;
/** Core's own protocol. Every other one is declared by a plugin. */
export const SSH_AUTH_PROTOCOL = "ssh";
export type AuthOverrideProtocol = (typeof AUTH_OVERRIDE_PROTOCOLS)[number];
const SUPPORTED_AUTH_OVERRIDE_PROTOCOLS =
AUTH_OVERRIDE_PROTOCOLS satisfies readonly AuthOverrideProtocol[];
export const AUTH_PROTOCOL_METADATA = {
ssh: {
label: "SSH",
credentialField: "credentialId",
},
rdp: {
label: "RDP",
credentialField: "rdpCredentialId",
},
vnc: {
label: "VNC",
credentialField: "vncCredentialId",
},
telnet: {
label: "Telnet",
credentialField: "telnetCredentialId",
},
} as const satisfies Record<
AuthOverrideProtocol,
{
label: string;
credentialField:
| "credentialId"
| "rdpCredentialId"
| "vncCredentialId"
| "telnetCredentialId";
}
>;
export function isAuthOverrideProtocol(
value: unknown,
): value is AuthOverrideProtocol {
return (
typeof value === "string" &&
AUTH_OVERRIDE_PROTOCOLS.includes(value as AuthOverrideProtocol)
);
}
export function isSupportedAuthOverrideProtocol(
protocol: AuthOverrideProtocol,
): boolean {
return SUPPORTED_AUTH_OVERRIDE_PROTOCOLS.includes(
protocol as (typeof SUPPORTED_AUTH_OVERRIDE_PROTOCOLS)[number],
);
}
/** "ssh", or a protocol id a plugin declares in contributes.protocols. */
export type AuthOverrideProtocol = string;
export interface HostAuthOverrideState<
CredentialId extends number | string = number,
+25 -32
View File
@@ -1,4 +1,8 @@
import type { HostSshOptions } from "@termix/plugin-sdk/frontend";
import type {
HostProtocolAuthSummary,
HostProtocolAuthType,
HostSshOptions,
} from "@termix/plugin-sdk/frontend";
import type { Request } from "express";
import type { RefObject } from "react";
import type { HostAuthOverrides } from "./auth-protocols.js";
@@ -15,6 +19,19 @@ export type {
export type SSHAuthType =
"password" | "key" | "credential" | "none" | "agent" | (string & {});
export type { HostProtocolAuthSummary, HostProtocolAuthType };
/** One plugin protocol's login in a host write. */
export interface HostProtocolAuthInput {
authType?: HostProtocolAuthType;
credentialId?: number | null;
username?: string | null;
/** Left out to keep the saved password. */
password?: string | null;
/** Declared credential fields; one left out keeps its value. */
fields?: Record<string, string | null>;
}
export type WebEndpointAccess = "direct" | "tunnel";
export type WebEndpointRender = "external" | "embedded";
@@ -109,23 +126,11 @@ export type Host = {
/** "ssh", or the id of the plugin protocol a host without SSH uses. */
connectionType?: string;
domain?: string;
enableSsh?: boolean;
sshPort?: number;
rdpCredentialId?: number | null;
rdpUser?: string;
rdpPassword?: string;
rdpDomain?: string;
vncCredentialId?: number | null;
vncPassword?: string;
vncUser?: string;
telnetUser?: string;
telnetPassword?: string;
telnetCredentialId?: number | null;
rdpAuthType?: "direct" | "credential" | "none" | null;
vncAuthType?: "direct" | "credential" | null;
telnetAuthType?: "direct" | "credential" | null;
/** Each plugin protocol's login, secrets left out. */
protocolAuth?: Record<string, HostProtocolAuthSummary>;
/**
* Stable identity across a desktop/server sync pair. `id` is an
* autoincrement local to whichever database produced the row, so it cannot
@@ -148,9 +153,6 @@ export type Host = {
// tell a stored secret from an empty one without receiving it.
hasPassword?: boolean;
hasSudoPassword?: boolean;
hasRdpPassword?: boolean;
hasVncPassword?: boolean;
hasTelnetPassword?: boolean;
isShared?: boolean;
authOverrides?: HostAuthOverrides;
@@ -228,23 +230,14 @@ export interface HostData {
/** "ssh", or the id of the plugin protocol a host without SSH uses. */
connectionType?: string;
domain?: string;
enableSsh?: boolean;
sshPort?: number;
rdpCredentialId?: number | null;
rdpUser?: string;
rdpPassword?: string;
rdpDomain?: string;
vncCredentialId?: number | null;
vncPassword?: string;
vncUser?: string;
telnetUser?: string;
telnetPassword?: string;
telnetCredentialId?: number | null;
rdpAuthType?: "direct" | "credential" | "none" | null;
vncAuthType?: "direct" | "credential" | null;
telnetAuthType?: "direct" | "credential" | null;
/**
* Plugin protocol logins to write, keyed by protocol id. A key left out
* keeps its login, null removes it, and a field left out keeps its value.
*/
protocolAuth?: Record<string, HostProtocolAuthInput | null>;
/** Desktop only: kept on this device, never synced to the server. */
localOnly?: boolean;
}
+6 -18
View File
@@ -1,9 +1,11 @@
import type {
HostProtocolAuthSummary,
HostSshOptions,
HostTerminalConfig,
SSHAuthType,
} from "./index.js";
import type { HostAuthOverrides } from "./auth-protocols.js";
import type { QuickConnectLogin } from "@termix/plugin-sdk/frontend";
export type Host = {
id: string;
@@ -44,6 +46,8 @@ export type Host = {
pin?: boolean;
/** Quick connect only: core can save this host as-is. */
quickConnectSavable?: boolean;
/** A Quick Connect host's plugin protocol login, never saved. */
quickConnectLogin?: QuickConnectLogin;
sortOrder?: number | null;
/** Stable identity across a desktop/server sync pair. */
@@ -80,24 +84,8 @@ export type Host = {
sshPort: number;
rdpAuthType?: "direct" | "credential" | "none";
rdpCredentialId?: string;
rdpUser?: string;
rdpPassword?: string;
hasRdpPassword?: boolean;
domain?: string;
vncAuthType?: "direct" | "credential";
vncCredentialId?: string;
vncPassword?: string;
hasVncPassword?: boolean;
vncUser?: string;
telnetAuthType?: "direct" | "credential";
telnetCredentialId?: string;
telnetUser?: string;
telnetPassword?: string;
hasTelnetPassword?: boolean;
/** Each plugin protocol's login, secrets left out. */
protocolAuth?: Record<string, HostProtocolAuthSummary>;
/** Host-scope plugin settings, keyed by plugin id. Secrets are redacted. */
pluginSettings?: Record<string, Record<string, unknown>>;