"""Reports endpoints — export coverage summaries and test results. Thin HTTP adapter: delegates all data logic to coverage_report_service. Endpoints --------- GET /reports/coverage-summary — full coverage JSON report GET /reports/coverage-csv — CSV export of coverage GET /reports/test-results — test results report (JSON) GET /reports/remediation-status — remediation status report (JSON) """ # Import csv import csv # Import io import io # Import datetime from datetime from datetime import datetime # Import Optional from typing from typing import Optional # Import APIRouter, Depends, Query from fastapi from fastapi import APIRouter, Depends, Query # Import StreamingResponse from fastapi.responses from fastapi.responses import StreamingResponse # Import Session from sqlalchemy.orm from sqlalchemy.orm import Session # Import get_db from app.database from app.database import get_db # Import get_current_user from app.dependencies.auth from app.dependencies.auth import get_current_user # Import User from app.models.user from app.models.user import User # Import from app.services.coverage_report_service from app.services.coverage_report_service import ( build_coverage_csv_rows, build_coverage_summary, build_remediation_status_report, build_test_results_report, ) # Assign router = APIRouter(prefix="/reports", tags=["reports"]) router = APIRouter(prefix="/reports", tags=["reports"]) # Apply the @router.get decorator @router.get("/coverage-summary") # Define function coverage_summary def coverage_summary( # Entry: tactic tactic: Optional[str] = Query(None, description="Filter by tactic"), # Entry: platform platform: Optional[str] = Query(None, description="Filter by platform (in techniques)"), # Entry: db db: Session = Depends(get_db), # Entry: current_user current_user: User = Depends(get_current_user), ) -> dict: """Full coverage report as JSON — technique-by-technique with test counts.""" # Return build_coverage_summary(db, tactic=tactic, platform=platform) return build_coverage_summary(db, tactic=tactic, platform=platform) # Apply the @router.get decorator @router.get("/coverage-csv") # Define function coverage_csv def coverage_csv( # Entry: tactic tactic: Optional[str] = Query(None), # Entry: platform platform: Optional[str] = Query(None), # Entry: db db: Session = Depends(get_db), # Entry: current_user current_user: User = Depends(get_current_user), ) -> StreamingResponse: """Export coverage as a downloadable CSV.""" # Assign rows = build_coverage_csv_rows(db, tactic=tactic, platform=platform) rows = build_coverage_csv_rows(db, tactic=tactic, platform=platform) # Assign output = io.StringIO() output = io.StringIO() # Assign writer = csv.writer(output) writer = csv.writer(output) # Iterate over rows for row in rows: # Call writer.writerow() writer.writerow(row) # Call output.seek() output.seek(0) # Assign filename = f"aegis_coverage_{datetime.utcnow().strftime('%Y%m%d')}.csv" filename = f"aegis_coverage_{datetime.utcnow().strftime('%Y%m%d')}.csv" # Return StreamingResponse( return StreamingResponse( iter([output.getvalue()]), # Keyword argument: media_type media_type="text/csv", # Keyword argument: headers headers={"Content-Disposition": f"attachment; filename={filename}"}, ) # Apply the @router.get decorator @router.get("/test-results") # Define function test_results def test_results( # Entry: state state: Optional[str] = Query(None), # Entry: date_from date_from: Optional[str] = Query(None, description="ISO date string YYYY-MM-DD"), # Entry: date_to date_to: Optional[str] = Query(None, description="ISO date string YYYY-MM-DD"), # Entry: db db: Session = Depends(get_db), # Entry: current_user current_user: User = Depends(get_current_user), ) -> dict: """Report of test results with optional filters.""" # Return build_test_results_report(db, state=state, date_from=date_from, dat... return build_test_results_report(db, state=state, date_from=date_from, date_to=date_to) # Apply the @router.get decorator @router.get("/remediation-status") # Define function remediation_status def remediation_status( # Entry: status status: Optional[str] = Query(None, description="Filter by remediation status"), # Entry: db db: Session = Depends(get_db), # Entry: current_user current_user: User = Depends(get_current_user), ) -> dict: """Report of remediation status across all tests.""" # Return build_remediation_status_report(db, status=status) return build_remediation_status_report(db, status=status)