Skip to content

Commit e0d5580

Browse files
committed
Update code
1 parent b0c74ad commit e0d5580

File tree

6 files changed

+29
-32
lines changed

6 files changed

+29
-32
lines changed
Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,36 @@
11
"""Views for OWASP project health metrics."""
22

3-
import re
4-
5-
from django.http import FileResponse, HttpResponseBadRequest, HttpResponseNotFound
3+
from django.http import FileResponse, Http404
64
from django.views.decorators.http import require_GET
75

6+
from apps.owasp.models.project import Project
7+
from apps.owasp.models.project_health_metrics import ProjectHealthMetrics
88
from apps.owasp.utils.pdf import generate_latest_metrics_pdf, generate_metrics_overview_pdf
99

1010

1111
@require_GET
12-
def generate_overview_pdf(_request):
12+
def generate_overview_pdf(request): # noqa: ARG001
1313
"""Generate a PDF overview of OWASP project health metrics."""
1414
return FileResponse(
15-
generate_metrics_overview_pdf(),
15+
generate_metrics_overview_pdf(ProjectHealthMetrics.get_stats()),
1616
as_attachment=True,
1717
filename="owasp_project_health_metrics_overview.pdf",
1818
)
1919

2020

2121
@require_GET
22-
def generate_project_health_metrics_pdf(_request, project_key: str):
22+
def generate_project_health_metrics_pdf(request, project_key: str): # noqa: ARG001
2323
"""Generate and return a PDF report of project health metrics."""
24-
if not re.match(r"^[a-zA-Z0-9_-]+$", project_key):
25-
return HttpResponseBadRequest("Invalid project key")
24+
if not (project := Project.objects.filter(key=f"www-project-{project_key}").first()):
25+
raise Http404
2626

27-
if pdf := generate_latest_metrics_pdf(project_key):
27+
if pdf := generate_latest_metrics_pdf(
28+
ProjectHealthMetrics.get_latest_health_metrics().filter(project=project).first()
29+
):
2830
return FileResponse(
2931
pdf,
3032
as_attachment=True,
3133
filename=f"{project_key}_health_metrics_report.pdf",
3234
)
3335

34-
return HttpResponseNotFound("No health metrics found for this project")
36+
raise Http404

backend/apps/owasp/utils/pdf.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from reportlab.pdfgen.canvas import Canvas
88
from reportlab.platypus import Table, TableStyle
99

10+
from apps.owasp.api.internal.nodes.project_health_stats import ProjectHealthStatsNode
1011
from apps.owasp.models.project_health_metrics import ProjectHealthMetrics
1112

1213

@@ -29,15 +30,16 @@ def create_table(data, col_widths="*"):
2930
)
3031

3132

32-
def generate_metrics_overview_pdf() -> BytesIO:
33+
def generate_metrics_overview_pdf(metrics_stats: ProjectHealthStatsNode) -> BytesIO:
3334
"""Generate a PDF overview of project health metrics.
3435
36+
Args:
37+
metrics_stats: The project health stats node.
38+
3539
Returns:
3640
BytesIO: PDF content as bytes.
3741
3842
"""
39-
metrics_stats = ProjectHealthMetrics.get_stats()
40-
4143
buffer = BytesIO()
4244
canvas = Canvas(buffer)
4345
canvas.setFont("Helvetica", 12)
@@ -84,22 +86,16 @@ def generate_metrics_overview_pdf() -> BytesIO:
8486
return buffer
8587

8688

87-
def generate_latest_metrics_pdf(project_key: str) -> BytesIO | None:
89+
def generate_latest_metrics_pdf(metrics: ProjectHealthMetrics) -> BytesIO | None:
8890
"""Generate a PDF report of the latest health metrics for a project.
8991
9092
Args:
91-
project_key (str): The key of the OWASP project.
93+
metrics (ProjectHealthMetrics): The project health metrics.
9294
9395
Returns:
9496
BytesIO: A buffer containing the generated PDF report.
9597
9698
"""
97-
metrics = (
98-
ProjectHealthMetrics.get_latest_health_metrics()
99-
.filter(project__key=f"www-project-{project_key}")
100-
.first()
101-
)
102-
10399
if not metrics:
104100
return None
105101

@@ -176,4 +172,5 @@ def generate_latest_metrics_pdf(project_key: str) -> BytesIO | None:
176172
pdf.showPage()
177173
pdf.save()
178174
buffer.seek(0)
175+
179176
return buffer

backend/tests/apps/owasp/utils/pdf_test.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def test_generate_overview_pdf(
6565
),
6666
)
6767
mock_get_stats.return_value = metrics_stats
68-
generate_metrics_overview_pdf()
68+
generate_metrics_overview_pdf(metrics_stats)
6969
mock_bytes_io.assert_called_once()
7070
mock_canvas.assert_called_once_with(mock_bytes_io.return_value)
7171
canvas = mock_canvas.return_value
@@ -95,18 +95,21 @@ def test_generate_detailed_pdf(
9595
):
9696
metrics = MagicMock(
9797
age_days=30,
98+
age_days_requirement=365,
9899
contributors_count=20,
99100
forks_count=15,
100101
is_funding_requirements_compliant=True,
101102
is_leader_requirements_compliant=True,
102103
last_commit_days=5,
103104
last_commit_days_requirement=7,
104105
last_pull_request_days=2,
106+
last_pull_request_days_requirement=30,
105107
last_release_days=10,
106108
last_release_days_requirement=14,
107109
open_issues_count=10,
108110
open_pull_requests_count=3,
109111
owasp_page_last_update_days=20,
112+
owasp_page_last_update_days_requirement=90,
110113
project=MagicMock(name="Test Project", key="www-project-test"),
111114
recent_releases_count=1,
112115
score=85.0,
@@ -117,10 +120,7 @@ def test_generate_detailed_pdf(
117120
unanswered_issues_count=2,
118121
unassigned_issues_count=5,
119122
)
120-
mock_get_latest_health_metrics.return_value.filter.return_value.first.return_value = (
121-
metrics
122-
)
123-
generate_latest_metrics_pdf("test")
123+
generate_latest_metrics_pdf(metrics)
124124
mock_bytes_io.assert_called_once()
125125
mock_canvas.assert_called_once_with(mock_bytes_io.return_value, pagesize=letter)
126126
canvas = mock_canvas.return_value

frontend/src/app/projects/dashboard/metrics/[projectKey]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ const ProjectHealthMetricsDetails: FC = () => {
6868
<h1 className="text-2xl font-bold">{metricsLatest.projectName}</h1>
6969
<MetricsPDFButton
7070
path={`${projectKey}/pdf`}
71-
fileName={`${projectKey}-health-metrics.pdf`}
71+
fileName={`${projectKey}-health-metrics`}
7272
/>
7373
</div>
7474
<div className="flex items-center gap-2">

frontend/src/app/projects/dashboard/page.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,7 @@ const ProjectsDashboardPage: FC = () => {
9898
<>
9999
<div className="mb-4 flex items-center justify-start">
100100
<h1 className="font-semibold">Project Health Dashboard Overview</h1>
101-
<MetricsPDFButton
102-
path="overview/pdf"
103-
fileName="owasp-project-health-metrics-overview.pdf"
104-
/>
101+
<MetricsPDFButton path="overview/pdf" fileName="owasp-project-health-metrics-overview" />
105102
</div>
106103
<div className="mt-4 grid grid-cols-1 gap-4 md:grid-cols-3">
107104
{projectsCardsItems.map((item) => (

frontend/src/server/fetchMetricsPDF.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { handleAppError } from 'app/global-error'
22
import { API_URL } from 'utils/credentials'
3+
34
export const fetchMetricsPDF = async (path: string, fileName: string): Promise<void> => {
45
const response = await fetch(`${API_URL}owasp/project-health-metrics/${path}`, {
56
method: 'GET',
@@ -20,7 +21,7 @@ export const fetchMetricsPDF = async (path: string, fileName: string): Promise<v
2021
const url = window.URL.createObjectURL(blob)
2122
const link = document.createElement('a')
2223
link.href = url
23-
link.setAttribute('download', `${fileName}_${new Date().toISOString().split('T')[0]}.pdf`)
24+
link.setAttribute('download', `${fileName}-${new Date().toISOString().split('T')[0]}.pdf`)
2425
document.body.appendChild(link)
2526
link.click()
2627
document.body.removeChild(link)

0 commit comments

Comments
 (0)