Add optional password requirement for SSH sessions (Issue #118)

Users can now choose whether to require a password when saving SSH sessions.
A new "Require Password" toggle has been added to the password authentication
tab, allowing sessions to be saved without entering a password when disabled.

- Add requirePassword boolean field to SSH host schema (defaults to true)
- Update form validation to conditionally require password based on setting
- Add "Require Password" toggle with description in Host Manager UI
- Update all backend SSH routes to handle requirePassword field correctly
- Add translations for new UI elements in English and Chinese
- Maintain full backward compatibility with existing hosts

Resolves #118
This commit is contained in:
ZacharyZcR
2025-09-16 11:21:50 +08:00
parent c2545f9279
commit 182b60a428
5 changed files with 56 additions and 1 deletions

View File

@@ -45,6 +45,9 @@ 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"),

View File

@@ -77,6 +77,7 @@ 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
@@ -137,6 +138,7 @@ router.post(
port,
username,
password,
requirePassword,
authMethod,
authType,
credentialId,
@@ -188,6 +190,7 @@ router.post(
if (effectiveAuthType === "password") {
sshDataObj.password = password || null;
sshDataObj.requirePassword = requirePassword !== false ? 1 : 0;
sshDataObj.key = null;
sshDataObj.keyPassword = null;
sshDataObj.keyType = null;
@@ -196,6 +199,14 @@ 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 {
@@ -222,6 +233,7 @@ router.post(
: []
: [],
pin: !!createdHost.pin,
requirePassword: !!createdHost.requirePassword,
enableTerminal: !!createdHost.enableTerminal,
enableTunnel: !!createdHost.enableTunnel,
tunnelConnections: createdHost.tunnelConnections
@@ -308,6 +320,7 @@ router.put(
port,
username,
password,
requirePassword,
authMethod,
authType,
credentialId,
@@ -362,6 +375,7 @@ router.put(
if (password) {
sshDataObj.password = password;
}
sshDataObj.requirePassword = requirePassword !== false ? 1 : 0;
sshDataObj.key = null;
sshDataObj.keyPassword = null;
sshDataObj.keyType = null;
@@ -376,6 +390,14 @@ 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 {
@@ -408,6 +430,7 @@ router.put(
: []
: [],
pin: !!updatedHost.pin,
requirePassword: !!updatedHost.requirePassword,
enableTerminal: !!updatedHost.enableTerminal,
enableTunnel: !!updatedHost.enableTunnel,
tunnelConnections: updatedHost.tunnelConnections
@@ -475,6 +498,7 @@ 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