Files
prowler/ui/actions/providers/providers.ts
2025-11-27 12:37:20 +01:00

310 lines
8.5 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { apiBaseUrl, getAuthHeaders, getFormValue, wait } from "@/lib";
import { buildSecretConfig } from "@/lib/provider-credentials/build-crendentials";
import { ProviderCredentialFields } from "@/lib/provider-credentials/provider-credential-fields";
import { handleApiError, handleApiResponse } from "@/lib/server-actions-helper";
import { ProvidersApiResponse, ProviderType } from "@/types/providers";
export const getProviders = async ({
page = 1,
query = "",
sort = "",
filters = {},
pageSize = 10,
}): Promise<ProvidersApiResponse | undefined> => {
const headers = await getAuthHeaders({ contentType: false });
if (isNaN(Number(page)) || page < 1) redirect("/providers");
const url = new URL(`${apiBaseUrl}/providers?include=provider_groups`);
if (page) url.searchParams.append("page[number]", page.toString());
if (pageSize) url.searchParams.append("page[size]", pageSize.toString());
if (query) url.searchParams.append("filter[search]", query);
if (sort) url.searchParams.append("sort", sort);
// Handle multiple filters
Object.entries(filters).forEach(([key, value]) => {
if (key !== "filter[search]") {
url.searchParams.append(key, String(value));
}
});
try {
const response = await fetch(url.toString(), {
headers,
});
return (await handleApiResponse(response)) as
| ProvidersApiResponse
| undefined;
} catch (error) {
console.error("Error fetching providers:", error);
return undefined;
}
};
export const getProvider = async (formData: FormData) => {
const headers = await getAuthHeaders({ contentType: false });
const providerId = formData.get("id");
const url = new URL(`${apiBaseUrl}/providers/${providerId}`);
try {
const response = await fetch(url.toString(), {
headers,
});
return handleApiResponse(response);
} catch (error) {
return handleApiError(error);
}
};
export const updateProvider = async (formData: FormData) => {
const headers = await getAuthHeaders({ contentType: true });
const providerId = formData.get(ProviderCredentialFields.PROVIDER_ID);
const providerAlias = formData.get(ProviderCredentialFields.PROVIDER_ALIAS);
const url = new URL(`${apiBaseUrl}/providers/${providerId}`);
try {
const response = await fetch(url.toString(), {
method: "PATCH",
headers,
body: JSON.stringify({
data: {
type: "providers",
id: providerId,
attributes: { alias: providerAlias },
},
}),
});
return handleApiResponse(response, "/providers");
} catch (error) {
return handleApiError(error);
}
};
export const addProvider = async (formData: FormData) => {
const headers = await getAuthHeaders({ contentType: true });
const providerType = formData.get("providerType") as ProviderType;
const providerUid = formData.get("providerUid") as string;
const providerAlias = formData.get("providerAlias") as string;
const url = new URL(`${apiBaseUrl}/providers`);
try {
const bodyData = {
data: {
type: "providers",
attributes: {
provider: providerType,
uid: providerUid,
...(providerAlias?.trim() && { alias: providerAlias.trim() }),
},
},
};
const response = await fetch(url.toString(), {
method: "POST",
headers,
body: JSON.stringify(bodyData),
});
return handleApiResponse(response, "/providers");
} catch (error) {
return handleApiError(error);
}
};
export const addCredentialsProvider = async (formData: FormData) => {
const headers = await getAuthHeaders({ contentType: true });
const url = new URL(`${apiBaseUrl}/providers/secrets`);
const providerId = getFormValue(
formData,
ProviderCredentialFields.PROVIDER_ID,
);
const providerType = getFormValue(
formData,
ProviderCredentialFields.PROVIDER_TYPE,
) as ProviderType;
const providerUid = getFormValue(
formData,
ProviderCredentialFields.PROVIDER_UID,
) as string | undefined;
try {
// For IaC provider, fetch the provider data to get the repository URL from uid
if (providerType === "iac") {
const providerUrl = new URL(`${apiBaseUrl}/providers/${providerId}`);
const providerResponse = await fetch(providerUrl.toString(), {
headers: await getAuthHeaders({ contentType: false }),
});
if (providerResponse.ok) {
const providerData = await providerResponse.json();
const providerUid = providerData?.data?.attributes?.uid;
// Add the repository URL to formData using the provider's uid
if (providerUid) {
formData.append(ProviderCredentialFields.REPOSITORY_URL, providerUid);
}
}
}
const { secretType, secret } = buildSecretConfig(
formData,
providerType,
providerUid,
);
const response = await fetch(url.toString(), {
method: "POST",
headers,
body: JSON.stringify({
data: {
type: "provider-secrets",
attributes: { secret_type: secretType, secret },
relationships: {
provider: {
data: { id: providerId, type: "providers" },
},
},
},
}),
});
return handleApiResponse(response, "/providers");
} catch (error) {
return handleApiError(error);
}
};
export const updateCredentialsProvider = async (
credentialsId: string,
formData: FormData,
) => {
const headers = await getAuthHeaders({ contentType: true });
const url = new URL(`${apiBaseUrl}/providers/secrets/${credentialsId}`);
const providerType = getFormValue(
formData,
ProviderCredentialFields.PROVIDER_TYPE,
) as ProviderType;
try {
const { secretType, secret } = buildSecretConfig(formData, providerType);
const response = await fetch(url.toString(), {
method: "PATCH",
headers,
body: JSON.stringify({
data: {
type: "provider-secrets",
id: credentialsId,
attributes: { secret_type: secretType, secret },
},
}),
});
return handleApiResponse(response, "/providers");
} catch (error) {
return handleApiError(error);
}
};
export const checkConnectionProvider = async (formData: FormData) => {
const headers = await getAuthHeaders({ contentType: false });
const providerId = formData.get(ProviderCredentialFields.PROVIDER_ID);
const url = new URL(`${apiBaseUrl}/providers/${providerId}/connection`);
try {
const response = await fetch(url.toString(), { method: "POST", headers });
await wait(2000);
return handleApiResponse(response, "/providers");
} catch (error) {
return handleApiError(error);
}
};
export const deleteCredentials = async (secretId: string) => {
const headers = await getAuthHeaders({ contentType: false });
if (!secretId) {
return { error: "Secret ID is required" };
}
const url = new URL(`${apiBaseUrl}/providers/secrets/${secretId}`);
try {
const response = await fetch(url.toString(), {
method: "DELETE",
headers,
});
if (!response.ok) {
try {
const errorData = await response.json();
throw new Error(
errorData?.message || "Failed to delete the credentials",
);
} catch {
throw new Error("Failed to delete the credentials");
}
}
let data = null;
if (response.status !== 204) {
data = await response.json();
}
revalidatePath("/providers");
return data || { success: true };
} catch (error) {
handleApiError(error);
}
};
export const deleteProvider = async (formData: FormData) => {
const headers = await getAuthHeaders({ contentType: false });
const providerId = formData.get(ProviderCredentialFields.PROVIDER_ID);
if (!providerId) {
return { error: "Provider ID is required" };
}
const url = new URL(`${apiBaseUrl}/providers/${providerId}`);
try {
const response = await fetch(url.toString(), {
method: "DELETE",
headers,
});
if (!response.ok) {
try {
const errorData = await response.json();
throw new Error(errorData?.message || "Failed to delete the provider");
} catch {
throw new Error("Failed to delete the provider");
}
}
let data = null;
if (response.status !== 204) {
data = await response.json();
}
revalidatePath("/providers");
return data || { success: true };
} catch (error) {
handleApiError(error);
}
};