Skip to content

Commit 3f57dab

Browse files
authored
Add the ability to download Product "Imports" input file (#296)
Signed-off-by: tdruez <tdruez@nexb.com>
1 parent 59d438b commit 3f57dab

File tree

5 files changed

+76
-2
lines changed

5 files changed

+76
-2
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ Release notes
125125

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

128+
- Add the ability to download Product "Imports" input file.
129+
https://github.com/aboutcode-org/dejacode/issues/156
130+
128131
### Version 5.2.1
129132

130133
- Fix the models documentation navigation.

product_portfolio/templates/product_portfolio/tabs/tab_imports.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<strong>
4545
{{ scancode_project.get_status_display|title }}
4646
{% if scancode_project.has_errors %}
47-
<div class="float-start"> with errors</div>
47+
<span class="float-start"> with errors</span>
4848
{% endif %}
4949
</strong>
5050
{% if scancode_project.project_uuid %}
@@ -56,7 +56,7 @@
5656
</td>
5757
<td>
5858
{% if scancode_project.input_file %}
59-
File: {{ scancode_project.input_file_filename }}
59+
File: <a href="{% url 'product_portfolio:scancodeio_project_download_input' scancode_project.uuid %}" target="_blank">{{ scancode_project.input_file_filename }}</a>
6060
{% elif scancode_project.project_uuid %}
6161
Project: {{ scancode_project.project_uuid }}
6262
{% endif %}

product_portfolio/tests/test_views.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from django.contrib.contenttypes.models import ContentType
1616
from django.core.files.base import ContentFile
17+
from django.core.files.uploadedfile import SimpleUploadedFile
1718
from django.shortcuts import resolve_url
1819
from django.test import TestCase
1920
from django.test.utils import override_settings
@@ -233,6 +234,18 @@ def test_product_portfolio_detail_view_tab_imports_view(self):
233234
self.assertNotContains(response, "hx-trigger")
234235
self.assertNotContains(response, "Imports are currently in progress.")
235236

237+
expected = "File:"
238+
download_url = reverse(
239+
"product_portfolio:scancodeio_project_download_input", args=[str(project.uuid)]
240+
)
241+
self.assertNotContains(response, expected)
242+
self.assertNotContains(response, download_url)
243+
project.input_file = ContentFile("Data", name="data.json")
244+
project.save()
245+
response = self.client.get(url)
246+
self.assertContains(response, expected)
247+
self.assertContains(response, download_url)
248+
236249
def test_product_portfolio_detail_view_tab_dependency_view(self):
237250
self.client.login(username="nexb_user", password="secret")
238251
url = self.product1.get_url("tab_dependencies")
@@ -3332,6 +3345,45 @@ def test_product_portfolio_improve_packages_from_purldb_view(self, mock_is_confi
33323345
self.assertEqual(200, response.status_code)
33333346
self.assertContains(response, "Improve Packages already in progress...")
33343347

3348+
def test_product_portfolio_scancodeio_project_download_input_view(self):
3349+
test_file_content = b"dummy input file content"
3350+
test_file = SimpleUploadedFile(
3351+
"input.zip", test_file_content, content_type="application/zip"
3352+
)
3353+
3354+
# Create a ScanCodeProject with file
3355+
scancode_project = ScanCodeProject.objects.create(
3356+
product=self.product1,
3357+
dataspace=self.product1.dataspace,
3358+
input_file=test_file,
3359+
type=ScanCodeProject.ProjectType.LOAD_SBOMS,
3360+
status=ScanCodeProject.Status.SUCCESS,
3361+
)
3362+
3363+
download_url = reverse(
3364+
"product_portfolio:scancodeio_project_download_input", args=[str(scancode_project.uuid)]
3365+
)
3366+
3367+
# No permission initially
3368+
self.client.login(username=self.basic_user.username, password="secret")
3369+
response = self.client.get(download_url)
3370+
self.assertEqual(response.status_code, 404)
3371+
3372+
# Grant permission
3373+
assign_perm("view_product", self.basic_user, self.product1)
3374+
response = self.client.get(download_url)
3375+
self.assertEqual(response.status_code, 200)
3376+
downloaded_content = b"".join(response.streaming_content)
3377+
self.assertEqual(test_file_content, downloaded_content)
3378+
self.assertEqual(
3379+
response["Content-Disposition"], f'attachment; filename="{test_file.name}"'
3380+
)
3381+
3382+
# Remove the file and test for 404
3383+
scancode_project.input_file.delete(save=True)
3384+
response = self.client.get(download_url)
3385+
self.assertEqual(response.status_code, 404)
3386+
33353387
@mock.patch("product_portfolio.models.Product.improve_packages_from_purldb")
33363388
def test_product_portfolio_improve_packages_from_purldb_task(self, mock_improve):
33373389
mock_improve.return_value = ["pkg1", "pkg2"]

product_portfolio/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from product_portfolio.views import improve_packages_from_purldb_view
3838
from product_portfolio.views import license_summary_view
3939
from product_portfolio.views import scan_all_packages_view
40+
from product_portfolio.views import scancodeio_project_download_input_view
4041
from product_portfolio.views import scancodeio_project_status_view
4142
from product_portfolio.views import vulnerability_analysis_form_view
4243

@@ -71,6 +72,11 @@ def product_path(path_segment, view):
7172
scancodeio_project_status_view,
7273
name="scancodeio_project_status",
7374
),
75+
path(
76+
"scancodeio_project_download_input/<uuid:scancodeproject_uuid>/",
77+
scancodeio_project_download_input_view,
78+
name="scancodeio_project_download_input",
79+
),
7480
path(
7581
"compare/<uuid:left_uuid>/<uuid:right_uuid>/",
7682
ProductTreeComparisonView.as_view(),

product_portfolio/views.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from django.db.models import Subquery
3232
from django.db.models.functions import Lower
3333
from django.forms import modelformset_factory
34+
from django.http import FileResponse
3435
from django.http import Http404
3536
from django.http import HttpResponse
3637
from django.http import JsonResponse
@@ -2486,6 +2487,18 @@ def scancodeio_project_status_view(request, scancodeproject_uuid):
24862487
return TemplateResponse(request, template, context)
24872488

24882489

2490+
@login_required
2491+
def scancodeio_project_download_input_view(request, scancodeproject_uuid):
2492+
secured_qs = ScanCodeProject.objects.product_secured(user=request.user)
2493+
scancode_project = get_object_or_404(secured_qs, uuid=scancodeproject_uuid)
2494+
input_file = scancode_project.input_file
2495+
2496+
if not input_file or not input_file.storage.exists(input_file.name):
2497+
raise Http404
2498+
2499+
return FileResponse(input_file.open("rb"), as_attachment=True)
2500+
2501+
24892502
@login_required
24902503
def improve_packages_from_purldb_view(request, dataspace, name, version=""):
24912504
user = request.user

0 commit comments

Comments
 (0)