Файли
openidea/src/features/ssh/index.ts
T
arookieofcтаa-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 рядки
1.7 KiB
TypeScript
Неформатований Анотація Історія

Цей файл містить неоднозначні символи Юнікоду
Цей файл містить символи Юнікоду, які можна сплутати з іншими символами. Якщо ви вважаєте, що це зроблено навмисно, можете сміливо ігнорувати це попередження. Щоб показати їх, скористайтеся кнопкою Escape.
/**
* 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: [] });
};
}