From 1d684ead53f065b3277038269513c8e126dbe478 Mon Sep 17 00:00:00 2001 From: Adetunji Oludele Adebayo <190939682+tungyhardDevOps@users.noreply.github.com> Date: Tue, 21 Jul 2026 15:38:34 +0100 Subject: [PATCH] Add GitHub product API settings --- dojo/product/api/serializer.py | 20 ++++++++ unittests/test_product_github_api.py | 72 ++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 unittests/test_product_github_api.py diff --git a/dojo/product/api/serializer.py b/dojo/product/api/serializer.py index 5df53d9d3cd..6b934bd1026 100644 --- a/dojo/product/api/serializer.py +++ b/dojo/product/api/serializer.py @@ -1,6 +1,7 @@ from rest_framework import serializers from rest_framework.exceptions import PermissionDenied +from dojo.github.models import GITHUB_Conf, GITHUB_PKey from dojo.models import DojoMeta, Product, Product_API_Scan_Configuration @@ -19,6 +20,13 @@ class Meta: class ProductSerializer(serializers.ModelSerializer): findings_count = serializers.SerializerMethodField() findings_list = serializers.SerializerMethodField() + github_project = serializers.CharField(allow_blank=True, max_length=200, required=False, write_only=True) + github_configuration = serializers.PrimaryKeyRelatedField( + allow_null=True, + queryset=GITHUB_Conf.objects.all(), + required=False, + write_only=True, + ) business_criticality = serializers.ChoiceField(choices=Product.BUSINESS_CRITICALITY_CHOICES, allow_blank=True, allow_null=True, required=False) platform = serializers.ChoiceField(choices=Product.PLATFORM_CHOICES, allow_blank=True, allow_null=True, required=False) @@ -43,6 +51,18 @@ def get_fields(self): fields["tags"] = TagListSerializerField(required=False) return fields + def create(self, validated_data): + github_project = validated_data.pop("github_project", "") + github_configuration = validated_data.pop("github_configuration", None) + product = super().create(validated_data) + if github_project or github_configuration: + GITHUB_PKey.objects.create( + product=product, + git_project=github_project, + git_conf=github_configuration, + ) + return product + def validate(self, data): async_updating = getattr(self.instance, "async_updating", None) if async_updating: diff --git a/unittests/test_product_github_api.py b/unittests/test_product_github_api.py new file mode 100644 index 00000000000..1ac09696af1 --- /dev/null +++ b/unittests/test_product_github_api.py @@ -0,0 +1,72 @@ +from django.urls import reverse +from rest_framework.authtoken.models import Token +from rest_framework.test import APIClient + +from dojo.github.models import GITHUB_Conf, GITHUB_PKey +from dojo.models import Product, User +from unittests.dojo_test_case import DojoAPITestCase, versioned_fixtures + + +@versioned_fixtures +class ProductGithubApiTest(DojoAPITestCase): + fixtures = ["dojo_testdata.json"] + + def setUp(self): + user = User.objects.get(username="admin") + token = Token.objects.get(user=user) + self.client = APIClient() + self.client.credentials(HTTP_AUTHORIZATION="Token " + token.key) + self.url = reverse("product-list") + self.github_configuration = GITHUB_Conf.objects.create( + configuration_name="Product API GitHub configuration", + api_key="not-a-real-secret", + ) + + def test_create_product_with_github_settings(self): + response = self.client.post( + self.url, + { + "name": "Product with GitHub settings", + "description": "Created through the product API", + "prod_type": 1, + "github_project": "DefectDojo/django-DefectDojo", + "github_configuration": self.github_configuration.id, + }, + format="json", + ) + + self.assertEqual(201, response.status_code, response.content[:1000]) + github_settings = GITHUB_PKey.objects.get(product_id=response.data["id"]) + self.assertEqual("DefectDojo/django-DefectDojo", github_settings.git_project) + self.assertEqual(self.github_configuration, github_settings.git_conf) + + def test_create_product_without_github_settings(self): + response = self.client.post( + self.url, + { + "name": "Product without GitHub settings", + "description": "Created through the product API", + "prod_type": 1, + }, + format="json", + ) + + self.assertEqual(201, response.status_code, response.content[:1000]) + self.assertFalse(GITHUB_PKey.objects.filter(product_id=response.data["id"]).exists()) + + def test_create_product_rejects_unknown_github_configuration(self): + product_name = "Product with unknown GitHub configuration" + response = self.client.post( + self.url, + { + "name": product_name, + "description": "Created through the product API", + "prod_type": 1, + "github_project": "DefectDojo/django-DefectDojo", + "github_configuration": 999999, + }, + format="json", + ) + + self.assertEqual(400, response.status_code, response.content[:1000]) + self.assertFalse(Product.objects.filter(name=product_name).exists())