mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 13:01:56 +00:00
feat(ui): forward provider filters in compliance server actions
- getCompliancesOverview and getComplianceRequirements forward provider filters and drop scan_id when present (backend XOR) - getComplianceRequirements now accepts an optional scanId Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const { fetchMock, getAuthHeadersMock, handleApiResponseMock } = vi.hoisted(
|
||||
() => ({
|
||||
fetchMock: vi.fn(),
|
||||
getAuthHeadersMock: vi.fn(),
|
||||
handleApiResponseMock: vi.fn(),
|
||||
}),
|
||||
);
|
||||
|
||||
vi.mock("@/lib", () => ({
|
||||
apiBaseUrl: "https://api.example.com/api/v1",
|
||||
getAuthHeaders: getAuthHeadersMock,
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/server-actions-helper", () => ({
|
||||
handleApiResponse: handleApiResponseMock,
|
||||
}));
|
||||
|
||||
import {
|
||||
getComplianceOverviewMetadataInfo,
|
||||
getComplianceRequirements,
|
||||
getCompliancesOverview,
|
||||
} from "./compliances";
|
||||
|
||||
const calledUrl = () => new URL(fetchMock.mock.calls[0][0] as string);
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" });
|
||||
fetchMock.mockResolvedValue(new Response(null, { status: 200 }));
|
||||
handleApiResponseMock.mockResolvedValue({ data: [] });
|
||||
});
|
||||
|
||||
describe("getCompliancesOverview", () => {
|
||||
it("sends scan_id and region in scan mode", async () => {
|
||||
await getCompliancesOverview({ scanId: "scan-1", region: "eu-west-1" });
|
||||
|
||||
const url = calledUrl();
|
||||
expect(url.searchParams.get("filter[scan_id]")).toBe("scan-1");
|
||||
expect(url.searchParams.get("filter[region__in]")).toBe("eu-west-1");
|
||||
});
|
||||
|
||||
it("forwards provider filters and omits scan_id in aggregated mode", async () => {
|
||||
await getCompliancesOverview({
|
||||
scanId: "scan-1",
|
||||
filters: { "filter[provider_type__in]": "aws,gcp" },
|
||||
});
|
||||
|
||||
const url = calledUrl();
|
||||
expect(url.searchParams.get("filter[provider_type__in]")).toBe("aws,gcp");
|
||||
// XOR: provider filters present -> never send scan_id (avoids backend 400)
|
||||
expect(url.searchParams.get("filter[scan_id]")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getComplianceOverviewMetadataInfo", () => {
|
||||
it("forwards provider filters", async () => {
|
||||
await getComplianceOverviewMetadataInfo({
|
||||
filters: { "filter[provider_groups__in]": "g1,g2" },
|
||||
});
|
||||
|
||||
expect(calledUrl().searchParams.get("filter[provider_groups__in]")).toBe(
|
||||
"g1,g2",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getComplianceRequirements", () => {
|
||||
it("appends compliance_id and scan_id in scan mode", async () => {
|
||||
await getComplianceRequirements({
|
||||
complianceId: "cis_2.0_aws",
|
||||
scanId: "scan-1",
|
||||
});
|
||||
|
||||
const url = calledUrl();
|
||||
expect(url.searchParams.get("filter[compliance_id]")).toBe("cis_2.0_aws");
|
||||
expect(url.searchParams.get("filter[scan_id]")).toBe("scan-1");
|
||||
});
|
||||
|
||||
it("forwards provider filters and omits scan_id in aggregated mode", async () => {
|
||||
await getComplianceRequirements({
|
||||
complianceId: "cis_2.0_aws",
|
||||
scanId: "scan-1",
|
||||
filters: { "filter[provider_id__in]": "p1,p2" },
|
||||
});
|
||||
|
||||
const url = calledUrl();
|
||||
expect(url.searchParams.get("filter[compliance_id]")).toBe("cis_2.0_aws");
|
||||
expect(url.searchParams.get("filter[provider_id__in]")).toBe("p1,p2");
|
||||
expect(url.searchParams.get("filter[scan_id]")).toBeNull();
|
||||
});
|
||||
|
||||
it("omits scan_id when no scan is provided", async () => {
|
||||
await getComplianceRequirements({ complianceId: "cis_2.0_aws" });
|
||||
|
||||
expect(calledUrl().searchParams.get("filter[scan_id]")).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
"use server";
|
||||
|
||||
import { apiBaseUrl, getAuthHeaders } from "@/lib";
|
||||
import { hasComplianceProviderFilters } from "@/lib/compliance/compliance-provider-filters";
|
||||
import { handleApiResponse } from "@/lib/server-actions-helper";
|
||||
|
||||
export const getCompliancesOverview = async ({
|
||||
@@ -27,7 +28,10 @@ export const getCompliancesOverview = async ({
|
||||
|
||||
Object.entries(filters).forEach(([key, value]) => setParam(key, value));
|
||||
|
||||
setParam("filter[scan_id]", scanId);
|
||||
// XOR: the backend rejects filter[scan_id] together with provider filters.
|
||||
if (!hasComplianceProviderFilters(filters)) {
|
||||
setParam("filter[scan_id]", scanId);
|
||||
}
|
||||
setParam("filter[region__in]", region);
|
||||
try {
|
||||
const response = await fetch(url.toString(), {
|
||||
@@ -111,22 +115,33 @@ export const getComplianceRequirements = async ({
|
||||
complianceId,
|
||||
scanId,
|
||||
region,
|
||||
filters = {},
|
||||
}: {
|
||||
complianceId: string;
|
||||
scanId: string;
|
||||
scanId?: string;
|
||||
region?: string | string[];
|
||||
filters?: Record<string, string | string[] | undefined>;
|
||||
}) => {
|
||||
const headers = await getAuthHeaders({ contentType: false });
|
||||
|
||||
try {
|
||||
const url = new URL(`${apiBaseUrl}/compliance-overviews/requirements`);
|
||||
url.searchParams.append("filter[compliance_id]", complianceId);
|
||||
url.searchParams.append("filter[scan_id]", scanId);
|
||||
|
||||
// Forward provider-scope filters (aggregated mode); XOR with scan_id.
|
||||
Object.entries(filters).forEach(([key, value]) => {
|
||||
if (value === undefined) return;
|
||||
const serialized = Array.isArray(value) ? value.join(",") : value;
|
||||
if (serialized.trim() !== "") url.searchParams.append(key, serialized);
|
||||
});
|
||||
|
||||
if (scanId && !hasComplianceProviderFilters(filters)) {
|
||||
url.searchParams.append("filter[scan_id]", scanId);
|
||||
}
|
||||
|
||||
if (region) {
|
||||
const regionValue = Array.isArray(region) ? region.join(",") : region;
|
||||
url.searchParams.append("filter[region__in]", regionValue);
|
||||
//remove page param
|
||||
}
|
||||
url.searchParams.delete("page");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user