[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
89
domain/passwordPromptAssist.ts
Normal file
89
domain/passwordPromptAssist.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import type { Host, Identity, SSHKey } from "./models";
|
||||
import { sanitizeCredentialValue } from "./credentials";
|
||||
import { resolveHostAuth, resolveHostAutofillPassword } from "./sshAuth";
|
||||
|
||||
export type PasswordPromptFillCandidate = {
|
||||
id: string;
|
||||
source: "host" | "identity";
|
||||
label: string;
|
||||
username?: string;
|
||||
/** Sanitized plaintext. Callers must not log or render this in UI. */
|
||||
password: string;
|
||||
};
|
||||
|
||||
const hostCandidateId = "host";
|
||||
const identityCandidateId = (identityId: string) => `identity:${identityId}`;
|
||||
|
||||
/**
|
||||
* Build the credential list for sudo/su password-prompt assist (#2156).
|
||||
* Host session password first, then every decryptable keychain password
|
||||
* identity. Dedupes by password value so the same secret is not listed twice.
|
||||
*/
|
||||
export const listPasswordPromptFillCandidates = (args: {
|
||||
host: Host;
|
||||
keys: SSHKey[];
|
||||
identities?: Identity[];
|
||||
}): PasswordPromptFillCandidate[] => {
|
||||
const candidates: PasswordPromptFillCandidate[] = [];
|
||||
const seenPasswords = new Set<string>();
|
||||
|
||||
const push = (candidate: PasswordPromptFillCandidate) => {
|
||||
if (!candidate.password || seenPasswords.has(candidate.password)) return;
|
||||
seenPasswords.add(candidate.password);
|
||||
candidates.push(candidate);
|
||||
};
|
||||
|
||||
// Same resolution path as login so group-inherited identities and identityId
|
||||
// references surface the correct username next to the session password.
|
||||
const resolvedAuth = resolveHostAuth(args);
|
||||
const hostPassword = resolveHostAutofillPassword(args);
|
||||
if (hostPassword) {
|
||||
const hostLabel =
|
||||
args.host.label?.trim()
|
||||
|| args.host.hostname?.trim()
|
||||
|| resolvedAuth.username?.trim()
|
||||
|| args.host.username?.trim()
|
||||
|| "Host";
|
||||
push({
|
||||
id: hostCandidateId,
|
||||
source: "host",
|
||||
label: hostLabel,
|
||||
username: resolvedAuth.username?.trim() || args.host.username?.trim() || undefined,
|
||||
password: hostPassword,
|
||||
});
|
||||
}
|
||||
|
||||
const identities = args.identities ?? [];
|
||||
// Stable order: explicit order field, then created, then id.
|
||||
const ordered = [...identities].sort((a, b) => {
|
||||
const ao = a.order ?? Number.MAX_SAFE_INTEGER;
|
||||
const bo = b.order ?? Number.MAX_SAFE_INTEGER;
|
||||
if (ao !== bo) return ao - bo;
|
||||
if (a.created !== b.created) return a.created - b.created;
|
||||
return a.id.localeCompare(b.id);
|
||||
});
|
||||
|
||||
for (const identity of ordered) {
|
||||
if (identity.authMethod !== "password") continue;
|
||||
const password = sanitizeCredentialValue(identity.password);
|
||||
if (!password) continue;
|
||||
const label = identity.label?.trim() || identity.username?.trim() || identity.id;
|
||||
push({
|
||||
id: identityCandidateId(identity.id),
|
||||
source: "identity",
|
||||
label,
|
||||
username: identity.username?.trim() || undefined,
|
||||
password,
|
||||
});
|
||||
}
|
||||
|
||||
return candidates;
|
||||
};
|
||||
|
||||
/** Prefer host candidate password; fall back to first available candidate. */
|
||||
export const resolveDefaultPasswordPromptFillPassword = (
|
||||
candidates: PasswordPromptFillCandidate[],
|
||||
): string | undefined => {
|
||||
const host = candidates.find((c) => c.source === "host");
|
||||
return host?.password ?? candidates[0]?.password;
|
||||
};
|
||||
Reference in New Issue
Block a user