diff --git a/Pipfile.lock b/Pipfile.lock index b0f3d3d4f..bce7ec084 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -95,10 +95,10 @@ }, "autobahn": { "hashes": [ - "sha256:884f79c50fdc55ade2c315946a9caa145e8b10075eee9d2c2594ea5e8f5226aa", - "sha256:bf7a9d302a34d0f719d43c57f65ca1f2f5c982dd6ea0c11e1e190ef6f43710fe" + "sha256:9195df8af03b0ff29ccd4b7f5abbde957ee90273465942205f9a1bad6c3f07ac", + "sha256:e126c1f583e872fb59e79d36977cfa1f2d0a8a79f90ae31f406faae7664b8e03" ], - "version": "==21.2.2" + "version": "==21.3.1" }, "automat": { "hashes": [ @@ -116,18 +116,18 @@ }, "boto3": { "hashes": [ - "sha256:3570a3c0fbd80bcb30449f87cf9d2f7abb67fac2a5e317d002f9921c59be9b17", - "sha256:ceff2f32ba05acc9ee35a6dd82e29ea285d63e889bed39a6ba7a700146f43749" + "sha256:c9513a9ea00f8d17ecdc02c391ae956bf0f990aa07deec11c421607c09b294e1", + "sha256:f84ca60e9605af69022f039c035b33d519531eeaac52724b9223a5465f4a8b6b" ], "index": "pypi", - "version": "==1.17.18" + "version": "==1.17.19" }, "botocore": { "hashes": [ - "sha256:51900b10da4ae45be4b16045e5b2ff7d1158a7955d9d7cc5e5a9ba3170f10586", - "sha256:b181f32d9075e5419a89fa9636ce95946c15459c9bfadfabb53ca902fc8072b8" + "sha256:135b5f30e6662b46d804f993bf31d9c7769c6c0848321ed0aa0393f5b9c19a94", + "sha256:8e42c78d2eb888551635309158c04ef2648a96d8c2c70dbce7712c6ce8629759" ], - "version": "==1.20.18" + "version": "==1.20.19" }, "cachetools": { "hashes": [ @@ -1249,10 +1249,10 @@ }, "websocket-client": { "hashes": [ - "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549", - "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010" + "sha256:44b5df8f08c74c3d82d28100fdc81f4536809ce98a17f0757557813275fbb663", + "sha256:63509b41d158ae5b7f67eb4ad20fecbb4eee99434e73e140354dc3ff8e09716f" ], - "version": "==0.57.0" + "version": "==0.58.0" }, "websockets": { "hashes": [ diff --git a/authentik/admin/api/tasks.py b/authentik/admin/api/tasks.py index ddeed8fb9..d3abd5dea 100644 --- a/authentik/admin/api/tasks.py +++ b/authentik/admin/api/tasks.py @@ -7,14 +7,14 @@ from django.http.response import Http404 from django.utils.translation import gettext_lazy as _ from drf_yasg2.utils import swagger_auto_schema from rest_framework.decorators import action -from rest_framework.fields import CharField, DateTimeField, IntegerField, ListField +from rest_framework.fields import CharField, ChoiceField, DateTimeField, ListField from rest_framework.permissions import IsAdminUser from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import Serializer from rest_framework.viewsets import ViewSet -from authentik.events.monitored_tasks import TaskInfo +from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus class TaskSerializer(Serializer): @@ -24,7 +24,10 @@ class TaskSerializer(Serializer): task_description = CharField() task_finish_timestamp = DateTimeField(source="finish_timestamp") - status = IntegerField(source="result.status.value") + status = ChoiceField( + source="result.status.name", + choices=[(x.name, x.name) for x in TaskResultStatus], + ) messages = ListField(source="result.messages") def create(self, validated_data: dict) -> Model: diff --git a/authentik/admin/api/version.py b/authentik/admin/api/version.py index 9201b2369..2d7a941d0 100644 --- a/authentik/admin/api/version.py +++ b/authentik/admin/api/version.py @@ -55,7 +55,7 @@ class VersionViewSet(ListModelMixin, GenericViewSet): def get_queryset(self): # pragma: no cover return None - @swagger_auto_schema(responses={200: VersionSerializer(many=True)}) + @swagger_auto_schema(responses={200: VersionSerializer(many=False)}) def list(self, request: Request) -> Response: """Get running and latest version.""" return Response(VersionSerializer(True).data) diff --git a/authentik/api/pagination_schema.py b/authentik/api/pagination_schema.py new file mode 100644 index 000000000..057bd8b72 --- /dev/null +++ b/authentik/api/pagination_schema.py @@ -0,0 +1,97 @@ +"""Swagger Pagination Schema class""" +from typing import OrderedDict + +from drf_yasg2 import openapi +from drf_yasg2.inspectors import PaginatorInspector + + +class PaginationInspector(PaginatorInspector): + """Swagger Pagination Schema class""" + + def get_paginated_response(self, paginator, response_schema): + """ + :param BasePagination paginator: the paginator + :param openapi.Schema response_schema: the response schema that must be paged. + :rtype: openapi.Schema + """ + + return openapi.Schema( + type=openapi.TYPE_OBJECT, + properties=OrderedDict( + ( + ( + "pagination", + openapi.Schema( + type=openapi.TYPE_OBJECT, + properties=OrderedDict( + ( + ("next", openapi.Schema(type=openapi.TYPE_NUMBER)), + ( + "previous", + openapi.Schema(type=openapi.TYPE_NUMBER), + ), + ("count", openapi.Schema(type=openapi.TYPE_NUMBER)), + ( + "current", + openapi.Schema(type=openapi.TYPE_NUMBER), + ), + ( + "total_pages", + openapi.Schema(type=openapi.TYPE_NUMBER), + ), + ( + "start_index", + openapi.Schema(type=openapi.TYPE_NUMBER), + ), + ( + "end_index", + openapi.Schema(type=openapi.TYPE_NUMBER), + ), + ) + ), + required=[ + "next", + "previous", + "count", + "current", + "total_pages", + "start_index", + "end_index", + ], + ), + ), + ("results", response_schema), + ) + ), + required=["results", "pagination"], + ) + + def get_paginator_parameters(self, paginator): + """ + Get the pagination parameters for a single paginator **instance**. + + Should return :data:`.NotHandled` if this inspector + does not know how to handle the given `paginator`. + + :param BasePagination paginator: the paginator + :rtype: list[openapi.Parameter] + """ + + return [ + openapi.Parameter( + "page", + openapi.IN_QUERY, + "Page Index", + False, + None, + openapi.TYPE_INTEGER, + ), + openapi.Parameter( + "page_size", + openapi.IN_QUERY, + "Page Size", + False, + None, + openapi.TYPE_INTEGER, + ), + ] diff --git a/authentik/api/v2/config.py b/authentik/api/v2/config.py index 012f20574..82c055fcd 100644 --- a/authentik/api/v2/config.py +++ b/authentik/api/v2/config.py @@ -1,10 +1,11 @@ """core Configs API""" from django.db.models import Model from drf_yasg2.utils import swagger_auto_schema +from rest_framework.fields import BooleanField, CharField from rest_framework.permissions import AllowAny from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ReadOnlyField, Serializer +from rest_framework.serializers import Serializer from rest_framework.viewsets import ViewSet from authentik.lib.config import CONFIG @@ -13,12 +14,12 @@ from authentik.lib.config import CONFIG class ConfigSerializer(Serializer): """Serialize authentik Config into DRF Object""" - branding_logo = ReadOnlyField() - branding_title = ReadOnlyField() + branding_logo = CharField(read_only=True) + branding_title = CharField(read_only=True) - error_reporting_enabled = ReadOnlyField() - error_reporting_environment = ReadOnlyField() - error_reporting_send_pii = ReadOnlyField() + error_reporting_enabled = BooleanField(read_only=True) + error_reporting_environment = CharField(read_only=True) + error_reporting_send_pii = BooleanField(read_only=True) def create(self, validated_data: dict) -> Model: raise NotImplementedError @@ -32,7 +33,7 @@ class ConfigsViewSet(ViewSet): permission_classes = [AllowAny] - @swagger_auto_schema(responses={200: ConfigSerializer(many=True)}) + @swagger_auto_schema(responses={200: ConfigSerializer(many=False)}) def list(self, request: Request) -> Response: """Retrive public configuration options""" config = ConfigSerializer( diff --git a/authentik/api/v2/messages.py b/authentik/api/v2/messages.py deleted file mode 100644 index b2509559d..000000000 --- a/authentik/api/v2/messages.py +++ /dev/null @@ -1,37 +0,0 @@ -"""core messages API""" -from django.contrib.messages import get_messages -from django.db.models import Model -from drf_yasg2.utils import swagger_auto_schema -from rest_framework.permissions import AllowAny -from rest_framework.request import Request -from rest_framework.response import Response -from rest_framework.serializers import ReadOnlyField, Serializer -from rest_framework.viewsets import ViewSet - - -class MessageSerializer(Serializer): - """Serialize Django Message into DRF Object""" - - message = ReadOnlyField() - level = ReadOnlyField() - tags = ReadOnlyField() - extra_tags = ReadOnlyField() - level_tag = ReadOnlyField() - - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class MessagesViewSet(ViewSet): - """Read-only view set that returns the current session's messages""" - - permission_classes = [AllowAny] - - @swagger_auto_schema(responses={200: MessageSerializer(many=True)}) - def list(self, request: Request) -> Response: - """List current messages and pass into Serializer""" - all_messages = list(get_messages(request)) - return Response(MessageSerializer(all_messages, many=True).data) diff --git a/authentik/api/v2/urls.py b/authentik/api/v2/urls.py index b8d36666b..8ea2ec4ae 100644 --- a/authentik/api/v2/urls.py +++ b/authentik/api/v2/urls.py @@ -10,7 +10,6 @@ from authentik.admin.api.tasks import TaskViewSet from authentik.admin.api.version import VersionViewSet from authentik.admin.api.workers import WorkerViewSet from authentik.api.v2.config import ConfigsViewSet -from authentik.api.v2.messages import MessagesViewSet from authentik.core.api.applications import ApplicationViewSet from authentik.core.api.groups import GroupViewSet from authentik.core.api.propertymappings import PropertyMappingViewSet @@ -77,7 +76,6 @@ from authentik.stages.user_write.api import UserWriteStageViewSet router = routers.DefaultRouter() -router.register("root/messages", MessagesViewSet, basename="messages") router.register("root/config", ConfigsViewSet, basename="configs") router.register("admin/version", VersionViewSet, basename="admin_version") diff --git a/authentik/core/tasks.py b/authentik/core/tasks.py index aaf2c3aef..6a4072a66 100644 --- a/authentik/core/tasks.py +++ b/authentik/core/tasks.py @@ -46,8 +46,7 @@ def backup_database(self: MonitoredTask): # pragma: no cover TaskResult( TaskResultStatus.SUCCESSFUL, [ - f"Successfully finished database backup {naturaltime(start)}", - out.getvalue(), + f"Successfully finished database backup {naturaltime(start)} {out.getvalue()}", ], ) ) diff --git a/authentik/core/templates/user/settings.html b/authentik/core/templates/user/settings.html index 50f70d560..ff803e4be 100644 --- a/authentik/core/templates/user/settings.html +++ b/authentik/core/templates/user/settings.html @@ -13,7 +13,7 @@

{% trans "Configure settings relevant to your user profile." %}

- +
diff --git a/authentik/events/api/event.py b/authentik/events/api/event.py index 77a769a11..f2bd1e437 100644 --- a/authentik/events/api/event.py +++ b/authentik/events/api/event.py @@ -29,7 +29,7 @@ class EventSerializer(ModelSerializer): ] -class EventTopPerUserSerialier(Serializer): +class EventTopPerUserSerializer(Serializer): """Response object of Event's top_per_user""" application = DictField() @@ -60,7 +60,7 @@ class EventViewSet(ReadOnlyModelViewSet): filterset_fields = ["action"] @swagger_auto_schema( - method="GET", responses={200: EventTopPerUserSerialier(many=True)} + method="GET", responses={200: EventTopPerUserSerializer(many=True)} ) @action(detail=False, methods=["GET"]) def top_per_user(self, request: Request): diff --git a/authentik/outposts/controllers/kubernetes.py b/authentik/outposts/controllers/kubernetes.py index 8476187e0..2489f203d 100644 --- a/authentik/outposts/controllers/kubernetes.py +++ b/authentik/outposts/controllers/kubernetes.py @@ -5,6 +5,7 @@ from typing import Type from kubernetes.client import OpenApiException from kubernetes.client.api_client import ApiClient from structlog.testing import capture_logs +from urllib3.exceptions import HTTPError from yaml import dump_all from authentik.outposts.controllers.base import BaseController, ControllerException @@ -42,7 +43,7 @@ class KubernetesController(BaseController): reconciler = self.reconcilers[reconcile_key](self) reconciler.up() - except OpenApiException as exc: + except (OpenApiException, HTTPError) as exc: raise ControllerException from exc def up_with_logs(self) -> list[str]: @@ -54,7 +55,7 @@ class KubernetesController(BaseController): reconciler.up() all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs] return all_logs - except OpenApiException as exc: + except (OpenApiException, HTTPError) as exc: raise ControllerException from exc def down(self): diff --git a/authentik/root/settings.py b/authentik/root/settings.py index 6b9153b0a..3e1e534f2 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -139,6 +139,9 @@ GUARDIAN_MONKEY_PATCH = False SWAGGER_SETTINGS = { "DEFAULT_INFO": "authentik.api.v2.urls.info", + "DEFAULT_PAGINATOR_INSPECTORS": [ + "authentik.api.pagination_schema.PaginationInspector", + ], "SECURITY_DEFINITIONS": { "token": {"type": "apiKey", "name": "Authorization", "in": "header"} }, @@ -147,7 +150,6 @@ SWAGGER_SETTINGS = { REST_FRAMEWORK = { "DEFAULT_PAGINATION_CLASS": "authentik.api.pagination.Pagination", "PAGE_SIZE": 100, - "DATETIME_FORMAT": "%s", "DEFAULT_FILTER_BACKENDS": [ "rest_framework_guardian.filters.ObjectPermissionsFilter", "django_filters.rest_framework.DjangoFilterBackend", diff --git a/authentik/stages/authenticator_validate/forms.py b/authentik/stages/authenticator_validate/forms.py index 12e5ea97d..16223a326 100644 --- a/authentik/stages/authenticator_validate/forms.py +++ b/authentik/stages/authenticator_validate/forms.py @@ -1,9 +1,6 @@ """OTP Validate stage forms""" from django import forms -from django.utils.translation import gettext_lazy as _ -from django_otp import match_token -from authentik.core.models import User from authentik.flows.models import NotConfiguredAction from authentik.stages.authenticator_validate.models import ( AuthenticatorValidateStage, @@ -11,35 +8,6 @@ from authentik.stages.authenticator_validate.models import ( ) -class ValidationForm(forms.Form): - """OTP Validate stage forms""" - - user: User - - code = forms.CharField( - label=_("Please enter the token from your device."), - widget=forms.TextInput( - attrs={ - "autocomplete": "one-time-code", - "placeholder": "123456", - "autofocus": "autofocus", - } - ), - ) - - def __init__(self, user, *args, **kwargs): - super().__init__(*args, **kwargs) - self.user = user - - def clean_code(self): - """Validate code against all confirmed devices""" - code = self.cleaned_data.get("code") - device = match_token(self.user, code) - if not device: - raise forms.ValidationError(_("Invalid Token")) - return code - - class AuthenticatorValidateStageForm(forms.ModelForm): """OTP Validate stage forms""" diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 76f8c2bd5..c38dc075e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -378,8 +378,8 @@ stages: python ./scripts/az_do_set_branch.py - task: Docker@2 inputs: - containerRegistry: 'GHCR' - repository: 'beryju/authentik' + containerRegistry: 'beryjuorg-harbor' + repository: 'authentik/server' command: 'buildAndPush' Dockerfile: 'Dockerfile' tags: "gh-$(branchName)" diff --git a/outpost/azure-pipelines.yml b/outpost/azure-pipelines.yml index 87dfb1526..6dfb8a5d9 100644 --- a/outpost/azure-pipelines.yml +++ b/outpost/azure-pipelines.yml @@ -98,8 +98,8 @@ stages: python ./scripts/az_do_set_branch.py - task: Docker@2 inputs: - containerRegistry: 'GHCR' - repository: 'beryju/authentik-proxy' + containerRegistry: 'beryjuorg-harbor' + repository: 'authentik/proxy' command: 'buildAndPush' Dockerfile: 'outpost/proxy.Dockerfile' buildContext: 'outpost/' diff --git a/swagger.yaml b/swagger.yaml index 36a416513..25d5741ae 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -84,22 +84,19 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: '200': description: Get running and latest version. schema: - description: '' - type: array - items: - $ref: '#/definitions/Version' + $ref: '#/definitions/Version' tags: - admin parameters: [] @@ -120,12 +117,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -133,20 +130,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -173,12 +185,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -186,20 +198,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -331,12 +358,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -344,20 +371,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -478,12 +520,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -491,20 +533,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -639,12 +696,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -652,20 +709,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -721,12 +793,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -813,12 +885,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -826,20 +898,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -983,12 +1070,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -996,20 +1083,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -1039,12 +1141,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -1054,7 +1156,7 @@ paths: description: '' type: array items: - $ref: '#/definitions/EventTopPerUserSerialier' + $ref: '#/definitions/EventTopPerUser' tags: - events parameters: [] @@ -1119,12 +1221,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -1132,20 +1234,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -1230,12 +1347,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -1243,20 +1360,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -1357,12 +1489,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -1370,20 +1502,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -1550,12 +1697,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -1563,20 +1710,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -1697,12 +1859,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -1710,20 +1872,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -1784,12 +1961,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -1904,12 +2081,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -1917,20 +2094,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -2053,12 +2245,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2066,20 +2258,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -2184,12 +2391,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2197,20 +2404,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -2256,12 +2478,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2371,12 +2593,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2384,20 +2606,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -2498,12 +2735,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2511,20 +2748,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -2635,12 +2887,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2648,20 +2900,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -2696,12 +2963,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2739,12 +3006,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2819,12 +3086,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2832,20 +3099,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -2946,12 +3228,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -2959,20 +3241,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -3073,12 +3370,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -3086,20 +3383,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -3200,12 +3512,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -3213,20 +3525,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -3327,12 +3654,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -3340,20 +3667,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -3454,12 +3796,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -3467,20 +3809,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -3581,12 +3938,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -3594,20 +3951,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -3708,12 +4080,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -3721,20 +4093,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -3835,12 +4222,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -3848,20 +4235,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -3902,12 +4304,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -3915,20 +4317,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -4028,12 +4445,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -4041,20 +4458,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -4219,12 +4651,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -4232,20 +4664,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -4275,12 +4722,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -4330,12 +4777,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -4343,20 +4790,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -4457,12 +4919,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -4470,20 +4932,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -4584,12 +5061,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -4597,20 +5074,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -4716,12 +5208,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -4729,20 +5221,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -4788,12 +5295,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -4883,12 +5390,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -4896,20 +5403,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -5027,12 +5549,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5040,20 +5562,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -5153,12 +5690,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5166,20 +5703,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -5289,26 +5841,7 @@ paths: '200': description: Serialize authentik Config into DRF Object schema: - description: '' - type: array - items: - $ref: '#/definitions/Config' - tags: - - root - parameters: [] - /root/messages/: - get: - operationId: root_messages_list - description: List current messages and pass into Serializer - parameters: [] - responses: - '200': - description: Serialize Django Message into DRF Object - schema: - description: '' - type: array - items: - $ref: '#/definitions/Message' + $ref: '#/definitions/Config' tags: - root parameters: [] @@ -5329,12 +5862,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5342,20 +5875,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -5380,12 +5928,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5436,12 +5984,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5449,20 +5997,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -5584,12 +6147,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5597,20 +6160,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -5712,12 +6290,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5725,20 +6303,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -5865,12 +6458,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5878,20 +6471,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -5921,12 +6529,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5976,12 +6584,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -5989,20 +6597,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -6103,12 +6726,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -6116,20 +6739,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -6230,12 +6868,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -6243,20 +6881,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -6357,12 +7010,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -6370,20 +7023,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -6484,12 +7152,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -6497,20 +7165,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -6611,12 +7294,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -6624,20 +7307,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -6738,12 +7436,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -6751,20 +7449,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -6865,12 +7578,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -6878,20 +7591,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -6992,12 +7720,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -7005,20 +7733,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -7119,12 +7862,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -7132,20 +7875,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -7256,12 +8014,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -7269,20 +8027,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -7383,12 +8156,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -7396,20 +8169,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -7510,12 +8298,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -7523,20 +8311,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -7657,12 +8460,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -7670,20 +8473,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -7784,12 +8602,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -7797,20 +8615,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -7911,12 +8744,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -7924,20 +8757,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -8038,12 +8886,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -8051,20 +8899,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -8165,12 +9028,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -8178,20 +9041,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -8292,12 +9170,12 @@ paths: type: string - name: page in: query - description: A page number within the paginated result set. + description: Page Index required: false type: integer - name: page_size in: query - description: Number of results to return per page. + description: Page Size required: false type: integer responses: @@ -8305,20 +9183,35 @@ paths: description: '' schema: required: - - count - results + - pagination type: object properties: - count: - type: integer - next: - type: string - format: uri - x-nullable: true - previous: - type: string - format: uri - x-nullable: true + pagination: + required: + - next + - previous + - count + - current + - total_pages + - start_index + - end_index + 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 results: type: array items: @@ -8439,7 +9332,11 @@ definitions: format: date-time status: title: Status - type: integer + type: string + enum: + - SUCCESSFUL + - WARNING + - ERROR messages: description: '' type: array @@ -8810,7 +9707,7 @@ definitions: type: string format: date-time readOnly: true - EventTopPerUserSerialier: + EventTopPerUser: description: Response object of Event's top_per_user required: - application @@ -10915,45 +11812,24 @@ definitions: title: Branding logo type: string readOnly: true + minLength: 1 branding_title: title: Branding title type: string readOnly: true + minLength: 1 error_reporting_enabled: title: Error reporting enabled - type: string + type: boolean readOnly: true error_reporting_environment: title: Error reporting environment type: string readOnly: true + minLength: 1 error_reporting_send_pii: title: Error reporting send pii - type: string - readOnly: true - Message: - description: Serialize Django Message into DRF Object - type: object - properties: - message: - title: Message - type: string - readOnly: true - level: - title: Level - type: string - readOnly: true - tags: - title: Tags - type: string - readOnly: true - extra_tags: - title: Extra tags - type: string - readOnly: true - level_tag: - title: Level tag - type: string + type: boolean readOnly: true Source: description: Source Serializer diff --git a/web/azure-pipelines.yml b/web/azure-pipelines.yml index 0b9f3da8c..b09e9fe58 100644 --- a/web/azure-pipelines.yml +++ b/web/azure-pipelines.yml @@ -78,8 +78,8 @@ stages: python ./scripts/az_do_set_branch.py - task: Docker@2 inputs: - containerRegistry: 'GHCR' - repository: 'beryju/authentik-static' + containerRegistry: 'beryjuorg-harbor' + repository: 'authentik/static' command: 'buildAndPush' Dockerfile: 'web/Dockerfile' tags: "gh-$(branchName)" diff --git a/web/src/api/Client.ts b/web/src/api/Client.ts index 55c593759..6f6359d69 100644 --- a/web/src/api/Client.ts +++ b/web/src/api/Client.ts @@ -1,3 +1,5 @@ +import { gettext } from "django"; +import { showMessage } from "../elements/messages/MessageContainer"; import { getCookie } from "../utils"; import { NotFoundError, RequestError } from "./Error"; @@ -47,6 +49,13 @@ export class Client { } return r; }) + .catch((e) => { + showMessage({ + level_tag: "error", + message: gettext(`Unexpected error while fetching: ${e.toString()}`), + }); + return e; + }) .then((r) => r.json()) .then((r) => r); } diff --git a/web/src/elements/AdminLoginsChart.ts b/web/src/elements/AdminLoginsChart.ts index 63d1b3c35..2d82dbf27 100644 --- a/web/src/elements/AdminLoginsChart.ts +++ b/web/src/elements/AdminLoginsChart.ts @@ -1,16 +1,21 @@ import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import Chart from "chart.js"; -import { showMessage } from "./messages/MessageContainer"; +import { DefaultClient } from "../api/Client"; interface TickValue { value: number; major: boolean; } +export interface LoginMetrics { + logins_failed_per_1h: { x: number, y: number }[]; + logins_per_1h: { x: number, y: number }[]; +} + @customElement("ak-admin-logins-chart") export class AdminLoginsChart extends LitElement { - @property() - url = ""; + @property({type: Array}) + url: string[] = []; chart?: Chart; @@ -40,15 +45,7 @@ export class AdminLoginsChart extends LitElement { } firstUpdated(): void { - fetch(this.url) - .then((r) => r.json()) - .catch((e) => { - showMessage({ - level_tag: "error", - message: "Unexpected error" - }); - console.error(e); - }) + DefaultClient.fetch(this.url) .then((r) => { const canvas = this.shadowRoot?.querySelector("canvas"); if (!canvas) { diff --git a/web/src/elements/Tabs.ts b/web/src/elements/Tabs.ts index 1144e793c..814106eb4 100644 --- a/web/src/elements/Tabs.ts +++ b/web/src/elements/Tabs.ts @@ -12,10 +12,17 @@ export class Tabs extends LitElement { @property() currentPage?: string; + @property({type: Boolean}) + vertical = false; + static get styles(): CSSResult[] { return [GlobalsStyle, TabsStyle, css` ::slotted(*) { height: 100%; + flex-grow: 2; + } + :host([vertical]) { + display: flex; } `]; } @@ -39,7 +46,7 @@ export class Tabs extends LitElement { } this.currentPage = pages[0].attributes.getNamedItem("slot")?.value; } - return html`
+ return html`
    ${pages.map((page) => this.renderTab(page))}
diff --git a/web/src/elements/messages/MessageContainer.ts b/web/src/elements/messages/MessageContainer.ts index 9061a7e75..2f66d8721 100644 --- a/web/src/elements/messages/MessageContainer.ts +++ b/web/src/elements/messages/MessageContainer.ts @@ -1,6 +1,5 @@ import { gettext } from "django"; import { LitElement, html, customElement, TemplateResult, property } from "lit-element"; -import { DefaultClient } from "../../api/Client"; import "./Message"; import { APIMessage } from "./Message"; @@ -15,7 +14,6 @@ export function showMessage(message: APIMessage): void { @customElement("ak-message-container") export class MessageContainer extends LitElement { - url = DefaultClient.makeUrl(["root", "messages"]); @property({attribute: false}) messages: APIMessage[] = []; @@ -36,10 +34,6 @@ export class MessageContainer extends LitElement { } } - firstUpdated(): void { - this.fetchMessages(); - } - connect(): void { const wsUrl = `${window.location.protocol.replace("http", "ws")}//${ window.location.host @@ -74,21 +68,6 @@ export class MessageContainer extends LitElement { }); } - /* Fetch messages which were stored in the session. - * This mostly gets messages which were created when the user arrives/leaves the site - * and especially the login flow */ - fetchMessages(): Promise { - console.debug("authentik/messages: fetching messages over direct api"); - return fetch(this.url) - .then((r) => r.json()) - .then((r: APIMessage[]) => { - r.forEach((m: APIMessage) => { - this.messages.push(m); - this.requestUpdate(); - }); - }); - } - render(): TemplateResult { return html`
    ${this.messages.map((m) => { diff --git a/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStage.ts b/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStage.ts index e9acacf76..a342c9c28 100644 --- a/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStage.ts +++ b/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStage.ts @@ -119,13 +119,15 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost { return html` + .deviceChallenge=${this.selectedDeviceChallenge} + .showBackButton=${(this.challenge?.device_challenges.length || []) > 1}> `; case DeviceClasses.WEBAUTHN: return html` + .deviceChallenge=${this.selectedDeviceChallenge} + .showBackButton=${(this.challenge?.device_challenges.length || []) > 1}> `; } } diff --git a/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStageCode.ts b/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStageCode.ts index 712c9677b..af7442b20 100644 --- a/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStageCode.ts +++ b/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStageCode.ts @@ -14,6 +14,9 @@ export class AuthenticatorValidateStageWebCode extends BaseStage { @property({ attribute: false }) deviceChallenge?: DeviceChallenge; + @property({ type: Boolean }) + showBackButton = false; + static get styles(): CSSResult[] { return COMMON_STYLES; } @@ -61,14 +64,16 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
`; } diff --git a/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts b/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts index 276352e15..089e47a73 100644 --- a/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts +++ b/web/src/elements/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts @@ -21,6 +21,9 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage { @property() authenticateMessage = ""; + @property({type: Boolean}) + showBackButton = false; + static get styles(): CSSResult[] { return COMMON_STYLES; } @@ -98,14 +101,16 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage {
`; } diff --git a/web/src/pages/admin-overview/AdminOverviewPage.ts b/web/src/pages/admin-overview/AdminOverviewPage.ts index 49df2ab09..5d902c2af 100644 --- a/web/src/pages/admin-overview/AdminOverviewPage.ts +++ b/web/src/pages/admin-overview/AdminOverviewPage.ts @@ -1,6 +1,5 @@ import { gettext } from "django"; import { CSSResult, customElement, html, LitElement, TemplateResult } from "lit-element"; -import { DefaultClient } from "../../api/Client"; import { COMMON_STYLES } from "../../common/styles"; import "../../elements/AdminLoginsChart"; @@ -31,7 +30,7 @@ export class AdminOverviewPage extends LitElement {
diff --git a/website/docs/expressions/index.md b/website/docs/expressions/index.md index 04876de6c..ca305aab9 100644 --- a/website/docs/expressions/index.md +++ b/website/docs/expressions/index.md @@ -12,8 +12,8 @@ These functions/objects are available wherever expressions are used. For more sp ## Global objects -- `ak_logger`: structlog BoundLogger. ([ref](https://www.structlog.org/en/stable/api.html#structlog.BoundLogger)) -- `requests`: requests Session object. ([ref](https://requests.readthedocs.io/en/master/user/advanced/)) +- `ak_logger`: structlog BoundLogger. ([ref](https://www.structlog.org/en/stable/api.html#structlog.BoundLogger)) +- `requests`: requests Session object. ([ref](https://requests.readthedocs.io/en/master/user/advanced/)) ## Generally available functions diff --git a/website/docs/expressions/reference/user-object.md b/website/docs/expressions/reference/user-object.md index 6563f429e..7f2ab93a0 100644 --- a/website/docs/expressions/reference/user-object.md +++ b/website/docs/expressions/reference/user-object.md @@ -4,16 +4,16 @@ title: User Object The User object has the following attributes: -- `username`: User's username. -- `email` User's email. -- `name` User's display name. -- `is_staff` Boolean field if user is staff. -- `is_active` Boolean field if user is active. -- `date_joined` Date user joined/was created. -- `password_change_date` Date password was last changed. -- `attributes` Dynamic attributes. -- `group_attributes` Merged attributes of all groups the user is member of and the user's own attributes. -- `ak_groups` This is a queryset of all the user's groups. +- `username`: User's username. +- `email` User's email. +- `name` User's display name. +- `is_staff` Boolean field if user is staff. +- `is_active` Boolean field if user is active. +- `date_joined` Date user joined/was created. +- `password_change_date` Date password was last changed. +- `attributes` Dynamic attributes. +- `group_attributes` Merged attributes of all groups the user is member of and the user's own attributes. +- `ak_groups` This is a queryset of all the user's groups. You can do additional filtering like `user.ak_groups.filter(name__startswith='test')`, see [here](https://docs.djangoproject.com/en/3.1/ref/models/querysets/#id4) diff --git a/website/docs/flow/stages/authenticator_static/index.md b/website/docs/flow/stages/authenticator_static/index.md index ee43781d6..03d8fd8ef 100644 --- a/website/docs/flow/stages/authenticator_static/index.md +++ b/website/docs/flow/stages/authenticator_static/index.md @@ -1,5 +1,5 @@ --- -title: Static Authenticator stage +title: Static Authentication Setup stage --- This stage configures static OTP Tokens, which can be used as a backup method to time-based OTP tokens. diff --git a/website/docs/flow/stages/authenticator_totp/index.md b/website/docs/flow/stages/authenticator_totp/index.md index 6d4961144..03410e013 100644 --- a/website/docs/flow/stages/authenticator_totp/index.md +++ b/website/docs/flow/stages/authenticator_totp/index.md @@ -1,7 +1,7 @@ --- -title: TOTP stage +title: TOTP Authentication Setup stage --- This stage configures a time-based OTP Device, such as Google Authenticator or Authy. -You can configure how many digest should be used for the OTP Token. +You can configure how many digits should be used for the OTP Token. diff --git a/website/docs/flow/stages/authenticator_validate/index.md b/website/docs/flow/stages/authenticator_validate/index.md index 9dffa3dc1..05b714b9c 100644 --- a/website/docs/flow/stages/authenticator_validate/index.md +++ b/website/docs/flow/stages/authenticator_validate/index.md @@ -2,7 +2,16 @@ title: Authenticator Validation Stage --- -This stage validates an already configured OTP Device. This device has to be configured using any of the other authenticator stages: +This stage validates an already configured Authenticator Device. This device has to be configured using any of the other authenticator stages: - [TOTP authenticator stage](../authenticator_totp/index.md) - [Static authenticator stage](../authenticator_static/index.md). +- [WebAuth authenticator stage](../authenticator_webauthn/index.md). + +You can select which type of device classes are allowed. + +Using the `Not configured action`, you can choose what happens when a user does not have any matching devices. + +- Skip: Validation is skipped and the flow continues +- Deny: Access is denied, the flow execution ends +- Configure: This option requires a *Configuration stage* to be set. The validation stage will be marked as successful, and the configuration stage will be injected into the flow. diff --git a/website/docs/flow/stages/authenticator_webauthn/index.md b/website/docs/flow/stages/authenticator_webauthn/index.md new file mode 100644 index 000000000..15369cfbe --- /dev/null +++ b/website/docs/flow/stages/authenticator_webauthn/index.md @@ -0,0 +1,7 @@ +--- +title: WebAuthn Authentication Setup stage +--- + +This stage configures a WebAuthn-based Authenticator. This can either be a browser, biometrics or a Security stick like a YubiKey. + +There are no stage-specific settings. diff --git a/website/docs/flow/stages/captcha/captcha-admin.png b/website/docs/flow/stages/captcha/captcha-admin.png index f33a52972..41cee855f 100644 Binary files a/website/docs/flow/stages/captcha/captcha-admin.png and b/website/docs/flow/stages/captcha/captcha-admin.png differ diff --git a/website/docs/flow/stages/deny.md b/website/docs/flow/stages/deny.md new file mode 100644 index 000000000..f5877336a --- /dev/null +++ b/website/docs/flow/stages/deny.md @@ -0,0 +1,10 @@ +--- +title: Deny stage +--- + +This stage stops the execution of a flow. This can be used to conditionally deny users access to a flow, +even if they are not signed in (and permissions can't be checked via groups). + +:::caution +To effectively use this stage, make sure to **disable** *Evaluate on plan* on the Stage binding. +::: diff --git a/website/docs/flow/stages/identification/index.md b/website/docs/flow/stages/identification/index.md index facbb6c65..3ce5ec69e 100644 --- a/website/docs/flow/stages/identification/index.md +++ b/website/docs/flow/stages/identification/index.md @@ -11,8 +11,8 @@ This stage provides a ready-to-go form for users to identify themselves. Select which fields the user can use to identify themselves. Multiple fields can be specified and separated with a comma. Valid choices: -- email -- username +- email +- username ### Template diff --git a/website/docs/integrations/services/apache-guacamole/index.mdx b/website/docs/integrations/services/apache-guacamole/index.mdx new file mode 100644 index 000000000..d3bc40130 --- /dev/null +++ b/website/docs/integrations/services/apache-guacamole/index.mdx @@ -0,0 +1,62 @@ +--- +title: Apache Guacamole™ +--- + +## What is Apache Guacamole™ + +From https://guacamole.apache.org/ + +:::note +Apache Guacamole is a clientless remote desktop gateway. It supports standard protocols like VNC, RDP, and SSH. +::: + +## Preparation + +The following placeholders will be used: + +- `guacamole.company` is the FQDN of the Guacamole install. +- `authentik.company` is the FQDN of the authentik install. + +Create an OAuth2/OpenID provider with the following parameters: + +- Client Type: `Confidential` +- JWT Algorithm: `RS256` +- Redirect URIs: `https://guacamole.company/` (depending on your Tomcat setup, you might have to add `/guacamole/` if the application runs in a subfolder) +- Scopes: OpenID, Email and Profile + +Note the Client ID value. Create an application, using the provider you've created above. + +## Guacamole + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + The docker containers are configured via environment variables. The following variables are required: + +```yaml +OPENID_AUTHORIZATION_ENDPOINT: https://authentik.company/application/o/authorize/ +OPENID_CLIENT_ID: # client ID from above +OPENID_ISSUER: https://authentik.company/application/o/apache-guacamole/ +OPENID_JWKS_ENDPOINT: https://authentik.company/application/o/apache-guacamole/jwks/ +OPENID_REDIRECT_URI: https://guacamole.company/ # This must match the redirect URI above +``` + + + Standalone Guacamole is configured using the `guacamole.properties` file. Add the following settings: + +``` +openid-authorization-endpoint=https://authentik.company/application/o/authorize/ +openid-client-id=# client ID from above +openid-issuer=https://authentik.company/application/o/apache-guacamole/ +openid-jwks-endpoint=https://authentik.company/application/o/apache-guacamole/jwks/ +openid-redirect-uri=https://guacamole.company/ # This must match the redirect URI above +``` + + diff --git a/website/docs/integrations/services/aws/index.md b/website/docs/integrations/services/aws/index.md index 95ae45bfc..4d2d5060d 100644 --- a/website/docs/integrations/services/aws/index.md +++ b/website/docs/integrations/services/aws/index.md @@ -12,14 +12,14 @@ Amazon Web Services (AWS) is the world’s most comprehensive and broadly adopte The following placeholders will be used: -- `authentik.company` is the FQDN of the authentik install. +- `authentik.company` is the FQDN of the authentik install. Create an application in authentik and note the slug, as this will be used later. Create a SAML provider with the following parameters: -- ACS URL: `https://signin.aws.amazon.com/saml` -- Audience: `urn:amazon:webservices` -- Issuer: `authentik` -- Binding: `Post` +- ACS URL: `https://signin.aws.amazon.com/saml` +- Audience: `urn:amazon:webservices` +- Issuer: `authentik` +- Binding: `Post` You can of course use a custom signing certificate, and adjust durations. diff --git a/website/docs/integrations/services/awx-tower/index.md b/website/docs/integrations/services/awx-tower/index.md index c566c7b6e..7176db458 100644 --- a/website/docs/integrations/services/awx-tower/index.md +++ b/website/docs/integrations/services/awx-tower/index.md @@ -20,15 +20,15 @@ AWX is the open-source version of Tower. The term "AWX" will be used interchange The following placeholders will be used: -- `awx.company` is the FQDN of the AWX/Tower install. -- `authentik.company` is the FQDN of the authentik install. +- `awx.company` is the FQDN of the AWX/Tower install. +- `authentik.company` is the FQDN of the authentik install. Create an application in authentik and note the slug, as this will be used later. Create a SAML provider with the following parameters: -- ACS URL: `https://awx.company/sso/complete/saml/` -- Audience: `awx` -- Service Provider Binding: Post -- Issuer: `https://awx.company/sso/metadata/saml/` +- ACS URL: `https://awx.company/sso/complete/saml/` +- Audience: `awx` +- Service Provider Binding: Post +- Issuer: `https://awx.company/sso/metadata/saml/` You can of course use a custom signing certificate, and adjust durations. diff --git a/website/docs/integrations/services/gitlab/index.md b/website/docs/integrations/services/gitlab/index.md index 097769ef4..4ff1177f4 100644 --- a/website/docs/integrations/services/gitlab/index.md +++ b/website/docs/integrations/services/gitlab/index.md @@ -14,15 +14,15 @@ GitLab is a complete DevOps platform, delivered as a single application. This ma The following placeholders will be used: -- `gitlab.company` is the FQDN of the GitLab Install -- `authentik.company` is the FQDN of the authentik Install +- `gitlab.company` is the FQDN of the GitLab Install +- `authentik.company` is the FQDN of the authentik Install Create an application in authentik and note the slug, as this will be used later. Create a SAML provider with the following parameters: -- ACS URL: `https://gitlab.company/users/auth/saml/callback` -- Audience: `https://gitlab.company` -- Issuer: `https://gitlab.company` -- Binding: `Post` +- ACS URL: `https://gitlab.company/users/auth/saml/callback` +- Audience: `https://gitlab.company` +- Issuer: `https://gitlab.company` +- Binding: `Post` You can of course use a custom signing certificate, and adjust durations. To get the value for `idp_cert_fingerprint`, you can use a tool like [this](https://www.samltool.com/fingerprint.php). diff --git a/website/docs/integrations/services/grafana/index.md b/website/docs/integrations/services/grafana/index.mdx similarity index 78% rename from website/docs/integrations/services/grafana/index.md rename to website/docs/integrations/services/grafana/index.mdx index 03ca9253d..eae0227cb 100644 --- a/website/docs/integrations/services/grafana/index.md +++ b/website/docs/integrations/services/grafana/index.mdx @@ -14,21 +14,31 @@ Grafana is a multi-platform open source analytics and interactive visualization The following placeholders will be used: -- `grafana.company` is the FQDN of the Grafana install. -- `authentik.company` is the FQDN of the authentik install. +- `grafana.company` is the FQDN of the Grafana install. +- `authentik.company` is the FQDN of the authentik install. Create an application in authentik. Create an OAuth2/OpenID provider with the following parameters: -- Client Type: `Confidential` -- JWT Algorithm: `RS256` -- Scopes: OpenID, Email and Profile -- RSA Key: Select any available key -- Redirect URIs: `https://grafana.company/login/generic_oauth` +- Client Type: `Confidential` +- JWT Algorithm: `RS256` +- Scopes: OpenID, Email and Profile +- RSA Key: Select any available key +- Redirect URIs: `https://grafana.company/login/generic_oauth` Note the Client ID and Client Secret values. Create an application, using the provider you've created above. Note the slug of the application you've created. ## Grafana +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + If your Grafana is running in docker, set the following environment variables: ```yaml @@ -45,7 +55,8 @@ environment: # Optionally enable auto-login GF_AUTH_OAUTH_AUTO_LOGIN: "true" ``` - + + If you are using a config-file instead, you have to set these options: ```ini @@ -64,3 +75,5 @@ auth_url = https://authentik.company/application/o/authorize/ token_url = https://authentik.company/application/o/token/ api_url = https://authentik.company/application/o/userinfo/ ``` + + diff --git a/website/docs/integrations/services/harbor/harbor.png b/website/docs/integrations/services/harbor/harbor.png index df8434f48..fd36b209b 100644 Binary files a/website/docs/integrations/services/harbor/harbor.png and b/website/docs/integrations/services/harbor/harbor.png differ diff --git a/website/docs/integrations/services/harbor/index.md b/website/docs/integrations/services/harbor/index.md index f1a5c40af..5bd445863 100644 --- a/website/docs/integrations/services/harbor/index.md +++ b/website/docs/integrations/services/harbor/index.md @@ -14,15 +14,15 @@ Harbor is an open source container image registry that secures images with role- The following placeholders will be used: -- `harbor.company` is the FQDN of the Harbor install. -- `authentik.company` is the FQDN of the authentik install. +- `harbor.company` is the FQDN of the Harbor install. +- `authentik.company` is the FQDN of the authentik install. Create an OAuth2/OpenID provider with the following parameters: -- Client Type: `Confidential` -- JWT Algorithm: `RS256` -- Redirect URIs: `https://harbor.company/c/oidc/callback` -- Scopes: OpenID, Email and Profile +- Client Type: `Confidential` +- JWT Algorithm: `RS256` +- Redirect URIs: `https://harbor.company/c/oidc/callback` +- Scopes: OpenID, Email and Profile Note the Client ID and Client Secret values. Create an application, using the provider you've created above. diff --git a/website/docs/integrations/services/home-assistant/index.md b/website/docs/integrations/services/home-assistant/index.md index 4546e0e21..1275e5b71 100644 --- a/website/docs/integrations/services/home-assistant/index.md +++ b/website/docs/integrations/services/home-assistant/index.md @@ -14,8 +14,8 @@ Open source home automation that puts local control and privacy first. Powered b The following placeholders will be used: -- `hass.company` is the FQDN of the Home-Assistant install. -- `authentik.company` is the FQDN of the authentik install. +- `hass.company` is the FQDN of the Home-Assistant install. +- `authentik.company` is the FQDN of the authentik install. :::note This setup uses https://github.com/BeryJu/hass-auth-header and the authentik proxy for authentication. When this [PR](https://github.com/home-assistant/core/pull/32926) is merged, this will no longer be necessary. @@ -42,13 +42,13 @@ additionalHeaders: Create a Proxy Provider with the following values -- Internal host +- Internal host If Home-Assistant is running in docker, and you're deploying the authentik proxy on the same host, set the value to `http://homeassistant:8123`, where Home-Assistant is the name of your container. If Home-Assistant is running on a different server than where you are deploying the authentik proxy, set the value to `http://hass.company:8123`. -- External host +- External host Set this to the external URL you will be accessing Home-Assistant from. diff --git a/website/docs/integrations/services/nextcloud/index.md b/website/docs/integrations/services/nextcloud/index.md index 08e2ec4ce..621912f1d 100644 --- a/website/docs/integrations/services/nextcloud/index.md +++ b/website/docs/integrations/services/nextcloud/index.md @@ -22,17 +22,17 @@ In case something goes wrong with the configuration, you can use the URL `http:/ The following placeholders will be used: -- `nextcloud.company` is the FQDN of the NextCloud install. -- `authentik.company` is the FQDN of the authentik install. +- `nextcloud.company` is the FQDN of the NextCloud install. +- `authentik.company` is the FQDN of the authentik install. Create an application in authentik and note the slug, as this will be used later. Create a SAML provider with the following parameters: -- ACS URL: `https://nextcloud.company/apps/user_saml/saml/acs` -- Issuer: `https://authentik.company` -- Service Provider Binding: `Post` -- Audience: `https://nextcloud.company/apps/user_saml/saml/metadata` -- Signing Keypair: Select any certificate you have. -- Property mappings: Select all Managed mappings. +- ACS URL: `https://nextcloud.company/apps/user_saml/saml/acs` +- Issuer: `https://authentik.company` +- Service Provider Binding: `Post` +- Audience: `https://nextcloud.company/apps/user_saml/saml/metadata` +- Signing Keypair: Select any certificate you have. +- Property mappings: Select all Managed mappings. You can of course use a custom signing certificate, and adjust durations. diff --git a/website/docs/integrations/services/sentry/index.md b/website/docs/integrations/services/sentry/index.md index ce318683b..833742917 100644 --- a/website/docs/integrations/services/sentry/index.md +++ b/website/docs/integrations/services/sentry/index.md @@ -18,16 +18,16 @@ better software faster with Sentry. Won’t you join them? The following placeholders will be used: -- `sentry.company` is the FQDN of the Sentry install. -- `authentik.company` is the FQDN of the authentik install. +- `sentry.company` is the FQDN of the Sentry install. +- `authentik.company` is the FQDN of the authentik install. Create an application in authentik. Create a SAML Provider with the following values -- ACS URL: `https://sentry.company/saml/acs//` -- Audience: `https://sentry.company/saml/metadata//` -- Issuer: `authentik` -- Service Provider Binding: `Post` -- Property Mapping: Select all Managed Mappings +- ACS URL: `https://sentry.company/saml/acs//` +- Audience: `https://sentry.company/saml/metadata//` +- Issuer: `authentik` +- Service Provider Binding: `Post` +- Property Mapping: Select all Managed Mappings ## Sentry diff --git a/website/docs/integrations/services/sonarr/index.md b/website/docs/integrations/services/sonarr/index.md index d3144c95e..26dbb8911 100644 --- a/website/docs/integrations/services/sonarr/index.md +++ b/website/docs/integrations/services/sonarr/index.md @@ -20,18 +20,18 @@ Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS fee The following placeholders will be used: -- `sonarr.company` is the FQDN of the Sonarr install. -- `authentik.company` is the FQDN of the authentik install. +- `sonarr.company` is the FQDN of the Sonarr install. +- `authentik.company` is the FQDN of the authentik install. Create a Proxy Provider with the following values -- Internal host +- Internal host If Sonarr is running in docker, and you're deploying the authentik proxy on the same host, set the value to `http://sonarr:8989`, where sonarr is the name of your container. If Sonarr is running on a different server than where you are deploying the authentik proxy, set the value to `http://sonarr.company:8989`. -- External host +- External host Set this to the external URL you will be accessing Sonarr from. diff --git a/website/docs/integrations/services/tautulli/index.md b/website/docs/integrations/services/tautulli/index.md index 32d472d46..ec26ab525 100644 --- a/website/docs/integrations/services/tautulli/index.md +++ b/website/docs/integrations/services/tautulli/index.md @@ -14,8 +14,8 @@ Tautulli is a 3rd party application that you can run alongside your Plex Media S The following placeholders will be used: -- `tautulli.company` is the FQDN of the Tautulli install. -- `authentik.company` is the FQDN of the authentik install. +- `tautulli.company` is the FQDN of the Tautulli install. +- `authentik.company` is the FQDN of the authentik install. ## authentik Setup @@ -30,13 +30,13 @@ Add all Tautulli users to the Group. You should also create a Group Membership P Create an application in authentik. Create a Proxy provider with the following parameters: -- Internal host +- Internal host If Tautulli is running in docker, and you're deploying the authentik proxy on the same host, set the value to `http://tautulli:3579`, where tautulli is the name of your container. If Tautulli is running on a different server to where you are deploying the authentik proxy, set the value to `http://tautulli.company:3579`. -- External host +- External host Set this to the external URL you will be accessing Tautulli from. diff --git a/website/docs/integrations/services/ubuntu-landscape/index.md b/website/docs/integrations/services/ubuntu-landscape/index.md index 42f789356..a05c4ca15 100644 --- a/website/docs/integrations/services/ubuntu-landscape/index.md +++ b/website/docs/integrations/services/ubuntu-landscape/index.md @@ -18,8 +18,8 @@ This requires authentik 0.10.3 or newer. The following placeholders will be used: -- `landscape.company` is the FQDN of the Landscape server. -- `authentik.company` is the FQDN of the authentik install. +- `landscape.company` is the FQDN of the Landscape server. +- `authentik.company` is the FQDN of the authentik install. Landscape uses the OpenID-Connect Protocol for single-sign on. diff --git a/website/docs/integrations/services/veeam-enterprise-manager/index.md b/website/docs/integrations/services/veeam-enterprise-manager/index.md index f709dc03b..e4333a565 100644 --- a/website/docs/integrations/services/veeam-enterprise-manager/index.md +++ b/website/docs/integrations/services/veeam-enterprise-manager/index.md @@ -14,8 +14,8 @@ Veeam Backup Enterprise Manager (Enterprise Manager) is a management and reporti The following placeholders will be used: -- `veeam.company` is the FQDN of the Veeam Enterprise Manager install. -- `authentik.company` is the FQDN of the authentik install. +- `veeam.company` is the FQDN of the Veeam Enterprise Manager install. +- `authentik.company` is the FQDN of the authentik install. You will need an existing group or multiple in authentik to assign roles in Veeam Enterprise Manager to. diff --git a/website/docs/integrations/services/vmware-vcenter/index.md b/website/docs/integrations/services/vmware-vcenter/index.md index 9774325e3..2597f5ddc 100644 --- a/website/docs/integrations/services/vmware-vcenter/index.md +++ b/website/docs/integrations/services/vmware-vcenter/index.md @@ -26,8 +26,8 @@ It seems that the vCenter still needs to be joined to the Active Directory Domai The following placeholders will be used: -- `vcenter.company` is the FQDN of the vCenter server. -- `authentik.company` is the FQDN of the authentik install. +- `vcenter.company` is the FQDN of the vCenter server. +- `authentik.company` is the FQDN of the authentik install. Since vCenter only allows OpenID-Connect in combination with Active Directory, it is recommended to have authentik sync with the same Active Directory. @@ -53,11 +53,11 @@ Under _Sources_, click _Edit_ and ensure that "authentik default Active Director Under _Providers_, create an OAuth2/OpenID provider with these settings: -- Client Type: Confidential -- JWT Algorithm: RS256 -- Redirect URI: `https://vcenter.company/ui/login/oauth2/authcode` -- Sub Mode: If your Email address Schema matches your UPN, select "Based on the User's Email...", otherwise select "Based on the User's UPN...". -- Scopes: Select the Scope Mapping you've created in Step 1 +- Client Type: Confidential +- JWT Algorithm: RS256 +- Redirect URI: `https://vcenter.company/ui/login/oauth2/authcode` +- Sub Mode: If your Email address Schema matches your UPN, select "Based on the User's Email...", otherwise select "Based on the User's UPN...". +- Scopes: Select the Scope Mapping you've created in Step 1 ![](./authentik_setup.png) diff --git a/website/docs/integrations/services/wiki-js/authentik_application.png b/website/docs/integrations/services/wiki-js/authentik_application.png new file mode 100644 index 000000000..3f2a843a7 Binary files /dev/null and b/website/docs/integrations/services/wiki-js/authentik_application.png differ diff --git a/website/docs/integrations/services/wiki-js/authentik_provider.png b/website/docs/integrations/services/wiki-js/authentik_provider.png new file mode 100644 index 000000000..d33301f9a Binary files /dev/null and b/website/docs/integrations/services/wiki-js/authentik_provider.png differ diff --git a/website/docs/integrations/services/wiki-js/index.md b/website/docs/integrations/services/wiki-js/index.md new file mode 100644 index 000000000..bff6cd460 --- /dev/null +++ b/website/docs/integrations/services/wiki-js/index.md @@ -0,0 +1,72 @@ +--- +title: Wiki.js +--- + +## What is Wiki.js + +From https://en.wikipedia.org/wiki/Wiki.js + +:::note +Wiki.js is a wiki engine running on Node.js and written in JavaScript. It is free software released under the Affero GNU General Public License. It is available as a self-hosted solution or using "single-click" install on the DigitalOcean and AWS marketplace. +::: + +:::note +This is based on authentik 2021.3 and Wiki.js 2.5. Instructions may differ between versions. +::: + +## Preparation + +The following placeholders will be used: + +- `wiki.company` is the FQDN of Wiki.js. +- `authentik.company` is the FQDN of authentik. + +### Step 1 + +In Wiki.js, navigate to the _Authentication_ section in the _Administration_ interface. + +Add a _Generic OpenID Connect / OAuth2_ strategy and note the _Callback URL / Redirect URI_ in the _Configuration Reference_ section at the bottom. + +### Step 2 + +In authentik, under _Providers_, create an _OAuth2/OpenID Provider_ with these settings: + +- Client Type: Confidential +- JWT Algorithm: RS256 +- Redirect URI: The _Callback URL / Redirect URI_ you noted from the previous step. +- Scopes: Default OAUth mappings for: OpenID, email, profile. +- RSA Key: Choose a certificate. +- Sub Mode: Based on username. + +Note the _client ID_ and _client secret_, then save the provider. If you need to retrieve these values, you can do so by editing the provider. + +![](./authentik_provider.png) + +### Step 3 + +In Wiki.js, configure the authentication strategy with these settings: + +- Client ID: Client ID from the authentik provider. +- Client Secret: Client Secret from the authentik provider. +- Authorization Endpoint URL: https://authentik.company/application/o/authorize/ +- Token Endpoint URL: https://authentik.company/application/o/token/ +- User Info Endpont URL: https://authentik.company/application/o/userinfo/ +- Issuer: https://authentik.company/application/o/wikijs/ +- Logout URL: https://authentik.company/application/o/wikijs/end-session/ +- Allow self-registration: Enabled +- Assign to group: The group to which new users logging in from authentik should be assigned. + +![](./wiki-js_strategy.png) + +:::note +You do not have to enable "Allow self-registration" and select a group to which new users should be assigned, but if you don't you will have to manually provision users in Wiki.js and ensure that their usernames match the username they have in authentik. +::: + +### Step 5 + +In authentik, create an application which uses this provider. Optionally apply access restrictions to the application using policy bindings. + +Set the Launch URL to the _Callback URL / Redirect URI_ without the `/callback` at the end, as shown below. This will skip Wiki.js' login prompt and log you in directly. + +![](./authentik_application.png) + diff --git a/website/docs/integrations/services/wiki-js/wiki-js_strategy.png b/website/docs/integrations/services/wiki-js/wiki-js_strategy.png new file mode 100644 index 000000000..6d8e7dd29 Binary files /dev/null and b/website/docs/integrations/services/wiki-js/wiki-js_strategy.png differ diff --git a/website/docs/integrations/sources/active-directory/index.md b/website/docs/integrations/sources/active-directory/index.md index 4d2cbe6b0..78fd8e3db 100644 --- a/website/docs/integrations/sources/active-directory/index.md +++ b/website/docs/integrations/sources/active-directory/index.md @@ -6,8 +6,8 @@ title: Active Directory The following placeholders will be used: -- `ad.company` is the Name of the Active Directory domain. -- `authentik.company` is the FQDN of the authentik install. +- `ad.company` is the Name of the Active Directory domain. +- `authentik.company` is the FQDN of the authentik install. ## Active Directory Setup @@ -33,25 +33,25 @@ In authentik, create a new LDAP Source in Administration -> Sources. Use these settings: -- Server URI: `ldap://ad.company` +- Server URI: `ldap://ad.company` For authentik to be able to write passwords back to Active Directory, make sure to use `ldaps://` -- Bind CN: `@ad.company` -- Bind Password: The password you've given the user above -- Base DN: The base DN which you want authentik to sync -- Property mappings: Control/Command-select all Mappings which start with "authentik default LDAP" and "authentik default Active Directory" -- Group property mappings: Select "authentik default LDAP Mapping: Name" +- Bind CN: `@ad.company` +- Bind Password: The password you've given the user above +- Base DN: The base DN which you want authentik to sync +- Property mappings: Control/Command-select all Mappings which start with "authentik default LDAP" and "authentik default Active Directory" +- Group property mappings: Select "authentik default LDAP Mapping: Name" The other settings might need to be adjusted based on the setup of your domain. -- Addition User/Group DN: Additional DN which is _prepended_ to your Base DN for user synchronization. -- Addition Group DN: Additional DN which is _prepended_ to your Base DN for group synchronization. -- User object filter: Which objects should be considered users. -- Group object filter: Which objects should be considered groups. -- Group membership field: Which user field saves the group membership -- Object uniqueness field: A user field which contains a unique Identifier -- Sync parent group: If enabled, all synchronized groups will be given this group as a parent. +- Addition User/Group DN: Additional DN which is _prepended_ to your Base DN for user synchronization. +- Addition Group DN: Additional DN which is _prepended_ to your Base DN for group synchronization. +- User object filter: Which objects should be considered users. +- Group object filter: Which objects should be considered groups. +- Group membership field: Which user field saves the group membership +- Object uniqueness field: A user field which contains a unique Identifier +- Sync parent group: If enabled, all synchronized groups will be given this group as a parent. After you save the source, a synchronization will start in the background. When its done, you cen see the summary on the System Tasks page. diff --git a/website/docs/outposts/outposts.md b/website/docs/outposts/outposts.md index ca27c5a1f..a00fe1980 100644 --- a/website/docs/outposts/outposts.md +++ b/website/docs/outposts/outposts.md @@ -10,12 +10,12 @@ Upon creation, a service account and a token is generated. The service account o authentik can manage the deployment, updating and general lifecycle of an Outpost. To communicate with the underlying platforms on which the outpost is deployed, authentik has "Service Connections". -- If you've deployed authentik on docker-compose, authentik automatically create a Service Connection for the local docker socket. -- If you've deployed authentik on Kubernetes, with `kubernetesIntegration` set to true (default), authentik automatically creates a Service Connection for the local Kubernetes Cluster. +- If you've deployed authentik on docker-compose, authentik automatically create a Service Connection for the local docker socket. +- If you've deployed authentik on Kubernetes, with `kubernetesIntegration` set to true (default), authentik automatically creates a Service Connection for the local Kubernetes Cluster. To deploy an outpost with these service connections, simply selected them during the creation of an Outpost. A background task is started, which creates the container/deployment. You can see that Status on the System Tasks page. To deploy an outpost manually, see: -- [Kubernetes](./manual-deploy-kubernetes.md) -- [docker-compose](./manual-deploy-docker-compose.md) +- [Kubernetes](./manual-deploy-kubernetes.md) +- [docker-compose](./manual-deploy-docker-compose.md) diff --git a/website/docs/policies/expression.md b/website/docs/policies/expression.md index cd02648f4..b2890ca44 100644 --- a/website/docs/policies/expression.md +++ b/website/docs/policies/expression.md @@ -23,14 +23,14 @@ return False ### Context variables -- `request`: A PolicyRequest object, which has the following properties: - - `request.user`: The current user, against which the policy is applied. ([ref](../expressions/reference/user-object.md)) - - `request.http_request`: The Django HTTP Request. ([ref](https://docs.djangoproject.com/en/3.0/ref/request-response/#httprequest-objects)) - - `request.obj`: A Django Model instance. This is only set if the policy is ran against an object. - - `request.context`: A dictionary with dynamic data. This depends on the origin of the execution. -- `geoip`: `geoip2.models.City` object, which is added when GeoIP is enabled. -- `ak_is_sso_flow`: Boolean which is true if request was initiated by authenticating through an external provider. -- `ak_client_ip`: Client's IP Address or 255.255.255.255 if no IP Address could be extracted. Can be [compared](../expressions/index.md#comparing-ip-addresses), for example +- `request`: A PolicyRequest object, which has the following properties: + - `request.user`: The current user, against which the policy is applied. ([ref](../expressions/reference/user-object.md)) + - `request.http_request`: The Django HTTP Request. ([ref](https://docs.djangoproject.com/en/3.0/ref/request-response/#httprequest-objects)) + - `request.obj`: A Django Model instance. This is only set if the policy is ran against an object. + - `request.context`: A dictionary with dynamic data. This depends on the origin of the execution. +- `geoip`: `geoip2.models.City` object, which is added when GeoIP is enabled. +- `ak_is_sso_flow`: Boolean which is true if request was initiated by authenticating through an external provider. +- `ak_client_ip`: Client's IP Address or 255.255.255.255 if no IP Address could be extracted. Can be [compared](../expressions/index.md#comparing-ip-addresses), for example ```python return ak_client_ip in ip_network('10.0.0.0/24') @@ -40,6 +40,6 @@ Additionally, when the policy is executed from a flow, every variable from the f This includes the following: -- `prompt_data`: Data which has been saved from a prompt stage or an external source. -- `application`: The application the user is in the process of authorizing. -- `pending_user`: The currently pending user +- `prompt_data`: Data which has been saved from a prompt stage or an external source. +- `application`: The application the user is in the process of authorizing. +- `pending_user`: The currently pending user diff --git a/website/docs/policies/index.md b/website/docs/policies/index.md index 078501684..bfae39d35 100644 --- a/website/docs/policies/index.md +++ b/website/docs/policies/index.md @@ -25,11 +25,11 @@ See [Expression Policy](expression.md). This policy allows you to specify password rules, such as length and required characters. The following rules can be set: -- Minimum amount of uppercase characters. -- Minimum amount of lowercase characters. -- Minimum amount of symbols characters. -- Minimum length. -- Symbol charset (define which characters are counted as symbols). +- Minimum amount of uppercase characters. +- Minimum amount of lowercase characters. +- Minimum amount of symbols characters. +- Minimum length. +- Symbol charset (define which characters are counted as symbols). ### Have I Been Pwned Policy diff --git a/website/docs/property-mappings/expression.md b/website/docs/property-mappings/expression.md index b50199093..37c8cdfdc 100644 --- a/website/docs/property-mappings/expression.md +++ b/website/docs/property-mappings/expression.md @@ -10,6 +10,6 @@ These variables are available in addition to the common variables/functions defi ### Context Variables -- `user`: The current user. This may be `None` if there is no contextual user. ([ref](../expressions/reference/user-object.md)) -- `request`: The current request. This may be `None` if there is no contextual request. ([ref](https://docs.djangoproject.com/en/3.0/ref/request-response/#httprequest-objects)) -- Other arbitrary arguments given by the provider, this is documented on the Provider/Source. +- `user`: The current user. This may be `None` if there is no contextual user. ([ref](../expressions/reference/user-object.md)) +- `request`: The current request. This may be `None` if there is no contextual request. ([ref](https://docs.djangoproject.com/en/3.0/ref/request-response/#httprequest-objects)) +- Other arbitrary arguments given by the provider, this is documented on the Provider/Source. diff --git a/website/docs/providers/oauth2.md b/website/docs/providers/oauth2.md index 6f9fe707d..cf2dca183 100644 --- a/website/docs/providers/oauth2.md +++ b/website/docs/providers/oauth2.md @@ -12,7 +12,6 @@ Scopes can be configured using Scope Mappings, a type of [Property Mappings](../ | Token | `/application/o/token/` | | User Info | `/application/o/userinfo/` | | End Session | `/application/o/end-session/` | -| Introspect | `/application/o/end-session/` | | JWKS | `/application/o//jwks/` | | OpenID Configuration | `/application/o//.well-known/openid-configuration` | diff --git a/website/docs/releases/0.10.md b/website/docs/releases/0.10.md index 9b2720139..755b308e8 100644 --- a/website/docs/releases/0.10.md +++ b/website/docs/releases/0.10.md @@ -4,33 +4,33 @@ title: Release 0.10 This update brings a lot of big features, such as: -- New OAuth2/OpenID Provider +- New OAuth2/OpenID Provider This new provider merges both OAuth2 and OpenID. It is based on the codebase of the old provider, which has been simplified and cleaned from the ground up. Support for Property Mappings has also been added. Because of this change, OpenID and OAuth2 Providers will have to be re-created. -- Proxy Provider +- Proxy Provider Due to this new OAuth2 Provider, the Application Gateway Provider, now simply called "Proxy Provider" has been revamped as well. The new authentik Proxy integrates more tightly with authentik via the new Outposts system. The new proxy also supports multiple applications per proxy instance, can configure TLS based on authentik Keypairs, and more. See [Proxy](../providers/proxy.md) -- Outpost System +- Outpost System This is a new Object type, currently used only by the Proxy Provider. It manages the creation and permissions of service accounts, which are used by the outposts to communicate with authentik. See [Outposts](../outposts/outposts.md) -- Flow Import/Export +- Flow Import/Export Flows can now be imported and exported. This feature can be used as a backup system, or to share complex flows with other people. Example flows have also been added to the documentation to help you get going with authentik. ## Under the hood -- authentik now runs on Django 3.1 and Channels with complete ASGI enabled -- uwsgi has been replaced with Gunicorn and uvicorn -- Elastic APM has been replaced with Sentry Performance metrics -- Flow title is now configurable separately from the name -- All logging output is now json +- authentik now runs on Django 3.1 and Channels with complete ASGI enabled +- uwsgi has been replaced with Gunicorn and uvicorn +- Elastic APM has been replaced with Sentry Performance metrics +- Flow title is now configurable separately from the name +- All logging output is now json ## Upgrading @@ -54,7 +54,7 @@ docker-compose up -d A few options have changed: -- `error_reporting` was changed from a simple boolean to a dictionary: +- `error_reporting` was changed from a simple boolean to a dictionary: ```yaml error_reporting: @@ -63,8 +63,8 @@ error_reporting: send_pii: false ``` -- The `apm` and `monitoring` blocks have been removed. -- `serverReplicas` and `workerReplicas` have been added +- The `apm` and `monitoring` blocks have been removed. +- `serverReplicas` and `workerReplicas` have been added ### Upgrading diff --git a/website/docs/releases/0.11.md b/website/docs/releases/0.11.md index 6ec5c079c..c162a7b7c 100644 --- a/website/docs/releases/0.11.md +++ b/website/docs/releases/0.11.md @@ -4,18 +4,18 @@ title: Release 0.11 This update brings these headline features: -- Add Backup and Restore, currently only externally schedulable, documented [here](../maintenance/backups/index.md) -- New Admin Dashboard with more metrics and Charts +- Add Backup and Restore, currently only externally schedulable, documented [here](../maintenance/backups/index.md) +- New Admin Dashboard with more metrics and Charts Shows successful and failed logins from the last 24 hours, as well as the most used applications -- Add search to all table views -- Outpost now supports a Docker Controller, which installs the Outpost on the same host as authentik, updates and manages it -- Add Token Identifier +- Add search to all table views +- Outpost now supports a Docker Controller, which installs the Outpost on the same host as authentik, updates and manages it +- Add Token Identifier Tokens now have an identifier which is used to reference to them, so the Primary key is not shown in URLs -- `core/applications/list` API now shows applications the user has access to via policies +- `core/applications/list` API now shows applications the user has access to via policies ## Upgrading diff --git a/website/docs/releases/0.9.md b/website/docs/releases/0.9.md index 09c38fca1..2cb638b34 100644 --- a/website/docs/releases/0.9.md +++ b/website/docs/releases/0.9.md @@ -6,14 +6,14 @@ Due to some database changes that had to be rather sooner than later, there is n To export data from your old instance, run this command: -- docker-compose +- docker-compose ``` docker-compose exec server ./manage.py dumpdata -o /tmp/authentik_dump.json authentik_core.User authentik_core.Group authentik_crypto.CertificateKeyPair authentik_audit.Event otp_totp.totpdevice otp_static.staticdevice otp_static.statictoken docker cp authentik_server_1:/tmp/authentik_dump.json authentik_dump.json ``` -- kubernetes +- kubernetes ``` kubectl exec -it authentik-web-... -- ./manage.py dumpdata -o /tmp/authentik_dump.json authentik_core.User authentik_core.Group authentik_crypto.CertificateKeyPair authentik_audit.Event otp_totp.totpdevice otp_static.staticdevice otp_static.statictoken @@ -22,14 +22,14 @@ kubectl cp authentik-web-...:/tmp/authentik_dump.json authentik_dump.json After that, create a new authentik instance in a different namespace (kubernetes) or in a different folder (docker-compose). Once this instance is running, you can use the following commands to restore the data. On docker-compose, you still have to run the `migrate` command, to create all database structures. -- docker-compose +- docker-compose ``` docker cp authentik_dump.json new_authentik_server_1:/tmp/authentik_dump.json docker-compose exec server ./manage.py loaddata /tmp/authentik_dump.json ``` -- kubernetes +- kubernetes ``` kubectl cp authentik_dump.json authentik-web-...:/tmp/authentik_dump.json diff --git a/website/docs/sources.md b/website/docs/sources.md index 97c45c707..d5e6a179b 100644 --- a/website/docs/sources.md +++ b/website/docs/sources.md @@ -10,12 +10,12 @@ Sources allow you to connect authentik to an existing user directory. They can a This source allows users to enroll themselves with an external OAuth-based Identity Provider. The generic provider expects the endpoint to return OpenID-Connect compatible information. Vendor-specific implementations have their own OAuth Source. -- Policies: Allow/Forbid users from linking their accounts with this provider. -- Request Token URL: This field is used for OAuth v1 implementations and will be provided by the provider. -- Authorization URL: This value will be provided by the provider. -- Access Token URL: This value will be provided by the provider. -- Profile URL: This URL is called by authentik to retrieve user information upon successful authentication. -- Consumer key/Consumer secret: These values will be provided by the provider. +- Policies: Allow/Forbid users from linking their accounts with this provider. +- Request Token URL: This field is used for OAuth v1 implementations and will be provided by the provider. +- Authorization URL: This value will be provided by the provider. +- Access Token URL: This value will be provided by the provider. +- Profile URL: This URL is called by authentik to retrieve user information upon successful authentication. +- Consumer key/Consumer secret: These values will be provided by the provider. ## SAML Source @@ -29,17 +29,17 @@ This source allows you to import users and groups from an LDAP Server. For Active Directory, follow the [Active Directory Integration](https://goauthentik.io/docs/integrations/sources/active-directory/index) ::: -- Server URI: URI to your LDAP server/Domain Controller. -- Bind CN: CN of the bind user. This can also be a UPN in the format of `user@domain.tld`. -- Bind password: Password used during the bind process. -- Enable StartTLS: Enables StartTLS functionality. To use LDAPS instead, use port `636`. -- Base DN: Base DN used for all LDAP queries. -- Addition User DN: Prepended to the base DN for user queries. -- Addition Group DN: Prepended to the base DN for group queries. -- User object filter: Consider objects matching this filter to be users. -- Group object filter: Consider objects matching this filter to be groups. -- User group membership field: This field contains the user's group memberships. -- Object uniqueness field: This field contains a unique identifier. -- Sync groups: Enable/disable group synchronization. Groups are synced in the background every 5 minutes. -- Sync parent group: Optionally set this group as the parent group for all synced groups. An example use case of this would be to import Active Directory groups under a root `imported-from-ad` group. -- Property mappings: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also [LDAP Property Mappings](property-mappings/index.md#ldap-property-mapping) +- Server URI: URI to your LDAP server/Domain Controller. +- Bind CN: CN of the bind user. This can also be a UPN in the format of `user@domain.tld`. +- Bind password: Password used during the bind process. +- Enable StartTLS: Enables StartTLS functionality. To use LDAPS instead, use port `636`. +- Base DN: Base DN used for all LDAP queries. +- Addition User DN: Prepended to the base DN for user queries. +- Addition Group DN: Prepended to the base DN for group queries. +- User object filter: Consider objects matching this filter to be users. +- Group object filter: Consider objects matching this filter to be groups. +- User group membership field: This field contains the user's group memberships. +- Object uniqueness field: This field contains a unique identifier. +- Sync groups: Enable/disable group synchronization. Groups are synced in the background every 5 minutes. +- Sync parent group: Optionally set this group as the parent group for all synced groups. An example use case of this would be to import Active Directory groups under a root `imported-from-ad` group. +- Property mappings: Define which LDAP properties map to which authentik properties. The default set of property mappings is generated for Active Directory. See also [LDAP Property Mappings](property-mappings/index.md#ldap-property-mapping) diff --git a/website/sidebars.js b/website/sidebars.js index 1ecace20e..1481752cd 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -49,7 +49,9 @@ module.exports = { "flow/stages/authenticator_static/index", "flow/stages/authenticator_totp/index", "flow/stages/authenticator_validate/index", + "flow/stages/authenticator_webauthn/index", "flow/stages/captcha/index", + "flow/stages/deny", "flow/stages/email/index", "flow/stages/identification/index", "flow/stages/invitation/index", @@ -106,6 +108,7 @@ module.exports = { type: "category", label: "as Provider", items: [ + "integrations/services/apache-guacamole/index", "integrations/services/aws/index", "integrations/services/awx-tower/index", "integrations/services/gitlab/index", @@ -120,6 +123,7 @@ module.exports = { "integrations/services/ubuntu-landscape/index", "integrations/services/veeam-enterprise-manager/index", "integrations/services/vmware-vcenter/index", + "integrations/services/wiki-js/index", ], }, ], @@ -141,6 +145,7 @@ module.exports = { "releases/0.14", "releases/2021.1", "releases/2021.2", + "releases/2021.3", ], }, {