Skip to content

Commit 4fe064d

Browse files
authored
Add deprecation notice for questionnaire API endpoints (#14285)
* feat: add deprecation notice for questionnaire endpoints with end-of-life date * feat: add documentation for deprecation and removal of Questionnaire API endpoints * fix: correct end-of-life date for deprecated Questionnaire API endpoints
1 parent 47319a2 commit 4fe064d

3 files changed

Lines changed: 156 additions & 7 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
title: 'Upgrading to DefectDojo Version 2.56.x'
3+
toc_hide: true
4+
weight: -20260215
5+
description: Deprecation of Questionnaire API Endpoints
6+
---
7+
8+
## Deprecation: Questionnaire API Endpoints
9+
10+
The following Questionnaire API endpoints are being deprecated and will be removed in DefectDojo 2.59.0 on June 1st, 2026:
11+
12+
- `/api/v2/questionnaire_answered_questionnaires/`
13+
- `/api/v2/questionnaire_answers/`
14+
- `/api/v2/questionnaire_engagement_questionnaires/`
15+
- `/api/v2/questionnaire_general_questionnaires/`
16+
- `/api/v2/questionnaire_questions`
17+
18+
### Required Actions
19+
20+
Support for these endpoints will be fully removed in DefectDojo 2.59.0 (scheduled for June 1st, 2026). After this date, any requests to these endpoints will return a 404 Not Found error.
21+
22+
### Timeline
23+
24+
- **DefectDojo 2.56.x onwards**: Endpoints are deprecated with deprecation headers
25+
- **DefectDojo 2.59.0 (June 1st, 2026)**: Endpoints will be removed entirely
26+
27+
For more information, check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.56.0).
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
title: 'Upgrading to DefectDojo Version 2.59.x'
3+
toc_hide: true
4+
weight: -20260602
5+
description: Removal of Questionnaire API Endpoints
6+
---
7+
8+
## Removal: Questionnaire API Endpoints
9+
10+
As announced in DefectDojo 2.56.0, the following Questionnaire API endpoints have been removed:
11+
12+
- `/api/v2/questionnaire_answered_questionnaires/`
13+
- `/api/v2/questionnaire_answers/`
14+
- `/api/v2/questionnaire_engagement_questionnaires/`
15+
- `/api/v2/questionnaire_general_questionnaires/`
16+
- `/api/v2/questionnaire_questions`
17+
18+
### Required Actions
19+
20+
Any requests to these endpoints will now return a 404 Not Found error.
21+
22+
For more information, check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.59.0).

dojo/api_v2/views.py

Lines changed: 107 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,19 @@ class PrefetchDojoModelViewSet(
243243
pass
244244

245245

246+
class DeprecationNoticeMixin:
247+
248+
deprecated: bool | None = None
249+
end_of_life_date: datetime | None = None
250+
251+
def finalize_response(self, request, response, *args, **kwargs):
252+
if self.deprecated is not None:
253+
response["X-Deprecated"] = self.deprecated
254+
if self.end_of_life_date is not None:
255+
response["X-End-Of-Life-Date"] = self.end_of_life_date.isoformat()
256+
return super().finalize_response(request, response, *args, **kwargs)
257+
258+
246259
# Authorization: authenticated users
247260
class RoleViewSet(viewsets.ReadOnlyModelViewSet):
248261
serializer_class = serializers.RoleSerializer
@@ -3186,7 +3199,10 @@ def get_queryset(self):
31863199
class QuestionnaireQuestionViewSet(
31873200
viewsets.ReadOnlyModelViewSet,
31883201
dojo_mixins.QuestionSubClassFieldsMixin,
3202+
DeprecationNoticeMixin,
31893203
):
3204+
deprecated = True
3205+
end_of_life_date = datetime(2026, 6, 1)
31903206
serializer_class = serializers.QuestionnaireQuestionSerializer
31913207
queryset = Question.objects.none()
31923208
filter_backends = (DjangoFilterBackend,)
@@ -3198,11 +3214,28 @@ class QuestionnaireQuestionViewSet(
31983214
def get_queryset(self):
31993215
return Question.objects.all().order_by("id")
32003216

3217+
@extend_schema(
3218+
deprecated=True,
3219+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3220+
)
3221+
def list(self, request, *args, **kwargs):
3222+
return super().list(request, *args, **kwargs)
3223+
3224+
@extend_schema(
3225+
deprecated=True,
3226+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3227+
)
3228+
def retrieve(self, request, *args, **kwargs):
3229+
return super().retrieve(request, *args, **kwargs)
3230+
32013231

32023232
class QuestionnaireAnswerViewSet(
32033233
viewsets.ReadOnlyModelViewSet,
32043234
dojo_mixins.AnswerSubClassFieldsMixin,
3235+
DeprecationNoticeMixin,
32053236
):
3237+
deprecated = True
3238+
end_of_life_date = datetime(2026, 6, 1)
32063239
serializer_class = serializers.QuestionnaireAnswerSerializer
32073240
queryset = Answer.objects.none()
32083241
filter_backends = (DjangoFilterBackend,)
@@ -3214,10 +3247,27 @@ class QuestionnaireAnswerViewSet(
32143247
def get_queryset(self):
32153248
return Answer.objects.all().order_by("id")
32163249

3250+
@extend_schema(
3251+
deprecated=True,
3252+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3253+
)
3254+
def list(self, request, *args, **kwargs):
3255+
return super().list(request, *args, **kwargs)
3256+
3257+
@extend_schema(
3258+
deprecated=True,
3259+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3260+
)
3261+
def retrieve(self, request, *args, **kwargs):
3262+
return super().retrieve(request, *args, **kwargs)
3263+
32173264

32183265
class QuestionnaireGeneralSurveyViewSet(
32193266
viewsets.ReadOnlyModelViewSet,
3267+
DeprecationNoticeMixin,
32203268
):
3269+
deprecated = True
3270+
end_of_life_date = datetime(2026, 6, 1)
32213271
serializer_class = serializers.QuestionnaireGeneralSurveySerializer
32223272
queryset = General_Survey.objects.none()
32233273
filter_backends = (DjangoFilterBackend,)
@@ -3229,10 +3279,27 @@ class QuestionnaireGeneralSurveyViewSet(
32293279
def get_queryset(self):
32303280
return General_Survey.objects.all().order_by("id")
32313281

3282+
@extend_schema(
3283+
deprecated=True,
3284+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3285+
)
3286+
def list(self, request, *args, **kwargs):
3287+
return super().list(request, *args, **kwargs)
3288+
3289+
@extend_schema(
3290+
deprecated=True,
3291+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3292+
)
3293+
def retrieve(self, request, *args, **kwargs):
3294+
return super().retrieve(request, *args, **kwargs)
3295+
32323296

32333297
class QuestionnaireEngagementSurveyViewSet(
32343298
viewsets.ReadOnlyModelViewSet,
3299+
DeprecationNoticeMixin,
32353300
):
3301+
deprecated = True
3302+
end_of_life_date = datetime(2026, 6, 1)
32363303
serializer_class = serializers.QuestionnaireEngagementSurveySerializer
32373304
queryset = Engagement_Survey.objects.none()
32383305
filter_backends = (DjangoFilterBackend,)
@@ -3245,13 +3312,29 @@ def get_queryset(self):
32453312
return Engagement_Survey.objects.all().order_by("id")
32463313

32473314
@extend_schema(
3248-
request=OpenApiTypes.NONE,
3249-
parameters=[
3250-
OpenApiParameter(
3251-
"engagement_id", OpenApiTypes.INT, OpenApiParameter.PATH,
3252-
),
3253-
],
3254-
responses={status.HTTP_200_OK: serializers.QuestionnaireAnsweredSurveySerializer},
3315+
deprecated=True,
3316+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3317+
)
3318+
def list(self, request, *args, **kwargs):
3319+
return super().list(request, *args, **kwargs)
3320+
3321+
@extend_schema(
3322+
deprecated=True,
3323+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3324+
)
3325+
def retrieve(self, request, *args, **kwargs):
3326+
return super().retrieve(request, *args, **kwargs)
3327+
3328+
@extend_schema(
3329+
deprecated=True,
3330+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3331+
request=OpenApiTypes.NONE,
3332+
parameters=[
3333+
OpenApiParameter(
3334+
"engagement_id", OpenApiTypes.INT, OpenApiParameter.PATH,
3335+
),
3336+
],
3337+
responses={status.HTTP_200_OK: serializers.QuestionnaireAnsweredSurveySerializer},
32553338
)
32563339
@action(
32573340
detail=True, methods=["post"], url_path=r"link_engagement/(?P<engagement_id>\d+)",
@@ -3273,7 +3356,10 @@ class QuestionnaireAnsweredSurveyViewSet(
32733356
prefetch.PrefetchListMixin,
32743357
prefetch.PrefetchRetrieveMixin,
32753358
viewsets.ReadOnlyModelViewSet,
3359+
DeprecationNoticeMixin,
32763360
):
3361+
deprecated = True
3362+
end_of_life_date = datetime(2026, 6, 1)
32773363
serializer_class = serializers.QuestionnaireAnsweredSurveySerializer
32783364
queryset = Answered_Survey.objects.none()
32793365
filter_backends = (DjangoFilterBackend,)
@@ -3285,6 +3371,20 @@ class QuestionnaireAnsweredSurveyViewSet(
32853371
def get_queryset(self):
32863372
return Answered_Survey.objects.all().order_by("id")
32873373

3374+
@extend_schema(
3375+
deprecated=True,
3376+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3377+
)
3378+
def list(self, request, *args, **kwargs):
3379+
return super().list(request, *args, **kwargs)
3380+
3381+
@extend_schema(
3382+
deprecated=True,
3383+
description="This endpoint is deprecated and will be removed on 2026-06-01.",
3384+
)
3385+
def retrieve(self, request, *args, **kwargs):
3386+
return super().retrieve(request, *args, **kwargs)
3387+
32883388

32893389
# Authorization: configuration
32903390
class AnnouncementViewSet(

0 commit comments

Comments
 (0)