"use client"; import { Checkbox } from "@heroui/checkbox"; import { zodResolver } from "@hookform/resolvers/zod"; import { Icon } from "@iconify/react"; import { useRouter } from "next/navigation"; import { useState } from "react"; import { useForm } from "react-hook-form"; import { z } from "zod"; import { checkConnectionProvider, deleteCredentials, } from "@/actions/providers"; import { scanOnDemand, scheduleDaily } from "@/actions/scans"; import { getTask } from "@/actions/task/tasks"; import { CheckIcon, RocketIcon } from "@/components/icons"; import { useToast } from "@/components/ui"; import { CustomButton } from "@/components/ui/custom"; import { CustomLink } from "@/components/ui/custom/custom-link"; import { Form } from "@/components/ui/form"; import { checkTaskStatus } from "@/lib/helper"; import { ProviderType } from "@/types"; import { ApiError, testConnectionFormSchema } from "@/types"; import { ProviderInfo } from "../.."; type FormValues = z.input; export const TestConnectionForm = ({ searchParams, providerData, }: { searchParams: { type: string; id: string; updated: string }; providerData: { data: { id: string; type: string; attributes: { uid: string; connection: { connected: boolean | null; last_checked_at: string | null; }; provider: ProviderType; alias: string; scanner_args: Record; }; relationships: { secret: { data: { type: string; id: string; } | null; }; }; }; }; }) => { const { toast } = useToast(); const router = useRouter(); const providerType = searchParams.type; const providerId = searchParams.id; const [apiErrorMessage, setApiErrorMessage] = useState(null); const [connectionStatus, setConnectionStatus] = useState<{ connected: boolean; error: string | null; } | null>(null); const [isResettingCredentials, setIsResettingCredentials] = useState(false); const [isRedirecting, setIsRedirecting] = useState(false); const formSchema = testConnectionFormSchema; const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { providerId, runOnce: false, }, }); const isLoading = form.formState.isSubmitting; const isUpdated = searchParams?.updated === "true"; const onSubmitClient = async (values: FormValues) => { const formData = new FormData(); formData.append("providerId", values.providerId); const data = await checkConnectionProvider(formData); if (data?.errors && data.errors.length > 0) { data.errors.forEach((error: ApiError) => { const errorMessage = error.detail; switch (errorMessage) { case "Not found.": setApiErrorMessage(errorMessage); break; default: toast({ variant: "destructive", title: `Error ${error.status}`, description: errorMessage, }); } }); } else { const taskId = data.data.id; setApiErrorMessage(null); // Use the helper function to check the task status const taskResult = await checkTaskStatus(taskId); if (taskResult.completed) { const task = await getTask(taskId); const { connected, error } = task.data.attributes.result; setConnectionStatus({ connected, error: connected ? null : error || "Unknown error", }); if (connected && isUpdated) return router.push("/providers"); if (connected && !isUpdated) { try { // Check if the runOnce checkbox is checked const runOnce = form.watch("runOnce"); let data; if (runOnce) { data = await scanOnDemand(formData); } else { data = await scheduleDaily(formData); } if (data.error) { setApiErrorMessage(data.error); form.setError("providerId", { type: "server", message: data.error, }); } else { setIsRedirecting(true); router.push("/scans"); } } catch (error) { form.setError("providerId", { type: "server", message: "An unexpected error occurred. Please try again.", }); } } else { setConnectionStatus({ connected: false, error: error || "Connection failed, please review credentials.", }); } } else { setConnectionStatus({ connected: false, error: taskResult.error || "Unknown error", }); } } }; const onResetCredentials = async () => { setIsResettingCredentials(true); // Check if provider the provider has no credentials const providerSecretId = providerData?.data?.relationships?.secret?.data?.id; const hasNoCredentials = !providerSecretId; if (hasNoCredentials) { // If no credentials, redirect to add credentials page router.push( `/providers/add-credentials?type=${providerType}&id=${providerId}`, ); return; } // If provider has credentials, delete them first try { await deleteCredentials(providerSecretId); // After successful deletion, redirect to add credentials page router.push( `/providers/add-credentials?type=${providerType}&id=${providerId}`, ); } catch (error) { // eslint-disable-next-line no-console console.error("Failed to delete credentials:", error); } finally { setIsResettingCredentials(false); } }; if (isRedirecting) { return (

Scan initiated successfully

Redirecting to scans job details...

); } return (
{!isUpdated ? "Check connection and launch scan" : "Check connection"}

{!isUpdated ? "After a successful connection, a scan will automatically run every 24 hours. To run a single scan instead, select the checkbox below." : "A successful connection will redirect you to the providers page."}

{apiErrorMessage && (

{`Provider ID ${apiErrorMessage?.toLowerCase()}. Please check and try again.`}

)} {connectionStatus && !connectionStatus.connected && ( <>

{connectionStatus.error || "Unknown error"}

It seems there was an issue with your credentials. Please review your credentials and try again.

)} {!isUpdated && !connectionStatus?.error && ( Run a single scan (no recurring schedule). )} {isUpdated && !connectionStatus?.error && (

Check the new credentials and test the connection.

)}
{apiErrorMessage ? ( Back to providers ) : connectionStatus?.error ? ( router.back() : onResetCredentials} type="button" ariaLabel={"Save"} className="w-1/2" variant="solid" color="warning" size="md" isLoading={isResettingCredentials} startContent={!isResettingCredentials && } isDisabled={isResettingCredentials} > {isResettingCredentials ? ( <>Loading ) : ( {isUpdated ? "Update credentials" : "Reset credentials"} )} ) : ( } > {isLoading ? ( <>Loading ) : ( {isUpdated ? "Check connection" : "Launch scan"} )} )}
); };