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,7 @@ interface SSHHost {
pin: boolean;
authType: string;
password?: string;
requirePassword?: boolean;
key?: string;
keyPassword?: string;
keyType?: string;
@@ -172,6 +173,7 @@ 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
@@ -206,7 +208,7 @@ export function HostManagerEditor({
})
.superRefine((data, ctx) => {
if (data.authType === "password") {
if (!data.password || data.password.trim() === "") {
if (data.requirePassword && (!data.password || data.password.trim() === "")) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: t("hosts.passwordRequired"),
@@ -274,6 +276,7 @@ export function HostManagerEditor({
authType: "password" as const,
credentialId: null,
password: "",
requirePassword: true,
key: null,
keyPassword: "",
keyType: "auto" as const,
@@ -330,6 +333,7 @@ export function HostManagerEditor({
authType: defaultAuthType as "password" | "key" | "credential",
credentialId: null,
password: "",
requirePassword: cleanedHost.requirePassword ?? true,
key: null,
keyPassword: "",
keyType: "auto" as const,
@@ -365,6 +369,7 @@ export function HostManagerEditor({
authType: "password" as const,
credentialId: null,
password: "",
requirePassword: true,
key: null,
keyPassword: "",
keyType: "auto" as const,
@@ -867,6 +872,24 @@ export function HostManagerEditor({
</TabsTrigger>
</TabsList>
<TabsContent value="password">
<FormField
control={form.control}
name="requirePassword"
render={({ field }) => (
<FormItem className="mb-4">
<FormLabel>{t("hosts.requirePassword")}</FormLabel>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<FormDescription>
{t("hosts.requirePasswordDescription")}
</FormDescription>
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
@@ -876,6 +899,7 @@ export function HostManagerEditor({
<FormControl>
<PasswordInput
placeholder={t("placeholders.password")}
disabled={!form.watch("requirePassword")}
{...field}
/>
</FormControl>