The credential expiry feature has been removed from both the Rust backend and the frontend. Stored credentials now include only username and password. - Remove expiresAt field from StoredCredential - Simplify API by removing expiry param from credSave - Drop expiry UI and expiry checks across the app
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
/**
|
|
* Derives a credential key from a remote URL, scoped to host + organisation —
|
|
* the same granularity Azure DevOps / GitHub use. Examples:
|
|
* https://github.com/owner/repo.git -> github.com/owner
|
|
* https://dev.azure.com/org/project/_git/repo -> dev.azure.com/org
|
|
* git@github.com:owner/repo.git -> github.com/owner
|
|
* ssh://git@host:2222/owner/repo -> host/owner
|
|
* Returns null when nothing usable can be parsed.
|
|
*/
|
|
export function orgKeyFromUrl(raw: string): string | null {
|
|
const url = raw.trim();
|
|
if (!url) return null;
|
|
|
|
let host = "";
|
|
let path = "";
|
|
|
|
// scp-like syntax: user@host:owner/repo.git (no scheme, single colon segment)
|
|
const scp = url.match(/^[^@/]+@([^:/]+):(.+)$/);
|
|
if (scp && !url.includes("://")) {
|
|
host = scp[1];
|
|
path = scp[2];
|
|
} else {
|
|
try {
|
|
const parsed = new URL(url);
|
|
host = parsed.host; // host:port, without userinfo
|
|
path = parsed.pathname;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
host = host.toLowerCase();
|
|
const org = path.replace(/^\/+/, "").split("/").filter(Boolean)[0] ?? "";
|
|
if (!host) return null;
|
|
return org ? `${host}/${org}` : host;
|
|
}
|
|
|
|
const AUTH_PREFIX = "AUTH_FAILED:";
|
|
|
|
export function isAuthError(message: string): boolean {
|
|
return message.startsWith(AUTH_PREFIX);
|
|
}
|
|
|
|
export function stripAuthPrefix(message: string): string {
|
|
return message.startsWith(AUTH_PREFIX)
|
|
? message.slice(AUTH_PREFIX.length).trim()
|
|
: message;
|
|
}
|
|
|
|
/**
|
|
* Condenses raw git stderr to the single most relevant line for the
|
|
* credential dialog. Prefers the server's own explanation ("remote: ...")
|
|
* over git's generic wrapper ("fatal: Authentication failed for ...").
|
|
*/
|
|
export function summarizeGitError(message: string): string {
|
|
const lines = message
|
|
.split("\n")
|
|
.map((line) => line.trim())
|
|
.filter(Boolean);
|
|
const remote = lines.find((line) => line.toLowerCase().startsWith("remote:"));
|
|
return remote ?? lines[0] ?? "";
|
|
}
|