Skip to content

Commit b8a1321

Browse files
authored
Add a REST API "action" endpoint to track product imports #273 (#327)
Signed-off-by: tdruez <[email protected]>
1 parent be76910 commit b8a1321

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ Release notes
3535
code_view_url, vcs_url, api_data_url, size, md5, sha1, sha256, sha512.
3636
https://github.com/aboutcode-org/dejacode/issues/255
3737

38+
- Add a Product REST API "action" endpoint to track product imports and their status:
39+
* `/products/{uuid}/imports/`
40+
https://github.com/aboutcode-org/dejacode/issues/273
41+
3842
### Version 5.3.0
3943

4044
- Rename ProductDependency is_resolved to is_pinned.

product_portfolio/api.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
from product_portfolio.models import ProductComponent
4848
from product_portfolio.models import ProductDependency
4949
from product_portfolio.models import ProductPackage
50+
from product_portfolio.models import ScanCodeProject
5051
from vulnerabilities.api import VulnerabilityAnalysisSerializer
5152

5253
base_extra_kwargs = {
@@ -289,6 +290,26 @@ class PullProjectDataSerializer(serializers.Serializer):
289290
)
290291

291292

293+
class ScanCodeProjectSerializer(DataspacedSerializer):
294+
input_filename = serializers.ReadOnlyField(source="input_file_filename")
295+
296+
class Meta:
297+
model = ScanCodeProject
298+
fields = (
299+
"uuid",
300+
"type",
301+
"project_uuid",
302+
"input_filename",
303+
"update_existing_packages",
304+
"scan_all_packages",
305+
"status",
306+
"import_log",
307+
"results",
308+
"created_date",
309+
"last_modified_date",
310+
)
311+
312+
292313
class ProductViewSet(
293314
SendAboutFilesMixin,
294315
AboutCodeFilesActionMixin,
@@ -346,6 +367,18 @@ def perform_create(self, serializer):
346367
super().perform_create(serializer)
347368
assign_all_object_permissions(self.request.user, serializer.instance)
348369

370+
@action(detail=True)
371+
def imports(self, request, uuid):
372+
"""
373+
List of Product Imports, including their current status, log, and results.
374+
375+
Statuses: "submitted", "importing", "success", "failure", "warning".
376+
"""
377+
product = self.get_object()
378+
scancode_projects = product.scancodeprojects.all()
379+
projects_data = ScanCodeProjectSerializer(scancode_projects, many=True).data
380+
return Response(projects_data)
381+
349382
@action(detail=True, methods=["post"], serializer_class=LoadSBOMsFormSerializer)
350383
def load_sboms(self, request, *args, **kwargs):
351384
"""

product_portfolio/tests/test_api.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,41 @@ def test_api_product_endpoint_update_permissions(self):
352352
product1 = Product.unsecured_objects.get(pk=self.product1.pk)
353353
self.assertEqual("Updated Name", product1.name)
354354

355+
def test_api_product_endpoint_imports_action(self):
356+
url = reverse("api_v2:product-imports", args=[self.product1.uuid])
357+
358+
self.client.login(username=self.base_user.username, password="secret")
359+
response = self.client.get(url)
360+
self.assertEqual(status.HTTP_404_NOT_FOUND, response.status_code)
361+
362+
# Required permissions
363+
add_perm(self.base_user, "add_product")
364+
assign_perm("view_product", self.base_user, self.product1)
365+
366+
response = self.client.get(url)
367+
self.assertEqual(status.HTTP_200_OK, response.status_code)
368+
self.assertEqual(0, self.product1.scancodeprojects.count())
369+
self.assertEqual([], response.data)
370+
371+
ScanCodeProject.objects.create(
372+
product=self.product1,
373+
dataspace=self.product1.dataspace,
374+
type=ScanCodeProject.ProjectType.LOAD_SBOMS,
375+
status=ScanCodeProject.Status.SUCCESS,
376+
input_file=ContentFile("Data", name="data.json"),
377+
)
378+
379+
response = self.client.get(url)
380+
self.assertEqual(status.HTTP_200_OK, response.status_code)
381+
self.assertEqual(1, self.product1.scancodeprojects.count())
382+
self.assertEqual(1, len(response.data))
383+
entry = response.data[0]
384+
self.assertEqual(ScanCodeProject.ProjectType.LOAD_SBOMS, entry["type"])
385+
self.assertEqual("data.json", entry["input_filename"])
386+
self.assertEqual(ScanCodeProject.Status.SUCCESS, entry["status"])
387+
self.assertEqual([], entry["import_log"])
388+
self.assertEqual({}, entry["results"])
389+
355390
def test_api_product_endpoint_load_sboms_action(self):
356391
url = reverse("api_v2:product-load-sboms", args=[self.product1.uuid])
357392

0 commit comments

Comments
 (0)