vanta-auditor-tui
Version:
Beautiful terminal UI for exporting Vanta audit evidence with ZIP support and progress tracking
138 lines • 7.89 kB
JavaScript
import React, { useEffect, useRef, useState } from "react";
import { Box, Text } from "ink";
import { SelectInput } from "../lib/inkModules.js";
import { theme } from "../theme.js";
import { BorderedInput } from "./ui/BorderedInput.js";
import { FormSection } from "./ui/FormSection.js";
import { StepIndicator } from "./ui/StepIndicator.js";
export function CredentialsForm({ onSubmit }) {
const [mode, setMode] = useState("oauth");
const [token, setToken] = useState("");
const [clientId, setClientId] = useState("");
const [clientSecret, setClientSecret] = useState("");
const [scope, setScope] = useState("auditor-api.audit:read auditor-api.auditor:read");
const [region, setRegion] = useState("us");
const [serverURL, setServerURL] = useState("");
const [debug, setDebug] = useState(process.argv.includes("--verbose"));
const [stage, setStage] = useState("mode");
useEffect(() => {
// focus order managed by stage
}, [stage]);
// Submit once stage transitions to done. This must be declared before any early returns
// so that hook order remains stable across renders.
const submittedRef = useRef(false);
useEffect(() => {
if (stage === "done" && !submittedRef.current) {
submittedRef.current = true;
onSubmit({
token: mode === "token" ? token : undefined,
clientId: mode === "oauth" ? clientId : undefined,
clientSecret: mode === "oauth" ? clientSecret : undefined,
scope: mode === "oauth" ? scope : undefined,
region,
serverURL: serverURL || undefined,
debug
});
}
}, [stage, mode, token, clientId, clientSecret, scope, region, serverURL, debug]);
// Auto-advance if env vars present for faster debugging
useEffect(() => {
if (stage !== "mode")
return;
if (token) {
setMode("token");
setStage("region");
}
else if (clientId && clientSecret) {
setMode("oauth");
setStage("region");
}
}, [stage]);
if (stage === "mode") {
const items = [
{ label: "OAuth client credentials", value: "oauth" },
{ label: "Bearer token", value: "token" }
];
return (React.createElement(FormSection, { title: "\uD83E\uDD99 Welcome to Vanta Auditor TUI!", subtitle: "Let's get your audit evidence exported", borderStyle: "double" },
React.createElement(StepIndicator, { steps: [
{ label: "Auth Method", status: "active" },
{ label: "Credentials", status: "pending" },
{ label: "Region", status: "pending" }
] }),
React.createElement(Box, { flexDirection: "column", marginTop: 1 },
React.createElement(Text, { color: theme.colors.primaryLight }, "Choose authentication method:"),
React.createElement(Box, { borderStyle: "single", borderColor: theme.colors.primary, paddingX: 1, paddingY: 1, marginTop: 1 },
React.createElement(SelectInput, { items: items, onSelect: (i) => {
setMode(i.value);
setStage(i.value === "oauth" ? "oauthClientId" : "token");
} })))));
}
if (stage === "token") {
return (React.createElement(FormSection, { title: "\uD83D\uDD10 Bearer Token Authentication", subtitle: "Enter your Vanta API bearer token" },
React.createElement(StepIndicator, { steps: [
{ label: "Auth Method", status: "completed" },
{ label: "API Token", status: "active" },
{ label: "Region", status: "pending" }
] }),
React.createElement(BorderedInput, { label: "API Token:", value: token, onChange: setToken, mask: "*", placeholder: "vat_...", onSubmit: () => setStage("region"), width: 50 })));
}
if (stage === "oauthClientId") {
return (React.createElement(FormSection, { title: "\uD83D\uDD10 OAuth Client Credentials", subtitle: "Step 1 of 3: Enter your Client ID" },
React.createElement(StepIndicator, { steps: [
{ label: "Auth Method", status: "completed" },
{ label: "Client ID", status: "active" },
{ label: "Client Secret", status: "pending" },
{ label: "Scopes", status: "pending" },
{ label: "Region", status: "pending" }
] }),
React.createElement(BorderedInput, { label: "Client ID:", value: clientId, onChange: setClientId, onSubmit: () => setStage("oauthClientSecret"), placeholder: "Enter your OAuth client ID", width: 50 })));
}
if (stage === "oauthClientSecret") {
return (React.createElement(FormSection, { title: "\uD83D\uDD10 OAuth Client Credentials", subtitle: "Step 2 of 3: Enter your Client Secret" },
React.createElement(StepIndicator, { steps: [
{ label: "Auth Method", status: "completed" },
{ label: "Client ID", status: "completed" },
{ label: "Client Secret", status: "active" },
{ label: "Scopes", status: "pending" },
{ label: "Region", status: "pending" }
] }),
React.createElement(BorderedInput, { label: "Client Secret:", value: clientSecret, onChange: setClientSecret, mask: "*", onSubmit: () => setStage("oauthScope"), placeholder: "Enter your OAuth client secret", width: 50 })));
}
if (stage === "oauthScope") {
return (React.createElement(FormSection, { title: "\uD83D\uDD10 OAuth Client Credentials", subtitle: "Step 3 of 3: Specify API scopes" },
React.createElement(StepIndicator, { steps: [
{ label: "Auth Method", status: "completed" },
{ label: "Client ID", status: "completed" },
{ label: "Client Secret", status: "completed" },
{ label: "Scopes", status: "active" },
{ label: "Region", status: "pending" }
] }),
React.createElement(BorderedInput, { label: "Scopes (space-separated):", value: scope, onChange: setScope, onSubmit: () => setStage("region"), placeholder: "auditor-api.audit:read auditor-api.auditor:read", width: 60 })));
}
if (stage === "region") {
const items = [
{ label: "US", value: "us" },
{ label: "EU", value: "eu" },
{ label: "AUS", value: "aus" },
{ label: "Custom URL", value: "custom" }
];
return (React.createElement(FormSection, { title: "\uD83C\uDF0E Select Your Vanta Region", subtitle: "Choose the region where your Vanta instance is hosted" },
React.createElement(Box, { borderStyle: "single", borderColor: theme.colors.primary, paddingX: 1, paddingY: 1 },
React.createElement(SelectInput, { items: items, onSelect: (i) => {
setRegion(i.value);
if (i.value === "custom")
setStage("custom");
else
setStage("done");
} }))));
}
if (stage === "custom") {
return (React.createElement(FormSection, { title: "\uD83C\uDF10 Custom Server URL", subtitle: "Enter the full URL for your Vanta API endpoint" },
React.createElement(BorderedInput, { label: "Server URL:", value: serverURL, onChange: setServerURL, placeholder: "https://api.aus.vanta.com/v1", onSubmit: () => setStage("done"), width: 60 })));
}
if (stage === "done")
return null;
return null;
}
export default CredentialsForm;
//# sourceMappingURL=CredentialsForm.js.map