Files
openidea/src/features/ssh/index.ts
T
arookieofcanda-rookie-of-C-language e85ffa2ae8 feat(git): remember HTTPS credentials in the app secret store (#321)
Git no longer asks for the HTTPS user name and password on every fetch, pull and push. The password prompt offers "Remember for this host"; the credential is saved in the app's secret store (next to the saved SSH passwords, never in git's global configuration) only after the git command that used it succeeds, and a stored credential the server rejects is forgotten so the next command asks again. Settings › Version Control › Git lists saved credentials and forgets them.

Each git child gets its own id, passed to the askpass helper, so concurrent commands never save or forget each other's credentials. ide-vcs reports command completion through an observer installed at start-up instead of depending on ide-ssh. Credentials are keyed by scheme, host and port, and only git's authentication errors (Authentication failed, HTTP 401/403 responses, invalid username or password) forget a stored credential.

Fixes #272

Co-authored-by: a-rookie-of-C-language <[email protected]>
2026-10-30 10:48:29 +08:00

44 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* SSH: credential prompts of `ssh` / `git` child processes (askpass) and
* Tools › Start SSH Session. The configurations live in Settings › Tools ›
* SSH Configurations.
*/
import { executeAction, registerActions } from "@/platform/actions";
import { onIdeEvent } from "@/platform/ipc";
import { registerOverlay } from "@/workbench/contributions";
import { dropAskpass, enqueueAskpass, useAskpass } from "./askpass";
import { AskpassHost } from "./AskpassDialog";
import { chooseSshSession, SSH_SETTINGS_PAGE, startSshSession } from "./session";
export function activate(): () => void {
const disposers = [
registerOverlay({ id: "ssh.askpass", component: AskpassHost }),
onIdeEvent("askpass", (e) => enqueueAskpass({ id: e.id, prompt: e.prompt, kind: e.kind, remember: e.remember })),
onIdeEvent("askpassDone", (e) => dropAskpass(e.id)),
registerActions([
{
id: "ssh.startSession",
title: "Start SSH Session…",
description: "Opens a terminal tab connected to an SSH configuration (`arg`: its id; otherwise a chooser).",
category: "Tools",
icon: "terminal",
when: "projectOpen",
keywords: ["ssh", "remote", "terminal", "shell", "connect"],
run: ({ arg }) => (typeof arg === "string" && arg ? startSshSession(arg) : chooseSshSession()),
},
{
id: "ssh.configurations",
title: "SSH Configurations…",
category: "Tools",
icon: "settings",
keywords: ["ssh", "remote", "host"],
run: () => void executeAction("file.settings", SSH_SETTINGS_PAGE),
},
]),
];
return () => {
disposers.reverse().forEach((d) => d());
useAskpass.setState({ queue: [] });
};
}