Skip to content
Draft
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
60 changes: 10 additions & 50 deletions dojo/api_v2/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,12 +466,6 @@ def validate(self, data):
return data


class ProductMetaSerializer(serializers.ModelSerializer):
class Meta:
model = DojoMeta
fields = ("name", "value")


class UserSerializer(serializers.ModelSerializer):
date_joined = serializers.DateTimeField(read_only=True)
last_login = serializers.DateTimeField(read_only=True, allow_null=True)
Expand Down Expand Up @@ -722,6 +716,16 @@ class Meta:
# RiskAcceptanceSerializer (below) still reference it. The other engagement
# serializers are imported directly from dojo.engagement.api by their consumers.
from dojo.engagement.api.serializer import EngagementSerializer # noqa: E402 -- backward compat

# Product serializers live in dojo/product/api/serializer.py. ProductSerializer is
# re-exported because ReportGenerateSerializer (below) still references it;
# ProductMetaSerializer because dojo/asset/api/serializers.py imports it.
# ProductAPIScanConfigurationSerializer is imported directly from
# dojo.product.api.serializer by its only consumer (the viewset).
from dojo.product.api.serializer import ( # noqa: E402 -- backward compat
ProductMetaSerializer, # noqa: F401 -- backward compat
ProductSerializer,
)
from dojo.product_type.api.serializer import ProductTypeSerializer # noqa: E402


Expand Down Expand Up @@ -940,12 +944,6 @@ class Meta:
fields = "__all__"


class ProductAPIScanConfigurationSerializer(serializers.ModelSerializer):
class Meta:
model = Product_API_Scan_Configuration
fields = "__all__"


class DevelopmentEnvironmentSerializer(serializers.ModelSerializer):
class Meta:
model = Development_Environment
Expand Down Expand Up @@ -1616,44 +1614,6 @@ def update(self, instance, validated_data):
return super().update(instance, validated_data)


class ProductSerializer(serializers.ModelSerializer):
findings_count = serializers.SerializerMethodField()
findings_list = serializers.SerializerMethodField()

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)
lifecycle = serializers.ChoiceField(choices=Product.LIFECYCLE_CHOICES, allow_blank=True, allow_null=True, required=False)
origin = serializers.ChoiceField(choices=Product.ORIGIN_CHOICES, allow_blank=True, allow_null=True, required=False)

tags = TagListSerializerField(required=False)
product_meta = ProductMetaSerializer(read_only=True, many=True)

class Meta:
model = Product
exclude = (
"tid",
"updated",
"async_updating",
)

def validate(self, data):
async_updating = getattr(self.instance, "async_updating", None)
if async_updating:
new_sla_config = data.get("sla_configuration", None)
old_sla_config = getattr(self.instance, "sla_configuration", None)
if new_sla_config and old_sla_config and new_sla_config != old_sla_config:
msg = "Finding SLA expiration dates are currently being recalculated. The SLA configuration for this product cannot be changed until the calculation is complete."
raise serializers.ValidationError(msg)
return data

def get_findings_count(self, obj) -> int:
return obj.findings_count

# TODO: maybe extend_schema_field is needed here?
def get_findings_list(self, obj) -> list[int]:
return obj.open_findings_list()


class CommonImportScanSerializer(serializers.Serializer):
scan_date = serializers.DateField(
required=False,
Expand Down
109 changes: 0 additions & 109 deletions dojo/api_v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
ApiDojoMetaFilter,
ApiEndpointFilter,
ApiFindingFilter,
ApiProductFilter,
ApiRiskAcceptanceFilter,
ApiTemplateFindingFilter,
ApiUserFilter,
Expand Down Expand Up @@ -93,7 +92,6 @@
NoteHistory,
Notes,
Product,
Product_API_Scan_Configuration,
Regulation,
Risk_Acceptance,
SLA_Configuration,
Expand All @@ -111,7 +109,6 @@
get_authorized_app_analysis,
get_authorized_dojo_meta,
get_authorized_languages,
get_authorized_product_api_scan_configurations,
get_authorized_products,
)
from dojo.query_utils import build_count_subquery
Expand All @@ -127,12 +124,10 @@
from dojo.user.authentication import reset_token_for_user
from dojo.user.utils import get_configuration_permissions_codenames
from dojo.utils import (
async_delete,
generate_file_response,
get_celery_queue_details,
get_celery_queue_length,
get_celery_worker_status,
get_setting,
get_system_setting,
process_tag_notifications,
purge_celery_queue,
Expand Down Expand Up @@ -1258,31 +1253,6 @@ def get_queryset(self):

# Authorization: object-based
@extend_schema_view(**schema_with_prefetch())
class ProductAPIScanConfigurationViewSet(
PrefetchDojoModelViewSet,
):
serializer_class = serializers.ProductAPIScanConfigurationSerializer
queryset = Product_API_Scan_Configuration.objects.none()
filter_backends = (DjangoFilterBackend,)
filterset_fields = [
"id",
"product",
"tool_configuration",
"service_key_1",
"service_key_2",
"service_key_3",
]
permission_classes = (
IsAuthenticated,
permissions.UserHasProductAPIScanConfigurationPermission,
)

def get_queryset(self):
return get_authorized_product_api_scan_configurations(
"view",
)


# Authorization: object-based
# @extend_schema_view(**schema_with_prefetch())
# Nested models with prefetch make the response schema too long for Swagger UI
Expand Down Expand Up @@ -1376,85 +1346,6 @@ def process_patch(self, request):
raise ValidationError(msg)


@extend_schema_view(**schema_with_prefetch())
class ProductViewSet(
prefetch.PrefetchListMixin,
prefetch.PrefetchRetrieveMixin,
mixins.CreateModelMixin,
mixins.DestroyModelMixin,
mixins.UpdateModelMixin,
viewsets.GenericViewSet,
dojo_mixins.DeletePreviewModelMixin,
):
serializer_class = serializers.ProductSerializer
queryset = Product.objects.none()
filter_backends = (DjangoFilterBackend,)
filterset_class = ApiProductFilter
permission_classes = (
IsAuthenticated,
permissions.UserHasProductPermission,
)

def get_queryset(self):
return get_authorized_products("view").distinct()

def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if get_setting("ASYNC_OBJECT_DELETE"):
async_del = async_delete()
async_del.delete(instance)
else:
instance.delete()
return Response(status=status.HTTP_204_NO_CONTENT)

# def list(self, request):
# # Note the use of `get_queryset()` instead of `self.queryset`
# queryset = self.get_queryset()
# serializer = self.serializer_class(queryset, many=True)
# return Response(serializer.data)

@extend_schema(
request=serializers.ReportGenerateOptionSerializer,
responses={status.HTTP_200_OK: serializers.ReportGenerateSerializer},
)
@action(
detail=True, methods=["post"],
# IsAuthenticated only: report generation requires View permission,
# enforced by the permission-filtered get_queryset(). The viewset's
# permission_classes would check Edit (POST), which is too restrictive.
permission_classes=[IsAuthenticated],
)
def generate_report(self, request, pk=None):
product = self.get_object()

options = {}
# prepare post data
report_options = serializers.ReportGenerateOptionSerializer(
data=request.data,
)
if report_options.is_valid():
options["include_finding_notes"] = report_options.validated_data[
"include_finding_notes"
]
options["include_finding_images"] = report_options.validated_data[
"include_finding_images"
]
options[
"include_executive_summary"
] = report_options.validated_data["include_executive_summary"]
options[
"include_table_of_contents"
] = report_options.validated_data["include_table_of_contents"]
else:
return Response(
report_options.errors, status=status.HTTP_400_BAD_REQUEST,
)

data = report_generate(request, product, options)
report = serializers.ReportGenerateSerializer(data)
return Response(report.data)


# Authorization: authenticated, configuration
class DevelopmentEnvironmentViewSet(
DojoModelViewSet,
Expand Down
2 changes: 1 addition & 1 deletion dojo/asset/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.urls import re_path

from dojo.engagement.ui import views as dojo_engagement_views
from dojo.product import views
from dojo.product.ui import views
from dojo.utils import redirect_view

# TODO: remove the else: branch once v3 migration is complete
Expand Down
2 changes: 1 addition & 1 deletion dojo/components/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from django.shortcuts import render

from dojo.components.sql_group_concat import Sql_GroupConcat
from dojo.filters import ComponentFilter, ComponentFilterWithoutObjectLookups
from dojo.finding.queries import get_authorized_findings
from dojo.product.ui.filters import ComponentFilter, ComponentFilterWithoutObjectLookups
from dojo.utils import add_breadcrumb, get_page_items, get_system_setting


Expand Down
Loading
Loading