Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions api/src/backend/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,12 @@ class ChoiceInFilter(BaseInFilter, ChoiceFilter):

class CommonFindingFilters(FilterSet):
# We filter providers from the scan in findings
# Both 'provider' and 'provider_id' parameters are supported for API consistency
# Frontend uses 'provider_id' uniformly across all endpoints
provider = UUIDFilter(field_name="scan__provider__id", lookup_expr="exact")
provider__in = UUIDInFilter(field_name="scan__provider__id", lookup_expr="in")
provider_id = UUIDFilter(field_name="scan__provider__id", lookup_expr="exact")
provider_id__in = UUIDInFilter(field_name="scan__provider__id", lookup_expr="in")
provider_type = ChoiceFilter(
choices=Provider.ProviderChoices.choices, field_name="scan__provider__provider"
)
Expand Down
23 changes: 4 additions & 19 deletions ui/app/(prowler)/_overview/_components/accounts-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useRouter, useSearchParams } from "next/navigation";
import { ReactNode } from "react";

import {
Expand Down Expand Up @@ -43,21 +43,10 @@ interface AccountsSelectorProps {

export function AccountsSelector({ providers }: AccountsSelectorProps) {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();

// Determine which filter key to use based on the current page
// - /findings uses provider__in (API expects this)
// - /overview and others use provider_id__in
const isFindingsPage = pathname?.startsWith("/findings");
const filterKey = isFindingsPage
? "filter[provider__in]"
: "filter[provider_id__in]";

// Read from both keys to support navigation between pages
const providerIn = searchParams.get("filter[provider__in]") || "";
const providerIdIn = searchParams.get("filter[provider_id__in]") || "";
const current = providerIn || providerIdIn;
const filterKey = "filter[provider_id__in]";
const current = searchParams.get(filterKey) || "";
const selectedTypes = searchParams.get("filter[provider_type__in]") || "";
const selectedTypesList = selectedTypes
? selectedTypes.split(",").filter(Boolean)
Expand All @@ -73,13 +62,9 @@ export function AccountsSelector({ providers }: AccountsSelectorProps) {

const handleMultiValueChange = (ids: string[]) => {
const params = new URLSearchParams(searchParams.toString());

// Clean up both potential provider filter keys first
params.delete("filter[provider_id__in]");
params.delete("filter[provider__in]");
params.delete(filterKey);

if (ids.length > 0) {
// Use the appropriate filter key for the current page
params.set(filterKey, ids.join(","));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ export const ProviderTypeSelector = ({
// Clear account selection when changing provider types
// User should manually select accounts if they want to filter by specific accounts
params.delete("filter[provider_id__in]");
params.delete("filter[provider__in]");

router.push(`?${params.toString()}`, { scroll: false });
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import Link from "next/link";

import { AttackSurfaceItem } from "@/actions/overview";
import { Card, CardContent } from "@/components/shadcn";
import { mapProviderFiltersForFindings } from "@/lib";

interface AttackSurfaceCardItemProps {
item: AttackSurfaceItem;
Expand All @@ -29,9 +28,6 @@ export function AttackSurfaceCardItem({
}
});

// Map provider filters for findings page compatibility
mapProviderFiltersForFindings(params);

return `/findings?${params.toString()}`;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { LinkToFindings } from "@/components/overview";
import { ColumnNewFindingsToDate } from "@/components/overview/new-findings-table/table/column-new-findings-to-date";
import { DataTable } from "@/components/ui/table";
import { createDict } from "@/lib/helper";
import { mapProviderFiltersForFindingsObject } from "@/lib/provider-helpers";
import { FindingProps, SearchParamsProps } from "@/types";

import { pickFilterParams } from "../../_lib/filter-params";
Expand All @@ -27,8 +26,7 @@ export async function FindingsViewSSR({ searchParams }: FindingsViewSSRProps) {
};

const filters = pickFilterParams(searchParams);
const mappedFilters = mapProviderFiltersForFindingsObject(filters);
const combinedFilters = { ...defaultFilters, ...mappedFilters };
const combinedFilters = { ...defaultFilters, ...filters };

const findingsData = await getLatestFindings({
query: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { HorizontalBarChart } from "@/components/graphs/horizontal-bar-chart";
import { ScatterPlot } from "@/components/graphs/scatter-plot";
import { AlertPill } from "@/components/graphs/shared/alert-pill";
import type { BarDataPoint } from "@/components/graphs/types";
import { mapProviderFiltersForFindings } from "@/lib/provider-helpers";
import { SEVERITY_FILTER_MAP } from "@/types/severities";

// Score color thresholds (0-100 scale, higher = better)
Expand Down Expand Up @@ -42,17 +41,14 @@ export function RiskPlotClient({ data }: RiskPlotClientProps) {
// Build the URL with current filters
const params = new URLSearchParams(searchParams.toString());

// Transform provider filters (provider_id__in -> provider__in)
mapProviderFiltersForFindings(params);

// Add severity filter
const severity = SEVERITY_FILTER_MAP[dataPoint.name];
if (severity) {
params.set("filter[severity__in]", severity);
}

// Add provider filter for the selected point
params.set("filter[provider__in]", selectedPoint.providerId);
params.set("filter[provider_id__in]", selectedPoint.providerId);

// Add exclude muted findings filter
params.set("filter[muted]", "false");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useRouter, useSearchParams } from "next/navigation";
import { HorizontalBarChart } from "@/components/graphs/horizontal-bar-chart";
import { BarDataPoint } from "@/components/graphs/types";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/shadcn";
import { mapProviderFiltersForFindings } from "@/lib/provider-helpers";
import { calculatePercentage } from "@/lib/utils";
import { SEVERITY_FILTER_MAP } from "@/types/severities";

Expand All @@ -31,8 +30,6 @@ export const RiskSeverityChart = ({
// Build the URL with current filters plus severity and muted
const params = new URLSearchParams(searchParams.toString());

mapProviderFiltersForFindings(params);

const severity = SEVERITY_FILTER_MAP[dataPoint.name];
if (severity) {
params.set("filter[severity__in]", severity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const FindingSeverityOverTime = ({
params.set("filter[provider_type__in]", providerType);
}
if (providerId) {
params.set("filter[provider__in]", providerId);
params.set("filter[provider_id__in]", providerId);
}

router.push(`/findings?${params.toString()}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
CardVariant,
ResourceStatsCard,
} from "@/components/shadcn";
import { mapProviderFiltersForFindings } from "@/lib/provider-helpers";
import { calculatePercentage } from "@/lib/utils";
interface FindingsData {
total: number;
Expand All @@ -39,8 +38,6 @@ export const StatusChart = ({
// Build the URL with current filters plus status and muted
const params = new URLSearchParams(searchParams.toString());

mapProviderFiltersForFindings(params);

// Add status filter based on which segment was clicked
if (dataPoint.name === "Fail Findings") {
params.set("filter[status__in]", "FAIL");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useRouter, useSearchParams } from "next/navigation";
import { useState } from "react";

import { ServiceOverview } from "@/actions/overview";
import { mapProviderFiltersForFindings } from "@/lib/provider-helpers";

import { SortToggleButton } from "./sort-toggle-button";
import { WatchlistCard, WatchlistItem } from "./watchlist-card";
Expand All @@ -29,9 +28,6 @@ export const ServiceWatchlist = ({ items }: { items: ServiceOverview[] }) => {

const handleItemClick = (item: WatchlistItem) => {
const params = new URLSearchParams(searchParams.toString());

mapProviderFiltersForFindings(params);

params.set("filter[service__in]", item.key);
params.set("filter[status__in]", "FAIL");
router.push(`/findings?${params.toString()}`);
Expand Down
10 changes: 2 additions & 8 deletions ui/components/graphs/sankey-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { Rectangle, ResponsiveContainer, Sankey, Tooltip } from "recharts";

import { PROVIDER_ICONS } from "@/components/icons/providers-badge";
import { initializeChartColors } from "@/lib/charts/colors";
import { mapProviderFiltersForFindings } from "@/lib/provider-helpers";
import { PROVIDER_DISPLAY_NAMES } from "@/types/providers";
import { SEVERITY_FILTER_MAP } from "@/types/severities";

Expand Down Expand Up @@ -463,9 +462,6 @@ export function SankeyChart({
const severityFilter = SEVERITY_FILTER_MAP[nodeName];
if (severityFilter) {
const params = new URLSearchParams(searchParams.toString());

mapProviderFiltersForFindings(params);

params.set("filter[severity__in]", severityFilter);
params.set("filter[status__in]", "FAIL");
params.set("filter[muted]", "false");
Expand All @@ -480,12 +476,10 @@ export function SankeyChart({
if (severityFilter) {
const params = new URLSearchParams(searchParams.toString());

mapProviderFiltersForFindings(params);

// Always set provider_type filter based on the clicked link's source (provider)
// This ensures clicking "AWS → High" filters by AWS even when no global filter is set
const hasProviderIdFilter = searchParams.has("filter[provider_id__in]");
if (providerType && !hasProviderIdFilter) {
const hasProviderFilter = searchParams.has("filter[provider_id__in]");
if (providerType && !hasProviderFilter) {
params.set("filter[provider_type__in]", providerType);
}

Expand Down
2 changes: 0 additions & 2 deletions ui/components/graphs/threat-map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { useRouter, useSearchParams } from "next/navigation";
import { useEffect, useRef, useState } from "react";

import { Card } from "@/components/shadcn/card/card";
import { mapProviderFiltersForFindings } from "@/lib/provider-helpers";

import { HorizontalBarChart } from "./horizontal-bar-chart";
import {
Expand Down Expand Up @@ -399,7 +398,6 @@ export function ThreatMap({
providerType?: string,
) => {
const params = new URLSearchParams(searchParams.toString());
mapProviderFiltersForFindings(params);
if (providerType) params.set("filter[provider_type__in]", providerType);
params.set("filter[region__in]", regionCode);
params.set("filter[status__in]", status);
Expand Down
40 changes: 0 additions & 40 deletions ui/lib/provider-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,6 @@ import {
ProviderType,
} from "@/types/providers";

/**
* Maps overview provider filters to findings page provider filters.
* Converts provider_id__in to provider__in and removes provider_type__in
* since provider__in is more specific.
*/
export const mapProviderFiltersForFindings = (
params: URLSearchParams,
): void => {
const providerIds = params.get("filter[provider_id__in]");
if (providerIds) {
params.delete("filter[provider_id__in]");
params.delete("filter[provider_type__in]");
params.set("filter[provider__in]", providerIds);
}
};

/**
* Maps overview provider filters to findings page provider filters (object version).
* Converts provider_id__in to provider__in and removes provider_type__in
* since provider__in is more specific.
*/
export const mapProviderFiltersForFindingsObject = <
T extends Record<string, unknown>,
>(
filters: T,
): T => {
const result = { ...filters };
const providerIdKey = "filter[provider_id__in]";
const providerTypeKey = "filter[provider_type__in]";
const providerKey = "filter[provider__in]";

if (providerIdKey in result) {
result[providerKey as keyof T] = result[providerIdKey as keyof T];
delete result[providerIdKey as keyof T];
delete result[providerTypeKey as keyof T];
}

return result;
};

export const extractProviderUIDs = (
providersData: ProvidersApiResponse,
): string[] => {
Expand Down