import type { Metadata } from "next";
import { Accordion, Label as MuLabel } from "@unlocalhosted/metalui";
import { deleteSshKeyAction } from "@/app/actions/settings";
import { ConfirmButton } from "@/components/confirm-button";
import { KeyIcon } from "@/components/icons";
import { AccordionItem, AccordionPanel, AccordionTrigger, SettingsRow, SettingsSection } from "@/components/metal";
import { CopyIconButton } from "@/components/settings-fields";
import { ListRow, PlateSection, RowGlyph } from "@/components/settings-plate";
import { Alert, Blankslate, Box, Label, PageTitle } from "@/components/ui";
import { requireViewer } from "@/lib/auth";
import { formatDate, timeAgo } from "@/lib/format";
import { listSshKeys } from "@/lib/keys";
import { serverHost } from "@/lib/request-origin";
import { SSH_ENABLED, sshTestCommand } from "@/lib/ssh-config";
import { AddKeyForm } from "./form";
export const metadata: Metadata = { title: "SSH keys" };
export default async function KeysPage() {
const viewer = await requireViewer();
const keys = await listSshKeys(viewer.id);
const test = sshTestCommand(await serverHost());
return (
<div>
<PageTitle
title="SSH keys"
description="Keys associated with your account let you clone and push over SSH without a password."
/>
<div className="flex flex-col gap-7">
{!SSH_ENABLED && <Alert>The SSH server is disabled on this instance (SSH_DISABLED=1).</Alert>}
{keys.length === 0 ? (
<PlateSection title="Your keys">
<Blankslate icon={<KeyIcon />} title="No SSH keys yet">
Add a key below to push with <code className="font-mono">git@</code> URLs.
</Blankslate>
</PlateSection>
) : (
<SettingsSection title={`Your keys · ${keys.length}`}>
{keys.map((key) => (
<ListRow
key={key.id}
lead={
<RowGlyph>
<KeyIcon />
</RowGlyph>
}
title={
<>
<span className="truncate">{key.title}</span>
<Label>{key.keyType.replace("ssh-", "").replace("ecdsa-sha2-", "ecdsa ")}</Label>
</>
}
meta={
<>
<code className="block truncate font-mono text-[11.5px] leading-4 text-ink2">{key.fingerprint}</code>
<MuLabel variant="engraved">
Added <b>{formatDate(key.createdAt)}</b> ·{" "}
{key.lastUsedAt ? (
<>
Last used <b>{timeAgo(key.lastUsedAt)}</b>
</>
) : (
"Never used"
)}
</MuLabel>
</>
}
>
<ConfirmButton
action={deleteSshKeyAction.bind(null, key.id)}
message={`Delete the SSH key “${key.title}”? Any machine using it will lose access.`}
variant="default"
>
Delete Key
</ConfirmButton>
</ListRow>
))}
</SettingsSection>
)}
<SettingsSection title="Connection">
<SettingsRow
name="Test your connection"
detail={<code className="block truncate font-mono text-[11.5px]">{test}</code>}
>
<CopyIconButton text={test} label="Copy command" />
</SettingsRow>
</SettingsSection>
<PlateSection title="Add new SSH key">
<AddKeyForm />
</PlateSection>
<Box className="p-1.5">
<Accordion>
<AccordionItem>
<AccordionTrigger>Don’t have a key yet?</AccordionTrigger>
<AccordionPanel>
<p>Generate one and paste the contents of the <code className="font-mono">.pub</code> file:</p>
<pre className="well mt-2 overflow-x-auto rounded-row px-3.5 py-3 font-mono text-[12px] leading-5 text-ink">
ssh-keygen -t ed25519 -C "{viewer.email}"{"\n"}cat ~/.ssh/id_ed25519.pub
</pre>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Box>
</div>
</div>
);
}