/** * @file GitIdentitySettings.tsx * @description Settings → Git → **Your git identity** (`/api/me/git`): the * commit author (name + email in the account's global git config — prefilled * from Settings → Account while unset, the email else `@smartgift.vn`, * since a member's commits fail without one; a new SSH key is labelled with * that email), the SSH * keys a clone (Add workspace → Clone) and the pushes from that clone use — * an ED25519 and/or an RSA one (AWS CodeCommit takes only RSA) — make one, copy its public half to add to GitHub/GitLab, replace or delete * it, and whether git typed in the account's own terminal uses it too (a * switch over `core.sshCommand` in its `~/.gitconfig`, issue #82), the SSH * login name per host (AWS CodeCommit's SSH key ID, a `url.<…>.insteadOf` in * that same file, so a plain `ssh://git-codecommit…` URL works) — and, for * a user with their own Linux account (S3), their own HTTPS * logins. The host account's HTTPS logins are the shared Git credentials * table above it, so this lists them only for a member. The private key and * every token are write-only: the server never returns them. A host identity * seen by a non-admin is read-only. * @author Nguyễn Ngọc Trí Vĩ */ import { useCallback, useEffect, useState, type ReactNode } from "react"; import { useTranslation } from "react-i18next"; import { Copy, KeyRound, Plus, RefreshCw, Trash2 } from "lucide-react"; import { api, type GitIdentity } from "../../lib/api"; import { confirmDialog } from "../../lib/confirm"; import { copyText } from "../../lib/clipboard"; import { toast } from "../../lib/toast"; import { useAuth } from "../AuthGate"; import { Switch } from "../Switch"; const INPUT = "w-full rounded border border-border-light bg-surface-0 px-2 py-1 text-xs text-fg-primary placeholder:text-fg-muted focus:border-accent focus:outline-none"; const BTN = "inline-flex items-center gap-1.5 rounded border border-border-light px-2.5 py-1 text-xs text-fg-secondary hover:bg-surface-3 disabled:cursor-not-allowed disabled:opacity-40"; const CODECOMMIT_RE = /^git-codecommit\.([a-z0-9-]+)\.amazonaws\.com$/; // The regions AWS CodeCommit runs in. const AWS_REGIONS = [ "ap-southeast-1", "ap-southeast-2", "ap-southeast-3", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", "ap-south-1", "ap-east-1", "us-east-1", "us-east-2", "us-west-1", "us-west-2", "ca-central-1", "eu-west-1", "eu-west-2", "eu-west-3", "eu-central-1", "eu-north-1", "eu-south-1", "sa-east-1", "me-south-1", "af-south-1", "il-central-1", ]; function Step({ n, children }: { n: number; children: ReactNode }) { return (
{n}
{children}
); } function Code({ children }: { children: ReactNode }) { return ( {children} ); } type Key = NonNullable[number]; /** * One kind of git host and the key it takes: no key → a Generate button; * a key → step 1 (copy its public half) followed by the host's own steps. */ function KeyCard({ title, sub, type, k, id, busy, onGenerate, onRemove, children, }: { title: string; sub: string; type: "ed25519" | "rsa"; k: Key | undefined; id: GitIdentity; busy: boolean; onGenerate: (type: "ed25519" | "rsa") => Promise; onRemove: (type: "ed25519" | "rsa") => Promise; children: ReactNode; }) { const { t } = useTranslation("settings"); return (
{title}
{sub}
{id.writable && ( )} {k && id.writable && ( )}
{k ? ( <>
{t("gitIdentity.stepCopy")}