mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
feat(ui): filter overview by provider group
- Add the provider group selector to the Overview filters - Scope risk plot, risk pipeline, and severity-over-time to the selected group Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+20
-3
@@ -18,11 +18,27 @@ export async function RiskPipelineViewSSR({
|
||||
|
||||
const providerTypeFilter = filters["filter[provider_type__in]"];
|
||||
const providerIdFilter = filters["filter[provider_id__in]"];
|
||||
const providerGroupsFilter = filters["filter[provider_groups__in]"];
|
||||
|
||||
// Fetch providers list to know account types
|
||||
const providersListResponse = await getAllProviders();
|
||||
const allProviders = providersListResponse?.data || [];
|
||||
|
||||
// Scope the provider set to the selected groups so we enumerate only their
|
||||
// provider types below (the per-type API calls also carry the group filter).
|
||||
const selectedGroupIds = providerGroupsFilter
|
||||
? String(providerGroupsFilter)
|
||||
.split(",")
|
||||
.map((id) => id.trim())
|
||||
: [];
|
||||
const scopedProviders = selectedGroupIds.length
|
||||
? allProviders.filter((p) =>
|
||||
p.relationships.provider_groups?.data?.some((group) =>
|
||||
selectedGroupIds.includes(group.id),
|
||||
),
|
||||
)
|
||||
: allProviders;
|
||||
|
||||
// Build severityByProviderType based on filters
|
||||
const severityByProviderType: SeverityByProviderType = {};
|
||||
let selectedProviderTypes: string[] | undefined;
|
||||
@@ -36,7 +52,7 @@ export async function RiskPipelineViewSSR({
|
||||
// Group selected accounts by provider type
|
||||
const accountsByType: Record<string, string[]> = {};
|
||||
for (const accountId of selectedAccountIds) {
|
||||
const provider = allProviders.find((p) => p.id === accountId);
|
||||
const provider = scopedProviders.find((p) => p.id === accountId);
|
||||
if (provider) {
|
||||
const type = provider.attributes.provider.toLowerCase();
|
||||
if (!accountsByType[type]) {
|
||||
@@ -93,9 +109,10 @@ export async function RiskPipelineViewSSR({
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Case: No filters - get all provider types and make parallel calls
|
||||
// Case: No account/type filter - enumerate provider types (scoped to the
|
||||
// selected groups when a group filter is active) and make parallel calls.
|
||||
const allProviderTypes = Array.from(
|
||||
new Set(allProviders.map((p) => p.attributes.provider.toLowerCase())),
|
||||
new Set(scopedProviders.map((p) => p.attributes.provider.toLowerCase())),
|
||||
);
|
||||
|
||||
const severityPromises = allProviderTypes.map(async (providerType) => {
|
||||
|
||||
@@ -19,6 +19,7 @@ export async function RiskPlotSSR({
|
||||
|
||||
const providerTypeFilter = filters["filter[provider_type__in]"];
|
||||
const providerIdFilter = filters["filter[provider_id__in]"];
|
||||
const providerGroupsFilter = filters["filter[provider_groups__in]"];
|
||||
|
||||
// Fetch all providers
|
||||
const providersListResponse = await getAllProviders();
|
||||
@@ -33,6 +34,16 @@ export async function RiskPlotSSR({
|
||||
.split(",")
|
||||
.map((id) => id.trim());
|
||||
filteredProviders = allProviders.filter((p) => selectedIds.includes(p.id));
|
||||
} else if (providerGroupsFilter) {
|
||||
// Filter by provider group membership
|
||||
const selectedGroupIds = String(providerGroupsFilter)
|
||||
.split(",")
|
||||
.map((id) => id.trim());
|
||||
filteredProviders = allProviders.filter((p) =>
|
||||
p.relationships.provider_groups?.data?.some((group) =>
|
||||
selectedGroupIds.includes(group.id),
|
||||
),
|
||||
);
|
||||
} else if (providerTypeFilter) {
|
||||
// Filter by provider types
|
||||
const selectedTypes = String(providerTypeFilter)
|
||||
|
||||
+2
@@ -44,8 +44,10 @@ export const FindingSeverityOverTime = ({
|
||||
const filters: Record<string, string> = {};
|
||||
const providerType = searchParams.get("filter[provider_type__in]");
|
||||
const providerId = searchParams.get("filter[provider_id__in]");
|
||||
const providerGroups = searchParams.get("filter[provider_groups__in]");
|
||||
if (providerType) filters["filter[provider_type__in]"] = providerType;
|
||||
if (providerId) filters["filter[provider_id__in]"] = providerId;
|
||||
if (providerGroups) filters["filter[provider_groups__in]"] = providerGroups;
|
||||
return filters;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Suspense } from "react";
|
||||
|
||||
import { getAllProviderGroups } from "@/actions/manage-groups/manage-groups";
|
||||
import { getAllProviders } from "@/actions/providers";
|
||||
import { ProviderAccountSelectors } from "@/components/filters/provider-account-selectors";
|
||||
import { ContentLayout } from "@/components/ui";
|
||||
import { SearchParamsProps } from "@/types";
|
||||
|
||||
import { ProviderGroupSelector } from "./_overview/_components/provider-group-selector";
|
||||
import {
|
||||
AttackSurfaceSkeleton,
|
||||
AttackSurfaceSSR,
|
||||
@@ -38,12 +40,16 @@ export default async function Home({
|
||||
searchParams: Promise<SearchParamsProps>;
|
||||
}) {
|
||||
const resolvedSearchParams = await searchParams;
|
||||
const providersData = await getAllProviders();
|
||||
const [providersData, providerGroupsData] = await Promise.all([
|
||||
getAllProviders(),
|
||||
getAllProviderGroups(),
|
||||
]);
|
||||
|
||||
return (
|
||||
<ContentLayout title="Overview" icon="lucide:square-chart-gantt">
|
||||
<div className="xxl:grid-cols-4 mb-6 grid grid-cols-1 gap-6 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
|
||||
<ProviderAccountSelectors providers={providersData?.data ?? []} />
|
||||
<ProviderGroupSelector groups={providerGroupsData?.data ?? []} />
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-6 xl:flex-row xl:flex-wrap xl:items-stretch">
|
||||
|
||||
Reference in New Issue
Block a user