<commit_before>from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404
from rest_framework import viewsets, mixins, status
from rest_framework.response import Response
from rest_framework.permissions import DjangoModelPermissions
from rest_framework.decorators import detail_route, action
from django_filters.rest_framework import DjangoFilterBackend

from dojo.engagement.services import close_engagement, reopen_engagement
from dojo.models import Product, Product_Type, Engagement, Test, Test_Type, Finding, \
    User, ScanSettings, Scan, Stub_Finding, Finding_Template, Notes, \
    JIRA_Issue, Tool_Product_Settings, Tool_Configuration, Tool_Type, \
    Endpoint, JIRA_PKey, JIRA_Conf, DojoMeta, Development_Environment, Dojo_User

from dojo.endpoint.views import get_endpoint_ids
from dojo.reports.views import report_url_resolver
from dojo.filters import ReportFindingFilter, ReportAuthedFindingFilter
from dateutil.relativedelta import relativedelta
from django.conf import settings
from datetime import datetime
from django.utils import timezone
from dojo.utils import get_period_counts_legacy

from dojo.api_v2 import serializers, permissions


class EndPointViewSet(mixins.ListModelMixin,
                      mixins.RetrieveModelMixin,
                      mixins.UpdateModelMixin,
                      mixins.DestroyModelMixin,
                      mixins.CreateModelMixin,
                      viewsets.GenericViewSet):
    serializer_class = serializers.EndpointSerializer
    queryset = Endpoint.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('id', 'host', 'product')

    def get_queryset(self):
        if not self.request.user.is_staff:
            return Endpoint.objects.filter(
                product__authorized_users__in=[self.request.user])
        else:
            return Endpoint.objects.all()

    @detail_route(methods=['post'], permission_classes=[permissions.UserHasReportGeneratePermission])
    def generate_report(self, request, pk=None):
        endpoint = get_object_or_404(Endpoint.objects, id=pk)

        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, endpoint, options)
        report = serializers.ReportGenerateSerializer(data)
        return Response(report.data)


class EngagementViewSet(mixins.ListModelMixin,
                        mixins.RetrieveModelMixin,
                        mixins.UpdateModelMixin,
                        mixins.DestroyModelMixin,
                        mixins.CreateModelMixin,
                        viewsets.GenericViewSet):
    serializer_class = serializers.EngagementSerializer
    queryset = Engagement.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('id', 'active', 'eng_type', 'target_start',
                     'target_end', 'requester', 'report_type',
                     'updated', 'threat_model', 'api_test',
                     'pen_test', 'status', 'product')

    def get_queryset(self):
        if not self.request.user.is_staff:
            return Engagement.objects.filter(
                product__authorized_users__in=[self.request.user])
        else:
            return Engagement.objects.all()

    @detail_route(methods=["post"])
    def close(self, request, pk=None):
        eng = get_object_or_404(Engagement.objects, id=pk)
        close_engagement(eng)
        return HttpResponse()

    @detail_route(methods=["post"])
    def reopen(self, request, pk=None):
        eng = get_object_or_404(Engagement.objects, id=pk)
        reopen_engagement(eng)
        return HttpResponse()

    @detail_route(methods=['post'], permission_classes=[permissions.UserHasReportGeneratePermission])
    def generate_report(self, request, pk=None):
        engagement = get_object_or_404(Engagement.objects, id=pk)

        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, engagement, options)
        report = serializers.ReportGenerateSerializer(data)
        return Response(report.data)


class FindingTemplatesViewSet(mixins.ListModelMixin,
                              mixins.RetrieveModelMixin,
                              mixins.UpdateModelMixin,
                              mixins.CreateModelMixin,
                              viewsets.GenericViewSet):
    serializer_class = serializers.FindingTemplateSerializer
    queryset = Finding_Template.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('id', 'title', 'cwe', 'severity', 'description',
                     'mitigation')

    # def get_queryset(self):
    #     if not self.request.user.is_staff:
    #         return Finding_Template.objects.filter(
    #             id__in=[self.request.user])
    #     else:
    #         return Finding_Template.objects.all()


class FindingViewSet(mixins.ListModelMixin,
                     mixins.RetrieveModelMixin,
                     mixins.UpdateModelMixin,
                     mixins.DestroyModelMixin,
                     mixins.CreateModelMixin,
                     viewsets.GenericViewSet):
    serializer_class = serializers.FindingSerializer
    queryset = Finding.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('id', 'title', 'date', 'severity', 'description',
                     'mitigated', 'endpoints', 'test', 'active', 'verified',
                     'false_p', 'reporter', 'url', 'out_of_scope',
                     'duplicate', 'test__engagement__product',
                     'test__engagement')

    def get_queryset(self):
        if not self.request.user.is_staff:
            return Finding.objects.filter(
                reporter_id__in=[self.request.user])
        else:
            return Finding.objects.all()

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return serializers.FindingCreateSerializer
        else:
            return serializers.FindingSerializer

    @detail_route(methods=['get', 'post', 'delete'])
    def tags(self, request, pk=None):
        finding = get_object_or_404(Finding.objects, id=pk)

        if request.method == 'POST':
            new_tags = serializers.TagSerializer(data=request.data)
            if new_tags.is_valid():
                all_tags = finding.tags
                all_tags = serializers.TagSerializer({"tags": all_tags}).data['tags']

                for tag in new_tags.validated_data['tags']:
                    tag = str(tag)
                    if tag not in all_tags:
                        all_tags += tag
                t = ", ".join(all_tags)
                finding.tags = t
                finding.save()
            else:
                return Response(new_tags.errors,
                    status=status.HTTP_400_BAD_REQUEST)

        elif request.method == 'DELETE':
            delete_tags = serializers.TagSerializer(data=request.data)
            if delete_tags.is_valid():
                all_tags = finding.tags
                all_tags = serializers.TagSerializer({"tags": all_tags}).data['tags']
                for tag in delete_tags.validated_data['tags']:
                    if tag not in all_tags:
                        return Response({"error": "'{}' is not a valid tag in list".format(tag)},
                            status=status.HTTP_400_BAD_REQUEST)
                    all_tags.remove(tag)
                t = ", ".join(all_tags)
                finding.tags = t
                finding.save()
                return Response({"success": "Tag(s) Deleted"},
                    status=status.HTTP_200_OK)
            else:
                return Response(delete_tags.errors,
                    status=status.HTTP_400_BAD_REQUEST)
<commit_msg>Return Error on Empty tag list delete request<commit_after>from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404
from rest_framework import viewsets, mixins, status
from rest_framework.response import Response
from rest_framework.permissions import DjangoModelPermissions
from rest_framework.decorators import detail_route, action
from django_filters.rest_framework import DjangoFilterBackend

from dojo.engagement.services import close_engagement, reopen_engagement
from dojo.models import Product, Product_Type, Engagement, Test, Test_Type, Finding, \
    User, ScanSettings, Scan, Stub_Finding, Finding_Template, Notes, \
    JIRA_Issue, Tool_Product_Settings, Tool_Configuration, Tool_Type, \
    Endpoint, JIRA_PKey, JIRA_Conf, DojoMeta, Development_Environment, Dojo_User

from dojo.endpoint.views import get_endpoint_ids
from dojo.reports.views import report_url_resolver
from dojo.filters import ReportFindingFilter, ReportAuthedFindingFilter
from dateutil.relativedelta import relativedelta
from django.conf import settings
from datetime import datetime
from django.utils import timezone
from dojo.utils import get_period_counts_legacy

from dojo.api_v2 import serializers, permissions


class EndPointViewSet(mixins.ListModelMixin,
                      mixins.RetrieveModelMixin,
                      mixins.UpdateModelMixin,
                      mixins.DestroyModelMixin,
                      mixins.CreateModelMixin,
                      viewsets.GenericViewSet):
    serializer_class = serializers.EndpointSerializer
    queryset = Endpoint.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('id', 'host', 'product')

    def get_queryset(self):
        if not self.request.user.is_staff:
            return Endpoint.objects.filter(
                product__authorized_users__in=[self.request.user])
        else:
            return Endpoint.objects.all()

    @detail_route(methods=['post'], permission_classes=[permissions.UserHasReportGeneratePermission])
    def generate_report(self, request, pk=None):
        endpoint = get_object_or_404(Endpoint.objects, id=pk)

        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, endpoint, options)
        report = serializers.ReportGenerateSerializer(data)
        return Response(report.data)


class EngagementViewSet(mixins.ListModelMixin,
                        mixins.RetrieveModelMixin,
                        mixins.UpdateModelMixin,
                        mixins.DestroyModelMixin,
                        mixins.CreateModelMixin,
                        viewsets.GenericViewSet):
    serializer_class = serializers.EngagementSerializer
    queryset = Engagement.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('id', 'active', 'eng_type', 'target_start',
                     'target_end', 'requester', 'report_type',
                     'updated', 'threat_model', 'api_test',
                     'pen_test', 'status', 'product')

    def get_queryset(self):
        if not self.request.user.is_staff:
            return Engagement.objects.filter(
                product__authorized_users__in=[self.request.user])
        else:
            return Engagement.objects.all()

    @detail_route(methods=["post"])
    def close(self, request, pk=None):
        eng = get_object_or_404(Engagement.objects, id=pk)
        close_engagement(eng)
        return HttpResponse()

    @detail_route(methods=["post"])
    def reopen(self, request, pk=None):
        eng = get_object_or_404(Engagement.objects, id=pk)
        reopen_engagement(eng)
        return HttpResponse()

    @detail_route(methods=['post'], permission_classes=[permissions.UserHasReportGeneratePermission])
    def generate_report(self, request, pk=None):
        engagement = get_object_or_404(Engagement.objects, id=pk)

        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, engagement, options)
        report = serializers.ReportGenerateSerializer(data)
        return Response(report.data)


class FindingTemplatesViewSet(mixins.ListModelMixin,
                              mixins.RetrieveModelMixin,
                              mixins.UpdateModelMixin,
                              mixins.CreateModelMixin,
                              viewsets.GenericViewSet):
    serializer_class = serializers.FindingTemplateSerializer
    queryset = Finding_Template.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('id', 'title', 'cwe', 'severity', 'description',
                     'mitigation')

    # def get_queryset(self):
    #     if not self.request.user.is_staff:
    #         return Finding_Template.objects.filter(
    #             id__in=[self.request.user])
    #     else:
    #         return Finding_Template.objects.all()


class FindingViewSet(mixins.ListModelMixin,
                     mixins.RetrieveModelMixin,
                     mixins.UpdateModelMixin,
                     mixins.DestroyModelMixin,
                     mixins.CreateModelMixin,
                     viewsets.GenericViewSet):
    serializer_class = serializers.FindingSerializer
    queryset = Finding.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('id', 'title', 'date', 'severity', 'description',
                     'mitigated', 'endpoints', 'test', 'active', 'verified',
                     'false_p', 'reporter', 'url', 'out_of_scope',
                     'duplicate', 'test__engagement__product',
                     'test__engagement')

    def get_queryset(self):
        if not self.request.user.is_staff:
            return Finding.objects.filter(
                reporter_id__in=[self.request.user])
        else:
            return Finding.objects.all()

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return serializers.FindingCreateSerializer
        else:
            return serializers.FindingSerializer

    @detail_route(methods=['get', 'post', 'delete'])
    def tags(self, request, pk=None):
        finding = get_object_or_404(Finding.objects, id=pk)

        if request.method == 'POST':
            new_tags = serializers.TagSerializer(data=request.data)
            if new_tags.is_valid():
                all_tags = finding.tags
                all_tags = serializers.TagSerializer({"tags": all_tags}).data['tags']

                for tag in new_tags.validated_data['tags']:
                    tag = str(tag)
                    if tag not in all_tags:
                        all_tags += tag
                t = ", ".join(all_tags)
                finding.tags = t
                finding.save()
            else:
                return Response(new_tags.errors,
                    status=status.HTTP_400_BAD_REQUEST)

        elif request.method == 'DELETE':
            delete_tags = serializers.TagSerializer(data=request.data)
            if delete_tags.is_valid():
                all_tags = finding.tags
                all_tags = serializers.TagSerializer({"tags": all_tags}).data['tags']
                del_tags = delete_tags.validated_data['tags']
                if len(del_tags) < 1:
                    return Response({"error": "Empty Tag List Not Allowed"},
                            status=status.HTTP_400_BAD_REQUEST)
                for tag in del_tags:
                    if tag not in all_tags:
                        return Response({"error": "'{}' is not a valid tag in list".format(tag)},
                            status=status.HTTP_400_BAD_REQUEST)
                    all_tags.remove(tag)
                t = ", ".join(all_tags)
                finding.tags = t
                finding.save()
                return Response({"success": "Tag(s) Deleted"},
                    status=status.HTTP_200_OK)
            else:
                return Response(delete_tags.errors,
                    status=status.HTTP_400_BAD_REQUEST)

{'fraction_non_alphanumeric': 0.08832619422002928, 'fraction_numerical': 0.004554573550940737, 'mean_word_length': 2.470831765148664, 'pattern_counts': {'":': 9, '<': 4, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5859759', 'n_tokens_mistral': 5075, 'n_tokens_neox': 4797, 'n_words': 888}