Compare commits
	
		
			4 Commits
		
	
	
		
			version/20
			...
			sources/ld
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2a6479062f | |||
| 52463b8f96 | |||
| 330f639a7e | |||
| 85ea4651e4 | 
							
								
								
									
										41
									
								
								authentik/core/migrations/0032_groupsourceconnection.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								authentik/core/migrations/0032_groupsourceconnection.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | |||||||
|  | # Generated by Django 4.2.5 on 2023-09-27 10:44 | ||||||
|  |  | ||||||
|  | import django.db.models.deletion | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |     dependencies = [ | ||||||
|  |         ("authentik_core", "0031_alter_user_type"), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name="GroupSourceConnection", | ||||||
|  |             fields=[ | ||||||
|  |                 ( | ||||||
|  |                     "id", | ||||||
|  |                     models.AutoField( | ||||||
|  |                         auto_created=True, primary_key=True, serialize=False, verbose_name="ID" | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |                 ("created", models.DateTimeField(auto_now_add=True)), | ||||||
|  |                 ("last_updated", models.DateTimeField(auto_now=True)), | ||||||
|  |                 ( | ||||||
|  |                     "group", | ||||||
|  |                     models.ForeignKey( | ||||||
|  |                         on_delete=django.db.models.deletion.CASCADE, to="authentik_core.group" | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |                 ( | ||||||
|  |                     "source", | ||||||
|  |                     models.ForeignKey( | ||||||
|  |                         on_delete=django.db.models.deletion.CASCADE, to="authentik_core.source" | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |             ], | ||||||
|  |             options={ | ||||||
|  |                 "unique_together": {("group", "source")}, | ||||||
|  |             }, | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @ -575,6 +575,23 @@ class UserSourceConnection(SerializerModel, CreatedUpdatedModel): | |||||||
|         unique_together = (("user", "source"),) |         unique_together = (("user", "source"),) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class GroupSourceConnection(SerializerModel, CreatedUpdatedModel): | ||||||
|  |     """Connection between Group and Source.""" | ||||||
|  |  | ||||||
|  |     group = models.ForeignKey(Group, on_delete=models.CASCADE) | ||||||
|  |     source = models.ForeignKey(Source, on_delete=models.CASCADE) | ||||||
|  |  | ||||||
|  |     objects = InheritanceManager() | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def serializer(self) -> type[Serializer]: | ||||||
|  |         """Get serializer for this model""" | ||||||
|  |         raise NotImplementedError | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |         unique_together = (("group", "source"),) | ||||||
|  |  | ||||||
|  |  | ||||||
| class ExpiringModel(models.Model): | class ExpiringModel(models.Model): | ||||||
|     """Base Model which can expire, and is automatically cleaned up.""" |     """Base Model which can expire, and is automatically cleaned up.""" | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								authentik/sources/ldap/api/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								authentik/sources/ldap/api/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										40
									
								
								authentik/sources/ldap/api/property_mappings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								authentik/sources/ldap/api/property_mappings.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | """Property mapping API Views""" | ||||||
|  | from django_filters.filters import AllValuesMultipleFilter | ||||||
|  | from django_filters.filterset import FilterSet | ||||||
|  | from drf_spectacular.types import OpenApiTypes | ||||||
|  | from drf_spectacular.utils import extend_schema_field | ||||||
|  | from rest_framework.viewsets import ModelViewSet | ||||||
|  |  | ||||||
|  | from authentik.core.api.propertymappings import PropertyMappingSerializer | ||||||
|  | from authentik.core.api.used_by import UsedByMixin | ||||||
|  | from authentik.sources.ldap.models import LDAPPropertyMapping | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LDAPPropertyMappingSerializer(PropertyMappingSerializer): | ||||||
|  |     """LDAP PropertyMapping Serializer""" | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |         model = LDAPPropertyMapping | ||||||
|  |         fields = PropertyMappingSerializer.Meta.fields + [ | ||||||
|  |             "object_field", | ||||||
|  |         ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LDAPPropertyMappingFilter(FilterSet): | ||||||
|  |     """Filter for LDAPPropertyMapping""" | ||||||
|  |  | ||||||
|  |     managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed")) | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |         model = LDAPPropertyMapping | ||||||
|  |         fields = "__all__" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LDAPPropertyMappingViewSet(UsedByMixin, ModelViewSet): | ||||||
|  |     """LDAP PropertyMapping Viewset""" | ||||||
|  |  | ||||||
|  |     queryset = LDAPPropertyMapping.objects.all() | ||||||
|  |     serializer_class = LDAPPropertyMappingSerializer | ||||||
|  |     filterset_class = LDAPPropertyMappingFilter | ||||||
|  |     search_fields = ["name"] | ||||||
|  |     ordering = ["name"] | ||||||
							
								
								
									
										32
									
								
								authentik/sources/ldap/api/source_connections.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								authentik/sources/ldap/api/source_connections.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | """LDAP Source Serializer""" | ||||||
|  | from django_filters.rest_framework import DjangoFilterBackend | ||||||
|  | from rest_framework.filters import OrderingFilter, SearchFilter | ||||||
|  | from rest_framework.viewsets import ModelViewSet | ||||||
|  |  | ||||||
|  | from authentik.api.authorization import OwnerFilter, OwnerSuperuserPermissions | ||||||
|  | from authentik.core.api.sources import UserSourceConnectionSerializer | ||||||
|  | from authentik.core.api.used_by import UsedByMixin | ||||||
|  | from authentik.sources.ldap.models import LDAPUserSourceConnection | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LDAPUserSourceConnectionSerializer(UserSourceConnectionSerializer): | ||||||
|  |     """LDAP Source Serializer""" | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |         model = LDAPUserSourceConnection | ||||||
|  |         fields = ["pk", "user", "source", "unique_identifier"] | ||||||
|  |         extra_kwargs = { | ||||||
|  |             "access_token": {"write_only": True}, | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LDAPUserSourceConnectionViewSet(UsedByMixin, ModelViewSet): | ||||||
|  |     """Source Viewset""" | ||||||
|  |  | ||||||
|  |     queryset = LDAPUserSourceConnection.objects.all() | ||||||
|  |     serializer_class = LDAPUserSourceConnectionSerializer | ||||||
|  |     filterset_fields = ["source__slug"] | ||||||
|  |     search_fields = ["source__slug"] | ||||||
|  |     permission_classes = [OwnerSuperuserPermissions] | ||||||
|  |     filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter] | ||||||
|  |     ordering = ["source__slug"] | ||||||
| @ -1,10 +1,7 @@ | |||||||
| """Source API Views""" | """Source API Views""" | ||||||
| from typing import Any | from typing import Any | ||||||
| 
 | 
 | ||||||
| from django_filters.filters import AllValuesMultipleFilter | from drf_spectacular.utils import extend_schema, inline_serializer | ||||||
| from django_filters.filterset import FilterSet |  | ||||||
| from drf_spectacular.types import OpenApiTypes |  | ||||||
| from drf_spectacular.utils import extend_schema, extend_schema_field, inline_serializer |  | ||||||
| from rest_framework.decorators import action | from rest_framework.decorators import action | ||||||
| from rest_framework.exceptions import ValidationError | from rest_framework.exceptions import ValidationError | ||||||
| from rest_framework.fields import DictField, ListField | from rest_framework.fields import DictField, ListField | ||||||
| @ -14,12 +11,11 @@ from rest_framework.response import Response | |||||||
| from rest_framework.viewsets import ModelViewSet | from rest_framework.viewsets import ModelViewSet | ||||||
| 
 | 
 | ||||||
| from authentik.admin.api.tasks import TaskSerializer | from authentik.admin.api.tasks import TaskSerializer | ||||||
| from authentik.core.api.propertymappings import PropertyMappingSerializer |  | ||||||
| from authentik.core.api.sources import SourceSerializer | from authentik.core.api.sources import SourceSerializer | ||||||
| from authentik.core.api.used_by import UsedByMixin | from authentik.core.api.used_by import UsedByMixin | ||||||
| from authentik.crypto.models import CertificateKeyPair | from authentik.crypto.models import CertificateKeyPair | ||||||
| from authentik.events.monitored_tasks import TaskInfo | from authentik.events.monitored_tasks import TaskInfo | ||||||
| from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource | from authentik.sources.ldap.models import LDAPSource | ||||||
| from authentik.sources.ldap.tasks import SYNC_CLASSES | from authentik.sources.ldap.tasks import SYNC_CLASSES | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -154,33 +150,3 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet): | |||||||
|                 obj.pop("raw_dn", None) |                 obj.pop("raw_dn", None) | ||||||
|                 all_objects[class_name].append(obj) |                 all_objects[class_name].append(obj) | ||||||
|         return Response(data=all_objects) |         return Response(data=all_objects) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class LDAPPropertyMappingSerializer(PropertyMappingSerializer): |  | ||||||
|     """LDAP PropertyMapping Serializer""" |  | ||||||
| 
 |  | ||||||
|     class Meta: |  | ||||||
|         model = LDAPPropertyMapping |  | ||||||
|         fields = PropertyMappingSerializer.Meta.fields + [ |  | ||||||
|             "object_field", |  | ||||||
|         ] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class LDAPPropertyMappingFilter(FilterSet): |  | ||||||
|     """Filter for LDAPPropertyMapping""" |  | ||||||
| 
 |  | ||||||
|     managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed")) |  | ||||||
| 
 |  | ||||||
|     class Meta: |  | ||||||
|         model = LDAPPropertyMapping |  | ||||||
|         fields = "__all__" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class LDAPPropertyMappingViewSet(UsedByMixin, ModelViewSet): |  | ||||||
|     """LDAP PropertyMapping Viewset""" |  | ||||||
| 
 |  | ||||||
|     queryset = LDAPPropertyMapping.objects.all() |  | ||||||
|     serializer_class = LDAPPropertyMappingSerializer |  | ||||||
|     filterset_class = LDAPPropertyMappingFilter |  | ||||||
|     search_fields = ["name"] |  | ||||||
|     ordering = ["name"] |  | ||||||
| @ -0,0 +1,58 @@ | |||||||
|  | # Generated by Django 4.2.5 on 2023-09-27 10:44 | ||||||
|  |  | ||||||
|  | import django.db.models.deletion | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |     dependencies = [ | ||||||
|  |         ("authentik_core", "0032_groupsourceconnection"), | ||||||
|  |         ("authentik_sources_ldap", "0003_ldapsource_client_certificate_ldapsource_sni_and_more"), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name="LDAPGroupSourceConnection", | ||||||
|  |             fields=[ | ||||||
|  |                 ( | ||||||
|  |                     "groupsourceconnection_ptr", | ||||||
|  |                     models.OneToOneField( | ||||||
|  |                         auto_created=True, | ||||||
|  |                         on_delete=django.db.models.deletion.CASCADE, | ||||||
|  |                         parent_link=True, | ||||||
|  |                         primary_key=True, | ||||||
|  |                         serialize=False, | ||||||
|  |                         to="authentik_core.groupsourceconnection", | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |                 ("unique_identifier", models.TextField(unique=True)), | ||||||
|  |             ], | ||||||
|  |             options={ | ||||||
|  |                 "verbose_name": "LDAP Group Source Connection", | ||||||
|  |                 "verbose_name_plural": "LDAP Group Source Connections", | ||||||
|  |             }, | ||||||
|  |             bases=("authentik_core.groupsourceconnection",), | ||||||
|  |         ), | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name="LDAPUserSourceConnection", | ||||||
|  |             fields=[ | ||||||
|  |                 ( | ||||||
|  |                     "usersourceconnection_ptr", | ||||||
|  |                     models.OneToOneField( | ||||||
|  |                         auto_created=True, | ||||||
|  |                         on_delete=django.db.models.deletion.CASCADE, | ||||||
|  |                         parent_link=True, | ||||||
|  |                         primary_key=True, | ||||||
|  |                         serialize=False, | ||||||
|  |                         to="authentik_core.usersourceconnection", | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |                 ("unique_identifier", models.TextField(unique=True)), | ||||||
|  |             ], | ||||||
|  |             options={ | ||||||
|  |                 "verbose_name": "LDAP User Source Connection", | ||||||
|  |                 "verbose_name_plural": "LDAP User Source Connections", | ||||||
|  |             }, | ||||||
|  |             bases=("authentik_core.usersourceconnection",), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @ -10,7 +10,13 @@ from ldap3 import ALL, NONE, RANDOM, Connection, Server, ServerPool, Tls | |||||||
| from ldap3.core.exceptions import LDAPInsufficientAccessRightsResult, LDAPSchemaError | from ldap3.core.exceptions import LDAPInsufficientAccessRightsResult, LDAPSchemaError | ||||||
| from rest_framework.serializers import Serializer | from rest_framework.serializers import Serializer | ||||||
|  |  | ||||||
| from authentik.core.models import Group, PropertyMapping, Source | from authentik.core.models import ( | ||||||
|  |     Group, | ||||||
|  |     GroupSourceConnection, | ||||||
|  |     PropertyMapping, | ||||||
|  |     Source, | ||||||
|  |     UserSourceConnection, | ||||||
|  | ) | ||||||
| from authentik.crypto.models import CertificateKeyPair | from authentik.crypto.models import CertificateKeyPair | ||||||
| from authentik.lib.config import CONFIG | from authentik.lib.config import CONFIG | ||||||
| from authentik.lib.models import DomainlessURLValidator | from authentik.lib.models import DomainlessURLValidator | ||||||
| @ -113,7 +119,7 @@ class LDAPSource(Source): | |||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def serializer(self) -> type[Serializer]: |     def serializer(self) -> type[Serializer]: | ||||||
|         from authentik.sources.ldap.api import LDAPSourceSerializer |         from authentik.sources.ldap.api.sources import LDAPSourceSerializer | ||||||
|  |  | ||||||
|         return LDAPSourceSerializer |         return LDAPSourceSerializer | ||||||
|  |  | ||||||
| @ -202,7 +208,7 @@ class LDAPPropertyMapping(PropertyMapping): | |||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def serializer(self) -> type[Serializer]: |     def serializer(self) -> type[Serializer]: | ||||||
|         from authentik.sources.ldap.api import LDAPPropertyMappingSerializer |         from authentik.sources.ldap.api.property_mappings import LDAPPropertyMappingSerializer | ||||||
|  |  | ||||||
|         return LDAPPropertyMappingSerializer |         return LDAPPropertyMappingSerializer | ||||||
|  |  | ||||||
| @ -212,3 +218,35 @@ class LDAPPropertyMapping(PropertyMapping): | |||||||
|     class Meta: |     class Meta: | ||||||
|         verbose_name = _("LDAP Property Mapping") |         verbose_name = _("LDAP Property Mapping") | ||||||
|         verbose_name_plural = _("LDAP Property Mappings") |         verbose_name_plural = _("LDAP Property Mappings") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LDAPUserSourceConnection(UserSourceConnection): | ||||||
|  |     """Connection between an authentik user and an LDAP source.""" | ||||||
|  |  | ||||||
|  |     unique_identifier = models.TextField(unique=True) | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def serializer(self) -> Serializer: | ||||||
|  |         from authentik.sources.ldap.api.source_connections import LDAPUserSourceConnectionSerializer | ||||||
|  |  | ||||||
|  |         return LDAPUserSourceConnectionSerializer | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |         verbose_name = _("LDAP User Source Connection") | ||||||
|  |         verbose_name_plural = _("LDAP User Source Connections") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LDAPGroupSourceConnection(GroupSourceConnection): | ||||||
|  |     """Connection between an authentik group and an LDAP source.""" | ||||||
|  |  | ||||||
|  |     unique_identifier = models.TextField(unique=True) | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def serializer(self) -> Serializer: | ||||||
|  |         from authentik.sources.ldap.api.source_connections import LDAPUserSourceConnectionSerializer | ||||||
|  |  | ||||||
|  |         return LDAPUserSourceConnectionSerializer | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |         verbose_name = _("LDAP Group Source Connection") | ||||||
|  |         verbose_name_plural = _("LDAP Group Source Connections") | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE | |||||||
|  |  | ||||||
| from authentik.core.models import Group | from authentik.core.models import Group | ||||||
| from authentik.events.models import Event, EventAction | from authentik.events.models import Event, EventAction | ||||||
|  | from authentik.sources.ldap.models import LDAPGroupSourceConnection | ||||||
| from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer | from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -63,7 +64,13 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer): | |||||||
|                     }, |                     }, | ||||||
|                     defaults, |                     defaults, | ||||||
|                 ) |                 ) | ||||||
|                 self._logger.debug("Created group with attributes", **defaults) |                 LDAPGroupSourceConnection.objects.update_or_create( | ||||||
|  |                     defaults={ | ||||||
|  |                         "unique_identifier": uniq, | ||||||
|  |                     }, | ||||||
|  |                     source=self._source, | ||||||
|  |                     group=ak_group, | ||||||
|  |                 ) | ||||||
|             except (IntegrityError, FieldError, TypeError, AttributeError) as exc: |             except (IntegrityError, FieldError, TypeError, AttributeError) as exc: | ||||||
|                 Event.new( |                 Event.new( | ||||||
|                     EventAction.CONFIGURATION_ERROR, |                     EventAction.CONFIGURATION_ERROR, | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE | |||||||
|  |  | ||||||
| from authentik.core.models import User | from authentik.core.models import User | ||||||
| from authentik.events.models import Event, EventAction | from authentik.events.models import Event, EventAction | ||||||
|  | from authentik.sources.ldap.models import LDAPUserSourceConnection | ||||||
| from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer | from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer | ||||||
| from authentik.sources.ldap.sync.vendor.freeipa import FreeIPA | from authentik.sources.ldap.sync.vendor.freeipa import FreeIPA | ||||||
| from authentik.sources.ldap.sync.vendor.ms_ad import MicrosoftActiveDirectory | from authentik.sources.ldap.sync.vendor.ms_ad import MicrosoftActiveDirectory | ||||||
| @ -58,6 +59,13 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer): | |||||||
|                 ak_user, created = self.update_or_create_attributes( |                 ak_user, created = self.update_or_create_attributes( | ||||||
|                     User, {f"attributes__{LDAP_UNIQUENESS}": uniq}, defaults |                     User, {f"attributes__{LDAP_UNIQUENESS}": uniq}, defaults | ||||||
|                 ) |                 ) | ||||||
|  |                 LDAPUserSourceConnection.objects.update_or_create( | ||||||
|  |                     defaults={ | ||||||
|  |                         "unique_identifier": uniq, | ||||||
|  |                     }, | ||||||
|  |                     source=self._source, | ||||||
|  |                     user=ak_user, | ||||||
|  |                 ) | ||||||
|             except (IntegrityError, FieldError, TypeError, AttributeError) as exc: |             except (IntegrityError, FieldError, TypeError, AttributeError) as exc: | ||||||
|                 Event.new( |                 Event.new( | ||||||
|                     EventAction.CONFIGURATION_ERROR, |                     EventAction.CONFIGURATION_ERROR, | ||||||
| @ -72,6 +80,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer): | |||||||
|             else: |             else: | ||||||
|                 self._logger.debug("Synced User", user=ak_user.username, created=created) |                 self._logger.debug("Synced User", user=ak_user.username, created=created) | ||||||
|                 user_count += 1 |                 user_count += 1 | ||||||
|  |                 # TODO: Optimise vendor sync to not create a new connection | ||||||
|                 MicrosoftActiveDirectory(self._source).sync(attributes, ak_user, created) |                 MicrosoftActiveDirectory(self._source).sync(attributes, ak_user, created) | ||||||
|                 FreeIPA(self._source).sync(attributes, ak_user, created) |                 FreeIPA(self._source).sync(attributes, ak_user, created) | ||||||
|         return user_count |         return user_count | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
| from rest_framework.test import APITestCase | from rest_framework.test import APITestCase | ||||||
|  |  | ||||||
| from authentik.lib.generators import generate_key | from authentik.lib.generators import generate_key | ||||||
| from authentik.sources.ldap.api import LDAPSourceSerializer | from authentik.sources.ldap.api.sources import LDAPSourceSerializer | ||||||
| from authentik.sources.ldap.models import LDAPSource | from authentik.sources.ldap.models import LDAPSource | ||||||
|  |  | ||||||
| LDAP_PASSWORD = generate_key() | LDAP_PASSWORD = generate_key() | ||||||
|  | |||||||
| @ -1,7 +1,10 @@ | |||||||
| """API URLs""" | """API URLs""" | ||||||
| from authentik.sources.ldap.api import LDAPPropertyMappingViewSet, LDAPSourceViewSet | from authentik.sources.ldap.api.property_mappings import LDAPPropertyMappingViewSet | ||||||
|  | from authentik.sources.ldap.api.source_connections import LDAPUserSourceConnectionViewSet | ||||||
|  | from authentik.sources.ldap.api.sources import LDAPSourceViewSet | ||||||
|  |  | ||||||
| api_urlpatterns = [ | api_urlpatterns = [ | ||||||
|     ("propertymappings/ldap", LDAPPropertyMappingViewSet), |     ("propertymappings/ldap", LDAPPropertyMappingViewSet), | ||||||
|  |     ("sources/user_connections/ldap", LDAPUserSourceConnectionViewSet), | ||||||
|     ("sources/ldap", LDAPSourceViewSet), |     ("sources/ldap", LDAPSourceViewSet), | ||||||
| ] | ] | ||||||
|  | |||||||
| @ -68,7 +68,7 @@ class OAuthSource(Source): | |||||||
|     # we're using Type[] instead of type[] here since type[] interferes with the property above |     # we're using Type[] instead of type[] here since type[] interferes with the property above | ||||||
|     @property |     @property | ||||||
|     def serializer(self) -> Type[Serializer]: |     def serializer(self) -> Type[Serializer]: | ||||||
|         from authentik.sources.oauth.api.source import OAuthSourceSerializer |         from authentik.sources.oauth.api.sources import OAuthSourceSerializer | ||||||
|  |  | ||||||
|         return OAuthSourceSerializer |         return OAuthSourceSerializer | ||||||
|  |  | ||||||
| @ -234,7 +234,7 @@ class UserOAuthSourceConnection(UserSourceConnection): | |||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def serializer(self) -> Serializer: |     def serializer(self) -> Serializer: | ||||||
|         from authentik.sources.oauth.api.source_connection import ( |         from authentik.sources.oauth.api.source_connections import ( | ||||||
|             UserOAuthSourceConnectionSerializer, |             UserOAuthSourceConnectionSerializer, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ from django.test import TestCase | |||||||
| from django.urls import reverse | from django.urls import reverse | ||||||
| from requests_mock import Mocker | from requests_mock import Mocker | ||||||
|  |  | ||||||
| from authentik.sources.oauth.api.source import OAuthSourceSerializer | from authentik.sources.oauth.api.sources import OAuthSourceSerializer | ||||||
| from authentik.sources.oauth.models import OAuthSource | from authentik.sources.oauth.models import OAuthSource | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -2,8 +2,8 @@ | |||||||
|  |  | ||||||
| from django.urls import path | from django.urls import path | ||||||
|  |  | ||||||
| from authentik.sources.oauth.api.source import OAuthSourceViewSet | from authentik.sources.oauth.api.source_connections import UserOAuthSourceConnectionViewSet | ||||||
| from authentik.sources.oauth.api.source_connection import UserOAuthSourceConnectionViewSet | from authentik.sources.oauth.api.sources import OAuthSourceViewSet | ||||||
| from authentik.sources.oauth.types.registry import RequestKind | from authentik.sources.oauth.types.registry import RequestKind | ||||||
| from authentik.sources.oauth.views.dispatcher import DispatcherView | from authentik.sources.oauth.views.dispatcher import DispatcherView | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	