From 2c781ae423242a24ea96106d91102f43b5e57826 Mon Sep 17 00:00:00 2001 From: Jens L Date: Tue, 18 Jun 2024 22:48:05 +0900 Subject: [PATCH] root: use custom model serializer that saves m2m without bulk (#10139) * use custom model serializer that saves m2m without bulk Signed-off-by: Jens Langhammer * sigh Signed-off-by: Jens Langhammer --------- Signed-off-by: Jens Langhammer --- authentik/brands/api.py | 3 +- authentik/core/api/applications.py | 2 +- authentik/core/api/authenticated_sessions.py | 2 +- authentik/core/api/groups.py | 4 +-- authentik/core/api/property_mappings.py | 4 +-- authentik/core/api/providers.py | 5 ++- authentik/core/api/sources.py | 3 +- authentik/core/api/tokens.py | 3 +- authentik/core/api/users.py | 8 +++-- authentik/core/api/utils.py | 36 +++++++++++++++++++ authentik/crypto/api.py | 3 +- authentik/enterprise/api.py | 3 +- .../providers/google_workspace/api/groups.py | 2 +- .../providers/google_workspace/api/users.py | 2 +- .../providers/microsoft_entra/api/groups.py | 2 +- .../providers/microsoft_entra/api/users.py | 2 +- .../providers/rac/api/connection_tokens.py | 2 +- .../enterprise/providers/rac/api/endpoints.py | 2 +- authentik/events/api/events.py | 3 +- authentik/events/api/notification_mappings.py | 2 +- authentik/events/api/notification_rules.py | 2 +- .../events/api/notification_transports.py | 3 +- authentik/events/api/notifications.py | 2 +- authentik/events/api/tasks.py | 2 +- authentik/flows/api/bindings.py | 2 +- authentik/flows/api/flows.py | 10 ++++-- authentik/flows/api/stages.py | 4 +-- authentik/lib/sync/outgoing/api.py | 3 +- authentik/outposts/api/outposts.py | 4 +-- authentik/outposts/api/service_connections.py | 2 +- authentik/policies/api/bindings.py | 4 ++- authentik/policies/api/policies.py | 3 +- authentik/policies/reputation/api.py | 2 +- authentik/providers/ldap/api.py | 2 +- authentik/providers/oauth2/api/tokens.py | 3 +- authentik/providers/proxy/api.py | 3 +- authentik/providers/radius/api.py | 2 +- authentik/providers/scim/api/groups.py | 2 +- authentik/providers/scim/api/users.py | 2 +- authentik/rbac/api/rbac.py | 3 +- authentik/rbac/api/rbac_assigned_by_roles.py | 3 +- authentik/rbac/api/rbac_assigned_by_users.py | 2 +- authentik/rbac/api/roles.py | 2 +- authentik/stages/authenticator_duo/api.py | 2 +- authentik/stages/authenticator_sms/api.py | 2 +- authentik/stages/authenticator_static/api.py | 2 +- authentik/stages/authenticator_totp/api.py | 2 +- .../authenticator_webauthn/api/devices.py | 2 +- authentik/stages/invitation/api.py | 3 +- authentik/tenants/api/domains.py | 2 +- authentik/tenants/api/settings.py | 2 +- 51 files changed, 105 insertions(+), 72 deletions(-) diff --git a/authentik/brands/api.py b/authentik/brands/api.py index a856cee4858f..3bf199b93bff 100644 --- a/authentik/brands/api.py +++ b/authentik/brands/api.py @@ -11,14 +11,13 @@ from rest_framework.permissions import AllowAny from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.validators import UniqueValidator from rest_framework.viewsets import ModelViewSet from authentik.api.authorization import SecretKeyFilter from authentik.brands.models import Brand from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.tenants.utils import get_current_tenant diff --git a/authentik/core/api/applications.py b/authentik/core/api/applications.py index eddad64bf8e5..cc747fd8c84d 100644 --- a/authentik/core/api/applications.py +++ b/authentik/core/api/applications.py @@ -17,7 +17,6 @@ from rest_framework.parsers import MultiPartParser from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger @@ -26,6 +25,7 @@ from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.core.models import Application, User from authentik.events.logs import LogEventSerializer, capture_logs from authentik.events.models import EventAction diff --git a/authentik/core/api/authenticated_sessions.py b/authentik/core/api/authenticated_sessions.py index b8094238bfbe..3e8c0b34ab72 100644 --- a/authentik/core/api/authenticated_sessions.py +++ b/authentik/core/api/authenticated_sessions.py @@ -8,12 +8,12 @@ from rest_framework.fields import SerializerMethodField from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.request import Request -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from ua_parser import user_agent_parser from authentik.api.authorization import OwnerSuperuserPermissions from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.core.models import AuthenticatedSession from authentik.events.context_processors.asn import ASN_CONTEXT_PROCESSOR, ASNDict from authentik.events.context_processors.geoip import GEOIP_CONTEXT_PROCESSOR, GeoIPDict diff --git a/authentik/core/api/groups.py b/authentik/core/api/groups.py index 9e6751ec8883..fd9358152bf3 100644 --- a/authentik/core/api/groups.py +++ b/authentik/core/api/groups.py @@ -17,12 +17,12 @@ from rest_framework.fields import CharField, IntegerField, SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ListSerializer, ModelSerializer, ValidationError +from rest_framework.serializers import ListSerializer, ValidationError from rest_framework.validators import UniqueValidator from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import JSONDictField, PassiveSerializer +from authentik.core.api.utils import JSONDictField, ModelSerializer, PassiveSerializer from authentik.core.models import Group, User from authentik.rbac.api.roles import RoleSerializer from authentik.rbac.decorators import permission_required diff --git a/authentik/core/api/property_mappings.py b/authentik/core/api/property_mappings.py index 0b2f04ab1ef6..34c8fa59103b 100644 --- a/authentik/core/api/property_mappings.py +++ b/authentik/core/api/property_mappings.py @@ -8,11 +8,10 @@ from rest_framework import mixins from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied -from rest_framework.fields import BooleanField, CharField +from rest_framework.fields import BooleanField, CharField, SerializerMethodField from rest_framework.relations import PrimaryKeyRelatedField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet from authentik.blueprints.api import ManagedSerializer @@ -20,6 +19,7 @@ from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import ( MetaNameSerializer, + ModelSerializer, PassiveSerializer, ) from authentik.core.expression.evaluator import PropertyMappingEvaluator diff --git a/authentik/core/api/providers.py b/authentik/core/api/providers.py index 2c33ccf1f6c1..ae5547fe660e 100644 --- a/authentik/core/api/providers.py +++ b/authentik/core/api/providers.py @@ -6,13 +6,12 @@ from django_filters.filters import BooleanFilter from django_filters.filterset import FilterSet from rest_framework import mixins -from rest_framework.fields import ReadOnlyField -from rest_framework.serializers import ModelSerializer, SerializerMethodField +from rest_framework.fields import ReadOnlyField, SerializerMethodField from rest_framework.viewsets import GenericViewSet from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import MetaNameSerializer +from authentik.core.api.utils import MetaNameSerializer, ModelSerializer from authentik.core.models import Provider diff --git a/authentik/core/api/sources.py b/authentik/core/api/sources.py index 977696c4075d..8349ca084ddb 100644 --- a/authentik/core/api/sources.py +++ b/authentik/core/api/sources.py @@ -11,7 +11,6 @@ from rest_framework.parsers import MultiPartParser from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from structlog.stdlib import get_logger @@ -19,7 +18,7 @@ from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import MetaNameSerializer +from authentik.core.api.utils import MetaNameSerializer, ModelSerializer from authentik.core.models import Source, UserSourceConnection from authentik.core.types import UserSettingSerializer from authentik.lib.utils.file import ( diff --git a/authentik/core/api/tokens.py b/authentik/core/api/tokens.py index 43637f10d7ea..a615f0d30eef 100644 --- a/authentik/core/api/tokens.py +++ b/authentik/core/api/tokens.py @@ -12,7 +12,6 @@ from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.api.authorization import OwnerSuperuserPermissions @@ -20,7 +19,7 @@ from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserSerializer -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.core.models import ( USER_ATTRIBUTE_TOKEN_EXPIRING, USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME, diff --git a/authentik/core/api/users.py b/authentik/core/api/users.py index a617c1ce2e25..afa7fc908b14 100644 --- a/authentik/core/api/users.py +++ b/authentik/core/api/users.py @@ -40,7 +40,6 @@ BooleanField, DateTimeField, ListSerializer, - ModelSerializer, PrimaryKeyRelatedField, ValidationError, ) @@ -52,7 +51,12 @@ from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT from authentik.brands.models import Brand from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import JSONDictField, LinkSerializer, PassiveSerializer +from authentik.core.api.utils import ( + JSONDictField, + LinkSerializer, + ModelSerializer, + PassiveSerializer, +) from authentik.core.middleware import ( SESSION_KEY_IMPERSONATE_ORIGINAL_USER, SESSION_KEY_IMPERSONATE_USER, diff --git a/authentik/core/api/utils.py b/authentik/core/api/utils.py index 08e4a66f22dd..e4c335f1260c 100644 --- a/authentik/core/api/utils.py +++ b/authentik/core/api/utils.py @@ -12,9 +12,12 @@ JSONField, SerializerMethodField, ) +from rest_framework.serializers import ModelSerializer as BaseModelSerializer from rest_framework.serializers import ( Serializer, ValidationError, + model_meta, + raise_errors_on_nested_writes, ) @@ -25,6 +28,39 @@ def is_dict(value: Any): raise ValidationError("Value must be a dictionary, and not have any duplicate keys.") +class ModelSerializer(BaseModelSerializer): + + def update(self, instance: Model, validated_data): + raise_errors_on_nested_writes("update", self, validated_data) + info = model_meta.get_field_info(instance) + + # Simply set each attribute on the instance, and then save it. + # Note that unlike `.create()` we don't need to treat many-to-many + # relationships as being a special case. During updates we already + # have an instance pk for the relationships to be associated with. + m2m_fields = [] + for attr, value in validated_data.items(): + if attr in info.relations and info.relations[attr].to_many: + m2m_fields.append((attr, value)) + else: + setattr(instance, attr, value) + + instance.save() + + # Note that many-to-many fields are set after updating instance. + # Setting m2m fields triggers signals which could potentially change + # updated instance and we do not want it to collide with .update() + for attr, value in m2m_fields: + field = getattr(instance, attr) + # We can't check for inheritance here as m2m managers are generated dynamically + if field.__class__.__name__ == "RelatedManager": + field.set(value, bulk=False) + else: + field.set(value) + + return instance + + class JSONDictField(JSONField): """JSON Field which only allows dictionaries""" diff --git a/authentik/crypto/api.py b/authentik/crypto/api.py index a3e174387d24..95f4513f6117 100644 --- a/authentik/crypto/api.py +++ b/authentik/crypto/api.py @@ -24,13 +24,12 @@ from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger from authentik.api.authorization import SecretKeyFilter from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.crypto.apps import MANAGED_KEY from authentik.crypto.builder import CertificateBuilder, PrivateKeyAlg from authentik.crypto.models import CertificateKeyPair diff --git a/authentik/enterprise/api.py b/authentik/enterprise/api.py index fbe5a4bee527..9f66cd06539c 100644 --- a/authentik/enterprise/api.py +++ b/authentik/enterprise/api.py @@ -13,11 +13,10 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.core.models import User, UserTypes from authentik.enterprise.license import LicenseKey, LicenseSummarySerializer from authentik.enterprise.models import License diff --git a/authentik/enterprise/providers/google_workspace/api/groups.py b/authentik/enterprise/providers/google_workspace/api/groups.py index cd8799df8e95..28d5eecc8987 100644 --- a/authentik/enterprise/providers/google_workspace/api/groups.py +++ b/authentik/enterprise/providers/google_workspace/api/groups.py @@ -1,11 +1,11 @@ """GoogleWorkspaceProviderGroup API Views""" from rest_framework import mixins -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserGroupSerializer +from authentik.core.api.utils import ModelSerializer from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProviderGroup from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin diff --git a/authentik/enterprise/providers/google_workspace/api/users.py b/authentik/enterprise/providers/google_workspace/api/users.py index 9b8926209e58..a04dd58ae19c 100644 --- a/authentik/enterprise/providers/google_workspace/api/users.py +++ b/authentik/enterprise/providers/google_workspace/api/users.py @@ -1,11 +1,11 @@ """GoogleWorkspaceProviderUser API Views""" from rest_framework import mixins -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.core.api.groups import GroupMemberSerializer from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProviderUser from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin diff --git a/authentik/enterprise/providers/microsoft_entra/api/groups.py b/authentik/enterprise/providers/microsoft_entra/api/groups.py index ac3876483118..596ea4f8fc96 100644 --- a/authentik/enterprise/providers/microsoft_entra/api/groups.py +++ b/authentik/enterprise/providers/microsoft_entra/api/groups.py @@ -1,11 +1,11 @@ """MicrosoftEntraProviderGroup API Views""" from rest_framework import mixins -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserGroupSerializer +from authentik.core.api.utils import ModelSerializer from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProviderGroup from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin diff --git a/authentik/enterprise/providers/microsoft_entra/api/users.py b/authentik/enterprise/providers/microsoft_entra/api/users.py index c30dc647f2a8..b42971c058b3 100644 --- a/authentik/enterprise/providers/microsoft_entra/api/users.py +++ b/authentik/enterprise/providers/microsoft_entra/api/users.py @@ -1,11 +1,11 @@ """MicrosoftEntraProviderUser API Views""" from rest_framework import mixins -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.core.api.groups import GroupMemberSerializer from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProviderUser from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin diff --git a/authentik/enterprise/providers/rac/api/connection_tokens.py b/authentik/enterprise/providers/rac/api/connection_tokens.py index 00fb8f546f87..3455112cf2c4 100644 --- a/authentik/enterprise/providers/rac/api/connection_tokens.py +++ b/authentik/enterprise/providers/rac/api/connection_tokens.py @@ -3,12 +3,12 @@ from django_filters.rest_framework.backends import DjangoFilterBackend from rest_framework import mixins from rest_framework.filters import OrderingFilter, SearchFilter -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.api.authorization import OwnerFilter, OwnerSuperuserPermissions from authentik.core.api.groups import GroupMemberSerializer from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.enterprise.api import EnterpriseRequiredMixin from authentik.enterprise.providers.rac.api.endpoints import EndpointSerializer from authentik.enterprise.providers.rac.api.providers import RACProviderSerializer diff --git a/authentik/enterprise/providers/rac/api/endpoints.py b/authentik/enterprise/providers/rac/api/endpoints.py index 0dab4ca5f215..6cb4aea8fa34 100644 --- a/authentik/enterprise/providers/rac/api/endpoints.py +++ b/authentik/enterprise/providers/rac/api/endpoints.py @@ -8,11 +8,11 @@ from rest_framework.fields import SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.core.models import Provider from authentik.enterprise.api import EnterpriseRequiredMixin from authentik.enterprise.providers.rac.api.providers import RACProviderSerializer diff --git a/authentik/events/api/events.py b/authentik/events/api/events.py index 2e4ae6f3073a..609161152f6c 100644 --- a/authentik/events/api/events.py +++ b/authentik/events/api/events.py @@ -15,12 +15,11 @@ from rest_framework.fields import DictField, IntegerField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.admin.api.metrics import CoordinateSerializer from authentik.core.api.object_types import TypeCreateSerializer -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.events.models import Event, EventAction diff --git a/authentik/events/api/notification_mappings.py b/authentik/events/api/notification_mappings.py index 86a23fa8104d..7924e3dcae95 100644 --- a/authentik/events/api/notification_mappings.py +++ b/authentik/events/api/notification_mappings.py @@ -1,9 +1,9 @@ """NotificationWebhookMapping API Views""" -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.events.models import NotificationWebhookMapping diff --git a/authentik/events/api/notification_rules.py b/authentik/events/api/notification_rules.py index ada4332bb93a..4b183b9f6cd7 100644 --- a/authentik/events/api/notification_rules.py +++ b/authentik/events/api/notification_rules.py @@ -1,10 +1,10 @@ """NotificationRule API Views""" -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.groups import GroupSerializer from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.events.models import NotificationRule diff --git a/authentik/events/api/notification_transports.py b/authentik/events/api/notification_transports.py index 682bb7248ffe..3838d2fa8c93 100644 --- a/authentik/events/api/notification_transports.py +++ b/authentik/events/api/notification_transports.py @@ -9,11 +9,10 @@ from rest_framework.fields import CharField, ListField, SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.events.models import ( Event, Notification, diff --git a/authentik/events/api/notifications.py b/authentik/events/api/notifications.py index 3df2744ace3b..35cbd8825284 100644 --- a/authentik/events/api/notifications.py +++ b/authentik/events/api/notifications.py @@ -9,11 +9,11 @@ from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.events.api.events import EventSerializer from authentik.events.models import Notification diff --git a/authentik/events/api/tasks.py b/authentik/events/api/tasks.py index 529464ad5ff5..51c0b611c478 100644 --- a/authentik/events/api/tasks.py +++ b/authentik/events/api/tasks.py @@ -16,10 +16,10 @@ ) from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ReadOnlyModelViewSet from structlog.stdlib import get_logger +from authentik.core.api.utils import ModelSerializer from authentik.events.logs import LogEventSerializer from authentik.events.models import SystemTask, TaskStatus from authentik.rbac.decorators import permission_required diff --git a/authentik/flows/api/bindings.py b/authentik/flows/api/bindings.py index 7aa6098bce32..9ac3f8cc684f 100644 --- a/authentik/flows/api/bindings.py +++ b/authentik/flows/api/bindings.py @@ -3,10 +3,10 @@ from typing import Any from rest_framework.exceptions import ValidationError -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.flows.api.stages import StageSerializer from authentik.flows.models import FlowStageBinding diff --git a/authentik/flows/api/flows.py b/authentik/flows/api/flows.py index 121b3f8077bb..767ceea309d7 100644 --- a/authentik/flows/api/flows.py +++ b/authentik/flows/api/flows.py @@ -7,18 +7,22 @@ from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiResponse, extend_schema from rest_framework.decorators import action -from rest_framework.fields import BooleanField, CharField, ReadOnlyField +from rest_framework.fields import BooleanField, CharField, ReadOnlyField, SerializerMethodField from rest_framework.parsers import MultiPartParser from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger from authentik.blueprints.v1.exporter import FlowExporter from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT, Importer from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import CacheSerializer, LinkSerializer, PassiveSerializer +from authentik.core.api.utils import ( + CacheSerializer, + LinkSerializer, + ModelSerializer, + PassiveSerializer, +) from authentik.events.logs import LogEventSerializer from authentik.flows.api.flows_diagram import FlowDiagram, FlowDiagramSerializer from authentik.flows.exceptions import FlowNonApplicableException diff --git a/authentik/flows/api/stages.py b/authentik/flows/api/stages.py index a4973a62ec98..94169187d865 100644 --- a/authentik/flows/api/stages.py +++ b/authentik/flows/api/stages.py @@ -4,15 +4,15 @@ from drf_spectacular.utils import extend_schema from rest_framework import mixins from rest_framework.decorators import action +from rest_framework.fields import SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet from structlog.stdlib import get_logger from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import MetaNameSerializer +from authentik.core.api.utils import MetaNameSerializer, ModelSerializer from authentik.core.types import UserSettingSerializer from authentik.flows.api.flows import FlowSetSerializer from authentik.flows.models import ConfigurableStage, Stage diff --git a/authentik/lib/sync/outgoing/api.py b/authentik/lib/sync/outgoing/api.py index 6b496efc612b..6ecb13ddd2b6 100644 --- a/authentik/lib/sync/outgoing/api.py +++ b/authentik/lib/sync/outgoing/api.py @@ -7,9 +7,8 @@ from rest_framework.fields import BooleanField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.events.api.tasks import SystemTaskSerializer from authentik.lib.sync.outgoing.models import OutgoingSyncProvider diff --git a/authentik/outposts/api/outposts.py b/authentik/outposts/api/outposts.py index f3e697b090ef..2106a0f4d9a6 100644 --- a/authentik/outposts/api/outposts.py +++ b/authentik/outposts/api/outposts.py @@ -6,17 +6,17 @@ from django_filters.filterset import FilterSet from drf_spectacular.utils import extend_schema from rest_framework.decorators import action +from rest_framework.exceptions import ValidationError from rest_framework.fields import BooleanField, CharField, DateTimeField, SerializerMethodField from rest_framework.relations import PrimaryKeyRelatedField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer, ValidationError from rest_framework.viewsets import ModelViewSet from authentik import get_build_hash from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import JSONDictField, PassiveSerializer +from authentik.core.api.utils import JSONDictField, ModelSerializer, PassiveSerializer from authentik.core.models import Provider from authentik.enterprise.license import LicenseKey from authentik.enterprise.providers.rac.models import RACProvider diff --git a/authentik/outposts/api/service_connections.py b/authentik/outposts/api/service_connections.py index 2c4484f83c07..a677ccb5a463 100644 --- a/authentik/outposts/api/service_connections.py +++ b/authentik/outposts/api/service_connections.py @@ -12,13 +12,13 @@ from rest_framework.fields import BooleanField, CharField, ReadOnlyField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.core.api.object_types import TypesMixin from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import ( MetaNameSerializer, + ModelSerializer, PassiveSerializer, ) from authentik.outposts.models import ( diff --git a/authentik/policies/api/bindings.py b/authentik/policies/api/bindings.py index f9a5ab1c7e2a..d5ced3d1a55e 100644 --- a/authentik/policies/api/bindings.py +++ b/authentik/policies/api/bindings.py @@ -5,13 +5,15 @@ from django.core.exceptions import ObjectDoesNotExist from django_filters.filters import BooleanFilter, ModelMultipleChoiceFilter from django_filters.filterset import FilterSet -from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField, ValidationError +from rest_framework.exceptions import ValidationError +from rest_framework.serializers import PrimaryKeyRelatedField from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger from authentik.core.api.groups import GroupSerializer from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserSerializer +from authentik.core.api.utils import ModelSerializer from authentik.policies.api.policies import PolicySerializer from authentik.policies.models import PolicyBinding, PolicyBindingModel diff --git a/authentik/policies/api/policies.py b/authentik/policies/api/policies.py index 93137a0ce8c4..aa1b7c238131 100644 --- a/authentik/policies/api/policies.py +++ b/authentik/policies/api/policies.py @@ -6,9 +6,9 @@ from guardian.shortcuts import get_objects_for_user from rest_framework import mixins from rest_framework.decorators import action +from rest_framework.fields import SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet from structlog.stdlib import get_logger @@ -18,6 +18,7 @@ from authentik.core.api.utils import ( CacheSerializer, MetaNameSerializer, + ModelSerializer, ) from authentik.events.logs import LogEventSerializer, capture_logs from authentik.policies.api.exec import PolicyTestResultSerializer, PolicyTestSerializer diff --git a/authentik/policies/reputation/api.py b/authentik/policies/reputation/api.py index deb66eb1bb16..45644350f48b 100644 --- a/authentik/policies/reputation/api.py +++ b/authentik/policies/reputation/api.py @@ -3,10 +3,10 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import mixins from rest_framework.exceptions import ValidationError -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.policies.api.policies import PolicySerializer from authentik.policies.reputation.models import Reputation, ReputationPolicy diff --git a/authentik/providers/ldap/api.py b/authentik/providers/ldap/api.py index 70fa78ccaefc..ddbb7c11c50c 100644 --- a/authentik/providers/ldap/api.py +++ b/authentik/providers/ldap/api.py @@ -5,11 +5,11 @@ from django_filters.filters import BooleanFilter from django_filters.filterset import FilterSet from rest_framework.fields import CharField, ListField, SerializerMethodField -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.providers.ldap.models import LDAPProvider diff --git a/authentik/providers/oauth2/api/tokens.py b/authentik/providers/oauth2/api/tokens.py index efe8dd962516..23e3a5dae75c 100644 --- a/authentik/providers/oauth2/api/tokens.py +++ b/authentik/providers/oauth2/api/tokens.py @@ -7,12 +7,11 @@ from rest_framework import mixins from rest_framework.fields import CharField, ListField, SerializerMethodField from rest_framework.filters import OrderingFilter, SearchFilter -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserSerializer -from authentik.core.api.utils import MetaNameSerializer +from authentik.core.api.utils import MetaNameSerializer, ModelSerializer from authentik.providers.oauth2.api.providers import OAuth2ProviderSerializer from authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken diff --git a/authentik/providers/proxy/api.py b/authentik/providers/proxy/api.py index 70c81d6d4c59..aed400aba268 100644 --- a/authentik/providers/proxy/api.py +++ b/authentik/providers/proxy/api.py @@ -6,12 +6,11 @@ from drf_spectacular.utils import extend_schema_field from rest_framework.exceptions import ValidationError from rest_framework.fields import CharField, ListField, ReadOnlyField, SerializerMethodField -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.lib.utils.time import timedelta_from_string from authentik.providers.oauth2.models import ScopeMapping from authentik.providers.oauth2.views.provider import ProviderInfoView diff --git a/authentik/providers/radius/api.py b/authentik/providers/radius/api.py index e2ac193b8215..f32e90c1f5ac 100644 --- a/authentik/providers/radius/api.py +++ b/authentik/providers/radius/api.py @@ -1,11 +1,11 @@ """RadiusProvider API Views""" from rest_framework.fields import CharField, ListField -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.providers.radius.models import RadiusProvider diff --git a/authentik/providers/scim/api/groups.py b/authentik/providers/scim/api/groups.py index 9bb36c8337ef..bfd1f44362f1 100644 --- a/authentik/providers/scim/api/groups.py +++ b/authentik/providers/scim/api/groups.py @@ -1,11 +1,11 @@ """SCIMProviderGroup API Views""" from rest_framework import mixins -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserGroupSerializer +from authentik.core.api.utils import ModelSerializer from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin from authentik.providers.scim.models import SCIMProviderGroup diff --git a/authentik/providers/scim/api/users.py b/authentik/providers/scim/api/users.py index 5d58d3fdacbc..519f1864781a 100644 --- a/authentik/providers/scim/api/users.py +++ b/authentik/providers/scim/api/users.py @@ -1,11 +1,11 @@ """SCIMProviderUser API Views""" from rest_framework import mixins -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.core.api.groups import GroupMemberSerializer from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin from authentik.providers.scim.models import SCIMProviderUser diff --git a/authentik/rbac/api/rbac.py b/authentik/rbac/api/rbac.py index 517217ec6448..e00ea5ec514a 100644 --- a/authentik/rbac/api/rbac.py +++ b/authentik/rbac/api/rbac.py @@ -13,10 +13,9 @@ ReadOnlyField, SerializerMethodField, ) -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ReadOnlyModelViewSet -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.core.models import User from authentik.lib.validators import RequiredTogetherValidator from authentik.policies.event_matcher.models import model_choices diff --git a/authentik/rbac/api/rbac_assigned_by_roles.py b/authentik/rbac/api/rbac_assigned_by_roles.py index e52815e4af9e..fab814f17502 100644 --- a/authentik/rbac/api/rbac_assigned_by_roles.py +++ b/authentik/rbac/api/rbac_assigned_by_roles.py @@ -12,10 +12,9 @@ from rest_framework.mixins import ListModelMixin from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet -from authentik.core.api.utils import PassiveSerializer +from authentik.core.api.utils import ModelSerializer, PassiveSerializer from authentik.policies.event_matcher.models import model_choices from authentik.rbac.api.rbac import PermissionAssignSerializer from authentik.rbac.decorators import permission_required diff --git a/authentik/rbac/api/rbac_assigned_by_users.py b/authentik/rbac/api/rbac_assigned_by_users.py index adf0c99c4c23..403fac1df104 100644 --- a/authentik/rbac/api/rbac_assigned_by_users.py +++ b/authentik/rbac/api/rbac_assigned_by_users.py @@ -13,10 +13,10 @@ from rest_framework.mixins import ListModelMixin from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.core.api.groups import GroupMemberSerializer +from authentik.core.api.utils import ModelSerializer from authentik.core.models import User, UserTypes from authentik.policies.event_matcher.models import model_choices from authentik.rbac.api.rbac import PermissionAssignSerializer diff --git a/authentik/rbac/api/roles.py b/authentik/rbac/api/roles.py index 96df4a703982..86b2f7cd65fa 100644 --- a/authentik/rbac/api/roles.py +++ b/authentik/rbac/api/roles.py @@ -1,9 +1,9 @@ """RBAC Roles""" -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.rbac.models import Role diff --git a/authentik/stages/authenticator_duo/api.py b/authentik/stages/authenticator_duo/api.py index 90825938ec52..c80baa6f022c 100644 --- a/authentik/stages/authenticator_duo/api.py +++ b/authentik/stages/authenticator_duo/api.py @@ -12,12 +12,12 @@ from rest_framework.permissions import IsAdminUser from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet from structlog.stdlib import get_logger from authentik.api.authorization import OwnerFilter, OwnerPermissions from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.flows.api.stages import StageSerializer from authentik.rbac.decorators import permission_required from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice diff --git a/authentik/stages/authenticator_sms/api.py b/authentik/stages/authenticator_sms/api.py index b8784ce2102c..c5819bba9f5b 100644 --- a/authentik/stages/authenticator_sms/api.py +++ b/authentik/stages/authenticator_sms/api.py @@ -4,11 +4,11 @@ from rest_framework import mixins from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.permissions import IsAdminUser -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.flows.api.stages import StageSerializer from authentik.stages.authenticator_sms.models import AuthenticatorSMSStage, SMSDevice diff --git a/authentik/stages/authenticator_static/api.py b/authentik/stages/authenticator_static/api.py index 2bc0eb6e97a8..11971a6402e1 100644 --- a/authentik/stages/authenticator_static/api.py +++ b/authentik/stages/authenticator_static/api.py @@ -4,11 +4,11 @@ from rest_framework import mixins from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.permissions import IsAdminUser -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.flows.api.stages import StageSerializer from authentik.stages.authenticator_static.models import ( AuthenticatorStaticStage, diff --git a/authentik/stages/authenticator_totp/api.py b/authentik/stages/authenticator_totp/api.py index b0ca4d480e09..6da7afbbffcc 100644 --- a/authentik/stages/authenticator_totp/api.py +++ b/authentik/stages/authenticator_totp/api.py @@ -5,11 +5,11 @@ from rest_framework.fields import ChoiceField from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.permissions import IsAdminUser -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.flows.api.stages import StageSerializer from authentik.stages.authenticator_totp.models import ( AuthenticatorTOTPStage, diff --git a/authentik/stages/authenticator_webauthn/api/devices.py b/authentik/stages/authenticator_webauthn/api/devices.py index e1ccf85bbff4..3b761c4a84ce 100644 --- a/authentik/stages/authenticator_webauthn/api/devices.py +++ b/authentik/stages/authenticator_webauthn/api/devices.py @@ -4,11 +4,11 @@ from rest_framework import mixins from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.permissions import IsAdminUser -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions from authentik.core.api.used_by import UsedByMixin +from authentik.core.api.utils import ModelSerializer from authentik.stages.authenticator_webauthn.api.device_types import WebAuthnDeviceTypeSerializer from authentik.stages.authenticator_webauthn.models import WebAuthnDevice diff --git a/authentik/stages/invitation/api.py b/authentik/stages/invitation/api.py index bc63ae38d8f7..df32cf50125c 100644 --- a/authentik/stages/invitation/api.py +++ b/authentik/stages/invitation/api.py @@ -2,12 +2,11 @@ from django_filters.filters import BooleanFilter from django_filters.filterset import FilterSet -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.groups import GroupMemberSerializer from authentik.core.api.used_by import UsedByMixin -from authentik.core.api.utils import JSONDictField +from authentik.core.api.utils import JSONDictField, ModelSerializer from authentik.flows.api.flows import FlowSerializer from authentik.flows.api.stages import StageSerializer from authentik.stages.invitation.models import Invitation, InvitationStage diff --git a/authentik/tenants/api/domains.py b/authentik/tenants/api/domains.py index 9532edd7ba50..244173dd6231 100644 --- a/authentik/tenants/api/domains.py +++ b/authentik/tenants/api/domains.py @@ -3,9 +3,9 @@ from django.apps import apps from django.http import HttpResponseNotFound from rest_framework.filters import OrderingFilter, SearchFilter -from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet +from authentik.core.api.utils import ModelSerializer from authentik.tenants.api.tenants import TenantApiKeyPermission from authentik.tenants.models import Domain diff --git a/authentik/tenants/api/settings.py b/authentik/tenants/api/settings.py index 60a37225b342..ad98165c057a 100644 --- a/authentik/tenants/api/settings.py +++ b/authentik/tenants/api/settings.py @@ -3,8 +3,8 @@ from django_tenants.utils import get_public_schema_name from rest_framework.generics import RetrieveUpdateAPIView from rest_framework.permissions import SAFE_METHODS -from rest_framework.serializers import ModelSerializer +from authentik.core.api.utils import ModelSerializer from authentik.rbac.permissions import HasPermission from authentik.tenants.models import Tenant