diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 846b8684d0..ccc95107d0 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the **Prowler API** are documented in this file. ## [v1.5.1] (Prowler v5.4.1) ### Fixed +- Added a handled response in case local files are missing [(#7183)](https://github.com/prowler-cloud/prowler/pull/7183). - Fixed a race condition when deleting export files after the S3 upload [(#7172)](https://github.com/prowler-cloud/prowler/pull/7172). --- diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index 2cb50e28e4..66290689d0 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -2284,6 +2284,25 @@ class TestScanViewSet: assert f'filename="{expected_filename}"' in content_disposition assert response.content == b"s3 zip content" + def test_report_s3_success_no_local_files( + self, authenticated_client, scans_fixture, monkeypatch + ): + """ + When output_location is a local path and glob.glob returns an empty list, + the view should return HTTP 404 with detail "The scan has no reports." + """ + scan = scans_fixture[0] + scan.output_location = "/tmp/nonexistent_report_pattern.zip" + scan.state = StateChoices.COMPLETED + scan.save() + monkeypatch.setattr("api.v1.views.glob.glob", lambda pattern: []) + + url = reverse("scan-report", kwargs={"pk": scan.id}) + response = authenticated_client.get(url) + + assert response.status_code == 404 + assert response.json()["errors"]["detail"] == "The scan has no reports." + def test_report_local_file( self, authenticated_client, scans_fixture, tmp_path, monkeypatch ): diff --git a/api/src/backend/api/v1/views.py b/api/src/backend/api/v1/views.py index 753828c8b4..1851bf5426 100644 --- a/api/src/backend/api/v1/views.py +++ b/api/src/backend/api/v1/views.py @@ -1,6 +1,7 @@ import glob import os +import sentry_sdk from allauth.socialaccount.providers.github.views import GitHubOAuth2Adapter from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter from botocore.exceptions import ClientError, NoCredentialsError, ParamValidationError @@ -1280,7 +1281,14 @@ class ScanViewSet(BaseRLSViewSet): filename = os.path.basename(output_location.split("/")[-1]) else: zip_files = glob.glob(output_location) - file_path = zip_files[0] + try: + file_path = zip_files[0] + except IndexError as e: + sentry_sdk.capture_exception(e) + return Response( + {"detail": "The scan has no reports."}, + status=status.HTTP_404_NOT_FOUND, + ) with open(file_path, "rb") as f: file_content = f.read() filename = os.path.basename(file_path)