From b1214f6c3505fadf89a1512e55a9f07a0e82dfd2 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 30 Mar 2021 15:50:00 +0200 Subject: [PATCH] *: add new base class for non-model serializers Signed-off-by: Jens Langhammer --- authentik/admin/api/metrics.py | 20 ++------- authentik/admin/api/tasks.py | 11 +---- authentik/admin/api/version.py | 11 +---- authentik/api/v2/config.py | 19 ++------- authentik/core/api/tokens.py | 12 ++---- authentik/core/api/users.py | 33 ++------------- authentik/core/api/utils.py | 42 +++++++------------ authentik/core/types.py | 20 ++------- authentik/crypto/api.py | 20 ++------- authentik/flows/challenge.py | 36 +++------------- .../api/outpost_service_connections.py | 17 ++++---- authentik/outposts/api/outposts.py | 20 ++------- authentik/policies/api/exec.py | 19 ++------- authentik/sources/ldap/api.py | 13 ++---- .../authenticator_validate/challenge.py | 12 ++---- authentik/stages/prompt/stage.py | 12 ++---- 16 files changed, 69 insertions(+), 248 deletions(-) diff --git a/authentik/admin/api/metrics.py b/authentik/admin/api/metrics.py index 360ce263b..d9d6b2dc4 100644 --- a/authentik/admin/api/metrics.py +++ b/authentik/admin/api/metrics.py @@ -3,7 +3,7 @@ import time from collections import Counter from datetime import timedelta -from django.db.models import Count, ExpressionWrapper, F, Model +from django.db.models import Count, ExpressionWrapper, F from django.db.models.fields import DurationField from django.db.models.functions import ExtractHour from django.utils.timezone import now @@ -12,9 +12,9 @@ from rest_framework.fields import IntegerField, SerializerMethodField 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.core.api.utils import PassiveSerializer from authentik.events.models import Event, EventAction @@ -45,20 +45,14 @@ def get_events_per_1h(**filter_kwargs) -> list[dict[str, int]]: return results -class CoordinateSerializer(Serializer): +class CoordinateSerializer(PassiveSerializer): """Coordinates for diagrams""" x_cord = IntegerField(read_only=True) y_cord = IntegerField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class LoginMetricsSerializer(Serializer): +class LoginMetricsSerializer(PassiveSerializer): """Login Metrics per 1h""" logins_per_1h = SerializerMethodField() @@ -74,12 +68,6 @@ class LoginMetricsSerializer(Serializer): """Get failed logins per hour for the last 24 hours""" return get_events_per_1h(action=EventAction.LOGIN_FAILED) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class AdministrationMetricsViewSet(ViewSet): """Login Metrics per 1h""" diff --git a/authentik/admin/api/tasks.py b/authentik/admin/api/tasks.py index dfbca3140..55c9e1807 100644 --- a/authentik/admin/api/tasks.py +++ b/authentik/admin/api/tasks.py @@ -2,7 +2,6 @@ from importlib import import_module from django.contrib import messages -from django.db.models import Model from django.http.response import Http404 from django.utils.translation import gettext_lazy as _ from drf_yasg.utils import swagger_auto_schema @@ -11,13 +10,13 @@ from rest_framework.fields import CharField, ChoiceField, DateTimeField, ListFie 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.core.api.utils import PassiveSerializer from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus -class TaskSerializer(Serializer): +class TaskSerializer(PassiveSerializer): """Serialize TaskInfo and TaskResult""" task_name = CharField() @@ -30,12 +29,6 @@ class TaskSerializer(Serializer): ) messages = ListField(source="result.messages") - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class TaskViewSet(ViewSet): """Read-only view set that returns all background tasks""" diff --git a/authentik/admin/api/version.py b/authentik/admin/api/version.py index 4f0f03178..40fcbffdf 100644 --- a/authentik/admin/api/version.py +++ b/authentik/admin/api/version.py @@ -2,7 +2,6 @@ from os import environ from django.core.cache import cache -from django.db.models import Model from drf_yasg.utils import swagger_auto_schema from packaging.version import parse from rest_framework.fields import SerializerMethodField @@ -10,14 +9,14 @@ from rest_framework.mixins import ListModelMixin 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 GenericViewSet from authentik import ENV_GIT_HASH_KEY, __version__ from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version +from authentik.core.api.utils import PassiveSerializer -class VersionSerializer(Serializer): +class VersionSerializer(PassiveSerializer): """Get running and latest version.""" version_current = SerializerMethodField() @@ -47,12 +46,6 @@ class VersionSerializer(Serializer): self.get_version_latest(instance) ) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class VersionViewSet(ListModelMixin, GenericViewSet): """Get running and latest version.""" diff --git a/authentik/api/v2/config.py b/authentik/api/v2/config.py index 858f7f5e2..808d0525c 100644 --- a/authentik/api/v2/config.py +++ b/authentik/api/v2/config.py @@ -1,30 +1,23 @@ """core Configs API""" -from django.db.models import Model from drf_yasg.utils import swagger_auto_schema from rest_framework.fields import BooleanField, CharField, ListField from rest_framework.permissions import AllowAny 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.core.api.utils import PassiveSerializer from authentik.lib.config import CONFIG -class FooterLinkSerializer(Serializer): +class FooterLinkSerializer(PassiveSerializer): """Links returned in Config API""" href = CharField(read_only=True) name = CharField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class ConfigSerializer(Serializer): +class ConfigSerializer(PassiveSerializer): """Serialize authentik Config into DRF Object""" branding_logo = CharField(read_only=True) @@ -35,12 +28,6 @@ class ConfigSerializer(Serializer): error_reporting_environment = CharField(read_only=True) error_reporting_send_pii = BooleanField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class ConfigsViewSet(ViewSet): """Read-only view set that returns the current session's Configs""" diff --git a/authentik/core/api/tokens.py b/authentik/core/api/tokens.py index 127440bfd..10d94b509 100644 --- a/authentik/core/api/tokens.py +++ b/authentik/core/api/tokens.py @@ -1,15 +1,15 @@ """Tokens API Viewset""" -from django.db.models.base import Model from django.http.response import Http404 from drf_yasg.utils import swagger_auto_schema from rest_framework.decorators import action from rest_framework.fields import CharField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer, Serializer +from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.users import UserSerializer +from authentik.core.api.utils import PassiveSerializer from authentik.core.models import Token from authentik.events.models import Event, EventAction @@ -34,17 +34,11 @@ class TokenSerializer(ModelSerializer): depth = 2 -class TokenViewSerializer(Serializer): +class TokenViewSerializer(PassiveSerializer): """Show token's current key""" key = CharField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class TokenViewSet(ModelViewSet): """Token Viewset""" diff --git a/authentik/core/api/users.py b/authentik/core/api/users.py index ae28c6e5d..17b0c706e 100644 --- a/authentik/core/api/users.py +++ b/authentik/core/api/users.py @@ -1,5 +1,4 @@ """User API Views""" -from django.db.models.base import Model from django.urls import reverse_lazy from django.utils.http import urlencode from drf_yasg.utils import swagger_auto_schema, swagger_serializer_method @@ -8,12 +7,12 @@ from rest_framework.decorators import action from rest_framework.fields import CharField, SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import BooleanField, ModelSerializer, Serializer +from rest_framework.serializers import BooleanField, ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h from authentik.api.decorators import permission_required -from authentik.core.api.utils import LinkSerializer +from authentik.core.api.utils import LinkSerializer, PassiveSerializer from authentik.core.middleware import ( SESSION_IMPERSONATE_ORIGINAL_USER, SESSION_IMPERSONATE_USER, @@ -44,33 +43,15 @@ class UserSerializer(ModelSerializer): ] -class SessionUserSerializer(Serializer): +class SessionUserSerializer(PassiveSerializer): """Response for the /user/me endpoint, returns the currently active user (as `user` property) and, if this user is being impersonated, the original user in the `original` property.""" user = UserSerializer() original = UserSerializer(required=False) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class UserRecoverySerializer(Serializer): - """Recovery link for a user to reset their password""" - - link = CharField() - - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class UserMetricsSerializer(Serializer): +class UserMetricsSerializer(PassiveSerializer): """User Metrics""" logins_per_1h = SerializerMethodField() @@ -99,12 +80,6 @@ class UserMetricsSerializer(Serializer): action=EventAction.AUTHORIZE_APPLICATION, user__pk=request.user.pk ) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class UserViewSet(ModelViewSet): """User Viewset""" diff --git a/authentik/core/api/utils.py b/authentik/core/api/utils.py index 5b39c0cc4..390955a39 100644 --- a/authentik/core/api/utils.py +++ b/authentik/core/api/utils.py @@ -4,18 +4,22 @@ from rest_framework.fields import CharField, IntegerField from rest_framework.serializers import Serializer, SerializerMethodField -class MetaNameSerializer(Serializer): +class PassiveSerializer(Serializer): + """Base serializer class which doesn't implement create/update methods""" + + def create(self, validated_data: dict) -> Model: + return Model() + + def update(self, instance: Model, validated_data: dict) -> Model: + return Model() + + +class MetaNameSerializer(PassiveSerializer): """Add verbose names to response""" verbose_name = SerializerMethodField() verbose_name_plural = SerializerMethodField() - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - def get_verbose_name(self, obj: Model) -> str: """Return object's verbose_name""" return obj._meta.verbose_name @@ -25,39 +29,21 @@ class MetaNameSerializer(Serializer): return obj._meta.verbose_name_plural -class TypeCreateSerializer(Serializer): +class TypeCreateSerializer(PassiveSerializer): """Types of an object that can be created""" name = CharField(required=True) description = CharField(required=True) link = CharField(required=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class CacheSerializer(Serializer): +class CacheSerializer(PassiveSerializer): """Generic cache stats for an object""" count = IntegerField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class LinkSerializer(Serializer): +class LinkSerializer(PassiveSerializer): """Returns a single link""" link = CharField() - - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError diff --git a/authentik/core/types.py b/authentik/core/types.py index 07855987d..523ce0ae8 100644 --- a/authentik/core/types.py +++ b/authentik/core/types.py @@ -2,9 +2,9 @@ from dataclasses import dataclass from typing import Optional -from django.db.models.base import Model from rest_framework.fields import CharField -from rest_framework.serializers import Serializer + +from authentik.core.api.utils import PassiveSerializer @dataclass @@ -21,29 +21,17 @@ class UILoginButton: icon_url: Optional[str] = None -class UILoginButtonSerializer(Serializer): +class UILoginButtonSerializer(PassiveSerializer): """Serializer for Login buttons of sources""" name = CharField() url = CharField() icon_url = CharField(required=False) - def create(self, validated_data: dict) -> Model: - return Model() - def update(self, instance: Model, validated_data: dict) -> Model: - return Model() - - -class UserSettingSerializer(Serializer): +class UserSettingSerializer(PassiveSerializer): """Serializer for User settings for stages and sources""" object_uid = CharField() component = CharField() title = CharField() - - def create(self, validated_data: dict) -> Model: - return Model() - - def update(self, instance: Model, validated_data: dict) -> Model: - return Model() diff --git a/authentik/crypto/api.py b/authentik/crypto/api.py index 97be5a06a..daa43e672 100644 --- a/authentik/crypto/api.py +++ b/authentik/crypto/api.py @@ -2,7 +2,6 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.x509 import load_pem_x509_certificate -from django.db.models import Model from django.utils.translation import gettext_lazy as _ from drf_yasg.utils import swagger_auto_schema from rest_framework.decorators import action @@ -14,10 +13,11 @@ from rest_framework.fields import ( ) from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer, Serializer, ValidationError +from rest_framework.serializers import ModelSerializer, ValidationError from rest_framework.viewsets import ModelViewSet from authentik.api.decorators import permission_required +from authentik.core.api.utils import PassiveSerializer from authentik.crypto.builder import CertificateBuilder from authentik.crypto.models import CertificateKeyPair from authentik.events.models import Event, EventAction @@ -79,19 +79,13 @@ class CertificateKeyPairSerializer(ModelSerializer): } -class CertificateDataSerializer(Serializer): +class CertificateDataSerializer(PassiveSerializer): """Get CertificateKeyPair's data""" data = CharField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class CertificateGenerationSerializer(Serializer): +class CertificateGenerationSerializer(PassiveSerializer): """Certificate generation parameters""" common_name = CharField() @@ -100,12 +94,6 @@ class CertificateGenerationSerializer(Serializer): ) validity_days = IntegerField(initial=365) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class CertificateKeyPairViewSet(ModelViewSet): """CertificateKeyPair Viewset""" diff --git a/authentik/flows/challenge.py b/authentik/flows/challenge.py index 6cfffc7fe..e209b1d55 100644 --- a/authentik/flows/challenge.py +++ b/authentik/flows/challenge.py @@ -2,11 +2,11 @@ from enum import Enum from typing import TYPE_CHECKING, Optional -from django.db.models.base import Model from django.http import JsonResponse from rest_framework.fields import ChoiceField, DictField -from rest_framework.serializers import CharField, Serializer +from rest_framework.serializers import CharField +from authentik.core.api.utils import PassiveSerializer from authentik.flows.transfer.common import DataclassEncoder if TYPE_CHECKING: @@ -21,20 +21,14 @@ class ChallengeTypes(Enum): REDIRECT = "redirect" -class ErrorDetailSerializer(Serializer): +class ErrorDetailSerializer(PassiveSerializer): """Serializer for rest_framework's error messages""" string = CharField() code = CharField() - def create(self, validated_data: dict) -> Model: - return Model() - def update(self, instance: Model, validated_data: dict) -> Model: - return Model() - - -class Challenge(Serializer): +class Challenge(PassiveSerializer): """Challenge that gets sent to the client based on which stage is currently active""" @@ -49,12 +43,6 @@ class Challenge(Serializer): child=ErrorDetailSerializer(many=True), allow_empty=True, required=False ) - def create(self, validated_data: dict) -> Model: - return Model() - - def update(self, instance: Model, validated_data: dict) -> Model: - return Model() - class RedirectChallenge(Challenge): """Challenge type to redirect the client""" @@ -81,20 +69,14 @@ class AccessDeniedChallenge(Challenge): error_message = CharField(required=False) -class PermissionSerializer(Serializer): +class PermissionSerializer(PassiveSerializer): """Permission used for consent""" name = CharField() id = CharField() - def create(self, validated_data: dict) -> Model: - return Model() - def update(self, instance: Model, validated_data: dict) -> Model: - return Model() - - -class ChallengeResponse(Serializer): +class ChallengeResponse(PassiveSerializer): """Base class for all challenge responses""" stage: Optional["StageView"] @@ -103,12 +85,6 @@ class ChallengeResponse(Serializer): self.stage = kwargs.pop("stage", None) super().__init__(instance=instance, data=data, **kwargs) - def create(self, validated_data: dict) -> Model: - return Model() - - def update(self, instance: Model, validated_data: dict) -> Model: - return Model() - class HttpChallengeResponse(JsonResponse): """Subclass of JsonResponse that uses the `DataclassEncoder`""" diff --git a/authentik/outposts/api/outpost_service_connections.py b/authentik/outposts/api/outpost_service_connections.py index b638bde55..757a2798e 100644 --- a/authentik/outposts/api/outpost_service_connections.py +++ b/authentik/outposts/api/outpost_service_connections.py @@ -1,17 +1,20 @@ """Outpost API Views""" from dataclasses import asdict -from django.db.models.base import Model from django.urls import reverse from drf_yasg.utils import swagger_auto_schema from rest_framework.decorators import action from rest_framework.fields import BooleanField, CharField, SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer, Serializer +from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet -from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer +from authentik.core.api.utils import ( + MetaNameSerializer, + PassiveSerializer, + TypeCreateSerializer, +) from authentik.lib.templatetags.authentik_utils import verbose_name from authentik.lib.utils.reflection import all_subclasses from authentik.outposts.models import ( @@ -43,18 +46,12 @@ class ServiceConnectionSerializer(ModelSerializer, MetaNameSerializer): ] -class ServiceConnectionStateSerializer(Serializer): +class ServiceConnectionStateSerializer(PassiveSerializer): """Serializer for Service connection state""" healthy = BooleanField(read_only=True) version = CharField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class ServiceConnectionViewSet(ModelViewSet): """ServiceConnection Viewset""" diff --git a/authentik/outposts/api/outposts.py b/authentik/outposts/api/outposts.py index 566b1c5d7..d1589b7ac 100644 --- a/authentik/outposts/api/outposts.py +++ b/authentik/outposts/api/outposts.py @@ -1,14 +1,14 @@ """Outpost API Views""" -from django.db.models import Model from drf_yasg.utils import swagger_auto_schema from rest_framework.decorators import action from rest_framework.fields import BooleanField, CharField, DateTimeField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import JSONField, ModelSerializer, Serializer +from rest_framework.serializers import JSONField, ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.providers import ProviderSerializer +from authentik.core.api.utils import PassiveSerializer from authentik.outposts.models import Outpost, default_outpost_config @@ -32,19 +32,13 @@ class OutpostSerializer(ModelSerializer): ] -class OutpostDefaultConfigSerializer(Serializer): +class OutpostDefaultConfigSerializer(PassiveSerializer): """Global default outpost config""" config = JSONField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class OutpostHealthSerializer(Serializer): +class OutpostHealthSerializer(PassiveSerializer): """Outpost health status""" last_seen = DateTimeField(read_only=True) @@ -52,12 +46,6 @@ class OutpostHealthSerializer(Serializer): version_should = CharField(read_only=True) version_outdated = BooleanField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class OutpostViewSet(ModelViewSet): """Outpost Viewset""" diff --git a/authentik/policies/api/exec.py b/authentik/policies/api/exec.py index 9d4069179..bb987080d 100644 --- a/authentik/policies/api/exec.py +++ b/authentik/policies/api/exec.py @@ -1,33 +1,20 @@ """Serializer for policy execution""" -from django.db.models import Model from rest_framework.fields import BooleanField, CharField, JSONField, ListField from rest_framework.relations import PrimaryKeyRelatedField -from rest_framework.serializers import Serializer +from authentik.core.api.utils import PassiveSerializer from authentik.core.models import User -class PolicyTestSerializer(Serializer): +class PolicyTestSerializer(PassiveSerializer): """Test policy execution for a user with context""" user = PrimaryKeyRelatedField(queryset=User.objects.all()) context = JSONField(required=False) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - - -class PolicyTestResultSerializer(Serializer): +class PolicyTestResultSerializer(PassiveSerializer): """result of a policy test""" passing = BooleanField() messages = ListField(child=CharField(), read_only=True) - - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError diff --git a/authentik/sources/ldap/api.py b/authentik/sources/ldap/api.py index ff4f20674..01aa37d1c 100644 --- a/authentik/sources/ldap/api.py +++ b/authentik/sources/ldap/api.py @@ -3,17 +3,16 @@ from datetime import datetime from time import time from django.core.cache import cache -from django.db.models.base import Model from drf_yasg.utils import swagger_auto_schema from rest_framework.decorators import action from rest_framework.fields import DateTimeField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer, Serializer +from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.sources import SourceSerializer -from authentik.core.api.utils import MetaNameSerializer +from authentik.core.api.utils import MetaNameSerializer, PassiveSerializer from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource @@ -44,17 +43,11 @@ class LDAPSourceSerializer(SourceSerializer): extra_kwargs = {"bind_password": {"write_only": True}} -class LDAPSourceSyncStatusSerializer(Serializer): +class LDAPSourceSyncStatusSerializer(PassiveSerializer): """LDAP Sync status""" last_sync = DateTimeField(read_only=True) - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - class LDAPSourceViewSet(ModelViewSet): """LDAP Source Viewset""" diff --git a/authentik/stages/authenticator_validate/challenge.py b/authentik/stages/authenticator_validate/challenge.py index d5781125c..92771a06d 100644 --- a/authentik/stages/authenticator_validate/challenge.py +++ b/authentik/stages/authenticator_validate/challenge.py @@ -1,5 +1,4 @@ """Validation stage challenge checking""" -from django.db.models import Model from django.http import HttpRequest from django.utils.translation import gettext_lazy as _ from django_otp import match_token @@ -7,7 +6,7 @@ from django_otp.models import Device from django_otp.plugins.otp_static.models import StaticDevice from django_otp.plugins.otp_totp.models import TOTPDevice from rest_framework.fields import CharField, JSONField -from rest_framework.serializers import Serializer, ValidationError +from rest_framework.serializers import ValidationError from webauthn import WebAuthnAssertionOptions, WebAuthnAssertionResponse, WebAuthnUser from webauthn.webauthn import ( AuthenticationRejectedException, @@ -15,24 +14,19 @@ from webauthn.webauthn import ( WebAuthnUserDataMissing, ) +from authentik.core.api.utils import PassiveSerializer from authentik.core.models import User from authentik.stages.authenticator_webauthn.models import WebAuthnDevice from authentik.stages.authenticator_webauthn.utils import generate_challenge, get_origin -class DeviceChallenge(Serializer): +class DeviceChallenge(PassiveSerializer): """Single device challenge""" device_class = CharField() device_uid = CharField() challenge = JSONField() - def create(self, validated_data: dict) -> Model: - raise NotImplementedError - - def update(self, instance: Model, validated_data: dict) -> Model: - raise NotImplementedError - def get_challenge_for_device(request: HttpRequest, device: Device) -> dict: """Generate challenge for a single device""" diff --git a/authentik/stages/prompt/stage.py b/authentik/stages/prompt/stage.py index c926a20dd..15cc9e772 100644 --- a/authentik/stages/prompt/stage.py +++ b/authentik/stages/prompt/stage.py @@ -3,16 +3,16 @@ from email.policy import Policy from types import MethodType from typing import Any, Callable, Iterator -from django.db.models.base import Model from django.db.models.query import QuerySet from django.http import HttpRequest, HttpResponse from django.http.request import QueryDict from django.utils.translation import gettext_lazy as _ from guardian.shortcuts import get_anonymous_user from rest_framework.fields import BooleanField, CharField, IntegerField -from rest_framework.serializers import Serializer, ValidationError +from rest_framework.serializers import ValidationError from structlog.stdlib import get_logger +from authentik.core.api.utils import PassiveSerializer from authentik.core.models import User from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan @@ -26,7 +26,7 @@ LOGGER = get_logger() PLAN_CONTEXT_PROMPT = "prompt_data" -class PromptSerializer(Serializer): +class PromptSerializer(PassiveSerializer): """Serializer for a single Prompt field""" field_key = CharField() @@ -36,12 +36,6 @@ class PromptSerializer(Serializer): placeholder = CharField() order = IntegerField() - def create(self, validated_data: dict) -> Model: - return Model() - - def update(self, instance: Model, validated_data: dict) -> Model: - return Model() - class PromptChallenge(Challenge): """Initial challenge being sent, define fields"""