feat(auth): include authentication in workspace and tht diagnostics
This commit is contained in:
@@ -23,6 +23,7 @@ import {
|
||||
saveWorkspaceSecrets,
|
||||
testWorkspace,
|
||||
validateWorkspace,
|
||||
type AuthDiagnostics,
|
||||
type WorkspaceRuntimeConfiguration,
|
||||
} from "../api/workspaces";
|
||||
import { captureAuthOperation, isAuthOperationCurrent, StaleAuthOperationError } from "../auth/authOperation";
|
||||
@@ -81,6 +82,7 @@ export function WorkspaceManager({
|
||||
const [validationDiagnostics, setValidationDiagnostics] = useState<string[]>([]);
|
||||
const [connectionNotice, setConnectionNotice] = useState<string>();
|
||||
const [connectionDiagnostics, setConnectionDiagnostics] = useState<string[]>([]);
|
||||
const [authentication, setAuthentication] = useState<AuthDiagnostics>();
|
||||
const [busyAction, setBusyAction] = useState<string>();
|
||||
const operationEpochRef = useRef(0);
|
||||
const selectedIdRef = useRef(selectedId);
|
||||
@@ -135,6 +137,7 @@ export function WorkspaceManager({
|
||||
setValidationDiagnostics([]);
|
||||
setConnectionNotice(undefined);
|
||||
setConnectionDiagnostics([]);
|
||||
setAuthentication(undefined);
|
||||
};
|
||||
|
||||
const clearGlobalMessages = () => {
|
||||
@@ -194,9 +197,10 @@ export function WorkspaceManager({
|
||||
setValidationNotice(undefined);
|
||||
setValidationDiagnostics([]);
|
||||
try {
|
||||
await validateWorkspace(detailQuery.data.workspace);
|
||||
const result = await validateWorkspace(detailQuery.data.workspace);
|
||||
if (!isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) return;
|
||||
setValidationNotice("Workspace source is valid.");
|
||||
setAuthentication(result.authentication);
|
||||
setValidationNotice(result.activatable ? "Workspace source and authentication are valid." : "Workspace source is valid.");
|
||||
} catch (error) {
|
||||
if (isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) {
|
||||
setValidationDiagnostics([publicError(error, "workspace_invalid: Workspace validation could not be completed")]);
|
||||
@@ -218,6 +222,7 @@ export function WorkspaceManager({
|
||||
try {
|
||||
const result = await testWorkspace(selectedId);
|
||||
if (!isAuthOperationCurrent(guard, { sessionId: selectedIdRef.current, disposalEpoch: operationEpochRef.current })) return;
|
||||
setAuthentication(result.authentication);
|
||||
const issues = result.diagnostics.filter(({ level }) => level !== "info");
|
||||
const informational = result.diagnostics.find(({ level }) => level === "info");
|
||||
setConnectionDiagnostics(issues.map(({ code, message }) => `${code}: ${message}`));
|
||||
@@ -480,6 +485,23 @@ export function WorkspaceManager({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{authentication && <section data-testid="workspace-authentication" className="rounded-lg border border-border p-4">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<h4 className="font-heading font-semibold">Authentication</h4>
|
||||
<span className={authentication.ready ? "text-sm font-medium text-emerald-700" : "text-sm font-medium text-amber-700"}>
|
||||
{authentication.ready ? "Passed" : "Failed"}
|
||||
</span>
|
||||
</div>
|
||||
{!authentication.ready && <div role="alert" className="mt-3 grid gap-1 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-sm">
|
||||
{authentication.checks.filter(({ level }) => level === "error").map(({ code, field, message }) => (
|
||||
<p key={`${code}:${field ?? ""}`} className="flex items-start gap-2">
|
||||
<AlertCircle className="mt-0.5 size-4 shrink-0 text-amber-700" />
|
||||
{code}: {field === undefined ? message : `${field} — ${message}`}
|
||||
</p>
|
||||
))}
|
||||
</div>}
|
||||
</section>}
|
||||
|
||||
{canManageSecrets && <div className="rounded-lg border border-border p-4">
|
||||
<div className="mb-4 flex items-start gap-3">
|
||||
<KeyRound className="mt-0.5 size-5 text-primary" />
|
||||
|
||||
Reference in New Issue
Block a user