fix: preserve omitted host protocol settings (#1350)

This commit is contained in:
ZacharyZcR
2026-08-27 13:41:25 +08:00
committed by GitHub
parent ef4e66659c
commit 6277d15c2a
3 changed files with 45 additions and 9 deletions
@@ -14,6 +14,25 @@ export function isOptionalBoolean(
return value === undefined || typeof value === "boolean"; return value === undefined || typeof value === "boolean";
} }
const PROTOCOL_ENABLE_FIELDS = [
"enableSsh",
"enableRdp",
"enableVnc",
"enableTelnet",
] as const;
export function normalizeProtocolEnableFields(
values: Record<string, unknown>,
): Partial<Record<(typeof PROTOCOL_ENABLE_FIELDS)[number], 0 | 1>> {
return Object.fromEntries(
PROTOCOL_ENABLE_FIELDS.flatMap((field) =>
typeof values[field] === "boolean"
? [[field, values[field] ? 1 : 0]]
: [],
),
);
}
export const OWNER_PRIVATE_AUTH_FIELDS = { export const OWNER_PRIVATE_AUTH_FIELDS = {
ssh: [ ssh: [
"authType", "authType",
+8 -9
View File
@@ -37,6 +37,7 @@ import {
isNonEmptyString, isNonEmptyString,
isOptionalBoolean, isOptionalBoolean,
isValidPort, isValidPort,
normalizeProtocolEnableFields,
OWNER_PRIVATE_AUTH_FIELDS, OWNER_PRIVATE_AUTH_FIELDS,
OWNER_PRIVATE_TERMINAL_CONFIG_FIELDS, OWNER_PRIVATE_TERMINAL_CONFIG_FIELDS,
sanitizeHostForRecipient, sanitizeHostForRecipient,
@@ -267,7 +268,8 @@ router.post(
!isNonEmptyString(userId) || !isNonEmptyString(userId) ||
!isNonEmptyString(ip) || !isNonEmptyString(ip) ||
!isValidPort(port) || !isValidPort(port) ||
!isOptionalBoolean(shareSshAuth) !isOptionalBoolean(shareSshAuth) ||
![enableSsh, enableRdp, enableVnc, enableTelnet].every(isOptionalBoolean)
) { ) {
sshLogger.warn("Invalid SSH data input validation failed", { sshLogger.warn("Invalid SSH data input validation failed", {
operation: "host_create", operation: "host_create",
@@ -398,10 +400,7 @@ router.post(
portKnockSequence: portKnockSequence portKnockSequence: portKnockSequence
? JSON.stringify(portKnockSequence) ? JSON.stringify(portKnockSequence)
: null, : null,
enableSsh: enableSsh ? 1 : 0, ...normalizeProtocolEnableFields(hostData),
enableRdp: enableRdp ? 1 : 0,
enableVnc: enableVnc ? 1 : 0,
enableTelnet: enableTelnet ? 1 : 0,
sshPort: sshPort || port || 22, sshPort: sshPort || port || 22,
rdpPort: rdpPort || 3389, rdpPort: rdpPort || 3389,
vncPort: vncPort || 5900, vncPort: vncPort || 5900,
@@ -971,6 +970,9 @@ router.put(
!isNonEmptyString(ip) || !isNonEmptyString(ip) ||
!isValidPort(port) || !isValidPort(port) ||
!isOptionalBoolean(shareSshAuth) || !isOptionalBoolean(shareSshAuth) ||
![enableSsh, enableRdp, enableVnc, enableTelnet].every(
isOptionalBoolean,
) ||
!hostId !hostId
) { ) {
sshLogger.warn("Invalid SSH data input validation failed for update", { sshLogger.warn("Invalid SSH data input validation failed for update", {
@@ -1102,10 +1104,7 @@ router.put(
portKnockSequence: portKnockSequence portKnockSequence: portKnockSequence
? JSON.stringify(portKnockSequence) ? JSON.stringify(portKnockSequence)
: null, : null,
enableSsh: enableSsh ? 1 : 0, ...normalizeProtocolEnableFields(hostData),
enableRdp: enableRdp ? 1 : 0,
enableVnc: enableVnc ? 1 : 0,
enableTelnet: enableTelnet ? 1 : 0,
sshPort: sshPort || port || 22, sshPort: sshPort || port || 22,
rdpPort: rdpPort || 3389, rdpPort: rdpPort || 3389,
vncPort: vncPort || 5900, vncPort: vncPort || 5900,
@@ -5,6 +5,7 @@ import {
isOptionalBoolean, isOptionalBoolean,
isValidPort, isValidPort,
normalizeImportedHost, normalizeImportedHost,
normalizeProtocolEnableFields,
renameFolderPath, renameFolderPath,
sanitizeHostForRecipient, sanitizeHostForRecipient,
stripSensitiveFields, stripSensitiveFields,
@@ -80,6 +81,23 @@ describe("isOptionalBoolean", () => {
}); });
}); });
describe("normalizeProtocolEnableFields", () => {
it("omits unspecified protocol fields so database defaults are preserved", () => {
expect(normalizeProtocolEnableFields({ name: "server" })).toEqual({});
});
it("converts explicitly provided protocol booleans to database integers", () => {
expect(
normalizeProtocolEnableFields({
enableSsh: true,
enableRdp: false,
enableVnc: undefined,
enableTelnet: true,
}),
).toEqual({ enableSsh: 1, enableRdp: 0, enableTelnet: 1 });
});
});
describe("renameFolderPath", () => { describe("renameFolderPath", () => {
it("renames an exact folder match", () => { it("renames an exact folder match", () => {
expect(renameFolderPath("Production", "Production", "Prod")).toBe("Prod"); expect(renameFolderPath("Production", "Production", "Prod")).toBe("Prod");