Skip to content

Conversation

melizeche
Copy link
Member

…package)

Details

REPLACE ME


Checklist

  • Local tests pass (ak test authentik/)
  • The code has been formatted (make lint-fix)

If an API change has been made

  • The API schema has been updated (make gen-build)

If changes to the frontend have been made

  • The code has been formatted (make web)

If applicable

  • The documentation has been updated
  • The documentation has been formatted (make docs)

@melizeche melizeche requested a review from a team as a code owner September 3, 2025 17:16
Copy link

netlify bot commented Sep 3, 2025

Deploy Preview for authentik-storybook canceled.

Name Link
🔨 Latest commit 5109a6f
🔍 Latest deploy log https://app.netlify.com/projects/authentik-storybook/deploys/68b877fc31ac03000735a1c4

Copy link

netlify bot commented Sep 3, 2025

Deploy Preview for authentik-docs ready!

Name Link
🔨 Latest commit 5109a6f
🔍 Latest deploy log https://app.netlify.com/projects/authentik-docs/deploys/68b877fc2a10890008028f10
😎 Deploy Preview https://deploy-preview-16594--authentik-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@melizeche melizeche added the dependencies Pull requests that update a dependency file label Sep 3, 2025
Copy link

netlify bot commented Sep 3, 2025

Deploy Preview for authentik-integrations canceled.

Name Link
🔨 Latest commit 5109a6f
🔍 Latest deploy log https://app.netlify.com/projects/authentik-integrations/deploys/68b877fcb631280007ff70c3

Copy link

codecov bot commented Sep 3, 2025

❌ 86 Tests Failed:

Tests completed Failed Passed Skipped
2057 86 1971 2
View the top 3 failed test(s) by shortest run time
authentik.stages.user_login.tests.TestUserLoginStage::test_inactive_account
Stack Traces | 0.62s run time
self = <unittest.case._Outcome object at 0x7fbcc365c4b0>
test_case = <authentik.stages.user_login.tests.TestUserLoginStage testMethod=test_inactive_account>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.13.7........./x64/lib/python3.13/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.stages.user_login.tests.TestUserLoginStage testMethod=test_inactive_account>
result = <TestCaseFunction test_inactive_account>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.13.7........./x64/lib/python3.13/unittest/case.py:651: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.stages.user_login.tests.TestUserLoginStage testMethod=test_inactive_account>
method = <bound method TestUserLoginStage.test_inactive_account of <authentik.stages.user_login.tests.TestUserLoginStage testMethod=test_inactive_account>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.13.7........./x64/lib/python3.13/unittest/case.py:606: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<authentik.stages.user_login.tests.TestUserLoginStage testMethod=test_inactive_account>,)
kwargs = {}, file = 'default/flow-default-user-settings-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - User settings flow\nentries:\n  - attrs:\n      designation: stage_configura...   stage: !KeyOf default-user-settings-write\n      target: !KeyOf flow\n    model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
>           Importer.from_string(content).apply()

.../blueprints/tests/__init__.py:24: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7fbcc0c874d0>

    def apply(self) -> bool:
        """Apply (create/update) models yaml, in database transaction"""
        try:
            with atomic():
>               if not self._apply_models():

.../blueprints/v1/importer.py:376: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7fbcc0c874d0>
raise_errors = False

    def _apply_models(self, raise_errors=False) -> bool:
        """Apply (create/update) models yaml"""
        self.__pk_map = {}
        for entry in self._import.iter_entries():
            model_app_label, model_name = entry.get_model(self._import).split(".")
            try:
                model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
            except LookupError:
                self.logger.warning(
                    "App or Model does not exist", app=model_app_label, model=model_name
                )
                return False
            # Validate each single entry
            serializer = None
            try:
>               serializer = self._validate_single(entry)

.../blueprints/v1/importer.py:399: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7fbcc0c874d0>
entry = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-user-settings` and a model instance') raised in repr()] BlueprintEntry object at 0x7fbcc1b80550>

    def _validate_single(self, entry: BlueprintEntry) -> BaseSerializer | None:  # noqa: PLR0915
        """Validate a single entry"""
        if not entry.check_all_conditions_match(self._import):
            self.logger.debug("One or more conditions of this entry are not fulfilled, skipping")
            return None
    
        model_app_label, model_name = entry.get_model(self._import).split(".")
        try:
            model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
        except LookupError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        # Don't use isinstance since we don't want to check for inheritance
        if not is_model_allowed(model):
            raise EntryInvalidError.from_entry(f"Model {model} not allowed", entry)
        if issubclass(model, BaseMetaModel):
            serializer_class: type[Serializer] = model.serializer()
            serializer = serializer_class(
                data=entry.get_attrs(self._import),
                context={
                    SERIALIZER_CONTEXT_BLUEPRINT: entry,
                },
            )
            try:
                serializer.is_valid(raise_exception=True)
            except ValidationError as exc:
                raise EntryInvalidError.from_entry(
                    f"Serializer errors {serializer.errors}",
                    validation_error=exc,
                    entry=entry,
                ) from exc
            return serializer
    
        # If we try to validate without referencing a possible instance
        # we'll get a duplicate error, hence we load the model here and return
        # the full serializer for later usage
        # Because a model might have multiple unique columns, we chain all identifiers together
        # to create an OR query.
        updated_identifiers = self.__update_pks_for_attrs(entry.get_identifiers(self._import))
        for key, value in list(updated_identifiers.items()):
            if isinstance(value, dict) and "pk" in value:
                del updated_identifiers[key]
                updated_identifiers[f"{key}"] = value["pk"]
    
        query = self.__query_from_identifier(updated_identifiers)
        if not query:
            raise EntryInvalidError.from_entry("No or invalid identifiers", entry)
    
        try:
            existing_models = model.objects.filter(query)
        except FieldError as exc:
            raise EntryInvalidError.from_entry(f"Invalid identifier field: {exc}", entry) from exc
    
        serializer_kwargs = {}
        model_instance = existing_models.first()
        if (
            not isinstance(model(), BaseMetaModel)
            and model_instance
            and entry.state != BlueprintEntryDesiredState.MUST_CREATED
        ):
            self.logger.debug(
                "Initialise serializer with instance",
                model=model,
                instance=model_instance,
                pk=model_instance.pk,
            )
            serializer_kwargs["instance"] = model_instance
            serializer_kwargs["partial"] = True
        elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED:
            msg = (
                f"State is set to {BlueprintEntryDesiredState.MUST_CREATED.value} "
                "and object exists already",
            )
            raise EntryInvalidError.from_entry(
                ValidationError({k: msg for k in entry.identifiers.keys()}, "unique"),
                entry,
            )
        else:
            self.logger.debug(
                "Initialised new serializer instance",
                model=model,
                **cleanse_dict(updated_identifiers),
            )
            model_instance = model()
            # pk needs to be set on the model instance otherwise a new one will be generated
            if "pk" in updated_identifiers:
                model_instance.pk = updated_identifiers["pk"]
            serializer_kwargs["instance"] = model_instance
        try:
            full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import))
        except ValueError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        always_merger.merge(full_data, updated_identifiers)
        serializer_kwargs["data"] = full_data
    
        serializer: Serializer = model().serializer(
            context={
                SERIALIZER_CONTEXT_BLUEPRINT: entry,
            },
            **serializer_kwargs,
        )
        try:
>           serializer.is_valid(raise_exception=True)

.../blueprints/v1/importer.py:353: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-user-settings` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7fbcc1019940>

    def is_valid(self, *, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )
    
        if not hasattr(self, '_validated_data'):
            try:
>               self._validated_data = self.run_validation(self.initial_data)

.venv/lib/python3.13........./site-packages/rest_framework/serializers.py:225: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-user-settings` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7fbcc1019940>
data = {'order': 20, 'stage': UUID('88d0f8a4-48bb-4ab6-b064-c3f826fa1d4f'), 'target': UUID('4052807c-c8c8-4ac5-98b7-2bf326bab789')}

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
    
        value = self.to_internal_value(data)
        try:
>           self.run_validators(value)

.venv/lib/python3.13........./site-packages/rest_framework/serializers.py:446: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-user-settings` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7fbcc1019940>
value = {'order': 20, 'stage': <Stage: Stage default-user-settings>, 'target': <Flow: Flow User settings (default-user-settings-flow)>}

    def run_validators(self, value):
        """
        Add read_only fields with defaults to value before running validators.
        """
        if isinstance(value, dict):
            to_validate = self._read_only_defaults()
            to_validate.update(value)
        else:
            to_validate = value
>       super().run_validators(to_validate)

.venv/lib/python3.13........./site-packages/rest_framework/serializers.py:479: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-user-settings` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7fbcc1019940>
value = {'order': 20, 'stage': <Stage: Stage default-user-settings>, 'target': <Flow: Flow User settings (default-user-settings-flow)>}

    def run_validators(self, value):
        """
        Test the given value against all the validators on the field,
        and either raise a `ValidationError` or simply return.
        """
        errors = []
        for validator in self.validators:
            try:
                if getattr(validator, 'requires_context', False):
>                   validator(value, self)

.venv/lib/python3.13.../site-packages/rest_framework/fields.py:551: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <UniqueTogetherValidator(queryset=FlowStageBinding.objects.all(), fields=('target', 'stage', 'order'))>
attrs = {'order': 20, 'stage': <Stage: Stage default-user-settings>, 'target': <Flow: Flow User settings (default-user-settings-flow)>}
serializer = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `default-user-settings` and a model instance') raised in repr()] FlowStageBindingSerializer object at 0x7fbcc1019940>

    def __call__(self, attrs, serializer):
        self.enforce_required_fields(attrs, serializer)
        queryset = self.queryset
        queryset = self.filter_queryset(attrs, queryset, serializer)
        queryset = self.exclude_current_instance(attrs, queryset, serializer.instance)
    
        checked_names = [
            serializer.fields[field_name].source for field_name in self.fields
        ]
        # Ignore validation if any field is None
        if serializer.instance is None:
            checked_values = [attrs[field_name] for field_name in checked_names]
        else:
            # Ignore validation if all field values are unchanged
            checked_values = [
                attrs[field_name]
                for field_name in checked_names
>               if attrs[field_name] != getattr(serializer.instance, field_name)
            ]

.venv/lib/python3.13.../site-packages/rest_framework/validators.py:188: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x7fbccc23ab20>
instance = <FlowStageBinding: Flow-stage binding #None to None>
cls = <class 'authentik.flows.models.FlowStageBinding'>

    def __get__(self, instance, cls=None):
        """
        Get the related instance through the forward relation.
    
        With the example above, when getting ``child.parent``:
    
        - ``self`` is the descriptor managing the ``parent`` attribute
        - ``instance`` is the ``child`` instance
        - ``cls`` is the ``Child`` class (we don't need it)
        """
        if instance is None:
            return self
    
        # The related instance is loaded from the database and then cached
        # by the field on the model instance state. It can also be pre-cached
        # by the reverse accessor (ReverseOneToOneDescriptor).
        try:
            rel_obj = self.field.get_cached_value(instance)
        except KeyError:
            has_value = None not in self.field.get_local_related_value(instance)
            ancestor_link = (
                instance._meta.get_ancestor_link(self.field.model)
                if has_value
                else None
            )
            if ancestor_link and ancestor_link.is_cached(instance):
                # An ancestor link will exist if this field is defined on a
                # multi-table inheritance parent of the instance's class.
                ancestor = ancestor_link.get_cached_value(instance)
                # The value might be cached on an ancestor if the instance
                # originated from walking down the inheritance chain.
                rel_obj = self.field.get_cached_value(ancestor, default=None)
            else:
                rel_obj = None
            if rel_obj is None and has_value:
                rel_obj = self.get_object(instance)
                remote_field = self.field.remote_field
                # If this is a one-to-one relation, set the reverse accessor
                # cache on the related object to the current instance to avoid
                # an extra SQL query if it's accessed later on.
                if not remote_field.multiple:
                    remote_field.set_cached_value(rel_obj, instance)
            self.field.set_cached_value(instance, rel_obj)
    
        if rel_obj is None and not self.field.null:
>           raise self.RelatedObjectDoesNotExist(
                "%s has no %s." % (self.field.model.__name__, self.field.name)
            )
E           authentik.flows.models.FlowStageBinding.target.RelatedObjectDoesNotExist: FlowStageBinding has no target.. Did you mean: 'target_id'?

.venv/lib/python3.13.../models/fields/related_descriptors.py:267: RelatedObjectDoesNotExist
authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI::test_create_transactional_bindings
Stack Traces | 1.01s run time
self = <unittest.case._Outcome object at 0x7fbcc1fae890>
test_case = <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.13.7........./x64/lib/python3.13/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>
result = <TestCaseFunction test_create_transactional_bindings>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.13.7........./x64/lib/python3.13/unittest/case.py:651: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>
method = <bound method TestTransactionalApplicationsAPI.test_create_transactional_bindings of <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.13.7........./x64/lib/python3.13/unittest/case.py:606: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.tests.test_transactional_applications_api.TestTransactionalApplicationsAPI testMethod=test_create_transactional_bindings>

    def test_create_transactional_bindings(self):
        """Test transactional Application + provider creation"""
        assign_perm("authentik_policies.add_policybinding", self.user)
        self.client.force_login(self.user)
        uid = generate_id()
        group = Group.objects.create(name=generate_id())
        authorization_flow = create_test_flow()
>       response = self.client.put(
            reverse("authentik_api:core-transactional-application"),
            data={
                "app": {
                    "name": uid,
                    "slug": uid,
                },
                "provider_model": "authentik_providers_oauth2.oauth2provider",
                "provider": {
                    "name": uid,
                    "authorization_flow": str(authorization_flow.pk),
                    "invalidation_flow": str(authorization_flow.pk),
                    "redirect_uris": [],
                },
                "policy_bindings": [{"group": group.pk, "order": 0}],
            },
        )

.../core/tests/test_transactional_applications_api.py:81: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7fbcbc1da8e0>
path = '.../core/transactional/applications/'
data = {'app': {'name': 'nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a', 'slug': 'nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a'}, 'pol...aVp2R1HWRyoXnoarylIUiGWAUEF25X8a', 'redirect_uris': []}, 'provider_model': 'authentik_providers_oauth2.oauth2provider'}
format = None, content_type = None, follow = False, extra = {}

    def put(self, path, data=None, format=None, content_type=None,
            follow=False, **extra):
>       response = super().put(
            path, data=data, format=format, content_type=content_type, **extra)

.venv/lib/python3.13.............../site-packages/rest_framework/test.py:307: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7fbcbc1da8e0>
path = '.../core/transactional/applications/'
data = b'{"app":{"name":"nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a","slug":"nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a"},"provid...be28-991b523ffc6e","redirect_uris":[]},"policy_bindings":[{"group":"8370199a-77bf-4d39-8a5f-e940726e421e","order":0}]}'
format = None, content_type = 'application/json', extra = {}

    def put(self, path, data=None, format=None, content_type=None, **extra):
        data, content_type = self._encode_data(data, format, content_type)
>       return self.generic('PUT', path, data, content_type, **extra)

.venv/lib/python3.13.............../site-packages/rest_framework/test.py:217: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7fbcbc1da8e0>, method = 'PUT'
path = '.../core/transactional/applications/'
data = b'{"app":{"name":"nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a","slug":"nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a"},"provid...be28-991b523ffc6e","redirect_uris":[]},"policy_bindings":[{"group":"8370199a-77bf-4d39-8a5f-e940726e421e","order":0}]}'
content_type = 'application/json', secure = False
extra = {'CONTENT_TYPE': 'application/json'}

    def generic(self, method, path, data='',
                content_type='application/octet-stream', secure=False, **extra):
        # Include the CONTENT_TYPE, regardless of whether or not data is empty.
        if content_type is not None:
            extra['CONTENT_TYPE'] = str(content_type)
    
>       return super().generic(
            method, path, data, content_type, secure, **extra)

.venv/lib/python3.13.............../site-packages/rest_framework/test.py:237: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7fbcbc1da8e0>, method = 'PUT'
path = '.../core/transactional/applications/'
data = b'{"app":{"name":"nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a","slug":"nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a"},"provid...be28-991b523ffc6e","redirect_uris":[]},"policy_bindings":[{"group":"8370199a-77bf-4d39-8a5f-e940726e421e","order":0}]}'
content_type = 'application/json', secure = False, headers = None
query_params = None, extra = {'CONTENT_TYPE': 'application/json'}
parsed = ParseResult(scheme='', netloc='', path='.../core/transactional/applications/', params='', query='', fragment='')
r = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'PATH_INFO': '.../core/transactional/applications/', 'QUERY_STRING': '', ...}
query_string = ''

    def generic(
        self,
        method,
        path,
        data="",
        content_type="application/octet-stream",
        secure=False,
        *,
        headers=None,
        query_params=None,
        **extra,
    ):
        """Construct an arbitrary HTTP request."""
        parsed = urlparse(str(path))  # path can be lazy
        data = force_bytes(data, settings.DEFAULT_CHARSET)
        r = {
            "PATH_INFO": self._get_path(parsed),
            "REQUEST_METHOD": method,
            "SERVER_PORT": "443" if secure else "80",
            "wsgi.url_scheme": "https" if secure else "http",
        }
        if data:
            r.update(
                {
                    "CONTENT_LENGTH": str(len(data)),
                    "CONTENT_TYPE": content_type,
                    "wsgi.input": FakePayload(data),
                }
            )
        if headers:
            extra.update(HttpHeaders.to_wsgi_names(headers))
        if query_params:
            extra["QUERY_STRING"] = urlencode(query_params, doseq=True)
        r.update(extra)
        # If QUERY_STRING is absent or empty, we want to extract it from the URL.
        if not r.get("QUERY_STRING"):
            # WSGI requires latin-1 encoded strings. See get_path_info().
            query_string = parsed[4].encode().decode("iso-8859-1")
            r["QUERY_STRING"] = query_string
>       return self.request(**r)

.venv/lib/python3.13.../django/test/client.py:676: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7fbcbc1da8e0>
kwargs = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'PATH_INFO': '.../core/transactional/applications/', 'QUERY_STRING': '', ...}

    def request(self, **kwargs):
        # Ensure that any credentials set get added to every request.
        kwargs.update(self._credentials)
>       return super().request(**kwargs)

.venv/lib/python3.13.............../site-packages/rest_framework/test.py:289: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7fbcbc1da8e0>
kwargs = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'PATH_INFO': '.../core/transactional/applications/', 'QUERY_STRING': '', ...}

    def request(self, **kwargs):
>       request = super().request(**kwargs)

.venv/lib/python3.13.............../site-packages/rest_framework/test.py:241: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7fbcbc1da8e0>
request = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'PATH_INFO': '.../core/transactional/applications/', 'QUERY_STRING': '', ...}
environ = {'CONTENT_LENGTH': '450', 'CONTENT_TYPE': 'application/json', 'HTTP_COOKIE': 'authentik_session=55k4lx6zk1mb5uphbeeg07chxuq4pvtp', 'PATH_INFO': '.../core/transactional/applications/', ...}
data = {}
on_template_render = functools.partial(<function store_rendered_templates at 0x7fbccc5b23e0>, {})
signal_uid = 'template-render-140448617294848'
exception_uid = 'request-exception-140448617294848'
response = <HttpResponseNotAllowed [GET, HEAD, OPTIONS] status_code=405, "text/html; charset=utf-8">

    def request(self, **request):
        """
        Make a generic request. Compose the environment dictionary and pass
        to the handler, return the result of the handler. Assume defaults for
        the query environment, which can be overridden using the arguments to
        the request.
        """
        environ = self._base_environ(**request)
    
        # Curry a data dictionary into an instance of the template renderer
        # callback function.
        data = {}
        on_template_render = partial(store_rendered_templates, data)
        signal_uid = "template-render-%s" % id(request)
        signals.template_rendered.connect(on_template_render, dispatch_uid=signal_uid)
        # Capture exceptions created by the handler.
        exception_uid = "request-exception-%s" % id(request)
        got_request_exception.connect(self.store_exc_info, dispatch_uid=exception_uid)
        try:
            response = self.handler(environ)
        finally:
            signals.template_rendered.disconnect(dispatch_uid=signal_uid)
            got_request_exception.disconnect(dispatch_uid=exception_uid)
        # Check for signaled exceptions.
>       self.check_exception(response)

.venv/lib/python3.13.../django/test/client.py:1092: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7fbcbc1da8e0>
response = <HttpResponseNotAllowed [GET, HEAD, OPTIONS] status_code=405, "text/html; charset=utf-8">

    def check_exception(self, response):
        """
        Look for a signaled exception, clear the current context exception
        data, re-raise the signaled exception, and clear the signaled exception
        from the local cache.
        """
        response.exc_info = self.exc_info
        if self.exc_info:
            _, exc_value, _ = self.exc_info
            self.exc_info = None
            if self.raise_request_exception:
>               raise exc_value

.venv/lib/python3.13.../django/test/client.py:805: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <WSGIRequest: PUT '.../core/transactional/applications/'>

    @wraps(get_response)
    def inner(request):
        try:
>           response = get_response(request)

.venv/lib/python3.13.../core/handlers/exception.py:55: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.ForceAuthClientHandler object at 0x7fbcc3d29750>
request = <WSGIRequest: PUT '.../core/transactional/applications/'>

    def _get_response(self, request):
        """
        Resolve and call the view, then apply view, exception, and
        template_response middleware. This method is everything that happens
        inside the request/response middleware.
        """
        response = None
        callback, callback_args, callback_kwargs = self.resolve_request(request)
    
        # Apply view middleware
        for middleware_method in self._view_middleware:
            response = middleware_method(
                request, callback, callback_args, callback_kwargs
            )
            if response:
                break
    
        if response is None:
            wrapped_callback = self.make_view_atomic(callback)
            # If it is an asynchronous view, run it in a subthread.
            if iscoroutinefunction(wrapped_callback):
                wrapped_callback = async_to_sync(wrapped_callback)
            try:
>               response = wrapped_callback(request, *callback_args, **callback_kwargs)

.venv/lib/python3.13.../core/handlers/base.py:197: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <WSGIRequest: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}
current_scope = <Scope id=0x7fbcd16966c0 name=None type=ScopeType.CURRENT>
sentry_scope = <Scope id=0x7fbcd1811540 name=None type=ScopeType.ISOLATION>

    @functools.wraps(callback)
    def sentry_wrapped_callback(request, *args, **kwargs):
        # type: (Any, *Any, **Any) -> Any
        current_scope = sentry_sdk.get_current_scope()
        if current_scope.transaction is not None:
            current_scope.transaction.update_active_thread()
    
        sentry_scope = sentry_sdk.get_isolation_scope()
        # set the active thread id to the handler thread for sync views
        # this isn't necessary for async views since that runs on main
        if sentry_scope.profile is not None:
            sentry_scope.profile.update_active_thread_id()
    
        with sentry_sdk.start_span(
            op=OP.VIEW_RENDER,
            name=request.resolver_match.view_name,
            origin=DjangoIntegration.origin,
        ):
>           return callback(request, *args, **kwargs)

.venv/lib/python3.13.../integrations/django/views.py:94: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <WSGIRequest: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}

    def _view_wrapper(request, *args, **kwargs):
>       return view_func(request, *args, **kwargs)

.venv/lib/python3.13.../views/decorators/csrf.py:65: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <WSGIRequest: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}
self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7fbcbcbd4640>

    def view(request, *args, **kwargs):
        self = cls(**initkwargs)
        self.setup(request, *args, **kwargs)
        if not hasattr(self, "request"):
            raise AttributeError(
                "%s instance has no 'request' attribute. Did you override "
                "setup() and forget to call super()?" % cls.__name__
            )
>       return self.dispatch(request, *args, **kwargs)

.venv/lib/python3.13.../views/generic/base.py:105: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7fbcbcbd4640>
request = <rest_framework.request.Request: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}
handler = <bound method TransactionalApplicationView.put of <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7fbcbcbd4640>>

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
    
        try:
            self.initial(request, *args, **kwargs)
    
            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
    
            response = handler(request, *args, **kwargs)
    
        except Exception as exc:
>           response = self.handle_exception(exc)

.venv/lib/python3.13............/site-packages/rest_framework/views.py:515: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7fbcbcbd4640>
exc = RelatedObjectDoesNotExist('PolicyBinding has no target.')

    def handle_exception(self, exc):
        """
        Handle any exception that occurs, by returning an appropriate response,
        or re-raising the error.
        """
        if isinstance(exc, (exceptions.NotAuthenticated,
                            exceptions.AuthenticationFailed)):
            # WWW-Authenticate header for 401 responses, else coerce to 403
            auth_header = self.get_authenticate_header(self.request)
    
            if auth_header:
                exc.auth_header = auth_header
            else:
                exc.status_code = status.HTTP_403_FORBIDDEN
    
        exception_handler = self.get_exception_handler()
    
        context = self.get_exception_handler_context()
        response = exception_handler(exc, context)
    
        if response is None:
>           self.raise_uncaught_exception(exc)

.venv/lib/python3.13............/site-packages/rest_framework/views.py:475: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7fbcbcbd4640>
exc = RelatedObjectDoesNotExist('PolicyBinding has no target.')

    def raise_uncaught_exception(self, exc):
        if settings.DEBUG:
            request = self.request
            renderer_format = getattr(request.accepted_renderer, 'format')
            use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin')
            request.force_plaintext_errors(use_plaintext_traceback)
>       raise exc

.venv/lib/python3.13............/site-packages/rest_framework/views.py:486: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7fbcbcbd4640>
request = <rest_framework.request.Request: PUT '.../core/transactional/applications/'>
args = (), kwargs = {}
handler = <bound method TransactionalApplicationView.put of <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7fbcbcbd4640>>

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
    
        try:
            self.initial(request, *args, **kwargs)
    
            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
    
>           response = handler(request, *args, **kwargs)

.venv/lib/python3.13............/site-packages/rest_framework/views.py:512: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.core.api.transactional_applications.TransactionalApplicationView object at 0x7fbcbcbd4640>
request = <rest_framework.request.Request: PUT '.../core/transactional/applications/'>

    @extend_schema(
        request=TransactionApplicationSerializer(),
        responses={
            200: TransactionApplicationResponseSerializer(),
        },
    )
    def put(self, request: Request) -> Response:
        """Convert data into a blueprint, validate it and apply it"""
        data = TransactionApplicationSerializer(data=request.data)
>       data.is_valid(raise_exception=True)

.../core/api/transactional_applications.py:166: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = TransactionApplicationSerializer(data={'app': {'name': 'nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a', 'slug': 'nOsqXUr5aV...equired=False)
        failure_result = BooleanField(help_text='Result if the Policy execution fails.', required=False)

    def is_valid(self, *, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )
    
        if not hasattr(self, '_validated_data'):
            try:
>               self._validated_data = self.run_validation(self.initial_data)

.venv/lib/python3.13.............../site-packages/rest_framework/serializers.py:225: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = TransactionApplicationSerializer(data={'app': {'name': 'nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a', 'slug': 'nOsqXUr5aV...equired=False)
        failure_result = BooleanField(help_text='Result if the Policy execution fails.', required=False)
data = {'app': {'name': 'nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a', 'slug': 'nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a'}, 'pol...aVp2R1HWRyoXnoarylIUiGWAUEF25X8a', 'redirect_uris': []}, 'provider_model': 'authentik_providers_oauth2.oauth2provider'}

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
    
        value = self.to_internal_value(data)
        try:
            self.run_validators(value)
>           value = self.validate(value)

.venv/lib/python3.13.............../site-packages/rest_framework/serializers.py:447: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = TransactionApplicationSerializer(data={'app': {'name': 'nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a', 'slug': 'nOsqXUr5aV...equired=False)
        failure_result = BooleanField(help_text='Result if the Policy execution fails.', required=False)
attrs = {'app': {'name': 'nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a', 'provider': <[EntryInvalidError('KeyOf: failed to find en...aVp2R1HWRyoXnoarylIUiGWAUEF25X8a', 'redirect_uris': []}, 'provider_model': 'authentik_providers_oauth2.oauth2provider'}

    def validate(self, attrs: dict) -> dict:
        blueprint = Blueprint()
        blueprint.entries.append(
            BlueprintEntry(
                model=attrs["provider_model"],
                state=BlueprintEntryDesiredState.MUST_CREATED,
                identifiers={
                    "name": attrs["provider"]["name"],
                },
                # Must match the name of the field on `self`
                id="provider",
                attrs=attrs["provider"],
            )
        )
        app_data = attrs["app"]
        app_data["provider"] = KeyOf(None, ScalarNode(tag="", value="provider"))
        blueprint.entries.append(
            BlueprintEntry(
                model="authentik_core.application",
                state=BlueprintEntryDesiredState.MUST_CREATED,
                identifiers={
                    "slug": attrs["app"]["slug"],
                },
                attrs=app_data,
                # Must match the name of the field on `self`
                id="app",
            )
        )
        for binding in attrs.get("policy_bindings", []):
            binding["target"] = KeyOf(None, ScalarNode(tag="", value="app"))
            for key, value in binding.items():
                if not isinstance(value, Model):
                    continue
                binding[key] = value.pk
            blueprint.entries.append(
                BlueprintEntry(
                    model="authentik_policies.policybinding",
                    state=BlueprintEntryDesiredState.MUST_CREATED,
                    identifiers=binding,
                )
            )
        importer = Importer(blueprint, {})
        try:
>           valid, _ = importer.validate(raise_validation_errors=True)

.../core/api/transactional_applications.py:133: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7fbcc11a5eb0>
raise_validation_errors = True

    def validate(self, raise_validation_errors=False) -> tuple[bool, list[LogEvent]]:
        """Validate loaded blueprint export, ensure all models are allowed
        and serializers have no errors"""
        self.logger.debug("Starting blueprint import validation")
        orig_import = deepcopy(self._import)
        if self._import.version != 1:
            self.logger.warning("Invalid blueprint version")
            return False, [LogEvent("Invalid blueprint version", log_level="warning", logger=None)]
        with (
            transaction_rollback(),
            capture_logs() as logs,
        ):
>           successful = self._apply_models(raise_errors=raise_validation_errors)

.../blueprints/v1/importer.py:458: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7fbcc11a5eb0>
raise_errors = True

    def _apply_models(self, raise_errors=False) -> bool:
        """Apply (create/update) models yaml"""
        self.__pk_map = {}
        for entry in self._import.iter_entries():
            model_app_label, model_name = entry.get_model(self._import).split(".")
            try:
                model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
            except LookupError:
                self.logger.warning(
                    "App or Model does not exist", app=model_app_label, model=model_name
                )
                return False
            # Validate each single entry
            serializer = None
            try:
>               serializer = self._validate_single(entry)

.../blueprints/v1/importer.py:399: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7fbcc11a5eb0>
entry = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] BlueprintEntry object at 0x7fbcc0fc7610>

    def _validate_single(self, entry: BlueprintEntry) -> BaseSerializer | None:  # noqa: PLR0915
        """Validate a single entry"""
        if not entry.check_all_conditions_match(self._import):
            self.logger.debug("One or more conditions of this entry are not fulfilled, skipping")
            return None
    
        model_app_label, model_name = entry.get_model(self._import).split(".")
        try:
            model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
        except LookupError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        # Don't use isinstance since we don't want to check for inheritance
        if not is_model_allowed(model):
            raise EntryInvalidError.from_entry(f"Model {model} not allowed", entry)
        if issubclass(model, BaseMetaModel):
            serializer_class: type[Serializer] = model.serializer()
            serializer = serializer_class(
                data=entry.get_attrs(self._import),
                context={
                    SERIALIZER_CONTEXT_BLUEPRINT: entry,
                },
            )
            try:
                serializer.is_valid(raise_exception=True)
            except ValidationError as exc:
                raise EntryInvalidError.from_entry(
                    f"Serializer errors {serializer.errors}",
                    validation_error=exc,
                    entry=entry,
                ) from exc
            return serializer
    
        # If we try to validate without referencing a possible instance
        # we'll get a duplicate error, hence we load the model here and return
        # the full serializer for later usage
        # Because a model might have multiple unique columns, we chain all identifiers together
        # to create an OR query.
        updated_identifiers = self.__update_pks_for_attrs(entry.get_identifiers(self._import))
        for key, value in list(updated_identifiers.items()):
            if isinstance(value, dict) and "pk" in value:
                del updated_identifiers[key]
                updated_identifiers[f"{key}"] = value["pk"]
    
        query = self.__query_from_identifier(updated_identifiers)
        if not query:
            raise EntryInvalidError.from_entry("No or invalid identifiers", entry)
    
        try:
            existing_models = model.objects.filter(query)
        except FieldError as exc:
            raise EntryInvalidError.from_entry(f"Invalid identifier field: {exc}", entry) from exc
    
        serializer_kwargs = {}
        model_instance = existing_models.first()
        if (
            not isinstance(model(), BaseMetaModel)
            and model_instance
            and entry.state != BlueprintEntryDesiredState.MUST_CREATED
        ):
            self.logger.debug(
                "Initialise serializer with instance",
                model=model,
                instance=model_instance,
                pk=model_instance.pk,
            )
            serializer_kwargs["instance"] = model_instance
            serializer_kwargs["partial"] = True
        elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED:
            msg = (
                f"State is set to {BlueprintEntryDesiredState.MUST_CREATED.value} "
                "and object exists already",
            )
            raise EntryInvalidError.from_entry(
                ValidationError({k: msg for k in entry.identifiers.keys()}, "unique"),
                entry,
            )
        else:
            self.logger.debug(
                "Initialised new serializer instance",
                model=model,
                **cleanse_dict(updated_identifiers),
            )
            model_instance = model()
            # pk needs to be set on the model instance otherwise a new one will be generated
            if "pk" in updated_identifiers:
                model_instance.pk = updated_identifiers["pk"]
            serializer_kwargs["instance"] = model_instance
        try:
            full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import))
        except ValueError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        always_merger.merge(full_data, updated_identifiers)
        serializer_kwargs["data"] = full_data
    
        serializer: Serializer = model().serializer(
            context={
                SERIALIZER_CONTEXT_BLUEPRINT: entry,
            },
            **serializer_kwargs,
        )
        try:
>           serializer.is_valid(raise_exception=True)

.../blueprints/v1/importer.py:353: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7fbcbcbd7ce0>

    def is_valid(self, *, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )
    
        if not hasattr(self, '_validated_data'):
            try:
>               self._validated_data = self.run_validation(self.initial_data)

.venv/lib/python3.13.............../site-packages/rest_framework/serializers.py:225: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7fbcbcbd7ce0>
data = {'group': UUID('8370199a-77bf-4d39-8a5f-e940726e421e'), 'order': 0, 'target': UUID('7fecc4f1-b167-4b0a-8fe3-7da845655234')}

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
    
        value = self.to_internal_value(data)
        try:
>           self.run_validators(value)

.venv/lib/python3.13.............../site-packages/rest_framework/serializers.py:446: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7fbcbcbd7ce0>
value = {'group': <Group: Group bO8CyPGdrRUhJFeSVg6NAp5mZuPj06VfdK9LnSUu>, 'order': 0, 'policy': None, 'target': <Application: nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a>}

    def run_validators(self, value):
        """
        Add read_only fields with defaults to value before running validators.
        """
        if isinstance(value, dict):
            to_validate = self._read_only_defaults()
            to_validate.update(value)
        else:
            to_validate = value
>       super().run_validators(to_validate)

.venv/lib/python3.13.............../site-packages/rest_framework/serializers.py:479: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7fbcbcbd7ce0>
value = {'group': <Group: Group bO8CyPGdrRUhJFeSVg6NAp5mZuPj06VfdK9LnSUu>, 'order': 0, 'policy': None, 'target': <Application: nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a>}

    def run_validators(self, value):
        """
        Test the given value against all the validators on the field,
        and either raise a `ValidationError` or simply return.
        """
        errors = []
        for validator in self.validators:
            try:
                if getattr(validator, 'requires_context', False):
>                   validator(value, self)

.venv/lib/python3.13.../site-packages/rest_framework/fields.py:551: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <UniqueTogetherValidator(queryset=PolicyBinding.objects.all(), fields=('policy', 'target', 'order'))>
attrs = {'group': <Group: Group bO8CyPGdrRUhJFeSVg6NAp5mZuPj06VfdK9LnSUu>, 'order': 0, 'policy': None, 'target': <Application: nOsqXUr5aVp2R1HWRyoXnoarylIUiGWAUEF25X8a>}
serializer = <[EntryInvalidError('KeyOf: failed to find entry with `id` of `app` and a model instance') raised in repr()] PolicyBindingSerializer object at 0x7fbcbcbd7ce0>

    def __call__(self, attrs, serializer):
        self.enforce_required_fields(attrs, serializer)
        queryset = self.queryset
        queryset = self.filter_queryset(attrs, queryset, serializer)
        queryset = self.exclude_current_instance(attrs, queryset, serializer.instance)
    
        checked_names = [
            serializer.fields[field_name].source for field_name in self.fields
        ]
        # Ignore validation if any field is None
        if serializer.instance is None:
            checked_values = [attrs[field_name] for field_name in checked_names]
        else:
            # Ignore validation if all field values are unchanged
            checked_values = [
                attrs[field_name]
                for field_name in checked_names
>               if attrs[field_name] != getattr(serializer.instance, field_name)
            ]

.venv/lib/python3.13.../site-packages/rest_framework/validators.py:188: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.lib.models.InheritanceForwardManyToOneDescriptor object at 0x7fbccc3ec410>
instance = <PolicyBinding: Binding - #None to Invalid invalid>
cls = <class 'authentik.policies.models.PolicyBinding'>

    def __get__(self, instance, cls=None):
        """
        Get the related instance through the forward relation.
    
        With the example above, when getting ``child.parent``:
    
        - ``self`` is the descriptor managing the ``parent`` attribute
        - ``instance`` is the ``child`` instance
        - ``cls`` is the ``Child`` class (we don't need it)
        """
        if instance is None:
            return self
    
        # The related instance is loaded from the database and then cached
        # by the field on the model instance state. It can also be pre-cached
        # by the reverse accessor (ReverseOneToOneDescriptor).
        try:
            rel_obj = self.field.get_cached_value(instance)
        except KeyError:
            has_value = None not in self.field.get_local_related_value(instance)
            ancestor_link = (
                instance._meta.get_ancestor_link(self.field.model)
                if has_value
                else None
            )
            if ancestor_link and ancestor_link.is_cached(instance):
                # An ancestor link will exist if this field is defined on a
                # multi-table inheritance parent of the instance's class.
                ancestor = ancestor_link.get_cached_value(instance)
                # The value might be cached on an ancestor if the instance
                # originated from walking down the inheritance chain.
                rel_obj = self.field.get_cached_value(ancestor, default=None)
            else:
                rel_obj = None
            if rel_obj is None and has_value:
                rel_obj = self.get_object(instance)
                remote_field = self.field.remote_field
                # If this is a one-to-one relation, set the reverse accessor
                # cache on the related object to the current instance to avoid
                # an extra SQL query if it's accessed later on.
                if not remote_field.multiple:
                    remote_field.set_cached_value(rel_obj, instance)
            self.field.set_cached_value(instance, rel_obj)
    
        if rel_obj is None and not self.field.null:
>           raise self.RelatedObjectDoesNotExist(
                "%s has no %s." % (self.field.model.__name__, self.field.name)
            )
E           authentik.policies.models.PolicyBinding.target.RelatedObjectDoesNotExist: PolicyBinding has no target.. Did you mean: 'target_id'?

.venv/lib/python3.13.../models/fields/related_descriptors.py:267: RelatedObjectDoesNotExist
authentik.blueprints.tests.test_v1.TestBlueprintsV1::test_export_validate_import
Stack Traces | 1.97s run time
self = <unittest.case._Outcome object at 0x7fdccf0d1240>
test_case = <authentik.blueprints.tests.test_v1.TestBlueprintsV1 testMethod=test_export_validate_import>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.13.7........./x64/lib/python3.13/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.tests.test_v1.TestBlueprintsV1 testMethod=test_export_validate_import>
result = <TestCaseFunction test_export_validate_import>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.13.7........./x64/lib/python3.13/unittest/case.py:651: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.tests.test_v1.TestBlueprintsV1 testMethod=test_export_validate_import>
method = <bound method TestBlueprintsV1.test_export_validate_import of <authentik.blueprints.tests.test_v1.TestBlueprintsV1 testMethod=test_export_validate_import>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.13.7........./x64/lib/python3.13/unittest/case.py:606: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.tests.test_v1.TestBlueprintsV1 testMethod=test_export_validate_import>

    def test_export_validate_import(self):
        """Test export and validate it"""
        flow_slug = generate_id()
        with transaction_rollback():
            login_stage = UserLoginStage.objects.create(name=generate_id())
    
            flow = Flow.objects.create(
                slug=flow_slug,
                designation=FlowDesignation.AUTHENTICATION,
                name=generate_id(),
                title=generate_id(),
            )
            FlowStageBinding.objects.update_or_create(
                target=flow,
                stage=login_stage,
                order=0,
            )
    
            exporter = FlowExporter(flow)
            export = exporter.export()
            self.assertEqual(len(export.entries), 3)
            export_yaml = exporter.export_to_string()
    
        importer = Importer.from_string(export_yaml)
>       self.assertTrue(importer.validate()[0])

.../blueprints/tests/test_v1.py:110: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7fdcce266250>
raise_validation_errors = False

    def validate(self, raise_validation_errors=False) -> tuple[bool, list[LogEvent]]:
        """Validate loaded blueprint export, ensure all models are allowed
        and serializers have no errors"""
        self.logger.debug("Starting blueprint import validation")
        orig_import = deepcopy(self._import)
        if self._import.version != 1:
            self.logger.warning("Invalid blueprint version")
            return False, [LogEvent("Invalid blueprint version", log_level="warning", logger=None)]
        with (
            transaction_rollback(),
            capture_logs() as logs,
        ):
>           successful = self._apply_models(raise_errors=raise_validation_errors)

.../blueprints/v1/importer.py:458: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7fdcce266250>
raise_errors = False

    def _apply_models(self, raise_errors=False) -> bool:
        """Apply (create/update) models yaml"""
        self.__pk_map = {}
        for entry in self._import.iter_entries():
            model_app_label, model_name = entry.get_model(self._import).split(".")
            try:
                model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
            except LookupError:
                self.logger.warning(
                    "App or Model does not exist", app=model_app_label, model=model_name
                )
                return False
            # Validate each single entry
            serializer = None
            try:
>               serializer = self._validate_single(entry)

.../blueprints/v1/importer.py:399: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.blueprints.v1.importer.Importer object at 0x7fdcce266250>
entry = BlueprintEntry(model='authentik_flows.flowstagebinding', state=<BlueprintEntryDesiredState.PRESENT: 'present'>, condit...engine_mode': 'any', 're_evaluate_policies': True}, permissions=[], id=None, _state=BlueprintEntryState(instance=None))

    def _validate_single(self, entry: BlueprintEntry) -> BaseSerializer | None:  # noqa: PLR0915
        """Validate a single entry"""
        if not entry.check_all_conditions_match(self._import):
            self.logger.debug("One or more conditions of this entry are not fulfilled, skipping")
            return None
    
        model_app_label, model_name = entry.get_model(self._import).split(".")
        try:
            model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
        except LookupError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        # Don't use isinstance since we don't want to check for inheritance
        if not is_model_allowed(model):
            raise EntryInvalidError.from_entry(f"Model {model} not allowed", entry)
        if issubclass(model, BaseMetaModel):
            serializer_class: type[Serializer] = model.serializer()
            serializer = serializer_class(
                data=entry.get_attrs(self._import),
                context={
                    SERIALIZER_CONTEXT_BLUEPRINT: entry,
                },
            )
            try:
                serializer.is_valid(raise_exception=True)
            except ValidationError as exc:
                raise EntryInvalidError.from_entry(
                    f"Serializer errors {serializer.errors}",
                    validation_error=exc,
                    entry=entry,
                ) from exc
            return serializer
    
        # If we try to validate without referencing a possible instance
        # we'll get a duplicate error, hence we load the model here and return
        # the full serializer for later usage
        # Because a model might have multiple unique columns, we chain all identifiers together
        # to create an OR query.
        updated_identifiers = self.__update_pks_for_attrs(entry.get_identifiers(self._import))
        for key, value in list(updated_identifiers.items()):
            if isinstance(value, dict) and "pk" in value:
                del updated_identifiers[key]
                updated_identifiers[f"{key}"] = value["pk"]
    
        query = self.__query_from_identifier(updated_identifiers)
        if not query:
            raise EntryInvalidError.from_entry("No or invalid identifiers", entry)
    
        try:
            existing_models = model.objects.filter(query)
        except FieldError as exc:
            raise EntryInvalidError.from_entry(f"Invalid identifier field: {exc}", entry) from exc
    
        serializer_kwargs = {}
        model_instance = existing_models.first()
        if (
            not isinstance(model(), BaseMetaModel)
            and model_instance
            and entry.state != BlueprintEntryDesiredState.MUST_CREATED
        ):
            self.logger.debug(
                "Initialise serializer with instance",
                model=model,
                instance=model_instance,
                pk=model_instance.pk,
            )
            serializer_kwargs["instance"] = model_instance
            serializer_kwargs["partial"] = True
        elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED:
            msg = (
                f"State is set to {BlueprintEntryDesiredState.MUST_CREATED.value} "
                "and object exists already",
            )
            raise EntryInvalidError.from_entry(
                ValidationError({k: msg for k in entry.identifiers.keys()}, "unique"),
                entry,
            )
        else:
            self.logger.debug(
                "Initialised new serializer instance",
                model=model,
                **cleanse_dict(updated_identifiers),
            )
            model_instance = model()
            # pk needs to be set on the model instance otherwise a new one will be generated
            if "pk" in updated_identifiers:
                model_instance.pk = updated_identifiers["pk"]
            serializer_kwargs["instance"] = model_instance
        try:
            full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import))
        except ValueError as exc:
            raise EntryInvalidError.from_entry(exc, entry) from exc
        always_merger.merge(full_data, updated_identifiers)
        serializer_kwargs["data"] = full_data
    
        serializer: Serializer = model().serializer(
            context={
                SERIALIZER_CONTEXT_BLUEPRINT: entry,
            },
            **serializer_kwargs,
        )
        try:
>           serializer.is_valid(raise_exception=True)

.../blueprints/v1/importer.py:353: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = FlowStageBindingSerializer(context={'blueprint_entry': BlueprintEntry(model='authentik_flows.flowstagebinding', state=... validators = [<UniqueTogetherValidator(queryset=FlowStageBinding.objects.all(), fields=('target', 'stage', 'order'))>]

    def is_valid(self, *, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )
    
        if not hasattr(self, '_validated_data'):
            try:
>               self._validated_data = self.run_validation(self.initial_data)

.venv/lib/python3.13........./site-packages/rest_framework/serializers.py:225: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = FlowStageBindingSerializer(context={'blueprint_entry': BlueprintEntry(model='authentik_flows.flowstagebinding', state=... validators = [<UniqueTogetherValidator(queryset=FlowStageBinding.objects.all(), fields=('target', 'stage', 'order'))>]
data = {'invalid_response_action': 'retry', 'order': 0, 'pk': '336f5dd1-b266-4090-bd63-a93f4e141c49', 'policy_engine_mode': 'any', ...}

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
    
        value = self.to_internal_value(data)
        try:
>           self.run_validators(value)

.venv/lib/python3.13........./site-packages/rest_framework/serializers.py:446: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = FlowStageBindingSerializer(context={'blueprint_entry': BlueprintEntry(model='authentik_flows.flowstagebinding', state=... validators = [<UniqueTogetherValidator(queryset=FlowStageBinding.objects.all(), fields=('target', 'stage', 'order'))>]
value = {'invalid_response_action': 'retry', 'order': 0, 'policy_engine_mode': 'any', 're_evaluate_policies': True, ...}

    def run_validators(self, value):
        """
        Add read_only fields with defaults to value before running validators.
        """
        if isinstance(value, dict):
            to_validate = self._read_only_defaults()
            to_validate.update(value)
        else:
            to_validate = value
>       super().run_validators(to_validate)

.venv/lib/python3.13........./site-packages/rest_framework/serializers.py:479: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = FlowStageBindingSerializer(context={'blueprint_entry': BlueprintEntry(model='authentik_flows.flowstagebinding', state=... validators = [<UniqueTogetherValidator(queryset=FlowStageBinding.objects.all(), fields=('target', 'stage', 'order'))>]
value = {'invalid_response_action': 'retry', 'order': 0, 'policy_engine_mode': 'any', 're_evaluate_policies': True, ...}

    def run_validators(self, value):
        """
        Test the given value against all the validators on the field,
        and either raise a `ValidationError` or simply return.
        """
        errors = []
        for validator in self.validators:
            try:
                if getattr(validator, 'requires_context', False):
>                   validator(value, self)

.venv/lib/python3.13.../site-packages/rest_framework/fields.py:551: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <UniqueTogetherValidator(queryset=FlowStageBinding.objects.all(), fields=('target', 'stage', 'order'))>
attrs = {'invalid_response_action': 'retry', 'order': 0, 'policy_engine_mode': 'any', 're_evaluate_policies': True, ...}
serializer = FlowStageBindingSerializer(context={'blueprint_entry': BlueprintEntry(model='authentik_flows.flowstagebinding', state=... validators = [<UniqueTogetherValidator(queryset=FlowStageBinding.objects.all(), fields=('target', 'stage', 'order'))>]

    def __call__(self, attrs, serializer):
        self.enforce_required_fields(attrs, serializer)
        queryset = self.queryset
        queryset = self.filter_queryset(attrs, queryset, serializer)
        queryset = self.exclude_current_instance(attrs, queryset, serializer.instance)
    
        checked_names = [
            serializer.fields[field_name].source for field_name in self.fields
        ]
        # Ignore validation if any field is None
        if serializer.instance is None:
            checked_values = [attrs[field_name] for field_name in checked_names]
        else:
            # Ignore validation if all field values are unchanged
            checked_values = [
                attrs[field_name]
                for field_name in checked_names
>               if attrs[field_name] != getattr(serializer.instance, field_name)
            ]

.venv/lib/python3.13.../site-packages/rest_framework/validators.py:188: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor object at 0x7fdcd853abc0>
instance = <FlowStageBinding: Flow-stage binding #None to None>
cls = <class 'authentik.flows.models.FlowStageBinding'>

    def __get__(self, instance, cls=None):
        """
        Get the related instance through the forward relation.
    
        With the example above, when getting ``child.parent``:
    
        - ``self`` is the descriptor managing the ``parent`` attribute
        - ``instance`` is the ``child`` instance
        - ``cls`` is the ``Child`` class (we don't need it)
        """
        if instance is None:
            return self
    
        # The related instance is loaded from the database and then cached
        # by the field on the model instance state. It can also be pre-cached
        # by the reverse accessor (ReverseOneToOneDescriptor).
        try:
            rel_obj = self.field.get_cached_value(instance)
        except KeyError:
            has_value = None not in self.field.get_local_related_value(instance)
            ancestor_link = (
                instance._meta.get_ancestor_link(self.field.model)
                if has_value
                else None
            )
            if ancestor_link and ancestor_link.is_cached(instance):
                # An ancestor link will exist if this field is defined on a
                # multi-table inheritance parent of the instance's class.
                ancestor = ancestor_link.get_cached_value(instance)
                # The value might be cached on an ancestor if the instance
                # originated from walking down the inheritance chain.
                rel_obj = self.field.get_cached_value(ancestor, default=None)
            else:
                rel_obj = None
            if rel_obj is None and has_value:
                rel_obj = self.get_object(instance)
                remote_field = self.field.remote_field
                # If this is a one-to-one relation, set the reverse accessor
                # cache on the related object to the current instance to avoid
                # an extra SQL query if it's accessed later on.
                if not remote_field.multiple:
                    remote_field.set_cached_value(rel_obj, instance)
            self.field.set_cached_value(instance, rel_obj)
    
        if rel_obj is None and not self.field.null:
>           raise self.RelatedObjectDoesNotExist(
                "%s has no %s." % (self.field.model.__name__, self.field.name)
            )
E           authentik.flows.models.FlowStageBinding.target.RelatedObjectDoesNotExist: FlowStageBinding has no target.. Did you mean: 'target_id'?

.venv/lib/python3.13.../models/fields/related_descriptors.py:267: RelatedObjectDoesNotExist

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant