Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions surface/sca/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,17 @@ class EndOfLifeDependencyAdmin(DefaultModelAdmin, DefaultFilterMixin, EndOfLifeD
"no_support",
"is_discontinued",
"is_lts",
"link",
"get_link",
]
list_filter = ["product", EndOfLifeDependencyBoolFilter, LTSFilter, DiscontinuedFilter, SupportFilter]
search_fields = ["product"]

@admin.display(description="Link")
def get_link(self, obj):
if obj.link:
return format_html(f'<a target="_blank" href="{obj.link}">{obj.link}</a>')
return ""


class SCADependencyForm(forms.ModelForm):
class Meta:
Expand Down Expand Up @@ -248,7 +254,16 @@ class SCAProjectAdmin(DefaultModelAdmin):
"git_source",
("git_source__apps", RelatedFieldAjaxListFilter),
]
search_fields = ["name", "purl", "depends_on__name", "depends_on__purl", "git_source__repo_url"]
search_fields = [
"name",
"purl",
"depends_on__name",
"depends_on__purl",
"git_source__repo_url",
"dependencies_list",
]

readonly_fields = []

def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
Expand Down Expand Up @@ -276,7 +291,11 @@ def change_view(self, request, object_id, form_url="", extra_context=None):

vulnerabilities = self.get_vulnerabilities(obj)
# set fixed_in as True by default if not passed in the request
if "fixed_in" not in request.GET:
if (
"fixed_in" not in request.GET
and int(request.GET.get("finding_type", models.SCAFinding.FindingType.VULN))
!= models.SCAFinding.FindingType.EOL
):
request.GET = request.GET.copy()
request.GET["fixed_in"] = "true"
extra_context["vulns_filter"] = SCAFindingFilter(request.GET, queryset=vulnerabilities)
Expand Down Expand Up @@ -372,7 +391,7 @@ def get_git_source(self, obj):
def get_sbom_link(self, obj):
if obj.sbom_uuid:
return format_html(
'<a href="{}" target="_blank">Download sbom json</a>',
'<a href="{}" target="_blank" title="Download SBOM JSON" aria-label="Download SBOM JSON"><span class="material-symbols-outlined text-lg">download</span></a>',
reverse("sca:download_sbom_as_json", args=[obj.sbom_uuid, obj.name]),
)

Expand Down
2 changes: 2 additions & 0 deletions surface/sca/management/commands/resync_sbom_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ def handle_sbom(self, sbom: str) -> bool:

if project:
project.update_vulnerability_counters()
project.dependencies_list = project.dependencies
project.save()

self.processed += 1
return True
Expand Down
4 changes: 3 additions & 1 deletion surface/sca/management/commands/resync_vulns_counters.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@


class Command(LogBaseCommand):
help = "Re-sync SCA Projects Vulnerabilities Counters"
help = "Re-sync SCA Projects Vulnerabilities Counters and dependencies list."

processed_projects = 0

def handle(self, *args, **options):
self.sync_time = timezone.now()
for project in tqdm.tqdm(SCADependency.objects.filter(is_project=True)):
project.update_vulnerability_counters()
project.dependencies_list = project.dependencies
project.save(update_fields=["dependencies_list"])
self.processed_projects += 1

SCAFindingCounter.objects.filter(last_sync__lt=self.sync_time).update(
Expand Down
18 changes: 18 additions & 0 deletions surface/sca/migrations/0004_scadependency_dependencies_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.2.8 on 2025-11-11 16:31

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('sca', '0003_scadependency_sbom_uuid_and_more'),
]

operations = [
migrations.AddField(
model_name='scadependency',
name='dependencies_list',
field=models.JSONField(default=list),
),
]
1 change: 1 addition & 0 deletions surface/sca/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class SCADependency(models.Model):
updated_at = models.DateTimeField(auto_now=True)
last_scan = models.DateTimeField()
sbom_uuid = models.CharField(max_length=255, default=None, null=True)
dependencies_list = models.JSONField(default=list)

@staticmethod
def get_dependencies_recursively(
Expand Down
2 changes: 1 addition & 1 deletion surface/sca/templates/views/dependencies.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
<form method="post" action="">
{% csrf_token %}
<input type="hidden" name="action" value="run_renovate_dependency">
<input type="hidden" name="dependency_id" value="{{ dep.pk }}">
<input type="hidden" name="dependency_id" value="{{ dep.id }}">
<button class="ui circular icon basic tertiary green button" title="Renovate Dependency">
<i class="recycle icon"></i>
</button>
Expand Down