api: optimise pagination in API schema (#6478)

This commit is contained in:
Jens L 2023-08-05 15:37:06 +02:00 committed by GitHub
parent efc660938c
commit 00fae2353c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 177 additions and 2052 deletions

View File

@ -2,6 +2,43 @@
from rest_framework import pagination from rest_framework import pagination
from rest_framework.response import Response from rest_framework.response import Response
PAGINATION_COMPONENT_NAME = "Pagination"
PAGINATION_SCHEMA = {
"type": "object",
"properties": {
"next": {
"type": "number",
},
"previous": {
"type": "number",
},
"count": {
"type": "number",
},
"current": {
"type": "number",
},
"total_pages": {
"type": "number",
},
"start_index": {
"type": "number",
},
"end_index": {
"type": "number",
},
},
"required": [
"next",
"previous",
"count",
"current",
"total_pages",
"start_index",
"end_index",
],
}
class Pagination(pagination.PageNumberPagination): class Pagination(pagination.PageNumberPagination):
"""Pagination which includes total pages and current page""" """Pagination which includes total pages and current page"""
@ -35,41 +72,7 @@ class Pagination(pagination.PageNumberPagination):
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
"pagination": { "pagination": {"$ref": f"#/components/schemas/{PAGINATION_COMPONENT_NAME}"},
"type": "object",
"properties": {
"next": {
"type": "number",
},
"previous": {
"type": "number",
},
"count": {
"type": "number",
},
"current": {
"type": "number",
},
"total_pages": {
"type": "number",
},
"start_index": {
"type": "number",
},
"end_index": {
"type": "number",
},
},
"required": [
"next",
"previous",
"count",
"current",
"total_pages",
"start_index",
"end_index",
],
},
"results": schema, "results": schema,
}, },
"required": ["pagination", "results"], "required": ["pagination", "results"],

View File

@ -1,5 +1,6 @@
"""Error Response schema, from https://github.com/axnsan12/drf-yasg/issues/224""" """Error Response schema, from https://github.com/axnsan12/drf-yasg/issues/224"""
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from drf_spectacular.generators import SchemaGenerator
from drf_spectacular.plumbing import ( from drf_spectacular.plumbing import (
ResolvedComponent, ResolvedComponent,
build_array_type, build_array_type,
@ -9,6 +10,8 @@ from drf_spectacular.plumbing import (
from drf_spectacular.settings import spectacular_settings from drf_spectacular.settings import spectacular_settings
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from authentik.api.pagination import PAGINATION_COMPONENT_NAME, PAGINATION_SCHEMA
def build_standard_type(obj, **kwargs): def build_standard_type(obj, **kwargs):
"""Build a basic type with optional add owns.""" """Build a basic type with optional add owns."""
@ -36,15 +39,7 @@ VALIDATION_ERROR = build_object_type(
) )
def postprocess_schema_responses(result, generator, **kwargs): # noqa: W0613 def create_component(generator: SchemaGenerator, name, schema, type_=ResolvedComponent.SCHEMA):
"""Workaround to set a default response for endpoints.
Workaround suggested at
<https://github.com/tfranzel/drf-spectacular/issues/119#issuecomment-656970357>
for the missing drf-spectacular feature discussed in
<https://github.com/tfranzel/drf-spectacular/issues/101>.
"""
def create_component(name, schema, type_=ResolvedComponent.SCHEMA):
"""Register a component and return a reference to it.""" """Register a component and return a reference to it."""
component = ResolvedComponent( component = ResolvedComponent(
name=name, name=name,
@ -55,8 +50,19 @@ def postprocess_schema_responses(result, generator, **kwargs): # noqa: W0613
generator.registry.register_on_missing(component) generator.registry.register_on_missing(component)
return component return component
generic_error = create_component("GenericError", GENERIC_ERROR)
validation_error = create_component("ValidationError", VALIDATION_ERROR) def postprocess_schema_responses(result, generator: SchemaGenerator, **kwargs): # noqa: W0613
"""Workaround to set a default response for endpoints.
Workaround suggested at
<https://github.com/tfranzel/drf-spectacular/issues/119#issuecomment-656970357>
for the missing drf-spectacular feature discussed in
<https://github.com/tfranzel/drf-spectacular/issues/101>.
"""
create_component(generator, PAGINATION_COMPONENT_NAME, PAGINATION_SCHEMA)
generic_error = create_component(generator, "GenericError", GENERIC_ERROR)
validation_error = create_component(generator, "ValidationError", VALIDATION_ERROR)
for path in result["paths"].values(): for path in result["paths"].values():
for method in path.values(): for method in path.values():

2067
schema.yml

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,8 @@ export class SystemTaskListPage extends TablePage<Task> {
startIndex: 1, startIndex: 1,
endIndex: tasks.length, endIndex: tasks.length,
current: page, current: page,
next: 0,
previous: 0,
}, },
results: tasks, results: tasks,
}; };

View File

@ -47,6 +47,8 @@ export class DeleteObjectsTable<T> extends Table<T> {
totalPages: 1, totalPages: 1,
startIndex: 1, startIndex: 1,
endIndex: this.objects.length, endIndex: this.objects.length,
next: 0,
previous: 0,
}, },
results: this.objects, results: this.objects,
}); });

View File

@ -7,7 +7,6 @@ import "@goauthentik/elements/chips/Chip";
import "@goauthentik/elements/chips/ChipGroup"; import "@goauthentik/elements/chips/ChipGroup";
import { getURLParam, updateURLParams } from "@goauthentik/elements/router/RouteMatch"; import { getURLParam, updateURLParams } from "@goauthentik/elements/router/RouteMatch";
import "@goauthentik/elements/table/TablePagination"; import "@goauthentik/elements/table/TablePagination";
import { Pagination } from "@goauthentik/elements/table/TablePagination";
import "@goauthentik/elements/table/TableSearch"; import "@goauthentik/elements/table/TableSearch";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
@ -24,6 +23,8 @@ import PFToolbar from "@patternfly/patternfly/components/Toolbar/toolbar.css";
import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css"; import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { Pagination } from "@goauthentik/api";
export class TableColumn { export class TableColumn {
title: string; title: string;
orderBy?: string; orderBy?: string;

View File

@ -8,17 +8,7 @@ import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFPagination from "@patternfly/patternfly/components/Pagination/pagination.css"; import PFPagination from "@patternfly/patternfly/components/Pagination/pagination.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
export interface Pagination { import { Pagination } from "@goauthentik/api";
next?: number;
previous?: number;
count: number;
current: number;
totalPages: number;
startIndex: number;
endIndex: number;
}
@customElement("ak-table-pagination") @customElement("ak-table-pagination")
export class TablePagination extends AKElement { export class TablePagination extends AKElement {

View File

@ -28,6 +28,8 @@ export class UserDeviceList extends MFADevicesPage {
totalPages: 1, totalPages: 1,
startIndex: 1, startIndex: 1,
endIndex: res.length, endIndex: res.length,
next: 0,
previous: 0,
}, },
results: res, results: res,
}; };

View File

@ -49,6 +49,8 @@ export class MFADevicesPage extends Table<Device> {
totalPages: 1, totalPages: 1,
startIndex: 1, startIndex: 1,
endIndex: devices.length, endIndex: devices.length,
next: 0,
previous: 0,
}, },
results: devices, results: devices,
}; };