Skip to content

Commit f0cbcbc

Browse files
committed
Resolve merge conflict
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
1 parent 94a5f10 commit f0cbcbc

5 files changed

Lines changed: 134 additions & 3 deletions

File tree

vulnerabilities/api_v3.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
from urllib.parse import urlencode
1212

1313
from django.contrib.postgres.aggregates import ArrayAgg
14+
from django.contrib.postgres.aggregates import JSONBAgg
1415
from django.db.models import Exists
1516
from django.db.models import Max
1617
from django.db.models import OuterRef
1718
from django.db.models import Prefetch
1819
from django.db.models import Q
20+
from django.db.models.functions import JSONObject
1921
from django_filters import rest_framework as filters
2022
from drf_spectacular.utils import extend_schema
2123
from packageurl import PackageURL
@@ -479,7 +481,23 @@ def get_affected_advisories_bulk(packages, max_advisories, base_url):
479481
"impacted_package__fixed_by_packages__package_url",
480482
distinct=True,
481483
filter=Q(impacted_package__fixed_by_packages__package_url__isnull=False),
482-
)
484+
),
485+
introduced_patches=JSONBAgg(
486+
JSONObject(
487+
commit_hash="impacted_package__introduced_by_package_commit_patches__commit_hash",
488+
vcs_url="impacted_package__introduced_by_package_commit_patches__vcs_url",
489+
),
490+
distinct=True,
491+
filter=Q(impacted_package__introduced_by_package_commit_patches__isnull=False),
492+
),
493+
fixed_patches=JSONBAgg(
494+
JSONObject(
495+
commit_hash="impacted_package__fixed_by_package_commit_patches__commit_hash",
496+
vcs_url="impacted_package__fixed_by_package_commit_patches__vcs_url",
497+
),
498+
distinct=True,
499+
filter=Q(impacted_package__fixed_by_package_commit_patches__isnull=False),
500+
),
483501
)
484502
)
485503

@@ -492,6 +510,20 @@ def get_affected_advisories_bulk(packages, max_advisories, base_url):
492510
for row in impacts
493511
}
494512

513+
introduced_patches_map = {
514+
(row["package_id"], row["impacted_package__advisory_id"]): [
515+
p for p in (row["introduced_patches"] or []) if p and p.get("commit_hash")
516+
]
517+
for row in impacts
518+
}
519+
520+
fixed_patches_map = {
521+
(row["package_id"], row["impacted_package__advisory_id"]): [
522+
p for p in (row["fixed_patches"] or []) if p and p.get("commit_hash")
523+
]
524+
for row in impacts
525+
}
526+
495527
# Package types with multiple importers
496528

497529
advisory_sets = list(
@@ -647,6 +679,8 @@ def get_affected_advisories_bulk(packages, max_advisories, base_url):
647679
"exploitability": exploitability,
648680
"risk_score": risk_score,
649681
"fixed_by_packages": fixed_by_packages,
682+
"introduced_in_patch": introduced_patches_map.get((package.id, primary.id), []),
683+
"fixed_in_patch": fixed_patches_map.get((package.id, primary.id), []),
650684
"ssvc_trees": adv.ssvc_trees,
651685
"resource_url": resource_url,
652686
}
@@ -742,6 +776,10 @@ def get_affected_advisories_bulk(packages, max_advisories, base_url):
742776
"exploitability": advisory.exploitability,
743777
"risk_score": advisory.risk_score,
744778
"fixed_by_packages": fixed_by_packages,
779+
"introduced_in_patch": introduced_patches_map.get(
780+
(package.id, advisory_id), []
781+
),
782+
"fixed_in_patch": fixed_patches_map.get((package.id, advisory_id), []),
745783
"ssvc_trees": [
746784
{
747785
"vector": ssvc.vector,

vulnerabilities/templates/advisory_package_commit_details.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
{% block content %}
1313

1414
{% if advisoryv2 %}
15-
<section class="section pt-0">
15+
<section class="section pt-4">
1616
<div class="details-container">
1717
<article class="panel is-info panel-header-only">
1818
<div class="panel-heading py-2 is-size-6">

vulnerabilities/tests/test_api_v3.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
from univers.version_range import PypiVersionRange
1717

1818
from vulnerabilities.importer import AdvisoryDataV2
19+
from vulnerabilities.importer import AffectedPackageV2
20+
from vulnerabilities.importer import PackageCommitPatchData
21+
from vulnerabilities.models import AdvisorySet
22+
from vulnerabilities.models import AdvisorySetMember
23+
from vulnerabilities.models import ImpactedPackage
24+
from vulnerabilities.models import ImpactedPackageAffecting
1925
from vulnerabilities.models import PackageV2
2026
from vulnerabilities.pipes.advisory import insert_advisory_v2
2127
from vulnerabilities.tests.pipelines import TestLogger
@@ -254,3 +260,84 @@ def test_get_all_vulnerable_purls(self):
254260
results = response.data["results"]
255261
self.assertEqual(len(results), 100)
256262
self.assertIn("next", response.data)
263+
264+
265+
class PackageCommitPatchTests(APITestCase):
266+
def setUp(self):
267+
self.advisory = AdvisoryDataV2(
268+
advisory_id="AVID-123",
269+
aliases=[],
270+
affected_packages=[
271+
AffectedPackageV2(
272+
package=PackageURL(type="pypi", name="sample"),
273+
affected_version_range=PypiVersionRange.from_string("vers:pypi/=1.0.0"),
274+
introduced_by_commit_patches=[
275+
PackageCommitPatchData(
276+
vcs_url="https://github.com/aboutcode-org/sample",
277+
commit_hash="06580c7f99c6fde7bcf18e30bdcc61f081430957",
278+
)
279+
],
280+
fixed_by_commit_patches=[
281+
PackageCommitPatchData(
282+
vcs_url="https://github.com/aboutcode-org/sample",
283+
commit_hash="98e516011d6e096e25247b82fc5f196bbeecff10",
284+
)
285+
],
286+
)
287+
],
288+
url="https://github.com/aboutcode-org/sample",
289+
)
290+
291+
self.advisory = insert_advisory_v2(self.advisory, "importer_1", print, 100)
292+
self.advisory.is_latest = True
293+
self.advisory._all_impacts_unfurled_at = timezone.now()
294+
self.advisory.save()
295+
self.package, _ = PackageV2.objects.get_or_create(
296+
package_url="pkg:pypi/sample@1.0.0",
297+
defaults={"name": "sample", "type": "pypi", "version": "1.0.0"},
298+
)
299+
300+
impacted_package = ImpactedPackage.objects.get(advisory=self.advisory)
301+
ImpactedPackageAffecting.objects.get_or_create(
302+
package=self.package,
303+
impacted_package=impacted_package,
304+
)
305+
adv_set = AdvisorySet.objects.create(
306+
package=self.package, primary_advisory=self.advisory, relation_type="affecting"
307+
)
308+
AdvisorySetMember.objects.create(advisory_set=adv_set, advisory=self.advisory)
309+
310+
self.client = APIClient(enforce_csrf_checks=True)
311+
312+
def test_packages_commit_patch(self):
313+
url = reverse("package-v3-list")
314+
response = self.client.post(
315+
url,
316+
data={"purls": ["pkg:pypi/sample@1.0.0"], "details": True},
317+
format="json",
318+
)
319+
320+
assert response.status_code == 200
321+
results = response.data["results"]
322+
assert len(results) == 1
323+
pkg = results[0]
324+
assert pkg["purl"] == "pkg:pypi/sample@1.0.0"
325+
326+
vulns = pkg.get("affected_by_vulnerabilities", [])
327+
assert len(vulns) == 1
328+
advisory_data = vulns[0]
329+
330+
assert advisory_data["advisory_id"] == "AVID-123"
331+
assert advisory_data["introduced_in_patch"] == [
332+
{
333+
"commit_hash": "06580c7f99c6fde7bcf18e30bdcc61f081430957",
334+
"vcs_url": "https://github.com/aboutcode-org/sample",
335+
}
336+
]
337+
338+
assert advisory_data["fixed_in_patch"] == [
339+
{
340+
"commit_hash": "98e516011d6e096e25247b82fc5f196bbeecff10",
341+
"vcs_url": "https://github.com/aboutcode-org/sample",
342+
}
343+
]

vulnerabilities/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ def get_queryset(self):
944944
class AdvisoryPackageCommitPatchDetails(DetailView):
945945
"""
946946
View to display all packages introduce by or fixing a specific vulnerability.
947-
URL: /advisories/{id}/commits
947+
URL: /advisories/commits/{id}
948948
"""
949949

950950
model = models.AdvisoryV2

vulnerablecode/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from vulnerabilities.api_v3 import PackageV3ViewSet
3232
from vulnerabilities.views import AdminLoginView
3333
from vulnerabilities.views import AdvisoryDetails
34+
from vulnerabilities.views import AdvisoryPackageCommitPatchDetails
3435
from vulnerabilities.views import AdvisoryPackageCurationView
3536
from vulnerabilities.views import AdvisoryPackagesDetails
3637
from vulnerabilities.views import AdvisoryToDoListView
@@ -131,6 +132,11 @@ def __init__(self, *args, **kwargs):
131132
AdvisoryPackagesDetails.as_view(),
132133
name="advisory_package_details",
133134
),
135+
path(
136+
"advisories/commits/<path:avid>",
137+
AdvisoryPackageCommitPatchDetails.as_view(),
138+
name="advisory_package_commit_details",
139+
),
134140
path(
135141
"advisories/<path:avid>",
136142
AdvisoryDetails.as_view(),

0 commit comments

Comments
 (0)