Save SSH passwords in Windows Credential Manager and auto-type at prompt

This commit is contained in:
megaproxy 2026-05-25 20:08:31 +01:00
parent 872fb0e80e
commit 1c243b3f3f
11 changed files with 538 additions and 38 deletions

View file

@ -5,6 +5,8 @@ import {
saveWorkspace,
listSshHosts,
saveSshHosts,
setHostPassword,
deleteHostPassword,
writeToPane,
killPane,
type PaneId,
@ -262,10 +264,41 @@ export default function App() {
const openHostManager = useCallback(() => setHostManagerOpen(true), []);
const closeHostManager = useCallback(() => setHostManagerOpen(false), []);
const saveHosts = useCallback((next: SshHost[]) => {
setHosts(next);
saveSshHosts(next).catch((e) =>
console.warn("saveSshHosts failed:", e),
const saveHosts = useCallback(
(next: SshHost[]) => {
// Preserve hasPassword flags that aren't included in the payload from
// HostManager (the manager strips them — backend recomputes on next
// list_ssh_hosts; we keep them locally so the badge doesn't flicker).
setHosts((prev) =>
next.map((h) => {
const hp = h.hasPassword ?? prev.find((p) => p.id === h.id)?.hasPassword;
return hp === undefined ? h : { ...h, hasPassword: hp };
}),
);
saveSshHosts(next).catch((e) =>
console.warn("saveSshHosts failed:", e),
);
},
[],
);
const savePassword = useCallback((hostId: string, password: string) => {
setHostPassword(hostId, password).then(
() =>
setHosts((prev) =>
prev.map((h) => (h.id === hostId ? { ...h, hasPassword: true } : h)),
),
(e) => console.warn("setHostPassword failed:", e),
);
}, []);
const clearPassword = useCallback((hostId: string) => {
deleteHostPassword(hostId).then(
() =>
setHosts((prev) =>
prev.map((h) => (h.id === hostId ? { ...h, hasPassword: false } : h)),
),
(e) => console.warn("deleteHostPassword failed:", e),
);
}, []);
@ -715,6 +748,8 @@ export default function App() {
<HostManager
hosts={hosts}
onSave={saveHosts}
onSavePassword={savePassword}
onClearPassword={clearPassword}
onClose={closeHostManager}
/>
)}