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
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ Release notes

- Fix an issue with ``urlize_target_blank`` when the URL contains curly braces.

- Add the ability to download Product "Imports" input file.
https://github.com/aboutcode-org/dejacode/issues/156

### Version 5.2.1

- Fix the models documentation navigation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<strong>
{{ scancode_project.get_status_display|title }}
{% if scancode_project.has_errors %}
<div class="float-start"> with errors</div>
<span class="float-start"> with errors</span>
{% endif %}
</strong>
{% if scancode_project.project_uuid %}
Expand All @@ -56,7 +56,7 @@
</td>
<td>
{% if scancode_project.input_file %}
File: {{ scancode_project.input_file_filename }}
File: <a href="{% url 'product_portfolio:scancodeio_project_download_input' scancode_project.uuid %}" target="_blank">{{ scancode_project.input_file_filename }}</a>
{% elif scancode_project.project_uuid %}
Project: {{ scancode_project.project_uuid }}
{% endif %}
Expand Down
52 changes: 52 additions & 0 deletions product_portfolio/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from django.contrib.contenttypes.models import ContentType
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.shortcuts import resolve_url
from django.test import TestCase
from django.test.utils import override_settings
Expand Down Expand Up @@ -233,6 +234,18 @@ def test_product_portfolio_detail_view_tab_imports_view(self):
self.assertNotContains(response, "hx-trigger")
self.assertNotContains(response, "Imports are currently in progress.")

expected = "File:"
download_url = reverse(
"product_portfolio:scancodeio_project_download_input", args=[str(project.uuid)]
)
self.assertNotContains(response, expected)
self.assertNotContains(response, download_url)
project.input_file = ContentFile("Data", name="data.json")
project.save()
response = self.client.get(url)
self.assertContains(response, expected)
self.assertContains(response, download_url)

def test_product_portfolio_detail_view_tab_dependency_view(self):
self.client.login(username="nexb_user", password="secret")
url = self.product1.get_url("tab_dependencies")
Expand Down Expand Up @@ -3332,6 +3345,45 @@ def test_product_portfolio_improve_packages_from_purldb_view(self, mock_is_confi
self.assertEqual(200, response.status_code)
self.assertContains(response, "Improve Packages already in progress...")

def test_product_portfolio_scancodeio_project_download_input_view(self):
test_file_content = b"dummy input file content"
test_file = SimpleUploadedFile(
"input.zip", test_file_content, content_type="application/zip"
)

# Create a ScanCodeProject with file
scancode_project = ScanCodeProject.objects.create(
product=self.product1,
dataspace=self.product1.dataspace,
input_file=test_file,
type=ScanCodeProject.ProjectType.LOAD_SBOMS,
status=ScanCodeProject.Status.SUCCESS,
)

download_url = reverse(
"product_portfolio:scancodeio_project_download_input", args=[str(scancode_project.uuid)]
)

# No permission initially
self.client.login(username=self.basic_user.username, password="secret")
response = self.client.get(download_url)
self.assertEqual(response.status_code, 404)

# Grant permission
assign_perm("view_product", self.basic_user, self.product1)
response = self.client.get(download_url)
self.assertEqual(response.status_code, 200)
downloaded_content = b"".join(response.streaming_content)
self.assertEqual(test_file_content, downloaded_content)
self.assertEqual(
response["Content-Disposition"], f'attachment; filename="{test_file.name}"'
)

# Remove the file and test for 404
scancode_project.input_file.delete(save=True)
response = self.client.get(download_url)
self.assertEqual(response.status_code, 404)

@mock.patch("product_portfolio.models.Product.improve_packages_from_purldb")
def test_product_portfolio_improve_packages_from_purldb_task(self, mock_improve):
mock_improve.return_value = ["pkg1", "pkg2"]
Expand Down
6 changes: 6 additions & 0 deletions product_portfolio/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from product_portfolio.views import improve_packages_from_purldb_view
from product_portfolio.views import license_summary_view
from product_portfolio.views import scan_all_packages_view
from product_portfolio.views import scancodeio_project_download_input_view
from product_portfolio.views import scancodeio_project_status_view
from product_portfolio.views import vulnerability_analysis_form_view

Expand Down Expand Up @@ -71,6 +72,11 @@ def product_path(path_segment, view):
scancodeio_project_status_view,
name="scancodeio_project_status",
),
path(
"scancodeio_project_download_input/<uuid:scancodeproject_uuid>/",
scancodeio_project_download_input_view,
name="scancodeio_project_download_input",
),
path(
"compare/<uuid:left_uuid>/<uuid:right_uuid>/",
ProductTreeComparisonView.as_view(),
Expand Down
13 changes: 13 additions & 0 deletions product_portfolio/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from django.db.models import Subquery
from django.db.models.functions import Lower
from django.forms import modelformset_factory
from django.http import FileResponse
from django.http import Http404
from django.http import HttpResponse
from django.http import JsonResponse
Expand Down Expand Up @@ -2486,6 +2487,18 @@ def scancodeio_project_status_view(request, scancodeproject_uuid):
return TemplateResponse(request, template, context)


@login_required
def scancodeio_project_download_input_view(request, scancodeproject_uuid):
secured_qs = ScanCodeProject.objects.product_secured(user=request.user)
scancode_project = get_object_or_404(secured_qs, uuid=scancodeproject_uuid)
input_file = scancode_project.input_file

if not input_file or not input_file.storage.exists(input_file.name):
raise Http404

return FileResponse(input_file.open("rb"), as_attachment=True)


@login_required
def improve_packages_from_purldb_view(request, dataspace, name, version=""):
user = request.user
Expand Down