import { useParams } from 'react-router-dom'; import { useQuery, useMutation } from '@tanstack/react-query'; import { getIssuer, testIssuerConnection, getCertificates } from '../api/client'; import PageHeader from '../components/PageHeader'; import StatusBadge from '../components/StatusBadge'; import DataTable from '../components/DataTable'; import type { Column } from '../components/DataTable'; import ErrorState from '../components/ErrorState'; import { formatDateTime } from '../api/utils'; import type { Certificate } from '../api/types'; const typeLabels: Record = { local_ca: 'Local CA', acme: 'ACME (Let\'s Encrypt)', step_ca: 'step-ca', openssl: 'OpenSSL / Custom', vault: 'Vault PKI', }; function InfoRow({ label, value }: { label: string; value: React.ReactNode }) { return (
{label} {value}
); } export default function IssuerDetailPage() { const { id } = useParams<{ id: string }>(); const { data: issuer, isLoading, error, refetch } = useQuery({ queryKey: ['issuer', id], queryFn: () => getIssuer(id!), enabled: !!id, }); const { data: certsData } = useQuery({ queryKey: ['certificates', { issuer_id: id }], queryFn: () => getCertificates({ issuer_id: id! }), enabled: !!id, }); const testMutation = useMutation({ mutationFn: () => testIssuerConnection(id!), }); if (error) { return ( <> refetch()} /> ); } if (isLoading || !issuer) { return ( <>
Loading issuer...
); } // Redact sensitive config fields const safeConfig = issuer.config ? Object.fromEntries( Object.entries(issuer.config).map(([k, v]) => { const sensitive = ['password', 'secret', 'token', 'key', 'hmac', 'private'].some(s => k.toLowerCase().includes(s)); return [k, sensitive ? '********' : v]; }) ) : {}; const certColumns: Column[] = [ { key: 'name', label: 'Certificate', render: (c) => (
{c.common_name}
{c.id}
), }, { key: 'status', label: 'Status', render: (c) => }, { key: 'expires', label: 'Expires', render: (c) => {formatDateTime(c.expires_at)} }, ]; return ( <> testMutation.mutate()} disabled={testMutation.isPending} className="btn btn-primary text-xs disabled:opacity-50" > {testMutation.isPending ? 'Testing...' : 'Test Connection'} } />
{testMutation.isSuccess && (
Connection test passed.
)} {testMutation.isError && (
Connection test failed: {(testMutation.error as Error).message}
)}
{/* Issuer info */}

Issuer Information

{issuer.id}} /> } />
{/* Config (redacted) */}

Configuration

{Object.keys(safeConfig).length > 0 ? (
{Object.entries(safeConfig).map(([key, val]) => ( {String(val)} } /> ))}
) : (
No configuration data
)}
{/* Issued certificates */}

Issued Certificates {certsData ? `(${certsData.total})` : ''}

); }