|
12 | 12 | from django.apps import apps
|
13 | 13 | from django.conf import settings
|
14 | 14 | from django.contrib.contenttypes.models import ContentType
|
15 |
| -from django.db.models import JSONField, Q |
| 15 | +from django.db.models import Count, JSONField, Q |
16 | 16 | from django.forms import HiddenInput
|
17 | 17 | from django.utils import timezone
|
18 | 18 | from django.utils.translation import gettext_lazy as _
|
@@ -135,6 +135,20 @@ def __init__(self, *args, **kwargs):
|
135 | 135 | super(CharFilter, self).__init__(*args, **kwargs)
|
136 | 136 |
|
137 | 137 |
|
| 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 | + |
138 | 152 | class FindingStatusFilter(ChoiceFilter):
|
139 | 153 | def any(self, qs, name):
|
140 | 154 | return qs
|
@@ -1204,11 +1218,20 @@ class ProductEngagementFilterWithoutObjectLookups(ProductEngagementFilterHelper,
|
1204 | 1218 | class ApiEngagementFilter(DojoFilter):
|
1205 | 1219 | product__prod_type = NumberInFilter(field_name="product__prod_type", lookup_expr="in")
|
1206 | 1220 | 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") |
1212 | 1235 |
|
1213 | 1236 | not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
|
1214 | 1237 | not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
|
@@ -1365,9 +1388,13 @@ class ApiProductFilter(DojoFilter):
|
1365 | 1388 | regulations = NumberInFilter(field_name="regulations", lookup_expr="in")
|
1366 | 1389 |
|
1367 | 1390 | 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") |
1371 | 1398 | not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
|
1372 | 1399 | not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
|
1373 | 1400 | help_text="Comma separated list of exact tags not present on product", exclude="True")
|
@@ -1511,16 +1538,34 @@ class ApiFindingFilter(DojoFilter):
|
1511 | 1538 | risk_acceptance = extend_schema_field(OpenApiTypes.NUMBER)(ReportRiskAcceptanceFilter())
|
1512 | 1539 |
|
1513 | 1540 | 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") |
1519 | 1562 | test__engagement__product__tags = CharFieldInFilter(
|
1520 | 1563 | field_name="test__engagement__product__tags__name",
|
1521 | 1564 | 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") |
1524 | 1569 | not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
|
1525 | 1570 | not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
|
1526 | 1571 | help_text="Comma separated list of exact tags not present on model", exclude="True")
|
@@ -2118,9 +2163,13 @@ def __init__(self, *args, **kwargs):
|
2118 | 2163 |
|
2119 | 2164 | class ApiTemplateFindingFilter(DojoFilter):
|
2120 | 2165 | 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") |
2124 | 2173 | not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
|
2125 | 2174 | not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
|
2126 | 2175 | help_text="Comma separated list of exact tags not present on model", exclude="True")
|
@@ -2695,9 +2744,13 @@ class Meta:
|
2695 | 2744 |
|
2696 | 2745 | class ApiEndpointFilter(DojoFilter):
|
2697 | 2746 | 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") |
2701 | 2754 | not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
|
2702 | 2755 | not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
|
2703 | 2756 | help_text="Comma separated list of exact tags not present on model", exclude="True")
|
@@ -2851,13 +2904,27 @@ def __init__(self, *args, **kwargs):
|
2851 | 2904 |
|
2852 | 2905 | class ApiTestFilter(DojoFilter):
|
2853 | 2906 | 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") |
2861 | 2928 |
|
2862 | 2929 | not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
|
2863 | 2930 | not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
|
@@ -2905,9 +2972,13 @@ class Meta:
|
2905 | 2972 |
|
2906 | 2973 | class ApiAppAnalysisFilter(DojoFilter):
|
2907 | 2974 | 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") |
2911 | 2982 | not_tag = CharFilter(field_name="tags__name", lookup_expr="icontains", help_text="Not Tag name contains", exclude="True")
|
2912 | 2983 | not_tags = CharFieldInFilter(field_name="tags__name", lookup_expr="in",
|
2913 | 2984 | help_text="Comma separated list of exact tags not present on model", exclude="True")
|
|
0 commit comments