Skip to content

Commit

Permalink
Improve license detection and summary related views
Browse files Browse the repository at this point in the history
Signed-off-by: Ayan Sinha Mahapatra <ayansmahapatra@gmail.com>
  • Loading branch information
AyanSinhaMahapatra committed Jul 17, 2024
1 parent 225c216 commit 973d7aa
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 56 deletions.
6 changes: 4 additions & 2 deletions scanpipe/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ class ResourceFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):
dropdown_widget_fields = [
"status",
"type",
"programming_language",
"tag",
"compliance_alert",
"in_package",
Expand Down Expand Up @@ -521,6 +522,7 @@ class ResourceFilterSet(FilterSetUtilsMixin, django_filters.FilterSet):
"related_from__from_resource__path",
],
)
programming_language = django_filters.AllValuesFilter()
compliance_alert = django_filters.ChoiceFilter(
choices=[(EMPTY_VAR, "None")] + CodebaseResource.Compliance.choices,
)
Expand Down Expand Up @@ -577,8 +579,8 @@ class Meta:

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
license_expression_filer = self.filters["detected_license_expression"]
license_expression_filer.extra["widget"] = HasValueDropdownWidget()
license_expression_filter = self.filters["detected_license_expression"]
license_expression_filter.extra["widget"] = HasValueDropdownWidget()

@classmethod
def filter_for_lookup(cls, field, lookup_type):
Expand Down
33 changes: 25 additions & 8 deletions scanpipe/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1365,14 +1365,28 @@ def license_detections_count(self):

@cached_property
def package_compliance_alert_count(self):
"""Return the number of packages related to this project which have."""
"""
Return the number of packages related to this project which have
a license compliance error alert.
"""
return self.discoveredpackages.has_compliance_alert().count()

@cached_property
def license_compliance_alert_count(self):
"""Return the number of packages related to this project which have."""
"""
Return the number of license detections related to this project
which have a license compliance error alert.
"""
return self.discoveredlicenses.has_compliance_alert().count()

@cached_property
def resource_compliance_alert_count(self):
"""
Return the number of codebase resources related to this project which have
a license compliance error alert.
"""
return self.codebaseresources.has_compliance_alert().count()

@cached_property
def message_count(self):
"""Return the number of messages related to this project."""
Expand Down Expand Up @@ -2042,7 +2056,15 @@ def convert_glob_to_django_regex(glob_pattern):
return escaped_pattern


class CodebaseResourceQuerySet(ProjectRelatedQuerySet):
class ComplianceAlertQuerySetMixin:
def has_compliance_alert(self):
return self.filter(Q(compliance_alert__exact=CodebaseResource.Compliance.ERROR))


class CodebaseResourceQuerySet(
ComplianceAlertQuerySetMixin,
ProjectRelatedQuerySet,
):
def prefetch_for_serializer(self):
"""
Optimized prefetching for a QuerySet to be consumed by the
Expand Down Expand Up @@ -2945,11 +2967,6 @@ def vulnerable(self):
return self.filter(~Q(affected_by_vulnerabilities__in=EMPTY_VALUES))


class ComplianceAlertQuerySetMixin:
def has_compliance_alert(self):
return self.filter(Q(compliance_alert__exact=CodebaseResource.Compliance.ERROR))


class DiscoveredPackageQuerySet(
VulnerabilityQuerySetMixin,
ComplianceAlertQuerySetMixin,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,17 @@
<div class="level-item has-text-centered">
<div>
<p class="heading">Resources</p>
<p class="{{ title_class }}">
<p class="{{ title_class }} is-flex is-align-items-center is-justify-content-center">
{% if project.resource_count %}
<a href="{{ project_resources_url }}">
{{ project.resource_count|intcomma }}
</a>
{% if project.resource_compliance_alert_count %}
<a href="{% url 'project_resources' project.slug %}?compliance_alert=error" class="has-text-danger is-size-5 ml-2">
{{ project.resource_compliance_alert_count|intcomma }}
<i class="fa-solid fa-scale-balanced is-size-6"></i>
</a>
{% endif %}
{% else %}
<span>0</span>
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion scanpipe/templates/scanpipe/license_detection_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<a href="{% url 'license_detail' project.slug license_detection.identifier %}">{{ license_detection.identifier }}</a>
{% if license_detection.has_compliance_alert %}
<a href="{% url 'license_detail' project.slug license_detection.identifier %}#detection">
<i class="fa-solid fa-scale-balanced fa-sm has-text-danger" title="License Compliance Error"></i>
<i class="fa-solid fa-scale-balanced fa-sm has-text-danger" title="License Compliance Alerts"></i>
</a>
{% endif %}
</td>
Expand Down
18 changes: 15 additions & 3 deletions scanpipe/templates/scanpipe/panels/license_detections_summary.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,29 @@
<div class="column is-half">
<nav class="panel is-info">
<p class="panel-heading py-2 is-size-6">
Top 10 Unique License detections
Unique License detections
</p>
{% for license_expression, count in license_detection_summary.items %}
<a class="panel-block is-align-items-flex-start break-word" href="{{ project_licenses_url }}?license_expression={{ license_expression|default:'_EMPTY_' }}" target="_blank">
<a class="panel-block is-align-items-flex-start break-word is-flex is-align-items-center" href="{{ project_licenses_url }}?license_expression={{ license_expression|default:'_EMPTY_' }}" target="_blank">
{{ license_expression|default:'<i>No licenses</i>' }}
<span class="tag is-rounded ml-1">{{ count|intcomma }}</span>
{% if license_expression in expressions_with_compliance_alert %}
&nbsp; <span class="fa-solid fa-scale-balanced has-text-danger" title="License Compliance Error"></span>
&nbsp; <span class="fa-solid fa-scale-balanced has-text-danger" title="License Compliance Alerts"></span>
{% endif %}
</a>
{% endfor %}
{% if total_counts.all %}
<a class="panel-block is-align-items-flex-start break-word is-flex is-align-items-center" href="{{ project_licenses_url }}" target="_blank">
See all License Detections
<span class="tag is-rounded ml-1">{{ total_counts.all|intcomma }}</span>
{% if total_counts.with_compliance_error %}
<span class="has-text-danger is-size-6 ml-2">
<i class="fa-solid fa-scale-balanced fa-sm"></i>
{{ total_counts.with_compliance_error|intcomma }}
</span>
{% endif %}
</a>
{% endif %}
</nav>
</div>
{% endif %}
162 changes: 147 additions & 15 deletions scanpipe/templates/scanpipe/panels/scan_summary_panel.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,80 @@
</div>
<div class="panel-block p-0">
<table class="table is-fullwidth border-bottom-radius">
{% for field_label, values in scan_summary.items %}
<tr>
<th class="is-narrow">
{{ field_label }}
</th>
<td>
<ul>
{% for entry in values %}
{% if entry.value %}
<tr>
<th class="is-narrow">
Declared license
</th>
<td>
<ul>
{% for entry in scan_summary.declared_license_expression %}
{% if entry.value %}
<li>
{{ entry.value }}
{% if entry.count %}
<span class="tag is-rounded">
{{ entry.count|intcomma }}
</span>
{% endif %}
</li>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
<tr>
<th class="is-narrow">
Declared holder
</th>
<td>
<ul>
{% for entry in scan_summary.declared_holder %}
{% if entry.value %}
<li>
{{ entry.value }}
{% if entry.count %}
<span class="tag is-rounded">
{{ entry.count|intcomma }}
</span>
{% endif %}
</li>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
<tr>
<th class="is-narrow">
Primary language
</th>
<td>
<ul>
{% for entry in scan_summary.primary_language %}
{% if entry.value %}
<li>
<a href="{% url 'project_resources' project.slug %}?programming_language={{ entry.value }}" target="_blank">
{{ entry.value }}
{% if entry.count %}
<span class="tag is-rounded">
{{ entry.count|intcomma }}
</span>
{% endif %}
</a>
</li>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
<tr>
<th class="is-narrow">
Other licenses
</th>
<td>
<ul>
{% for entry in scan_summary.other_license_expressions %}
{% if entry.value %}
<a href="{% url 'project_licenses' project.slug %}?license_expression={{ entry.value }}" target="_blank">
<li>
{{ entry.value }}
{% if entry.count %}
Expand All @@ -23,12 +88,79 @@
</span>
{% endif %}
</li>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</a>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
<tr>
<th class="is-narrow">
Other holders
</th>
<td>
<ul>
{% for entry in scan_summary.other_holders %}
{% if entry.value %}
<li>
{{ entry.value }}
{% if entry.count %}
<span class="tag is-rounded">
{{ entry.count|intcomma }}
</span>
{% endif %}
</li>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
<tr>
<th class="is-narrow">
Other languages
</th>
<td>
<ul>
{% for entry in scan_summary.other_languages %}
{% if entry.value %}
<a href="{% url 'project_resources' project.slug %}?programming_language={{ entry.value }}" target="_blank">
<li>
{{ entry.value }}
{% if entry.count %}
<span class="tag is-rounded">
{{ entry.count|intcomma }}
</span>
{% endif %}
</li>
</a>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
<tr>
<th class="is-narrow">
Key Files
</th>
<td>
<ul>
{% for path, license in scan_summary.key_file_licenses.items %}
{% if path %}
<a href="{% url 'resource_detail' project.slug path %}#detection" target="_blank">
<li>
{{ path }}
{% if license %}
<span class="tag is-rounded">
{{ license }}
</span>
{% endif %}
</li>
</a>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
</table>
</div>
</article>
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
{{ match.license_expression }}
</td>
<td class="break-all">
{{ match.from_file }}
<a href="{% url 'resource_detail' project.slug match.from_file %}#detection">{{ match.from_file }}</a>
</td>
<td class="break-all">
{{ match.rule_url }}
Expand Down Expand Up @@ -73,7 +73,7 @@
{% for file_region in tab_data.fields.file_regions.value %}
<tr>
<td class="break-all">
{{ file_region.path }}
<a href="{% url 'resource_detail' project.slug file_region.path %}#detection">{{ file_region.path }}</a>
</td>
<td class="break-all">
{{ file_region.start_line }}
Expand Down
19 changes: 10 additions & 9 deletions scanpipe/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,16 +475,17 @@ def test_scanpipe_views_project_details_get_scan_summary_data(self):

scan_summary = self.data / "scancode" / "is-npm-1.0.0_scan_package_summary.json"
scan_summary_json = json.loads(scan_summary.read_text())
scan_summary_data = get_scan_summary_data(scan_summary_json)
scan_summary_data = get_scan_summary_data(self.project1, scan_summary_json)

self.assertEqual(6, len(scan_summary_data))
self.assertEqual(7, len(scan_summary_data))
expected = [
"Declared license",
"Declared holder",
"Primary language",
"Other licenses",
"Other holders",
"Other languages",
"declared_license_expression",
"declared_holder",
"primary_language",
"other_license_expressions",
"other_holders",
"other_languages",
"key_file_licenses",
]
self.assertEqual(expected, list(scan_summary_data.keys()))

Expand Down Expand Up @@ -956,7 +957,7 @@ def test_scanpipe_views_codebase_resource_views(self):
package1.add_resources([resource1, resource2])

url = reverse("project_resources", args=[self.project1.slug])
with self.assertNumQueries(8):
with self.assertNumQueries(9):
self.client.get(url)

with self.assertNumQueries(8):
Expand Down
Loading

0 comments on commit 973d7aa

Please sign in to comment.