diff --git a/dojo/api_v2/serializers.py b/dojo/api_v2/serializers.py index 4f87f6e418b..de5344d4ecf 100644 --- a/dojo/api_v2/serializers.py +++ b/dojo/api_v2/serializers.py @@ -24,7 +24,7 @@ Network_Locations, UserContactInfo, Product_API_Scan_Configuration, DEFAULT_NOTIFICATION, \ Vulnerability_Id, Vulnerability_Id_Template, get_current_date, \ Question, TextQuestion, ChoiceQuestion, Answer, TextAnswer, ChoiceAnswer, \ - Engagement_Survey, Answered_Survey, General_Survey + Engagement_Survey, Answered_Survey, General_Survey, Check_List from dojo.tools.factory import requires_file, get_choices_sorted, requires_tool_type from dojo.utils import is_scan_file_too_large @@ -796,6 +796,12 @@ def to_representation(self, data): return new_data +class EngagementCheckListSerializer(serializers.ModelSerializer): + class Meta: + model = Check_List + fields = '__all__' + + class AppAnalysisSerializer(TaggitSerializer, serializers.ModelSerializer): tags = TagListSerializerField(required=False) diff --git a/dojo/api_v2/views.py b/dojo/api_v2/views.py index 82ae07589d1..2c271dfe3b3 100644 --- a/dojo/api_v2/views.py +++ b/dojo/api_v2/views.py @@ -32,7 +32,7 @@ BurpRawRequestResponse, FileUpload, Product_Type_Member, Product_Member, Dojo_Group, \ Product_Group, Product_Type_Group, Role, Global_Role, Dojo_Group_Member, Engagement_Presets, Network_Locations, \ UserContactInfo, Product_API_Scan_Configuration, Cred_Mapping, Cred_User, Question, Answer, \ - Engagement_Survey, Answered_Survey, General_Survey + Engagement_Survey, Answered_Survey, General_Survey, Check_List from dojo.endpoint.views import get_endpoint_ids from dojo.reports.views import report_url_resolver, prefetch_related_findings_for_report from dojo.finding.views import set_finding_as_original_internal, reset_finding_duplicate_status_internal, \ @@ -258,7 +258,9 @@ class EngagementViewSet(prefetch.PrefetchListMixin, queryset = Engagement.objects.none() filter_backends = (DjangoFilterBackend,) filterset_class = ApiEngagementFilter - swagger_schema = prefetch.get_prefetch_schema(["engagements_list", "engagements_read"], serializers.EngagementSerializer).to_schema() + swagger_schema = prefetch.get_prefetch_schema(["engagements_list", "engagements_read"], serializers.EngagementSerializer).composeWith( + prefetch.get_prefetch_schema(["engagements_complete_checklist_read"], serializers.EngagementCheckListSerializer) + ).to_schema() permission_classes = (IsAuthenticated, permissions.UserHasEngagementPermission) @property @@ -429,6 +431,41 @@ def files(self, request, pk=None): }) return Response(serialized_files.data, status=status.HTTP_200_OK) + @extend_schema( + methods=['POST'], + request=serializers.EngagementCheckListSerializer, + responses={status.HTTP_201_CREATED: serializers.EngagementCheckListSerializer} + ) + @swagger_auto_schema( + method='post', + request_body=serializers.EngagementCheckListSerializer, + responses={status.HTTP_201_CREATED: serializers.EngagementCheckListSerializer} + ) + @action(detail=True, methods=["get", "post"]) + def complete_checklist(self, request, pk=None): + from dojo.api_v2.prefetch.prefetcher import _Prefetcher + engagement = self.get_object() + check_lists = Check_List.objects.filter(engagement=engagement) + if request.method == 'POST': + if check_lists.count() > 0: + return Response({"message": "A completed checklist for this engagement already exists."}, status=status.HTTP_400_BAD_REQUEST) + check_list = serializers.EngagementCheckListSerializer(data=request.data) + if not check_list.is_valid(): + return Response(check_list.errors, status=status.HTTP_400_BAD_REQUEST) + check_list = Check_List(**check_list.data) + check_list.engagement = engagement + check_list.save() + serialized_check_list = serializers.EngagementCheckListSerializer(check_list) + return Response(serialized_check_list.data, status=status.HTTP_201_CREATED) + prefetch_params = request.GET.get("prefetch", "").split(",") + prefetcher = _Prefetcher() + entry = check_lists.first() + # Get the queried object representation + result = serializers.EngagementCheckListSerializer(centry).data + prefetcher._prefetch(entry, prefetch_params) + result["prefetch"] = prefetcher.prefetched_data + return Response(result, status=status.HTTP_200_OK) + @extend_schema( methods=['GET'], responses={ @@ -2770,6 +2807,25 @@ def get_queryset(self): return get_authorized_engagement_presets(Permissions.Product_View) +class EngagementCheckListViewset(prefetch.PrefetchListMixin, + prefetch.PrefetchRetrieveMixin, + mixins.ListModelMixin, + mixins.RetrieveModelMixin, + mixins.UpdateModelMixin, + mixins.DestroyModelMixin, + mixins.CreateModelMixin, + viewsets.GenericViewSet, + dojo_mixins.DeletePreviewModelMixin): + serializer_class = serializers.EngagementCheckListSerializer + queryset = Check_List.objects.none() + filter_backends = (DjangoFilterBackend,) + swagger_schema = prefetch.get_prefetch_schema(["engagement_checklists_list", "engagement_checklists_read"], serializers.EngagementCheckListSerializer).to_schema() + permission_classes = (IsAuthenticated, permissions.UserHasEngagementPermission) + + def get_queryset(self): + return get_authorized_engagement_checklists(Permissions.Product_View) + + class NetworkLocationsViewset(mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin,