Skip to content

Commit 1c51535

Browse files
committed
Merge branch 'mitigation_filter' of https://github.com/bendnema/django-DefectDojo-spring-26-yc26 into mitigation_filter
2 parents 0e4636c + 7ad51d1 commit 1c51535

127 files changed

Lines changed: 2576 additions & 1804 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Dockerfile.django-debian

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Dockerfile.nginx to use the caching mechanism of Docker.
66

77
# Ref: https://devguide.python.org/#branchstatus
8-
FROM python:3.13.12-slim-trixie@sha256:739e7213785e88c0f702dcdc12c0973afcbd606dbf021a589cab77d6b00b579d AS base
8+
FROM python:3.13.13-slim-trixie@sha256:d2462a6bed37b4fc6cabecf5a2132ae70df772fe03c7393c4d98a0c2fb48aa2e AS base
99
FROM base AS build
1010
WORKDIR /app
1111
RUN \

Dockerfile.integration-tests-debian

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22
# code: language=Dockerfile
33

4-
FROM openapitools/openapi-generator-cli:v7.21.0@sha256:ce308310f3c1f8761e65338b8ab87b651bf4862c6acb80de510f381fffc4510b AS openapitools
4+
FROM openapitools/openapi-generator-cli:v7.22.0@sha256:1f459499a7c794aa0ea769c3c9b0eb54806c5ad2f68510a0ebb9338d0a626ced AS openapitools
55
# currently only supports x64, no arm yet due to chrome and selenium dependencies
6-
FROM python:3.13.12-slim-trixie@sha256:739e7213785e88c0f702dcdc12c0973afcbd606dbf021a589cab77d6b00b579d AS build
6+
FROM python:3.13.13-slim-trixie@sha256:d2462a6bed37b4fc6cabecf5a2132ae70df772fe03c7393c4d98a0c2fb48aa2e AS build
77
WORKDIR /app
88
RUN \
99
apt-get -y update && \

components/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"chosen-bootstrap": "https://github.com/dbtek/chosen-bootstrap",
1313
"chosen-js": "^1.8.7",
1414
"clipboard": "^2.0.11",
15-
"datatables.net": "^2.3.7",
15+
"datatables.net": "^2.3.8",
1616
"datatables.net-buttons-bs": "^3.2.6",
1717
"datatables.net-colreorder": "^2.1.2",
1818
"drmonty-datatables-plugins": "^1.0.0",

components/yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,10 @@ datatables.net@2.3.2:
167167
dependencies:
168168
jquery ">=1.7"
169169

170-
datatables.net@^2, datatables.net@^2.3.7:
171-
version "2.3.7"
172-
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.3.7.tgz#3cd34f6f5d1f40a46b5a20a4ba32604bdbcd6738"
173-
integrity sha512-AvsjG/Nkp6OxeyBKYZauemuzQCPogE1kOtKwG4sYjvdqGCSLiGaJagQwXv4YxG+ts5vaJr6qKGG9ec3g6vTo3w==
170+
datatables.net@^2, datatables.net@^2.3.8:
171+
version "2.3.8"
172+
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.3.8.tgz#55a8dbe3bd2196951c498ab79bf44602a2bf3229"
173+
integrity sha512-uhViowhlDlheAuo5a8TrkQqADsjrtGeOyvrigvr4t0+K3MyAWqClORXWAYIcN9VLX6iIX0C8O9gwJNd01hITRg==
174174
dependencies:
175175
jquery ">=1.7"
176176

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
title: 'Upgrading to DefectDojo Version 2.58.x'
3+
toc_hide: true
4+
weight: -20260504
5+
description: Notification .tpl templates relocated under dojo/notifications/
6+
---
7+
8+
## Notification `.tpl` templates relocated
9+
10+
The notification domain has been consolidated under a new `dojo/notifications/` package, and the 62 channel `.tpl` templates that drive alert, mail, MS Teams, Slack, and webhook notifications have moved on disk. The Django template lookup name (e.g. `notifications/mail/scan_added.tpl`) is unchanged, so most customizations keep working without any edits — but operators who override `.tpl` files by mounting them into the source tree need to update their paths.
11+
12+
### What moved
13+
14+
The channel templates under `alert/`, `mail/`, `msteams/`, `slack/`, `webhooks/`, and `webhooks_summary/` have been relocated:
15+
16+
| Old on-disk location | New on-disk location |
17+
| --- | --- |
18+
| `dojo/templates/notifications/{channel}/{event}.tpl` | `dojo/notifications/templates/notifications/{channel}/{event}.tpl` |
19+
20+
For example, `dojo/templates/notifications/mail/scan_added.tpl` now lives at `dojo/notifications/templates/notifications/mail/scan_added.tpl`. A new `TEMPLATES["DIRS"]` entry pointing at `dojo/notifications/templates/` is registered automatically, so the lookup path used by `render_to_string()` (e.g. `notifications/slack/sla_breach.tpl`) resolves exactly as before.
21+
22+
### Required actions
23+
24+
- **Customizing `.tpl` files via your own templates directory (recommended pattern):** No action required. Overrides resolved by lookup name continue to take precedence.
25+
- **Customizing `.tpl` files via a Docker volume mount or in-tree patch at the old `dojo/templates/notifications/...` path:** Update the mount/patch target to the new `dojo/notifications/templates/notifications/...` path, or move your override into a project-level templates directory keyed by the lookup name.
26+
- **No customizations:** No action required.
27+
28+
For more information, check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.58.0).

docs/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dojo/api_v2/serializers.py

Lines changed: 3 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from rest_framework import serializers
2222
from rest_framework.exceptions import NotFound
2323
from rest_framework.exceptions import ValidationError as RestFrameworkValidationError
24-
from rest_framework.fields import DictField, MultipleChoiceField
24+
from rest_framework.fields import DictField
2525

2626
import dojo.finding.helper as finding_helper
2727
import dojo.jira_link.helper as jira_helper
@@ -42,9 +42,7 @@
4242
from dojo.importers.default_reimporter import DefaultReImporter
4343
from dojo.location.models import Location, LocationFindingReference
4444
from dojo.models import (
45-
DEFAULT_NOTIFICATION,
4645
IMPORT_ACTIONS,
47-
NOTIFICATION_CHOICES,
4846
SEVERITIES,
4947
SEVERITY_CHOICES,
5048
STATS_FIELDS,
@@ -84,8 +82,6 @@
8482
Note_Type,
8583
NoteHistory,
8684
Notes,
87-
Notification_Webhooks,
88-
Notifications,
8985
Product,
9086
Product_API_Scan_Configuration,
9187
Product_Group,
@@ -3138,110 +3134,7 @@ class FindingNoteSerializer(serializers.Serializer):
31383134
note_id = serializers.IntegerField()
31393135

31403136

3141-
class NotificationsSerializer(serializers.ModelSerializer):
3142-
product = serializers.PrimaryKeyRelatedField(
3143-
queryset=Product.objects.all(),
3144-
required=False,
3145-
default=None,
3146-
allow_null=True,
3147-
)
3148-
user = serializers.PrimaryKeyRelatedField(
3149-
queryset=Dojo_User.objects.all(),
3150-
required=False,
3151-
default=None,
3152-
allow_null=True,
3153-
)
3154-
product_type_added = MultipleChoiceField(
3155-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3156-
)
3157-
product_added = MultipleChoiceField(
3158-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3159-
)
3160-
engagement_added = MultipleChoiceField(
3161-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3162-
)
3163-
test_added = MultipleChoiceField(
3164-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3165-
)
3166-
scan_added = MultipleChoiceField(
3167-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3168-
)
3169-
jira_update = MultipleChoiceField(
3170-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3171-
)
3172-
upcoming_engagement = MultipleChoiceField(
3173-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3174-
)
3175-
stale_engagement = MultipleChoiceField(
3176-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3177-
)
3178-
auto_close_engagement = MultipleChoiceField(
3179-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3180-
)
3181-
close_engagement = MultipleChoiceField(
3182-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3183-
)
3184-
user_mentioned = MultipleChoiceField(
3185-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3186-
)
3187-
code_review = MultipleChoiceField(
3188-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3189-
)
3190-
review_requested = MultipleChoiceField(
3191-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3192-
)
3193-
other = MultipleChoiceField(
3194-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3195-
)
3196-
sla_breach = MultipleChoiceField(
3197-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3198-
)
3199-
sla_breach_combined = MultipleChoiceField(
3200-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3201-
)
3202-
risk_acceptance_expiration = MultipleChoiceField(
3203-
choices=NOTIFICATION_CHOICES, default=DEFAULT_NOTIFICATION,
3204-
)
3205-
template = serializers.BooleanField(default=False)
3206-
3207-
class Meta:
3208-
model = Notifications
3209-
fields = "__all__"
3210-
3211-
def validate(self, data):
3212-
user = None
3213-
product = None
3214-
template = False
3215-
3216-
if self.instance is not None:
3217-
user = self.instance.user
3218-
product = self.instance.product
3219-
3220-
if "user" in data:
3221-
user = data.get("user")
3222-
if "product" in data:
3223-
product = data.get("product")
3224-
if "template" in data:
3225-
template = data.get("template")
3226-
3227-
if (
3228-
template
3229-
and Notifications.objects.filter(template=True).count() > 0
3230-
):
3231-
msg = "Notification template already exists"
3232-
raise ValidationError(msg)
3233-
if (
3234-
self.instance is None
3235-
or user != self.instance.user
3236-
or product != self.instance.product
3237-
):
3238-
notifications = Notifications.objects.filter(
3239-
user=user, product=product, template=template,
3240-
).count()
3241-
if notifications > 0:
3242-
msg = "Notification for user and product already exists"
3243-
raise ValidationError(msg)
3244-
return data
3137+
from dojo.notifications.api.serializer import NotificationsSerializer # noqa: E402, F401 -- backward compat
32453138

32463139

32473140
class EngagementPresetsSerializer(serializers.ModelSerializer):
@@ -3418,7 +3311,4 @@ def create(self, validated_data):
34183311
raise
34193312

34203313

3421-
class NotificationWebhooksSerializer(serializers.ModelSerializer):
3422-
class Meta:
3423-
model = Notification_Webhooks
3424-
fields = "__all__"
3314+
from dojo.notifications.api.serializer import NotificationWebhooksSerializer # noqa: E402, F401 -- backward compat

dojo/api_v2/views.py

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,6 @@
126126
Note_Type,
127127
NoteHistory,
128128
Notes,
129-
Notification_Webhooks,
130-
Notifications,
131129
Product,
132130
Product_API_Scan_Configuration,
133131
Product_Group,
@@ -3473,21 +3471,6 @@ def queue_task_purge(self, request):
34733471
return Response({"purged": purged})
34743472

34753473

3476-
# Authorization: superuser
3477-
@extend_schema_view(**schema_with_prefetch())
3478-
class NotificationsViewSet(
3479-
PrefetchDojoModelViewSet,
3480-
):
3481-
serializer_class = serializers.NotificationsSerializer
3482-
queryset = Notifications.objects.none()
3483-
filter_backends = (DjangoFilterBackend,)
3484-
filterset_fields = ["id", "user", "product", "template"]
3485-
permission_classes = (permissions.IsSuperUser, DjangoModelPermissions)
3486-
3487-
def get_queryset(self):
3488-
return Notifications.objects.all().order_by("id")
3489-
3490-
34913474
@extend_schema_view(**schema_with_prefetch())
34923475
class EngagementPresetsViewset(
34933476
PrefetchDojoModelViewSet,
@@ -3750,13 +3733,3 @@ class AnnouncementViewSet(
37503733

37513734
def get_queryset(self):
37523735
return Announcement.objects.all().order_by("id")
3753-
3754-
3755-
class NotificationWebhooksViewSet(
3756-
PrefetchDojoModelViewSet,
3757-
):
3758-
serializer_class = serializers.NotificationWebhooksSerializer
3759-
queryset = Notification_Webhooks.objects.all()
3760-
filter_backends = (DjangoFilterBackend,)
3761-
filterset_fields = "__all__"
3762-
permission_classes = (permissions.IsSuperUser, DjangoModelPermissions) # TODO: add permission also for other users

dojo/apps.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ def ready(self):
8484
import dojo.file_uploads.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady
8585
import dojo.finding_group.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady
8686
import dojo.notes.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady
87+
import dojo.notifications.admin # noqa: PLC0415, F401 raised: AppRegistryNotReady
88+
import dojo.notifications.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady
8789
import dojo.product.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady
8890
import dojo.product_type.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady
8991
import dojo.risk_acceptance.signals # noqa: PLC0415, F401 raised: AppRegistryNotReady

dojo/context_processors.py

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import contextlib
2-
import time
32

43
# import the settings file
54
from django.conf import settings
65
from django.contrib import messages
76

87
from dojo.announcement.os_message import get_os_banner
98
from dojo.labels import get_labels
10-
from dojo.models import Alerts, System_Settings, UserAnnouncement
9+
from dojo.models import System_Settings, UserAnnouncement
1110

1211

1312
def globalize_vars(request):
@@ -86,14 +85,6 @@ def bind_system_settings(request):
8685
return {"system_settings": system_settings}
8786

8887

89-
def bind_alert_count(request):
90-
if not settings.DISABLE_ALERT_COUNTER:
91-
92-
if hasattr(request, "user") and request.user.is_authenticated:
93-
return {"alert_count": Alerts.objects.filter(user_id=request.user).count()}
94-
return {}
95-
96-
9788
def bind_announcement(request):
9889
with contextlib.suppress(Exception): # TODO: this should be replaced with more meaningful exception
9990
if request.user.is_authenticated:
@@ -104,21 +95,10 @@ def bind_announcement(request):
10495
return {}
10596

10697

107-
def session_expiry_notification(request):
108-
try:
109-
if request.user.is_authenticated:
110-
last_activity = request.session.get("_last_activity", time.time())
111-
expiry_time = last_activity + settings.SESSION_COOKIE_AGE # When the session will expire
112-
warning_time = settings.SESSION_EXPIRE_WARNING # Show warning X seconds before expiry
113-
notify_time = expiry_time - warning_time
114-
else:
115-
notify_time = None
116-
except Exception:
117-
return {}
118-
else:
119-
return {
120-
"session_notify_time": notify_time,
121-
}
98+
from dojo.notifications.context_processors import ( # noqa: E402, F401 -- backward compat
99+
bind_alert_count,
100+
session_expiry_notification,
101+
)
122102

123103

124104
def labels(request):

0 commit comments

Comments
 (0)