mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-08-29 18:31:33 +00:00
fix: harden connection, payload, and persisted state handling (#1354)
* fix: clean up Cloudflare tunnel timeouts * fix: couple tunnel socket lifecycle * fix: validate Docker console messages * fix: bound homepage proxy responses * fix: bound reconnect and response failures * fix: harden persisted and socket state * fix: support local connections to shared hosts
This commit is contained in:
@@ -11,10 +11,66 @@ export function markRemoteSharedHosts(hosts: SSHHost[]): SSHHost[] {
|
||||
// Local SQLite ids are positive. Negative ids keep remote-only shared
|
||||
// rows distinct while syncId remains the delegated backend identity.
|
||||
id: -Math.abs(host.id),
|
||||
connectionOrigin: "remote" as const,
|
||||
}));
|
||||
}
|
||||
|
||||
export interface SharedHostConnectionAuth {
|
||||
username?: string | null;
|
||||
authType?: string | null;
|
||||
password?: string | null;
|
||||
key?: string | null;
|
||||
keyPassword?: string | null;
|
||||
keyType?: string | null;
|
||||
}
|
||||
|
||||
export async function getRemoteSharedHostConnectionAuth(
|
||||
localHostId: number,
|
||||
): Promise<SharedHostConnectionAuth> {
|
||||
if (localHostId >= 0) {
|
||||
throw new Error("Expected a remote shared host id");
|
||||
}
|
||||
const api = await getConnectedRemoteApi();
|
||||
if (!api) throw new Error("Remote server is not connected");
|
||||
const response = await api.get(
|
||||
`/host/db/host/${Math.abs(localHostId)}/local-connection-auth`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function hydrateLocalSharedHostAuth<
|
||||
T extends {
|
||||
id?: number;
|
||||
isShared?: unknown;
|
||||
syncId?: string | null;
|
||||
credentialId?: number;
|
||||
username: string;
|
||||
authType?: string;
|
||||
password?: string;
|
||||
key?: string;
|
||||
keyPassword?: string;
|
||||
keyType?: string;
|
||||
},
|
||||
>(host: T): Promise<T> {
|
||||
if (!host.isShared || typeof host.id !== "number" || host.id >= 0) {
|
||||
return host;
|
||||
}
|
||||
|
||||
const auth = await getRemoteSharedHostConnectionAuth(host.id);
|
||||
return {
|
||||
...host,
|
||||
// This row deliberately does not exist in the embedded database. Avoid
|
||||
// asking the local backend to resolve its remote sync identity again.
|
||||
syncId: null,
|
||||
credentialId: undefined,
|
||||
username: auth.username || host.username,
|
||||
authType: auth.authType || host.authType,
|
||||
password: auth.password || undefined,
|
||||
key: auth.key || undefined,
|
||||
keyPassword: auth.keyPassword || undefined,
|
||||
keyType: auth.keyType || undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getConnectedRemoteApi(): Promise<AxiosInstance | null> {
|
||||
if (!isElectron()) return null;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user