api: allow configuring default page_size and max_page_size (#18165)

Co-authored-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
Nuno Alves
2025-12-11 14:45:50 +00:00
committed by GitHub
parent a0c33233d5
commit 196bce348f
9 changed files with 91 additions and 5 deletions
+5
View File
@@ -13,6 +13,11 @@ class Pagination(pagination.PageNumberPagination):
page_query_param = "page"
page_size_query_param = "page_size"
def get_page_size(self, request):
if self.page_size_query_param in request.query_params:
return min(super().get_page_size(request), request.tenant.pagination_max_page_size)
return request.tenant.pagination_default_page_size
def get_paginated_response(self, data):
previous_page_number = 0
if self.page.has_previous():
-1
View File
@@ -207,7 +207,6 @@ SPECTACULAR_SETTINGS = {
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "authentik.api.pagination.Pagination",
"PAGE_SIZE": 100,
"DEFAULT_FILTER_BACKENDS": [
"authentik.rbac.filters.ObjectFilter",
"django_filters.rest_framework.DjangoFilterBackend",
+1 -3
View File
@@ -3,7 +3,6 @@
from typing import Any
from uuid import UUID
from django.conf import settings
from django.core.paginator import Page, Paginator
from django.db.models import Q, QuerySet
from django.http import HttpRequest
@@ -86,10 +85,9 @@ class SCIMView(APIView):
)
def paginate_query(self, query: QuerySet) -> Page:
per_page = 50
per_page = int(self.request.tenant.pagination_default_page_size)
start_index = 1
try:
per_page = int(settings.REST_FRAMEWORK["PAGE_SIZE"])
start_index = int(self.request.query_params.get("startIndex", 1))
except ValueError:
pass
@@ -37,7 +37,7 @@ class ServiceProviderConfigView(SCIMView):
"bulk": {"supported": False, "maxOperations": 0, "maxPayloadSize": 0},
"filter": {
"supported": True,
"maxResults": int(settings.REST_FRAMEWORK["PAGE_SIZE"]),
"maxResults": request.tenant.pagination_default_page_size,
},
"changePassword": {"supported": False},
"sort": {"supported": False},
+2
View File
@@ -69,6 +69,8 @@ class SettingsSerializer(ModelSerializer):
"impersonation_require_reason",
"default_token_duration",
"default_token_length",
"pagination_default_page_size",
"pagination_max_page_size",
"flags",
]
@@ -0,0 +1,26 @@
# Generated by Django 5.2.8 on 2025-12-10 03:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_tenants", "0006_tenant_flags"),
]
operations = [
migrations.AddField(
model_name="tenant",
name="pagination_default_page_size",
field=models.PositiveIntegerField(
default=20,
help_text="Default page size for API responses, if no size was requested.",
),
),
migrations.AddField(
model_name="tenant",
name="pagination_max_page_size",
field=models.PositiveIntegerField(default=100, help_text="Maximum page size"),
),
]
+10
View File
@@ -113,6 +113,16 @@ class Tenant(TenantMixin, SerializerModel):
default=DEFAULT_TOKEN_LENGTH,
validators=[MinValueValidator(1)],
)
pagination_default_page_size = models.PositiveIntegerField(
help_text=_("Default page size for API responses, if no size was requested."),
default=20,
)
pagination_max_page_size = models.PositiveIntegerField(
help_text=_("Maximum page size"),
default=100,
)
flags = models.JSONField(default=dict)
def save(self, *args, **kwargs):
+30
View File
@@ -48744,6 +48744,16 @@ components:
maximum: 2147483647
minimum: 1
description: Default token length
pagination_default_page_size:
type: integer
maximum: 2147483647
minimum: 0
description: Default page size for API responses, if no size was requested.
pagination_max_page_size:
type: integer
maximum: 2147483647
minimum: 0
description: Maximum page size
flags:
type: object
properties:
@@ -53235,6 +53245,16 @@ components:
maximum: 2147483647
minimum: 1
description: Default token length
pagination_default_page_size:
type: integer
maximum: 2147483647
minimum: 0
description: Default page size for API responses, if no size was requested.
pagination_max_page_size:
type: integer
maximum: 2147483647
minimum: 0
description: Maximum page size
flags:
type: object
properties:
@@ -53300,6 +53320,16 @@ components:
maximum: 2147483647
minimum: 1
description: Default token length
pagination_default_page_size:
type: integer
maximum: 2147483647
minimum: 0
description: Default page size for API responses, if no size was requested.
pagination_max_page_size:
type: integer
maximum: 2147483647
minimum: 0
description: Maximum page size
flags:
type: object
properties:
@@ -26,6 +26,8 @@ import PFList from "@patternfly/patternfly/components/List/list.css";
const DEFAULT_REPUTATION_LOWER_LIMIT = -5;
const DEFAULT_REPUTATION_UPPER_LIMIT = 5;
const DEFAULT_PAGE_SIZE = 20;
const DEFAULT_PAGE_MAX = 100;
@customElement("ak-admin-settings-form")
export class AdminSettingsForm extends Form<SettingsRequest> {
@@ -245,6 +247,20 @@ export class AdminSettingsForm extends Form<SettingsRequest> {
value="${settings.defaultTokenLength ?? 60}"
help=${msg("Default length of generated tokens")}
></ak-number-input>
<ak-number-input
label=${msg("Pagination: default page size")}
required
name="paginationDefaultPageSize"
value="${settings.paginationDefaultPageSize ?? DEFAULT_PAGE_SIZE}"
help=${msg("Default page size for API requests not specifying a page size.")}
></ak-number-input>
<ak-number-input
label=${msg("Pagination: maximum page size")}
required
name="paginationMaxPageSize"
value="${settings.paginationMaxPageSize ?? DEFAULT_PAGE_MAX}"
help=${msg("Maximum page size for API requests.")}
></ak-number-input>
<ak-form-group
label=${msg("Flags")}
description=${msg(