diff --git a/docs/release-notes/version-3.0.md b/docs/release-notes/version-3.0.md index eb0cb948f..727d067ac 100644 --- a/docs/release-notes/version-3.0.md +++ b/docs/release-notes/version-3.0.md @@ -13,6 +13,7 @@ * [#7084](https://github.com/netbox-community/netbox/issues/7084) - Fix KeyError exception when editing access VLAN on an interface * [#7089](https://github.com/netbox-community/netbox/issues/7089) - Fix ContentTypeFilterSet not filtering on q filter * [#7096](https://github.com/netbox-community/netbox/issues/7096) - Home links should honor `BASE_PATH` configuration +* [#7101](https://github.com/netbox-community/netbox/issues/7101) - Enforce `MAX_PAGE_SIZE` for table and REST API pagination --- diff --git a/netbox/netbox/api/pagination.py b/netbox/netbox/api/pagination.py index d489ce951..77af755ce 100644 --- a/netbox/netbox/api/pagination.py +++ b/netbox/netbox/api/pagination.py @@ -34,23 +34,13 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination): return list(queryset[self.offset:]) def get_limit(self, request): + limit = super().get_limit(request) - if self.limit_query_param: - try: - limit = int(request.query_params[self.limit_query_param]) - if limit < 0: - raise ValueError() - # Enforce maximum page size, if defined - if settings.MAX_PAGE_SIZE: - if limit == 0: - return settings.MAX_PAGE_SIZE - else: - return min(limit, settings.MAX_PAGE_SIZE) - return limit - except (KeyError, ValueError): - pass + # Enforce maximum page size + if settings.MAX_PAGE_SIZE: + limit = min(limit, settings.MAX_PAGE_SIZE) - return self.default_limit + return limit def get_next_link(self): diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index b05097f3b..4f0e8956e 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -560,6 +560,10 @@ RQ_QUEUES = { # # Pagination +if MAX_PAGE_SIZE and PAGINATE_COUNT > MAX_PAGE_SIZE: + raise ImproperlyConfigured( + f"PAGINATE_COUNT ({PAGINATE_COUNT}) must be less than or equal to MAX_PAGE_SIZE ({MAX_PAGE_SIZE}), if set." + ) PER_PAGE_DEFAULTS = [ 25, 50, 100, 250, 500, 1000 ] diff --git a/netbox/utilities/paginator.py b/netbox/utilities/paginator.py index 3b9e1cb37..e46af4b3e 100644 --- a/netbox/utilities/paginator.py +++ b/netbox/utilities/paginator.py @@ -49,21 +49,25 @@ class EnhancedPage(Page): def get_paginate_count(request): """ - Determine the length of a page, using the following in order: + Determine the desired length of a page, using the following in order: 1. per_page URL query parameter 2. Saved user preference 3. PAGINATE_COUNT global setting. + + Return the lesser of the calculated value and MAX_PAGE_SIZE. """ if 'per_page' in request.GET: try: per_page = int(request.GET.get('per_page')) if request.user.is_authenticated: request.user.config.set('pagination.per_page', per_page, commit=True) - return per_page + return min(per_page, settings.MAX_PAGE_SIZE) except ValueError: pass if request.user.is_authenticated: - return request.user.config.get('pagination.per_page', settings.PAGINATE_COUNT) - return settings.PAGINATE_COUNT + per_page = request.user.config.get('pagination.per_page', settings.PAGINATE_COUNT) + return min(per_page, settings.MAX_PAGE_SIZE) + + return min(settings.PAGINATE_COUNT, settings.MAX_PAGE_SIZE)