*: add new base class for non-model serializers

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-03-30 15:50:00 +02:00
parent c7dcf92a2e
commit b1214f6c35
16 changed files with 69 additions and 248 deletions

View file

@ -3,7 +3,7 @@ import time
from collections import Counter from collections import Counter
from datetime import timedelta 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.fields import DurationField
from django.db.models.functions import ExtractHour from django.db.models.functions import ExtractHour
from django.utils.timezone import now 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.permissions import IsAdminUser
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.viewsets import ViewSet from rest_framework.viewsets import ViewSet
from authentik.core.api.utils import PassiveSerializer
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
@ -45,20 +45,14 @@ def get_events_per_1h(**filter_kwargs) -> list[dict[str, int]]:
return results return results
class CoordinateSerializer(Serializer): class CoordinateSerializer(PassiveSerializer):
"""Coordinates for diagrams""" """Coordinates for diagrams"""
x_cord = IntegerField(read_only=True) x_cord = IntegerField(read_only=True)
y_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: class LoginMetricsSerializer(PassiveSerializer):
raise NotImplementedError
class LoginMetricsSerializer(Serializer):
"""Login Metrics per 1h""" """Login Metrics per 1h"""
logins_per_1h = SerializerMethodField() logins_per_1h = SerializerMethodField()
@ -74,12 +68,6 @@ class LoginMetricsSerializer(Serializer):
"""Get failed logins per hour for the last 24 hours""" """Get failed logins per hour for the last 24 hours"""
return get_events_per_1h(action=EventAction.LOGIN_FAILED) 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): class AdministrationMetricsViewSet(ViewSet):
"""Login Metrics per 1h""" """Login Metrics per 1h"""

View file

@ -2,7 +2,6 @@
from importlib import import_module from importlib import import_module
from django.contrib import messages from django.contrib import messages
from django.db.models import Model
from django.http.response import Http404 from django.http.response import Http404
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from drf_yasg.utils import swagger_auto_schema 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.permissions import IsAdminUser
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.viewsets import ViewSet from rest_framework.viewsets import ViewSet
from authentik.core.api.utils import PassiveSerializer
from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus
class TaskSerializer(Serializer): class TaskSerializer(PassiveSerializer):
"""Serialize TaskInfo and TaskResult""" """Serialize TaskInfo and TaskResult"""
task_name = CharField() task_name = CharField()
@ -30,12 +29,6 @@ class TaskSerializer(Serializer):
) )
messages = ListField(source="result.messages") 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): class TaskViewSet(ViewSet):
"""Read-only view set that returns all background tasks""" """Read-only view set that returns all background tasks"""

View file

@ -2,7 +2,6 @@
from os import environ from os import environ
from django.core.cache import cache from django.core.cache import cache
from django.db.models import Model
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from packaging.version import parse from packaging.version import parse
from rest_framework.fields import SerializerMethodField 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.permissions import IsAdminUser
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import GenericViewSet
from authentik import ENV_GIT_HASH_KEY, __version__ from authentik import ENV_GIT_HASH_KEY, __version__
from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_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.""" """Get running and latest version."""
version_current = SerializerMethodField() version_current = SerializerMethodField()
@ -47,12 +46,6 @@ class VersionSerializer(Serializer):
self.get_version_latest(instance) 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): class VersionViewSet(ListModelMixin, GenericViewSet):
"""Get running and latest version.""" """Get running and latest version."""

View file

@ -1,30 +1,23 @@
"""core Configs API""" """core Configs API"""
from django.db.models import Model
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from rest_framework.fields import BooleanField, CharField, ListField from rest_framework.fields import BooleanField, CharField, ListField
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.viewsets import ViewSet from rest_framework.viewsets import ViewSet
from authentik.core.api.utils import PassiveSerializer
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
class FooterLinkSerializer(Serializer): class FooterLinkSerializer(PassiveSerializer):
"""Links returned in Config API""" """Links returned in Config API"""
href = CharField(read_only=True) href = CharField(read_only=True)
name = 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: class ConfigSerializer(PassiveSerializer):
raise NotImplementedError
class ConfigSerializer(Serializer):
"""Serialize authentik Config into DRF Object""" """Serialize authentik Config into DRF Object"""
branding_logo = CharField(read_only=True) branding_logo = CharField(read_only=True)
@ -35,12 +28,6 @@ class ConfigSerializer(Serializer):
error_reporting_environment = CharField(read_only=True) error_reporting_environment = CharField(read_only=True)
error_reporting_send_pii = BooleanField(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): class ConfigsViewSet(ViewSet):
"""Read-only view set that returns the current session's Configs""" """Read-only view set that returns the current session's Configs"""

View file

@ -1,15 +1,15 @@
"""Tokens API Viewset""" """Tokens API Viewset"""
from django.db.models.base import Model
from django.http.response import Http404 from django.http.response import Http404
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.fields import CharField from rest_framework.fields import CharField
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response 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 rest_framework.viewsets import ModelViewSet
from authentik.core.api.users import UserSerializer from authentik.core.api.users import UserSerializer
from authentik.core.api.utils import PassiveSerializer
from authentik.core.models import Token from authentik.core.models import Token
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
@ -34,17 +34,11 @@ class TokenSerializer(ModelSerializer):
depth = 2 depth = 2
class TokenViewSerializer(Serializer): class TokenViewSerializer(PassiveSerializer):
"""Show token's current key""" """Show token's current key"""
key = CharField(read_only=True) 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): class TokenViewSet(ModelViewSet):
"""Token Viewset""" """Token Viewset"""

View file

@ -1,5 +1,4 @@
"""User API Views""" """User API Views"""
from django.db.models.base import Model
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.http import urlencode from django.utils.http import urlencode
from drf_yasg.utils import swagger_auto_schema, swagger_serializer_method 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.fields import CharField, SerializerMethodField
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response 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 rest_framework.viewsets import ModelViewSet
from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h
from authentik.api.decorators import permission_required 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 ( from authentik.core.middleware import (
SESSION_IMPERSONATE_ORIGINAL_USER, SESSION_IMPERSONATE_ORIGINAL_USER,
SESSION_IMPERSONATE_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) """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.""" and, if this user is being impersonated, the original user in the `original` property."""
user = UserSerializer() user = UserSerializer()
original = UserSerializer(required=False) original = UserSerializer(required=False)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model: class UserMetricsSerializer(PassiveSerializer):
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):
"""User Metrics""" """User Metrics"""
logins_per_1h = SerializerMethodField() logins_per_1h = SerializerMethodField()
@ -99,12 +80,6 @@ class UserMetricsSerializer(Serializer):
action=EventAction.AUTHORIZE_APPLICATION, user__pk=request.user.pk 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): class UserViewSet(ModelViewSet):
"""User Viewset""" """User Viewset"""

View file

@ -4,18 +4,22 @@ from rest_framework.fields import CharField, IntegerField
from rest_framework.serializers import Serializer, SerializerMethodField 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""" """Add verbose names to response"""
verbose_name = SerializerMethodField() verbose_name = SerializerMethodField()
verbose_name_plural = 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: def get_verbose_name(self, obj: Model) -> str:
"""Return object's verbose_name""" """Return object's verbose_name"""
return obj._meta.verbose_name return obj._meta.verbose_name
@ -25,39 +29,21 @@ class MetaNameSerializer(Serializer):
return obj._meta.verbose_name_plural return obj._meta.verbose_name_plural
class TypeCreateSerializer(Serializer): class TypeCreateSerializer(PassiveSerializer):
"""Types of an object that can be created""" """Types of an object that can be created"""
name = CharField(required=True) name = CharField(required=True)
description = CharField(required=True) description = CharField(required=True)
link = 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: class CacheSerializer(PassiveSerializer):
raise NotImplementedError
class CacheSerializer(Serializer):
"""Generic cache stats for an object""" """Generic cache stats for an object"""
count = IntegerField(read_only=True) count = IntegerField(read_only=True)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model: class LinkSerializer(PassiveSerializer):
raise NotImplementedError
class LinkSerializer(Serializer):
"""Returns a single link""" """Returns a single link"""
link = CharField() link = CharField()
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model:
raise NotImplementedError

View file

@ -2,9 +2,9 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional from typing import Optional
from django.db.models.base import Model
from rest_framework.fields import CharField from rest_framework.fields import CharField
from rest_framework.serializers import Serializer
from authentik.core.api.utils import PassiveSerializer
@dataclass @dataclass
@ -21,29 +21,17 @@ class UILoginButton:
icon_url: Optional[str] = None icon_url: Optional[str] = None
class UILoginButtonSerializer(Serializer): class UILoginButtonSerializer(PassiveSerializer):
"""Serializer for Login buttons of sources""" """Serializer for Login buttons of sources"""
name = CharField() name = CharField()
url = CharField() url = CharField()
icon_url = CharField(required=False) icon_url = CharField(required=False)
def create(self, validated_data: dict) -> Model:
return Model()
def update(self, instance: Model, validated_data: dict) -> Model: class UserSettingSerializer(PassiveSerializer):
return Model()
class UserSettingSerializer(Serializer):
"""Serializer for User settings for stages and sources""" """Serializer for User settings for stages and sources"""
object_uid = CharField() object_uid = CharField()
component = CharField() component = CharField()
title = CharField() title = CharField()
def create(self, validated_data: dict) -> Model:
return Model()
def update(self, instance: Model, validated_data: dict) -> Model:
return Model()

View file

@ -2,7 +2,6 @@
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.x509 import load_pem_x509_certificate from cryptography.x509 import load_pem_x509_certificate
from django.db.models import Model
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action from rest_framework.decorators import action
@ -14,10 +13,11 @@ from rest_framework.fields import (
) )
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response 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 rest_framework.viewsets import ModelViewSet
from authentik.api.decorators import permission_required from authentik.api.decorators import permission_required
from authentik.core.api.utils import PassiveSerializer
from authentik.crypto.builder import CertificateBuilder from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
@ -79,19 +79,13 @@ class CertificateKeyPairSerializer(ModelSerializer):
} }
class CertificateDataSerializer(Serializer): class CertificateDataSerializer(PassiveSerializer):
"""Get CertificateKeyPair's data""" """Get CertificateKeyPair's data"""
data = CharField(read_only=True) data = CharField(read_only=True)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model: class CertificateGenerationSerializer(PassiveSerializer):
raise NotImplementedError
class CertificateGenerationSerializer(Serializer):
"""Certificate generation parameters""" """Certificate generation parameters"""
common_name = CharField() common_name = CharField()
@ -100,12 +94,6 @@ class CertificateGenerationSerializer(Serializer):
) )
validity_days = IntegerField(initial=365) 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): class CertificateKeyPairViewSet(ModelViewSet):
"""CertificateKeyPair Viewset""" """CertificateKeyPair Viewset"""

View file

@ -2,11 +2,11 @@
from enum import Enum from enum import Enum
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional
from django.db.models.base import Model
from django.http import JsonResponse from django.http import JsonResponse
from rest_framework.fields import ChoiceField, DictField 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 from authentik.flows.transfer.common import DataclassEncoder
if TYPE_CHECKING: if TYPE_CHECKING:
@ -21,20 +21,14 @@ class ChallengeTypes(Enum):
REDIRECT = "redirect" REDIRECT = "redirect"
class ErrorDetailSerializer(Serializer): class ErrorDetailSerializer(PassiveSerializer):
"""Serializer for rest_framework's error messages""" """Serializer for rest_framework's error messages"""
string = CharField() string = CharField()
code = CharField() code = CharField()
def create(self, validated_data: dict) -> Model:
return Model()
def update(self, instance: Model, validated_data: dict) -> Model: class Challenge(PassiveSerializer):
return Model()
class Challenge(Serializer):
"""Challenge that gets sent to the client based on which stage """Challenge that gets sent to the client based on which stage
is currently active""" is currently active"""
@ -49,12 +43,6 @@ class Challenge(Serializer):
child=ErrorDetailSerializer(many=True), allow_empty=True, required=False 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): class RedirectChallenge(Challenge):
"""Challenge type to redirect the client""" """Challenge type to redirect the client"""
@ -81,20 +69,14 @@ class AccessDeniedChallenge(Challenge):
error_message = CharField(required=False) error_message = CharField(required=False)
class PermissionSerializer(Serializer): class PermissionSerializer(PassiveSerializer):
"""Permission used for consent""" """Permission used for consent"""
name = CharField() name = CharField()
id = CharField() id = CharField()
def create(self, validated_data: dict) -> Model:
return Model()
def update(self, instance: Model, validated_data: dict) -> Model: class ChallengeResponse(PassiveSerializer):
return Model()
class ChallengeResponse(Serializer):
"""Base class for all challenge responses""" """Base class for all challenge responses"""
stage: Optional["StageView"] stage: Optional["StageView"]
@ -103,12 +85,6 @@ class ChallengeResponse(Serializer):
self.stage = kwargs.pop("stage", None) self.stage = kwargs.pop("stage", None)
super().__init__(instance=instance, data=data, **kwargs) 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): class HttpChallengeResponse(JsonResponse):
"""Subclass of JsonResponse that uses the `DataclassEncoder`""" """Subclass of JsonResponse that uses the `DataclassEncoder`"""

View file

@ -1,17 +1,20 @@
"""Outpost API Views""" """Outpost API Views"""
from dataclasses import asdict from dataclasses import asdict
from django.db.models.base import Model
from django.urls import reverse from django.urls import reverse
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.fields import BooleanField, CharField, SerializerMethodField from rest_framework.fields import BooleanField, CharField, SerializerMethodField
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response 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 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.templatetags.authentik_utils import verbose_name
from authentik.lib.utils.reflection import all_subclasses from authentik.lib.utils.reflection import all_subclasses
from authentik.outposts.models import ( from authentik.outposts.models import (
@ -43,18 +46,12 @@ class ServiceConnectionSerializer(ModelSerializer, MetaNameSerializer):
] ]
class ServiceConnectionStateSerializer(Serializer): class ServiceConnectionStateSerializer(PassiveSerializer):
"""Serializer for Service connection state""" """Serializer for Service connection state"""
healthy = BooleanField(read_only=True) healthy = BooleanField(read_only=True)
version = CharField(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): class ServiceConnectionViewSet(ModelViewSet):
"""ServiceConnection Viewset""" """ServiceConnection Viewset"""

View file

@ -1,14 +1,14 @@
"""Outpost API Views""" """Outpost API Views"""
from django.db.models import Model
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.fields import BooleanField, CharField, DateTimeField from rest_framework.fields import BooleanField, CharField, DateTimeField
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response 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 rest_framework.viewsets import ModelViewSet
from authentik.core.api.providers import ProviderSerializer from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.utils import PassiveSerializer
from authentik.outposts.models import Outpost, default_outpost_config 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""" """Global default outpost config"""
config = JSONField(read_only=True) config = JSONField(read_only=True)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model: class OutpostHealthSerializer(PassiveSerializer):
raise NotImplementedError
class OutpostHealthSerializer(Serializer):
"""Outpost health status""" """Outpost health status"""
last_seen = DateTimeField(read_only=True) last_seen = DateTimeField(read_only=True)
@ -52,12 +46,6 @@ class OutpostHealthSerializer(Serializer):
version_should = CharField(read_only=True) version_should = CharField(read_only=True)
version_outdated = BooleanField(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): class OutpostViewSet(ModelViewSet):
"""Outpost Viewset""" """Outpost Viewset"""

View file

@ -1,33 +1,20 @@
"""Serializer for policy execution""" """Serializer for policy execution"""
from django.db.models import Model
from rest_framework.fields import BooleanField, CharField, JSONField, ListField from rest_framework.fields import BooleanField, CharField, JSONField, ListField
from rest_framework.relations import PrimaryKeyRelatedField 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 from authentik.core.models import User
class PolicyTestSerializer(Serializer): class PolicyTestSerializer(PassiveSerializer):
"""Test policy execution for a user with context""" """Test policy execution for a user with context"""
user = PrimaryKeyRelatedField(queryset=User.objects.all()) user = PrimaryKeyRelatedField(queryset=User.objects.all())
context = JSONField(required=False) context = JSONField(required=False)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model: class PolicyTestResultSerializer(PassiveSerializer):
raise NotImplementedError
class PolicyTestResultSerializer(Serializer):
"""result of a policy test""" """result of a policy test"""
passing = BooleanField() passing = BooleanField()
messages = ListField(child=CharField(), read_only=True) 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

View file

@ -3,17 +3,16 @@ from datetime import datetime
from time import time from time import time
from django.core.cache import cache from django.core.cache import cache
from django.db.models.base import Model
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.fields import DateTimeField from rest_framework.fields import DateTimeField
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response 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 rest_framework.viewsets import ModelViewSet
from authentik.core.api.sources import SourceSerializer 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 from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
@ -44,17 +43,11 @@ class LDAPSourceSerializer(SourceSerializer):
extra_kwargs = {"bind_password": {"write_only": True}} extra_kwargs = {"bind_password": {"write_only": True}}
class LDAPSourceSyncStatusSerializer(Serializer): class LDAPSourceSyncStatusSerializer(PassiveSerializer):
"""LDAP Sync status""" """LDAP Sync status"""
last_sync = DateTimeField(read_only=True) 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): class LDAPSourceViewSet(ModelViewSet):
"""LDAP Source Viewset""" """LDAP Source Viewset"""

View file

@ -1,5 +1,4 @@
"""Validation stage challenge checking""" """Validation stage challenge checking"""
from django.db.models import Model
from django.http import HttpRequest from django.http import HttpRequest
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_otp import match_token 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_static.models import StaticDevice
from django_otp.plugins.otp_totp.models import TOTPDevice from django_otp.plugins.otp_totp.models import TOTPDevice
from rest_framework.fields import CharField, JSONField 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 import WebAuthnAssertionOptions, WebAuthnAssertionResponse, WebAuthnUser
from webauthn.webauthn import ( from webauthn.webauthn import (
AuthenticationRejectedException, AuthenticationRejectedException,
@ -15,24 +14,19 @@ from webauthn.webauthn import (
WebAuthnUserDataMissing, WebAuthnUserDataMissing,
) )
from authentik.core.api.utils import PassiveSerializer
from authentik.core.models import User from authentik.core.models import User
from authentik.stages.authenticator_webauthn.models import WebAuthnDevice from authentik.stages.authenticator_webauthn.models import WebAuthnDevice
from authentik.stages.authenticator_webauthn.utils import generate_challenge, get_origin from authentik.stages.authenticator_webauthn.utils import generate_challenge, get_origin
class DeviceChallenge(Serializer): class DeviceChallenge(PassiveSerializer):
"""Single device challenge""" """Single device challenge"""
device_class = CharField() device_class = CharField()
device_uid = CharField() device_uid = CharField()
challenge = JSONField() 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: def get_challenge_for_device(request: HttpRequest, device: Device) -> dict:
"""Generate challenge for a single device""" """Generate challenge for a single device"""

View file

@ -3,16 +3,16 @@ from email.policy import Policy
from types import MethodType from types import MethodType
from typing import Any, Callable, Iterator from typing import Any, Callable, Iterator
from django.db.models.base import Model
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.http.request import QueryDict from django.http.request import QueryDict
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from guardian.shortcuts import get_anonymous_user from guardian.shortcuts import get_anonymous_user
from rest_framework.fields import BooleanField, CharField, IntegerField 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 structlog.stdlib import get_logger
from authentik.core.api.utils import PassiveSerializer
from authentik.core.models import User from authentik.core.models import User
from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
@ -26,7 +26,7 @@ LOGGER = get_logger()
PLAN_CONTEXT_PROMPT = "prompt_data" PLAN_CONTEXT_PROMPT = "prompt_data"
class PromptSerializer(Serializer): class PromptSerializer(PassiveSerializer):
"""Serializer for a single Prompt field""" """Serializer for a single Prompt field"""
field_key = CharField() field_key = CharField()
@ -36,12 +36,6 @@ class PromptSerializer(Serializer):
placeholder = CharField() placeholder = CharField()
order = IntegerField() 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): class PromptChallenge(Challenge):
"""Initial challenge being sent, define fields""" """Initial challenge being sent, define fields"""