From 2f15cc080d573707cdb80dd714b975c1ab51c928 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:44:15 -0600 Subject: [PATCH] Add page size restrictions --- dojo/api_v2/mixins.py | 44 ++++++++++++++++++++++++++++++++++ dojo/settings/settings.dist.py | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/dojo/api_v2/mixins.py b/dojo/api_v2/mixins.py index 6c6b4792757..45499e375e9 100644 --- a/dojo/api_v2/mixins.py +++ b/dojo/api_v2/mixins.py @@ -6,6 +6,8 @@ from rest_framework import status from rest_framework.authtoken.models import Token from rest_framework.decorators import action +from rest_framework.pagination import LimitOffsetPagination +from rest_framework.response import Response from dojo.api_v2 import serializers from dojo.models import Answer, Question @@ -56,3 +58,45 @@ def get_queryset(self): class AnswerSubClassFieldsMixin: def get_queryset(self): return Answer.objects.select_subclasses() + + +class DeprecationWarningLimitOffsetPagination(LimitOffsetPagination): + # Newly introduced max limit + max_limit = 250 + # Represents no limit previously + default_max_limit = None + + def get_paginated_response(self, data): + # Determine the limit from the request + limit = self.request.query_params.get("limit", None) + limit = int(limit) if limit and limit.isdigit() else None + # Base response + response_data = { + "count": self.count, + "next": self.get_next_link(), + "previous": self.get_previous_link(), + "results": data, + } + # Add a deprecation warning if the limit exceeds the new max_limit + if limit > self.max_limit: + response_data["meta"] = { + "warning": ( + f"The requested limit of {limit} exceeds the newly introduced maximum limit of {self.max_limit}. " + f"Starting in version 2.45.0, requests exceeding this limit will be truncated to {self.max_limit} results. " + "Please adjust your requests to ensure compatibility." + ), + } + + return Response(response_data) + + # This entire function can be removed during the cut over + def get_limit(self, request): + limit = super().get_limit(request) + # If no max limit was previously set, allow any requested limit + if self.default_max_limit is None: + return limit + # Clamp the limit to the new max_limit if it exceeds the maximum + if limit and limit > self.max_limit: + return self.max_limit + + return limit \ No newline at end of file diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 7d1513f13a6..742c02ec790 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -765,7 +765,7 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param "DEFAULT_RENDERER_CLASSES": ( "rest_framework.renderers.JSONRenderer", ), - "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination", + "DEFAULT_PAGINATION_CLASS": "dojo.api_v2.mixins.DeprecationWarningLimitOffsetPagination", "PAGE_SIZE": 25, "EXCEPTION_HANDLER": "dojo.api_v2.exception_handler.custom_exception_handler", }