From 540cfaa0f6ee19c41fea537554f9227872a7d518 Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Fri, 19 Sep 2025 01:21:00 +0800 Subject: [PATCH] Fix SSH password authentication logic by removing requirePassword field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit eliminates the confusing requirePassword field that was causing authentication issues where users couldn't disable password requirements. Changes: - Remove requirePassword field from database schema and migrations - Simplify SSH authentication logic by removing special case branches - Update frontend to remove requirePassword UI controls - Clean up translation files to remove unused strings - Support standard SSH empty password authentication The new design follows the principle of "good taste" - password field itself now expresses the requirement: null/empty = no password auth, value = use password. Fixes the issue where setting requirePassword=false didn't work as expected. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/backend/database/db/index.ts | 5 --- src/backend/database/db/schema.ts | 3 -- src/backend/database/routes/ssh.ts | 12 ------ src/backend/utils/database-sqlite-export.ts | 3 -- src/locales/en/translation.json | 2 - src/locales/zh/translation.json | 2 - .../Apps/Host Manager/HostManagerEditor.tsx | 37 +------------------ 7 files changed, 1 insertion(+), 63 deletions(-) diff --git a/src/backend/database/db/index.ts b/src/backend/database/db/index.ts index de401ce4..7974716e 100644 --- a/src/backend/database/db/index.ts +++ b/src/backend/database/db/index.ts @@ -365,11 +365,6 @@ const migrateSchema = () => { "INTEGER REFERENCES ssh_credentials(id)", ); - addColumnIfNotExists( - "ssh_data", - "require_password", - "INTEGER NOT NULL DEFAULT 1", - ); // SSH credentials table migrations for encryption support addColumnIfNotExists("ssh_credentials", "private_key", "TEXT"); diff --git a/src/backend/database/db/schema.ts b/src/backend/database/db/schema.ts index dd764c22..7e64d754 100644 --- a/src/backend/database/db/schema.ts +++ b/src/backend/database/db/schema.ts @@ -45,9 +45,6 @@ export const sshData = sqliteTable("ssh_data", { authType: text("auth_type").notNull(), password: text("password"), - requirePassword: integer("require_password", { mode: "boolean" }) - .notNull() - .default(true), key: text("key", { length: 8192 }), keyPassword: text("key_password"), keyType: text("key_type"), diff --git a/src/backend/database/routes/ssh.ts b/src/backend/database/routes/ssh.ts index 34bc9451..dfe9643b 100644 --- a/src/backend/database/routes/ssh.ts +++ b/src/backend/database/routes/ssh.ts @@ -77,7 +77,6 @@ router.get("/db/host/internal", async (req: Request, res: Response) => { : [] : [], pin: !!row.pin, - requirePassword: !!row.requirePassword, enableTerminal: !!row.enableTerminal, enableTunnel: !!row.enableTunnel, tunnelConnections: row.tunnelConnections @@ -138,7 +137,6 @@ router.post( port, username, password, - requirePassword, authMethod, authType, credentialId, @@ -190,7 +188,6 @@ router.post( if (effectiveAuthType === "password") { sshDataObj.password = password || null; - sshDataObj.requirePassword = requirePassword !== false ? 1 : 0; sshDataObj.key = null; sshDataObj.keyPassword = null; sshDataObj.keyType = null; @@ -199,14 +196,12 @@ router.post( sshDataObj.keyPassword = keyPassword || null; sshDataObj.keyType = keyType; sshDataObj.password = null; - sshDataObj.requirePassword = 1; // Default to true for non-password auth } else { // For credential auth sshDataObj.password = null; sshDataObj.key = null; sshDataObj.keyPassword = null; sshDataObj.keyType = null; - sshDataObj.requirePassword = 1; // Default to true for non-password auth } try { @@ -237,7 +232,6 @@ router.post( : [] : [], pin: !!createdHost.pin, - requirePassword: !!createdHost.requirePassword, enableTerminal: !!createdHost.enableTerminal, enableTunnel: !!createdHost.enableTunnel, tunnelConnections: createdHost.tunnelConnections @@ -324,7 +318,6 @@ router.put( port, username, password, - requirePassword, authMethod, authType, credentialId, @@ -379,7 +372,6 @@ router.put( if (password) { sshDataObj.password = password; } - sshDataObj.requirePassword = requirePassword !== false ? 1 : 0; sshDataObj.key = null; sshDataObj.keyPassword = null; sshDataObj.keyType = null; @@ -394,14 +386,12 @@ router.put( sshDataObj.keyType = keyType; } sshDataObj.password = null; - sshDataObj.requirePassword = 1; // Default to true for non-password auth } else { // For credential auth sshDataObj.password = null; sshDataObj.key = null; sshDataObj.keyPassword = null; sshDataObj.keyType = null; - sshDataObj.requirePassword = 1; // Default to true for non-password auth } try { @@ -441,7 +431,6 @@ router.put( : [] : [], pin: !!updatedHost.pin, - requirePassword: !!updatedHost.requirePassword, enableTerminal: !!updatedHost.enableTerminal, enableTunnel: !!updatedHost.enableTunnel, tunnelConnections: updatedHost.tunnelConnections @@ -509,7 +498,6 @@ router.get("/db/host", authenticateJWT, async (req: Request, res: Response) => { : [] : [], pin: !!row.pin, - requirePassword: !!row.requirePassword, enableTerminal: !!row.enableTerminal, enableTunnel: !!row.enableTunnel, tunnelConnections: row.tunnelConnections diff --git a/src/backend/utils/database-sqlite-export.ts b/src/backend/utils/database-sqlite-export.ts index d586ce31..56c3aa7b 100644 --- a/src/backend/utils/database-sqlite-export.ts +++ b/src/backend/utils/database-sqlite-export.ts @@ -126,7 +126,6 @@ class DatabaseSQLiteExport { pin INTEGER NOT NULL DEFAULT 0, auth_type TEXT NOT NULL, password TEXT, - require_password INTEGER NOT NULL DEFAULT 1, key TEXT, key_password TEXT, key_type TEXT, @@ -225,7 +224,6 @@ class DatabaseSQLiteExport { const fieldMappings: Record = { userId: "user_id", authType: "auth_type", - requirePassword: "require_password", keyPassword: "key_password", keyType: "key_type", credentialId: "credential_id", @@ -464,7 +462,6 @@ class DatabaseSQLiteExport { const columnToFieldMappings: Record = { user_id: "userId", auth_type: "authType", - require_password: "requirePassword", key_password: "keyPassword", key_type: "keyType", credential_id: "credentialId", diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 5f74a015..4545dae8 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -576,8 +576,6 @@ "upload": "Upload", "authentication": "Authentication", "password": "Password", - "requirePassword": "Require Password", - "requirePasswordDescription": "When disabled, sessions can be saved without entering a password", "key": "Key", "credential": "Credential", "selectCredential": "Select Credential", diff --git a/src/locales/zh/translation.json b/src/locales/zh/translation.json index e902cdae..9a83e9c4 100644 --- a/src/locales/zh/translation.json +++ b/src/locales/zh/translation.json @@ -576,8 +576,6 @@ "upload": "上传", "authentication": "认证方式", "password": "密码", - "requirePassword": "要求密码", - "requirePasswordDescription": "禁用时,可以在不输入密码的情况下保存会话", "key": "密钥", "credential": "凭证", "selectCredential": "选择凭证", diff --git a/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx b/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx index 9e1f5c75..687aff3f 100644 --- a/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx +++ b/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx @@ -45,7 +45,6 @@ interface SSHHost { pin: boolean; authType: string; password?: string; - requirePassword?: boolean; key?: string; keyPassword?: string; keyType?: string; @@ -173,7 +172,6 @@ export function HostManagerEditor({ authType: z.enum(["password", "key", "credential"]), credentialId: z.number().optional().nullable(), password: z.string().optional(), - requirePassword: z.boolean().default(true), key: z.any().optional().nullable(), keyPassword: z.string().optional(), keyType: z @@ -207,18 +205,7 @@ export function HostManagerEditor({ defaultPath: z.string().optional(), }) .superRefine((data, ctx) => { - if (data.authType === "password") { - if ( - data.requirePassword && - (!data.password || data.password.trim() === "") - ) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: t("hosts.passwordRequired"), - path: ["password"], - }); - } - } else if (data.authType === "key") { + if (data.authType === "key") { if ( !data.key || (typeof data.key === "string" && data.key.trim() === "") @@ -279,7 +266,6 @@ export function HostManagerEditor({ authType: "password" as const, credentialId: null, password: "", - requirePassword: true, key: null, keyPassword: "", keyType: "auto" as const, @@ -336,7 +322,6 @@ export function HostManagerEditor({ authType: defaultAuthType as "password" | "key" | "credential", credentialId: null, password: "", - requirePassword: cleanedHost.requirePassword ?? true, key: null, keyPassword: "", keyType: "auto" as const, @@ -372,7 +357,6 @@ export function HostManagerEditor({ authType: "password" as const, credentialId: null, password: "", - requirePassword: true, key: null, keyPassword: "", keyType: "auto" as const, @@ -879,24 +863,6 @@ export function HostManagerEditor({ - ( - - {t("hosts.requirePassword")} - - - - - {t("hosts.requirePasswordDescription")} - - - )} - />