refactor(api): remove ServiceOverviewFilter and update related tests (#9248)

This commit is contained in:
Adrián Jesús Peña Rodríguez
2025-11-19 10:33:31 +01:00
committed by GitHub
parent 148a6f341b
commit 3dc4ab5b83
6 changed files with 228 additions and 30 deletions

View File

@@ -20,6 +20,7 @@ All notable changes to the **Prowler API** are documented in this file.
### Changed
- Optimized database write queries for scan related tasks [(#9190)](https://github.com/prowler-cloud/prowler/pull/9190)
- Date filters are now optional for `GET /api/v1/overviews/services` endpoint; returns latest scan data by default [(#9248)](https://github.com/prowler-cloud/prowler/pull/9248)
### Fixed
- Scans no longer fail when findings have UIDs exceeding 300 characters; such findings are now skipped with detailed logging [(#9246)](https://github.com/prowler-cloud/prowler/pull/9246)

View File

@@ -860,26 +860,6 @@ class ScanSummarySeverityFilter(ScanSummaryFilter):
}
class ServiceOverviewFilter(ScanSummaryFilter):
def is_valid(self):
# Check if at least one of the inserted_at filters is present
inserted_at_filters = [
self.data.get("inserted_at"),
self.data.get("inserted_at__gte"),
self.data.get("inserted_at__lte"),
]
if not any(inserted_at_filters):
raise ValidationError(
{
"inserted_at": [
"At least one of filter[inserted_at], filter[inserted_at__gte], or "
"filter[inserted_at__lte] is required."
]
}
)
return super().is_valid()
class IntegrationFilter(FilterSet):
inserted_at = DateFilter(field_name="inserted_at", lookup_expr="date")
integration_type = ChoiceFilter(choices=Integration.IntegrationChoices.choices)

View File

@@ -2282,9 +2282,6 @@ class ThreatScoreSnapshot(RowLevelSecurityProtectedModel):
Snapshots are created automatically after each ThreatScore report generation.
"""
objects = models.Manager()
all_objects = models.Manager()
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
inserted_at = models.DateTimeField(auto_now_add=True, editable=False)

View File

@@ -4956,8 +4956,7 @@ paths:
operationId: overviews_services_retrieve
description: Retrieve an aggregated summary of findings grouped by service.
The response includes the total count of findings for each service, as long
as there are at least one finding for that service. At least one of the `inserted_at`
filters must be provided.
as there are at least one finding for that service.
summary: Get findings data by service
parameters:
- in: query
@@ -5120,6 +5119,90 @@ paths:
schema:
$ref: '#/components/schemas/OverviewServiceResponse'
description: ''
/api/v1/overviews/threatscore:
get:
operationId: overviews_threatscore_retrieve
description: Retrieve ThreatScore metrics. By default, returns the latest snapshot
for each provider. Use snapshot_id to retrieve a specific historical snapshot.
summary: Get ThreatScore snapshots
parameters:
- in: query
name: fields[threatscore-snapshots]
schema:
type: array
items:
type: string
enum:
- id
- inserted_at
- scan
- provider
- compliance_id
- overall_score
- score_delta
- section_scores
- critical_requirements
- total_requirements
- passed_requirements
- failed_requirements
- manual_requirements
- total_findings
- passed_findings
- failed_findings
description: endpoint return only specific fields in the response on a per-type
basis by including a fields[TYPE] query parameter.
explode: false
- in: query
name: include
schema:
type: array
items:
type: string
enum:
- scan
- provider
description: include query parameter to allow the client to customize which
related resources should be returned.
explode: false
- in: query
name: provider_id
schema:
type: string
format: uuid
description: Filter by specific provider ID
- in: query
name: provider_id__in
schema:
type: string
description: Filter by multiple provider IDs (comma-separated UUIDs)
- in: query
name: provider_type
schema:
type: string
description: Filter by provider type (aws, azure, gcp, etc.)
- in: query
name: provider_type__in
schema:
type: string
description: Filter by multiple provider types (comma-separated)
- in: query
name: snapshot_id
schema:
type: string
format: uuid
description: Retrieve a specific snapshot by ID. If not provided, returns
latest snapshots.
tags:
- Overviews
security:
- JWT or API Key: []
responses:
'200':
content:
application/vnd.api+json:
schema:
$ref: '#/components/schemas/ThreatScoreSnapshotResponse'
description: ''
/api/v1/processors:
get:
operationId: processors_list
@@ -18581,6 +18664,143 @@ components:
$ref: '#/components/schemas/Tenant'
required:
- data
ThreatScoreSnapshot:
type: object
required:
- type
- id
additionalProperties: false
properties:
type:
type: string
description: The [type](https://jsonapi.org/format/#document-resource-object-identification)
member is used to describe resource objects that share common attributes
and relationships.
enum:
- threatscore-snapshots
id: {}
attributes:
type: object
properties:
id:
type: string
readOnly: true
inserted_at:
type: string
format: date-time
readOnly: true
compliance_id:
type: string
readOnly: true
description: Compliance framework ID (e.g., 'prowler_threatscore_aws')
overall_score:
type: string
format: decimal
pattern: ^-?\d{0,3}(?:\.\d{0,2})?$
readOnly: true
description: Overall ThreatScore percentage (0-100)
score_delta:
type: string
format: decimal
pattern: ^-?\d{0,3}(?:\.\d{0,2})?$
readOnly: true
nullable: true
description: Score change compared to previous snapshot (positive =
improvement)
section_scores:
readOnly: true
description: ThreatScore breakdown by section
critical_requirements:
readOnly: true
description: List of critical failed requirements (risk >= 4)
total_requirements:
type: integer
readOnly: true
description: Total number of requirements evaluated
passed_requirements:
type: integer
readOnly: true
description: Number of requirements with PASS status
failed_requirements:
type: integer
readOnly: true
description: Number of requirements with FAIL status
manual_requirements:
type: integer
readOnly: true
description: Number of requirements with MANUAL status
total_findings:
type: integer
readOnly: true
description: Total number of findings across all requirements
passed_findings:
type: integer
readOnly: true
description: Number of findings with PASS status
failed_findings:
type: integer
readOnly: true
description: Number of findings with FAIL status
relationships:
type: object
properties:
scan:
type: object
properties:
data:
type: object
properties:
id:
type: string
format: uuid
type:
type: string
enum:
- scans
title: Resource Type Name
description: The [type](https://jsonapi.org/format/#document-resource-object-identification)
member is used to describe resource objects that share common
attributes and relationships.
required:
- id
- type
required:
- data
description: The identifier of the related object.
title: Resource Identifier
readOnly: true
provider:
type: object
properties:
data:
type: object
properties:
id:
type: string
format: uuid
type:
type: string
enum:
- providers
title: Resource Type Name
description: The [type](https://jsonapi.org/format/#document-resource-object-identification)
member is used to describe resource objects that share common
attributes and relationships.
required:
- id
- type
required:
- data
description: The identifier of the related object.
title: Resource Identifier
readOnly: true
ThreatScoreSnapshotResponse:
type: object
properties:
data:
$ref: '#/components/schemas/ThreatScoreSnapshot'
required:
- data
Token:
type: object
required:

View File

@@ -6758,7 +6758,9 @@ class TestOverviewViewSet:
self, authenticated_client, scan_summaries_fixture
):
response = authenticated_client.get(reverse("overview-services"))
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert response.status_code == status.HTTP_200_OK
# Should return services from latest scans
assert len(response.json()["data"]) == 2
def test_overview_services_list(self, authenticated_client, scan_summaries_fixture):
response = authenticated_client.get(

View File

@@ -119,7 +119,6 @@ from api.filters import (
ScanFilter,
ScanSummaryFilter,
ScanSummarySeverityFilter,
ServiceOverviewFilter,
TaskFilter,
TenantApiKeyFilter,
TenantFilter,
@@ -3866,8 +3865,7 @@ class ComplianceOverviewViewSet(BaseRLSViewSet, TaskManagementMixin):
summary="Get findings data by service",
description=(
"Retrieve an aggregated summary of findings grouped by service. The response includes the total count "
"of findings for each service, as long as there are at least one finding for that service. At least "
"one of the `inserted_at` filters must be provided."
"of findings for each service, as long as there are at least one finding for that service."
),
filters=True,
),
@@ -3913,7 +3911,7 @@ class OverviewViewSet(BaseRLSViewSet):
elif self.action == "findings_severity":
return ScanSummarySeverityFilter
elif self.action == "services":
return ServiceOverviewFilter
return ScanSummaryFilter
return None
@extend_schema(exclude=True)