mirror of
https://github.com/prowler-cloud/prowler.git
synced 2025-12-19 05:17:47 +00:00
Co-authored-by: Alan Buscaglia <alanbuscaglia@MacBook-Pro.local> Co-authored-by: alejandrobailo <alejandrobailo94@gmail.com> Co-authored-by: César Arroba <cesar@prowler.com> Co-authored-by: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com>
142 lines
4.2 KiB
TypeScript
142 lines
4.2 KiB
TypeScript
"use server";
|
|
|
|
import { pollTaskUntilSettled } from "@/actions/task/poll";
|
|
import { apiBaseUrl, getAuthHeaders } from "@/lib";
|
|
import { handleApiError } from "@/lib/server-actions-helper";
|
|
import type {
|
|
IntegrationProps,
|
|
JiraDispatchRequest,
|
|
JiraDispatchResponse,
|
|
} from "@/types/integrations";
|
|
|
|
export const getJiraIntegrations = async (): Promise<
|
|
| { success: true; data: IntegrationProps[] }
|
|
| { success: false; error: string }
|
|
> => {
|
|
const headers = await getAuthHeaders({ contentType: false });
|
|
const url = new URL(`${apiBaseUrl}/integrations`);
|
|
|
|
// Filter for Jira integrations only
|
|
url.searchParams.append("filter[integration_type]", "jira");
|
|
|
|
try {
|
|
const response = await fetch(url.toString(), { method: "GET", headers });
|
|
|
|
if (response.ok) {
|
|
const data: { data: IntegrationProps[] } = await response.json();
|
|
// Filter for enabled integrations on the client side
|
|
const enabledIntegrations = (data.data || []).filter(
|
|
(integration: IntegrationProps) =>
|
|
integration.attributes.enabled === true,
|
|
);
|
|
return { success: true, data: enabledIntegrations };
|
|
}
|
|
|
|
const errorData: unknown = await response.json().catch(() => ({}));
|
|
const errorMessage =
|
|
(errorData as { errors?: { detail?: string }[] }).errors?.[0]?.detail ||
|
|
`Unable to fetch Jira integrations: ${response.statusText}`;
|
|
return { success: false, error: errorMessage };
|
|
} catch (error) {
|
|
const errorResult = handleApiError(error);
|
|
return { success: false, error: errorResult.error || "An error occurred" };
|
|
}
|
|
};
|
|
|
|
export const sendFindingToJira = async (
|
|
integrationId: string,
|
|
findingId: string,
|
|
projectKey: string,
|
|
_issueType: string,
|
|
): Promise<
|
|
| { success: true; taskId: string; message: string }
|
|
| { success: false; error: string }
|
|
> => {
|
|
const headers = await getAuthHeaders({ contentType: true });
|
|
const url = new URL(
|
|
`${apiBaseUrl}/integrations/${integrationId}/jira/dispatches`,
|
|
);
|
|
|
|
// Single finding: use direct filter without array notation
|
|
url.searchParams.append("filter[finding_id]", findingId);
|
|
|
|
const payload: JiraDispatchRequest = {
|
|
data: {
|
|
type: "integrations-jira-dispatches",
|
|
attributes: {
|
|
project_key: projectKey,
|
|
// Temporarily hardcode to "Task" regardless of the provided value
|
|
issue_type: "Task",
|
|
},
|
|
},
|
|
};
|
|
|
|
try {
|
|
const response = await fetch(url.toString(), {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify(payload),
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data: JiraDispatchResponse = await response.json();
|
|
const taskId = data?.data?.id;
|
|
|
|
if (taskId) {
|
|
return {
|
|
success: true,
|
|
taskId,
|
|
message: "Jira issue creation started. Processing...",
|
|
};
|
|
} else {
|
|
return {
|
|
success: false,
|
|
error: "Failed to start Jira dispatch. No task ID received.",
|
|
};
|
|
}
|
|
}
|
|
|
|
const errorData: unknown = await response.json().catch(() => ({}));
|
|
const errorMessage =
|
|
(errorData as { errors?: { detail?: string }[] }).errors?.[0]?.detail ||
|
|
`Unable to send finding to Jira: ${response.statusText}`;
|
|
return { success: false, error: errorMessage };
|
|
} catch (error) {
|
|
const errorResult = handleApiError(error);
|
|
return { success: false, error: errorResult.error || "An error occurred" };
|
|
}
|
|
};
|
|
|
|
export const pollJiraDispatchTask = async (
|
|
taskId: string,
|
|
): Promise<
|
|
{ success: true; message: string } | { success: false; error: string }
|
|
> => {
|
|
const res = await pollTaskUntilSettled(taskId, {
|
|
maxAttempts: 10,
|
|
delayMs: 2000,
|
|
});
|
|
if (!res.ok) {
|
|
return { success: false, error: res.error };
|
|
}
|
|
const { state, result } = res;
|
|
type JiraTaskResult = JiraDispatchResponse["data"]["attributes"]["result"];
|
|
const jiraResult = result as JiraTaskResult | undefined;
|
|
|
|
if (state === "completed") {
|
|
if (!jiraResult?.error) {
|
|
return { success: true, message: "Finding successfully sent to Jira!" };
|
|
}
|
|
return {
|
|
success: false,
|
|
error: jiraResult?.error || "Failed to create Jira issue.",
|
|
};
|
|
}
|
|
|
|
if (state === "failed") {
|
|
return { success: false, error: jiraResult?.error || "Task failed." };
|
|
}
|
|
|
|
return { success: false, error: `Unknown task state: ${state}` };
|
|
};
|