Skip to content

Commit 1d31513

Browse files
fix(ui): avoid scan schedule fallback from scans
1 parent 5980321 commit 1d31513

4 files changed

Lines changed: 15 additions & 68 deletions

File tree

ui/app/(prowler)/providers/providers-page.utils.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,8 +1010,10 @@ describe("loadProvidersAccountsViewData", () => {
10101010
);
10111011
});
10121012

1013-
it("falls back to scan-based detection when /schedules is unavailable (OSS)", async () => {
1014-
// Given — /schedules errors, but provider-1 has a materialized scheduled scan.
1013+
it("does not infer provider schedules from materialized scans when /schedules is unavailable", async () => {
1014+
// Given — /schedules errors, and provider-1 still has a materialized
1015+
// scheduled scan. That scan is historical execution state, not schedule
1016+
// configuration.
10151017
providersActionsMock.getProviders.mockResolvedValue(providersResponse);
10161018
providersActionsMock.getAllProviders.mockResolvedValue(providersResponse);
10171019
scansActionsMock.getScans.mockResolvedValue({
@@ -1034,9 +1036,9 @@ describe("loadProvidersAccountsViewData", () => {
10341036
isCloud: false,
10351037
});
10361038

1037-
// Then — scan-based path still flags the provider; no throw from the error.
1039+
// Then — only provider scan_* fields or /schedules can mark a schedule.
10381040
expect(findProviderRow(viewData.rows, "provider-1")?.hasSchedule).toBe(
1039-
true,
1041+
false,
10401042
);
10411043
expect(findProviderRow(viewData.rows, "provider-2")?.hasSchedule).toBe(
10421044
false,

ui/app/(prowler)/providers/providers-page.utils.ts

Lines changed: 5 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
listOrganizationUnitsSafe,
44
} from "@/actions/organizations/organizations";
55
import { getAllProviders, getProviders } from "@/actions/providers";
6-
import { getScans } from "@/actions/scans";
76
import { getSchedules } from "@/actions/schedules";
87
import {
98
extractFiltersAndQuery,
@@ -34,7 +33,7 @@ import {
3433
ProvidersTableRow,
3534
ProvidersTableRowsInput,
3635
} from "@/types/providers-table";
37-
import { SCAN_TRIGGER, ScanProps, ScanScheduleSummary } from "@/types/scans";
36+
import { ScanScheduleSummary } from "@/types/scans";
3837
import { ScheduleAttributes } from "@/types/schedules";
3938

4039
const PROVIDERS_STATUS_MAPPING = [
@@ -115,26 +114,6 @@ const createProviderGroupLookup = (
115114
return lookup;
116115
};
117116

118-
const ACTIVE_SCAN_STATES = new Set(["scheduled", "available", "executing"]);
119-
120-
const buildScheduledProviderIds = (scans: ScanProps[]): Set<string> => {
121-
const scheduled = new Set<string>();
122-
123-
for (const scan of scans) {
124-
if (
125-
scan.attributes.trigger === SCAN_TRIGGER.SCHEDULED &&
126-
ACTIVE_SCAN_STATES.has(scan.attributes.state)
127-
) {
128-
const providerId = scan.relationships.provider?.data?.id;
129-
if (providerId) {
130-
scheduled.add(providerId);
131-
}
132-
}
133-
}
134-
135-
return scheduled;
136-
};
137-
138117
// A schedule is backed by the Provider row itself, so its `/schedules` entry
139118
// exists before the first scheduled Scan is materialized — only enabled,
140119
// configured ones carry a displayable cadence summary.
@@ -160,7 +139,6 @@ const getProviderLastScanAt = (
160139

161140
const enrichProviders = (
162141
providersResponse: ProvidersApiResponse | undefined,
163-
scanScheduledProviderIds: Set<string>,
164142
schedulesByProviderId: Record<string, ScheduleAttributes>,
165143
): ProvidersProviderRow[] => {
166144
const providerGroupLookup = createProviderGroupLookup(providersResponse);
@@ -176,8 +154,6 @@ const enrichProviders = (
176154
scheduleAttributes,
177155
now,
178156
);
179-
const hasProviderScheduleAttributes =
180-
providerScheduleAttributes !== undefined;
181157

182158
return {
183159
...provider,
@@ -187,12 +163,9 @@ const enrichProviders = (
187163
(providerGroup: { id: string }) =>
188164
providerGroupLookup.get(providerGroup.id) ?? "Unknown Group",
189165
) ?? [],
190-
// Provider scan_* fields are authoritative when present. The scheduled
191-
// scan fallback only exists for older APIs that do not expose them.
192-
hasSchedule: hasProviderScheduleAttributes
193-
? scheduleSummary !== undefined
194-
: scanScheduledProviderIds.has(provider.id) ||
195-
scheduleSummary !== undefined,
166+
// Provider scan_* fields are authoritative when present; otherwise we
167+
// only fall back to the /schedules resource, never materialized scans.
168+
hasSchedule: scheduleSummary !== undefined,
196169
scheduleSummary,
197170
lastScanAt: getProviderLastScanAt(provider),
198171
};
@@ -529,7 +502,6 @@ export async function loadProvidersAccountsViewData({
529502
const [
530503
providersResponse,
531504
allProvidersResponse,
532-
scansResponse,
533505
schedulesResponse,
534506
organizationsResponse,
535507
organizationUnitsResponse,
@@ -546,16 +518,6 @@ export async function loadProvidersAccountsViewData({
546518
// Unfiltered fetch for ProviderTypeSelector — only needs distinct types;
547519
// TODO: Replace with a dedicated lightweight endpoint when available.
548520
resolveActionResult(getAllProviders()),
549-
// Fetch active scheduled scans to flag providers whose schedule has fired.
550-
resolveActionResult(
551-
getScans({
552-
pageSize: 500,
553-
filters: {
554-
"filter[trigger]": SCAN_TRIGGER.SCHEDULED,
555-
"filter[state__in]": "scheduled,available",
556-
},
557-
}),
558-
),
559521
// Fetch configured schedules to also flag providers whose schedule has not
560522
// fired yet (best-effort: absent in OSS, where the helper yields no ids).
561523
resolveActionResult(getSchedules()),
@@ -567,18 +529,11 @@ export async function loadProvidersAccountsViewData({
567529
: Promise.resolve(emptyOrganizationUnitsResponse),
568530
]);
569531

570-
const scanScheduledProviderIds = buildScheduledProviderIds(
571-
scansResponse?.data ?? [],
572-
);
573532
const schedulesByProviderId = buildSchedulesByProviderId(schedulesResponse);
574533

575534
const orgs = organizationsResponse?.data ?? [];
576535
const ous = organizationUnitsResponse?.data ?? [];
577-
const providers = enrichProviders(
578-
providersResponse,
579-
scanScheduledProviderIds,
580-
schedulesByProviderId,
581-
);
536+
const providers = enrichProviders(providersResponse, schedulesByProviderId);
582537

583538
const rows = buildProvidersTableRows({
584539
isCloud,

ui/components/providers/link-to-scans.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ import { formatLocalTimeWithZone } from "@/lib/date-utils";
55
import type { ScanScheduleSummary } from "@/types/scans";
66

77
interface LinkToScansProps {
8-
hasSchedule: boolean;
98
schedule?: ScanScheduleSummary;
109
}
1110

1211
// Matches the scans table Schedule column: cadence on top, next-run local time
13-
// underneath. Falls back to a plain label when the cadence is unknown.
14-
export const LinkToScans = ({ hasSchedule, schedule }: LinkToScansProps) => {
12+
// underneath. Falls back to None when no configured schedule is present.
13+
export const LinkToScans = ({ schedule }: LinkToScansProps) => {
1514
if (schedule) {
1615
return (
1716
<StackedCell
@@ -21,9 +20,5 @@ export const LinkToScans = ({ hasSchedule, schedule }: LinkToScansProps) => {
2120
);
2221
}
2322

24-
return (
25-
<span className="text-text-neutral-secondary text-sm">
26-
{hasSchedule ? "Scheduled" : "None"}
27-
</span>
28-
);
23+
return <span className="text-text-neutral-secondary text-sm">None</span>;
2924
};

ui/components/providers/table/column-providers.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,12 +258,7 @@ export function getColumnProviders(
258258
);
259259
}
260260

261-
return (
262-
<LinkToScans
263-
hasSchedule={row.original.hasSchedule}
264-
schedule={row.original.scheduleSummary}
265-
/>
266-
);
261+
return <LinkToScans schedule={row.original.scheduleSummary} />;
267262
},
268263
enableSorting: false,
269264
},

0 commit comments

Comments
 (0)