Skip to content

Commit 400437f

Browse files
authored
Merge pull request #11887 from DefectDojo/release/2.43.4
Release: Merge release into master from: release/2.43.4
2 parents 2df98da + a7383ef commit 400437f

File tree

8 files changed

+122
-42
lines changed

8 files changed

+122
-42
lines changed

components/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "defectdojo",
3-
"version": "2.43.3",
3+
"version": "2.43.4",
44
"license" : "BSD-3-Clause",
55
"private": true,
66
"dependencies": {

dojo/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
# Django starts so that shared_task will use this app.
55
from .celery import app as celery_app # noqa: F401
66

7-
__version__ = "2.43.3"
7+
__version__ = "2.43.4"
88
__url__ = "https://github.com/DefectDojo/django-DefectDojo"
99
__docs__ = "https://documentation.defectdojo.com"

dojo/filters.py

Lines changed: 103 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from django.apps import apps
1313
from django.conf import settings
1414
from django.contrib.contenttypes.models import ContentType
15-
from django.db.models import JSONField, Q
15+
from django.db.models import Count, JSONField, Q
1616
from django.forms import HiddenInput
1717
from django.utils import timezone
1818
from django.utils.translation import gettext_lazy as _
@@ -135,6 +135,20 @@ def __init__(self, *args, **kwargs):
135135
super(CharFilter, self).__init__(*args, **kwargs)
136136

137137

138+
class CharFieldFilterANDExpression(CharFieldInFilter):
139+
def filter(self, queryset, value):
140+
# Catch the case where a value if not supplied
141+
if not value:
142+
return queryset
143+
# Do the filtering
144+
objects = set(value.split(","))
145+
return (
146+
queryset.filter(**{f"{self.field_name}__in": objects})
147+
.annotate(object_count=Count(self.field_name))
148+
.filter(object_count=len(objects))
149+
)
150+
151+
138152
class FindingStatusFilter(ChoiceFilter):
139153
def any(self, qs, name):
140154
return qs
@@ -1204,11 +1218,20 @@ class ProductEngagementFilterWithoutObjectLookups(ProductEngagementFilterHelper,
12041218
class ApiEngagementFilter(DojoFilter):
12051219
product__prod_type = NumberInFilter(field_name="product__prod_type", lookup_expr="in")
12061220
tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Tag name contains")
1207-
tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
1208-
help_text="Comma separated list of exact tags")
1209-
product__tags = CharFieldInFilter(field_name="product__tags__name",
1210-
lookup_expr="in",
1211-
help_text="Comma separated list of exact tags present on product")
1221+
tags = CharFieldInFilter(
1222+
field_name="tags__name",
1223+
lookup_expr="in",
1224+
help_text="Comma separated list of exact tags (uses OR for multiple values)")
1225+
tags__and = CharFieldFilterANDExpression(
1226+
field_name="tags__name",
1227+
help_text="Comma separated list of exact tags to match with an AND expression")
1228+
product__tags = CharFieldInFilter(
1229+
field_name="product__tags__name",
1230+
lookup_expr="in",
1231+
help_text="Comma separated list of exact tags present on product (uses OR for multiple values)")
1232+
product__tags__and = CharFieldFilterANDExpression(
1233+
field_name="product__tags__name",
1234+
help_text="Comma separated list of exact tags to match with an AND expression present on product")
12121235

12131236
not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
12141237
not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
@@ -1365,9 +1388,13 @@ class ApiProductFilter(DojoFilter):
13651388
regulations = NumberInFilter(field_name="regulations", lookup_expr="in")
13661389

13671390
tag = CharFilter(field_name="tags__name", lookup_expr="icontains", label="Tag name contains")
1368-
tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
1369-
help_text="Comma separated list of exact tags")
1370-
1391+
tags = CharFieldInFilter(
1392+
field_name="tags__name",
1393+
lookup_expr="in",
1394+
help_text="Comma separated list of exact tags (uses OR for multiple values)")
1395+
tags__and = CharFieldFilterANDExpression(
1396+
field_name="tags__name",
1397+
help_text="Comma separated list of exact tags to match with an AND expression")
13711398
not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
13721399
not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
13731400
help_text="Comma separated list of exact tags not present on product", exclude="True")
@@ -1511,16 +1538,34 @@ class ApiFindingFilter(DojoFilter):
15111538
risk_acceptance = extend_schema_field(OpenApiTypes.NUMBER)(ReportRiskAcceptanceFilter())
15121539

15131540
tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Tag name contains")
1514-
tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
1515-
help_text="Comma separated list of exact tags")
1516-
test__tags = CharFieldInFilter(field_name="test__tags__name", lookup_expr="in", help_text="Comma separated list of exact tags present on test")
1517-
test__engagement__tags = CharFieldInFilter(field_name="test__engagement__tags__name", lookup_expr="in",
1518-
help_text="Comma separated list of exact tags present on engagement")
1541+
tags = CharFieldInFilter(
1542+
field_name="tags__name",
1543+
lookup_expr="in",
1544+
help_text="Comma separated list of exact tags (uses OR for multiple values)")
1545+
tags__and = CharFieldFilterANDExpression(
1546+
field_name="tags__name",
1547+
help_text="Comma separated list of exact tags to match with an AND expression")
1548+
test__tags = CharFieldInFilter(
1549+
field_name="test__tags__name",
1550+
lookup_expr="in",
1551+
help_text="Comma separated list of exact tags present on test (uses OR for multiple values)")
1552+
test__tags__and = CharFieldFilterANDExpression(
1553+
field_name="test__tags__name",
1554+
help_text="Comma separated list of exact tags to match with an AND expression present on test")
1555+
test__engagement__tags = CharFieldInFilter(
1556+
field_name="test__engagement__tags__name",
1557+
lookup_expr="in",
1558+
help_text="Comma separated list of exact tags present on engagement (uses OR for multiple values)")
1559+
test__engagement__tags__and = CharFieldFilterANDExpression(
1560+
field_name="test__engagement__tags__name",
1561+
help_text="Comma separated list of exact tags to match with an AND expression present on engagement")
15191562
test__engagement__product__tags = CharFieldInFilter(
15201563
field_name="test__engagement__product__tags__name",
15211564
lookup_expr="in",
1522-
help_text="Comma separated list of exact tags present on product")
1523-
1565+
help_text="Comma separated list of exact tags present on product (uses OR for multiple values)")
1566+
test__engagement__product__tags__and = CharFieldFilterANDExpression(
1567+
field_name="test__engagement__product__tags__name",
1568+
help_text="Comma separated list of exact tags to match with an AND expression present on product")
15241569
not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
15251570
not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
15261571
help_text="Comma separated list of exact tags not present on model", exclude="True")
@@ -2118,9 +2163,13 @@ def __init__(self, *args, **kwargs):
21182163

21192164
class ApiTemplateFindingFilter(DojoFilter):
21202165
tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Tag name contains")
2121-
tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
2122-
help_text="Comma separated list of exact tags")
2123-
2166+
tags = CharFieldInFilter(
2167+
field_name="tags__name",
2168+
lookup_expr="in",
2169+
help_text="Comma separated list of exact tags (uses OR for multiple values)")
2170+
tags__and = CharFieldFilterANDExpression(
2171+
field_name="tags__name",
2172+
help_text="Comma separated list of exact tags to match with an AND expression")
21242173
not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
21252174
not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
21262175
help_text="Comma separated list of exact tags not present on model", exclude="True")
@@ -2695,9 +2744,13 @@ class Meta:
26952744

26962745
class ApiEndpointFilter(DojoFilter):
26972746
tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Tag name contains")
2698-
tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
2699-
help_text="Comma separated list of exact tags")
2700-
2747+
tags = CharFieldInFilter(
2748+
field_name="tags__name",
2749+
lookup_expr="in",
2750+
help_text="Comma separated list of exact tags (uses OR for multiple values)")
2751+
tags__and = CharFieldFilterANDExpression(
2752+
field_name="tags__name",
2753+
help_text="Comma separated list of exact tags to match with an AND expression")
27012754
not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
27022755
not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
27032756
help_text="Comma separated list of exact tags not present on model", exclude="True")
@@ -2851,13 +2904,27 @@ def __init__(self, *args, **kwargs):
28512904

28522905
class ApiTestFilter(DojoFilter):
28532906
tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Tag name contains")
2854-
tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
2855-
help_text="Comma separated list of exact tags")
2856-
engagement__tags = CharFieldInFilter(field_name="engagement__tags__name", lookup_expr="in",
2857-
help_text="Comma separated list of exact tags present on engagement")
2858-
engagement__product__tags = CharFieldInFilter(field_name="engagement__product__tags__name",
2859-
lookup_expr="in",
2860-
help_text="Comma separated list of exact tags present on product")
2907+
tags = CharFieldInFilter(
2908+
field_name="tags__name",
2909+
lookup_expr="in",
2910+
help_text="Comma separated list of exact tags (uses OR for multiple values)")
2911+
tags__and = CharFieldFilterANDExpression(
2912+
field_name="tags__name",
2913+
help_text="Comma separated list of exact tags to match with an AND expression")
2914+
engagement__tags = CharFieldInFilter(
2915+
field_name="engagement__tags__name",
2916+
lookup_expr="in",
2917+
help_text="Comma separated list of exact tags present on engagement (uses OR for multiple values)")
2918+
engagement__tags__and = CharFieldFilterANDExpression(
2919+
field_name="engagement__tags__name",
2920+
help_text="Comma separated list of exact tags to match with an AND expression present on engagement")
2921+
engagement__product__tags = CharFieldInFilter(
2922+
field_name="engagement__product__tags__name",
2923+
lookup_expr="in",
2924+
help_text="Comma separated list of exact tags present on product (uses OR for multiple values)")
2925+
engagement__product__tags__and = CharFieldFilterANDExpression(
2926+
field_name="engagement__product__tags__name",
2927+
help_text="Comma separated list of exact tags to match with an AND expression present on product")
28612928

28622929
not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
28632930
not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
@@ -2905,9 +2972,13 @@ class Meta:
29052972

29062973
class ApiAppAnalysisFilter(DojoFilter):
29072974
tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Tag name contains")
2908-
tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
2909-
help_text="Comma separated list of exact tags")
2910-
2975+
tags = CharFieldInFilter(
2976+
field_name="tags__name",
2977+
lookup_expr="in",
2978+
help_text="Comma separated list of exact tags (uses OR for multiple values)")
2979+
tags__and = CharFieldFilterANDExpression(
2980+
field_name="tags__name",
2981+
help_text="Comma separated list of exact tags to match with an AND expression")
29112982
not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
29122983
not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
29132984
help_text="Comma separated list of exact tags not present on model", exclude="True")

dojo/survey/views.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -539,17 +539,17 @@ def edit_question(request, qid):
539539
extra_tags="alert-info")
540540
type = str(ContentType.objects.get_for_model(question))
541541

542-
if type == "dojo | text question":
542+
if type in {"dojo | text question", "Defect Dojo | text question"}:
543543
form = EditTextQuestionForm(instance=question)
544-
elif type == "dojo | choice question":
544+
elif type in {"dojo | choice question", "Defect Dojo | choice question"}:
545545
form = EditChoiceQuestionForm(instance=question)
546546
else:
547547
raise Http404
548548

549549
if request.method == "POST":
550-
if type == "dojo | text question":
550+
if type in {"dojo | text question", "Defect Dojo | text question"}:
551551
form = EditTextQuestionForm(request.POST, instance=question)
552-
elif type == "dojo | choice question":
552+
elif type in {"dojo | choice question", "Defect Dojo | choice question"}:
553553
form = EditChoiceQuestionForm(request.POST, instance=question)
554554
else:
555555
raise Http404

dojo/tools/zap/parser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ def get_description_for_scan_types(self, scan_type):
2727
return "ZAP XML report format."
2828

2929
def get_findings(self, file, test):
30+
if not file.name.endswith(".xml"):
31+
msg = "Internal error: Wrong file format, please use xml."
32+
raise ValueError(msg)
3033
tree = ET.parse(file)
3134
items = []
3235
for node in tree.findall("site"):

helm/defectdojo/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
apiVersion: v2
2-
appVersion: "2.43.3"
2+
appVersion: "2.43.4"
33
description: A Helm chart for Kubernetes to install DefectDojo
44
name: defectdojo
5-
version: 1.6.174
5+
version: 1.6.175
66
icon: https://www.defectdojo.org/img/favicon.ico
77
maintainers:
88
- name: madchap

unittests/dojo_test_case.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -716,8 +716,8 @@ def get_finding_tags_api(self, finding_id):
716716
response = self.do_finding_tags_api(self.client.get, finding_id)
717717
return response.data
718718

719-
def get_finding_api_filter_tags(self, tags):
720-
response = self.client.get(reverse("finding-list") + f"?tags={tags}", format="json")
719+
def get_finding_api_filter_tags(self, tags, parameter="tags"):
720+
response = self.client.get(reverse("finding-list") + f"?{parameter}={tags}", format="json")
721721
self.assertEqual(200, response.status_code, response.content[:1000])
722722
return response.data
723723

unittests/test_tags.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ def test_finding_filter_tags(self):
5858

5959
response = self.get_finding_api_filter_tags("tag4")
6060
self.assertEqual(response["count"], 0)
61+
# Test the tags__and filter for a case with no matches
62+
response = self.get_finding_api_filter_tags("tag2,tag3", parameter="tags__and")
63+
self.assertEqual(response["count"], 0)
64+
# Test the tags__and filter for a case with one exact match
65+
response = self.get_finding_api_filter_tags("tag1,tag2", parameter="tags__and")
66+
self.assertEqual(response["count"], 1)
6167

6268
def test_finding_post_tags(self):
6369
# create finding

0 commit comments

Comments
 (0)