sources/scim: cleanup service account when source is deleted (#9319)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
		| @ -7,7 +7,6 @@ from rest_framework.viewsets import ModelViewSet | |||||||
| from authentik.core.api.sources import SourceSerializer | from authentik.core.api.sources import SourceSerializer | ||||||
| from authentik.core.api.tokens import TokenSerializer | from authentik.core.api.tokens import TokenSerializer | ||||||
| from authentik.core.api.used_by import UsedByMixin | from authentik.core.api.used_by import UsedByMixin | ||||||
| from authentik.core.models import Token, TokenIntents, User, UserTypes |  | ||||||
| from authentik.sources.scim.models import SCIMSource | from authentik.sources.scim.models import SCIMSource | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -27,25 +26,6 @@ class SCIMSourceSerializer(SourceSerializer): | |||||||
|             return relative_url |             return relative_url | ||||||
|         return self.context["request"].build_absolute_uri(relative_url) |         return self.context["request"].build_absolute_uri(relative_url) | ||||||
|  |  | ||||||
|     def create(self, validated_data): |  | ||||||
|         instance: SCIMSource = super().create(validated_data) |  | ||||||
|         identifier = f"ak-source-scim-{instance.pk}" |  | ||||||
|         user = User.objects.create( |  | ||||||
|             username=identifier, |  | ||||||
|             name=f"SCIM Source {instance.name} Service-Account", |  | ||||||
|             type=UserTypes.SERVICE_ACCOUNT, |  | ||||||
|         ) |  | ||||||
|         token = Token.objects.create( |  | ||||||
|             user=user, |  | ||||||
|             identifier=identifier, |  | ||||||
|             intent=TokenIntents.INTENT_API, |  | ||||||
|             expiring=False, |  | ||||||
|             managed=f"goauthentik.io/sources/scim/{instance.pk}", |  | ||||||
|         ) |  | ||||||
|         instance.token = token |  | ||||||
|         instance.save() |  | ||||||
|         return instance |  | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|  |  | ||||||
|         model = SCIMSource |         model = SCIMSource | ||||||
|  | |||||||
| @ -1,12 +1,13 @@ | |||||||
| """Authentik SCIM app config""" | """Authentik SCIM app config""" | ||||||
|  |  | ||||||
| from django.apps import AppConfig | from authentik.blueprints.apps import ManagedAppConfig | ||||||
|  |  | ||||||
|  |  | ||||||
| class AuthentikSourceSCIMConfig(AppConfig): | class AuthentikSourceSCIMConfig(ManagedAppConfig): | ||||||
|     """authentik SCIM Source app config""" |     """authentik SCIM Source app config""" | ||||||
|  |  | ||||||
|     name = "authentik.sources.scim" |     name = "authentik.sources.scim" | ||||||
|     label = "authentik_sources_scim" |     label = "authentik_sources_scim" | ||||||
|     verbose_name = "authentik Sources.SCIM" |     verbose_name = "authentik Sources.SCIM" | ||||||
|     mountpoint = "source/scim/" |     mountpoint = "source/scim/" | ||||||
|  |     default = True | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| """SCIM Source""" | """SCIM Source""" | ||||||
|  |  | ||||||
|  | from uuid import uuid4 | ||||||
|  |  | ||||||
| from django.db import models | from django.db import models | ||||||
| from django.utils.translation import gettext_lazy as _ | from django.utils.translation import gettext_lazy as _ | ||||||
| from rest_framework.serializers import BaseSerializer | from rest_framework.serializers import BaseSerializer | ||||||
| @ -14,6 +16,12 @@ class SCIMSource(Source): | |||||||
|  |  | ||||||
|     token = models.ForeignKey(Token, on_delete=models.CASCADE, null=True, default=None) |     token = models.ForeignKey(Token, on_delete=models.CASCADE, null=True, default=None) | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def service_account_identifier(self) -> str: | ||||||
|  |         if not self.pk: | ||||||
|  |             self.pk = uuid4() | ||||||
|  |         return f"ak-source-scim-{self.pk}" | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def component(self) -> str: |     def component(self) -> str: | ||||||
|         """Return component used to edit this object""" |         """Return component used to edit this object""" | ||||||
|  | |||||||
							
								
								
									
										38
									
								
								authentik/sources/scim/signals.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								authentik/sources/scim/signals.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | from django.db.models import Model | ||||||
|  | from django.db.models.signals import pre_delete, pre_save | ||||||
|  | from django.dispatch import receiver | ||||||
|  |  | ||||||
|  | from authentik.core.models import Token, TokenIntents, User, UserTypes | ||||||
|  | from authentik.sources.scim.models import SCIMSource | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @receiver(pre_save, sender=SCIMSource) | ||||||
|  | def scim_source_pre_save(sender: type[Model], instance: SCIMSource, **_): | ||||||
|  |     """Create service account before source is saved""" | ||||||
|  |     # .service_account_identifier will auto-assign a primary key uuid to the source | ||||||
|  |     # if none is set yet, just so we can get the identifier before we save | ||||||
|  |     identifier = instance.service_account_identifier | ||||||
|  |     user = User.objects.create( | ||||||
|  |         username=identifier, | ||||||
|  |         name=f"SCIM Source {instance.name} Service-Account", | ||||||
|  |         type=UserTypes.SERVICE_ACCOUNT, | ||||||
|  |     ) | ||||||
|  |     token = Token.objects.create( | ||||||
|  |         user=user, | ||||||
|  |         identifier=identifier, | ||||||
|  |         intent=TokenIntents.INTENT_API, | ||||||
|  |         expiring=False, | ||||||
|  |         managed=f"goauthentik.io/sources/scim/{instance.pk}", | ||||||
|  |     ) | ||||||
|  |     instance.token = token | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @receiver(pre_delete, sender=SCIMSource) | ||||||
|  | def scim_source_pre_delete(sender: type[Model], instance: SCIMSource, **_): | ||||||
|  |     """Delete SCIM Source service account before deleting source""" | ||||||
|  |     Token.objects.filter( | ||||||
|  |         identifier=instance.service_account_identifier, intent=TokenIntents.INTENT_API | ||||||
|  |     ).delete() | ||||||
|  |     User.objects.filter( | ||||||
|  |         username=instance.service_account_identifier, type=UserTypes.SERVICE_ACCOUNT | ||||||
|  |     ).delete() | ||||||
| @ -14,27 +14,13 @@ class TestSCIMAuth(APITestCase): | |||||||
|  |  | ||||||
|     def setUp(self) -> None: |     def setUp(self) -> None: | ||||||
|         self.user = create_test_admin_user() |         self.user = create_test_admin_user() | ||||||
|         self.token = Token.objects.create( |  | ||||||
|             user=self.user, |  | ||||||
|             identifier=generate_id(), |  | ||||||
|             intent=TokenIntents.INTENT_API, |  | ||||||
|         ) |  | ||||||
|         self.token2 = Token.objects.create( |  | ||||||
|             user=self.user, |  | ||||||
|             identifier=generate_id(), |  | ||||||
|             intent=TokenIntents.INTENT_API, |  | ||||||
|         ) |  | ||||||
|         self.token3 = Token.objects.create( |         self.token3 = Token.objects.create( | ||||||
|             user=self.user, |             user=self.user, | ||||||
|             identifier=generate_id(), |             identifier=generate_id(), | ||||||
|             intent=TokenIntents.INTENT_API, |             intent=TokenIntents.INTENT_API, | ||||||
|         ) |         ) | ||||||
|         self.source = SCIMSource.objects.create( |         self.source = SCIMSource.objects.create(name=generate_id(), slug=generate_id()) | ||||||
|             name=generate_id(), slug=generate_id(), token=self.token |         self.source2 = SCIMSource.objects.create(name=generate_id(), slug=generate_id()) | ||||||
|         ) |  | ||||||
|         self.source2 = SCIMSource.objects.create( |  | ||||||
|             name=generate_id(), slug=generate_id(), token=self.token2 |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def test_auth_ok(self): |     def test_auth_ok(self): | ||||||
|         """Test successful auth""" |         """Test successful auth""" | ||||||
| @ -45,7 +31,7 @@ class TestSCIMAuth(APITestCase): | |||||||
|                     "source_slug": self.source.slug, |                     "source_slug": self.source.slug, | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|  |  | ||||||
| @ -71,7 +57,7 @@ class TestSCIMAuth(APITestCase): | |||||||
|                     "source_slug": self.source.slug, |                     "source_slug": self.source.slug, | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token2.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source2.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 403) |         self.assertEqual(response.status_code, 403) | ||||||
|         # Token for no source |         # Token for no source | ||||||
|  | |||||||
| @ -3,8 +3,6 @@ | |||||||
| from django.urls import reverse | from django.urls import reverse | ||||||
| from rest_framework.test import APITestCase | from rest_framework.test import APITestCase | ||||||
|  |  | ||||||
| from authentik.core.models import Token, TokenIntents |  | ||||||
| from authentik.core.tests.utils import create_test_admin_user |  | ||||||
| from authentik.lib.generators import generate_id | from authentik.lib.generators import generate_id | ||||||
| from authentik.sources.scim.models import SCIMSource | from authentik.sources.scim.models import SCIMSource | ||||||
|  |  | ||||||
| @ -13,14 +11,9 @@ class TestSCIMResourceTypes(APITestCase): | |||||||
|     """Test SCIM ResourceTypes view""" |     """Test SCIM ResourceTypes view""" | ||||||
|  |  | ||||||
|     def setUp(self) -> None: |     def setUp(self) -> None: | ||||||
|         self.user = create_test_admin_user() |  | ||||||
|         self.token = Token.objects.create( |  | ||||||
|             user=self.user, |  | ||||||
|             identifier=generate_id(), |  | ||||||
|             intent=TokenIntents.INTENT_API, |  | ||||||
|         ) |  | ||||||
|         self.source = SCIMSource.objects.create( |         self.source = SCIMSource.objects.create( | ||||||
|             name=generate_id(), slug=generate_id(), token=self.token |             name=generate_id(), | ||||||
|  |             slug=generate_id(), | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def test_resource_type(self): |     def test_resource_type(self): | ||||||
| @ -32,7 +25,7 @@ class TestSCIMResourceTypes(APITestCase): | |||||||
|                     "source_slug": self.source.slug, |                     "source_slug": self.source.slug, | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|  |  | ||||||
| @ -46,7 +39,7 @@ class TestSCIMResourceTypes(APITestCase): | |||||||
|                     "resource_type": "ServiceProviderConfig", |                     "resource_type": "ServiceProviderConfig", | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|  |  | ||||||
| @ -60,6 +53,6 @@ class TestSCIMResourceTypes(APITestCase): | |||||||
|                     "resource_type": "foo", |                     "resource_type": "foo", | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 404) |         self.assertEqual(response.status_code, 404) | ||||||
|  | |||||||
| @ -3,8 +3,6 @@ | |||||||
| from django.urls import reverse | from django.urls import reverse | ||||||
| from rest_framework.test import APITestCase | from rest_framework.test import APITestCase | ||||||
|  |  | ||||||
| from authentik.core.models import Token, TokenIntents |  | ||||||
| from authentik.core.tests.utils import create_test_admin_user |  | ||||||
| from authentik.lib.generators import generate_id | from authentik.lib.generators import generate_id | ||||||
| from authentik.sources.scim.models import SCIMSource | from authentik.sources.scim.models import SCIMSource | ||||||
|  |  | ||||||
| @ -13,15 +11,7 @@ class TestSCIMSchemas(APITestCase): | |||||||
|     """Test SCIM Schema view""" |     """Test SCIM Schema view""" | ||||||
|  |  | ||||||
|     def setUp(self) -> None: |     def setUp(self) -> None: | ||||||
|         self.user = create_test_admin_user() |         self.source = SCIMSource.objects.create(name=generate_id(), slug=generate_id()) | ||||||
|         self.token = Token.objects.create( |  | ||||||
|             user=self.user, |  | ||||||
|             identifier=generate_id(), |  | ||||||
|             intent=TokenIntents.INTENT_API, |  | ||||||
|         ) |  | ||||||
|         self.source = SCIMSource.objects.create( |  | ||||||
|             name=generate_id(), slug=generate_id(), token=self.token |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def test_schema(self): |     def test_schema(self): | ||||||
|         """Test full schema view""" |         """Test full schema view""" | ||||||
| @ -32,7 +22,7 @@ class TestSCIMSchemas(APITestCase): | |||||||
|                     "source_slug": self.source.slug, |                     "source_slug": self.source.slug, | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|  |  | ||||||
| @ -46,7 +36,7 @@ class TestSCIMSchemas(APITestCase): | |||||||
|                     "schema_uri": "urn:ietf:params:scim:schemas:core:2.0:Meta", |                     "schema_uri": "urn:ietf:params:scim:schemas:core:2.0:Meta", | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|  |  | ||||||
| @ -60,6 +50,6 @@ class TestSCIMSchemas(APITestCase): | |||||||
|                     "schema_uri": "foo", |                     "schema_uri": "foo", | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 404) |         self.assertEqual(response.status_code, 404) | ||||||
|  | |||||||
| @ -3,8 +3,6 @@ | |||||||
| from django.urls import reverse | from django.urls import reverse | ||||||
| from rest_framework.test import APITestCase | from rest_framework.test import APITestCase | ||||||
|  |  | ||||||
| from authentik.core.models import Token, TokenIntents |  | ||||||
| from authentik.core.tests.utils import create_test_admin_user |  | ||||||
| from authentik.lib.generators import generate_id | from authentik.lib.generators import generate_id | ||||||
| from authentik.sources.scim.models import SCIMSource | from authentik.sources.scim.models import SCIMSource | ||||||
|  |  | ||||||
| @ -13,14 +11,9 @@ class TestSCIMServiceProviderConfig(APITestCase): | |||||||
|     """Test SCIM ServiceProviderConfig view""" |     """Test SCIM ServiceProviderConfig view""" | ||||||
|  |  | ||||||
|     def setUp(self) -> None: |     def setUp(self) -> None: | ||||||
|         self.user = create_test_admin_user() |  | ||||||
|         self.token = Token.objects.create( |  | ||||||
|             user=self.user, |  | ||||||
|             identifier=generate_id(), |  | ||||||
|             intent=TokenIntents.INTENT_API, |  | ||||||
|         ) |  | ||||||
|         self.source = SCIMSource.objects.create( |         self.source = SCIMSource.objects.create( | ||||||
|             name=generate_id(), slug=generate_id(), token=self.token |             name=generate_id(), | ||||||
|  |             slug=generate_id(), | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def test_config(self): |     def test_config(self): | ||||||
| @ -32,6 +25,6 @@ class TestSCIMServiceProviderConfig(APITestCase): | |||||||
|                     "source_slug": self.source.slug, |                     "source_slug": self.source.slug, | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								authentik/sources/scim/tests/test_signals.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								authentik/sources/scim/tests/test_signals.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | """Test SCIM Source creation""" | ||||||
|  |  | ||||||
|  | from rest_framework.test import APITestCase | ||||||
|  |  | ||||||
|  | from authentik.core.models import Token, User | ||||||
|  | from authentik.lib.generators import generate_id | ||||||
|  | from authentik.sources.scim.models import SCIMSource | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestSCIMSignals(APITestCase): | ||||||
|  |     """Test SCIM Signals view""" | ||||||
|  |  | ||||||
|  |     def setUp(self) -> None: | ||||||
|  |         self.uid = generate_id() | ||||||
|  |  | ||||||
|  |     def test_create(self) -> None: | ||||||
|  |         source = SCIMSource.objects.create(name=self.uid, slug=self.uid) | ||||||
|  |         self.assertIsNotNone(source.token) | ||||||
|  |         self.assertIsNotNone(source.token.user) | ||||||
|  |  | ||||||
|  |     def test_delete(self): | ||||||
|  |         self.test_create() | ||||||
|  |         source = SCIMSource.objects.filter(slug=self.uid).first() | ||||||
|  |         identifier = source.service_account_identifier | ||||||
|  |         source.delete() | ||||||
|  |         self.assertFalse(User.objects.filter(username=identifier).exists()) | ||||||
|  |         self.assertFalse(Token.objects.filter(identifier=identifier).exists()) | ||||||
| @ -6,8 +6,8 @@ from uuid import uuid4 | |||||||
| from django.urls import reverse | from django.urls import reverse | ||||||
| from rest_framework.test import APITestCase | from rest_framework.test import APITestCase | ||||||
|  |  | ||||||
| from authentik.core.models import Token, TokenIntents | from authentik.core.tests.utils import create_test_user | ||||||
| from authentik.core.tests.utils import create_test_admin_user | from authentik.events.models import Event, EventAction | ||||||
| from authentik.lib.generators import generate_id | from authentik.lib.generators import generate_id | ||||||
| from authentik.providers.scim.clients.schema import User as SCIMUserSchema | from authentik.providers.scim.clients.schema import User as SCIMUserSchema | ||||||
| from authentik.sources.scim.models import SCIMSource, SCIMSourceUser | from authentik.sources.scim.models import SCIMSource, SCIMSourceUser | ||||||
| @ -18,15 +18,7 @@ class TestSCIMUsers(APITestCase): | |||||||
|     """Test SCIM User view""" |     """Test SCIM User view""" | ||||||
|  |  | ||||||
|     def setUp(self) -> None: |     def setUp(self) -> None: | ||||||
|         self.user = create_test_admin_user() |         self.source = SCIMSource.objects.create(name=generate_id(), slug=generate_id()) | ||||||
|         self.token = Token.objects.create( |  | ||||||
|             user=self.user, |  | ||||||
|             identifier=generate_id(), |  | ||||||
|             intent=TokenIntents.INTENT_API, |  | ||||||
|         ) |  | ||||||
|         self.source = SCIMSource.objects.create( |  | ||||||
|             name=generate_id(), slug=generate_id(), token=self.token |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def test_user_list(self): |     def test_user_list(self): | ||||||
|         """Test full user list""" |         """Test full user list""" | ||||||
| @ -37,15 +29,16 @@ class TestSCIMUsers(APITestCase): | |||||||
|                     "source_slug": self.source.slug, |                     "source_slug": self.source.slug, | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|  |  | ||||||
|     def test_user_list_single(self): |     def test_user_list_single(self): | ||||||
|         """Test full user list (single user)""" |         """Test full user list (single user)""" | ||||||
|  |         user = create_test_user() | ||||||
|         SCIMSourceUser.objects.create( |         SCIMSourceUser.objects.create( | ||||||
|             source=self.source, |             source=self.source, | ||||||
|             user=self.user, |             user=user, | ||||||
|             id=str(uuid4()), |             id=str(uuid4()), | ||||||
|         ) |         ) | ||||||
|         response = self.client.get( |         response = self.client.get( | ||||||
| @ -53,16 +46,17 @@ class TestSCIMUsers(APITestCase): | |||||||
|                 "authentik_sources_scim:v2-users", |                 "authentik_sources_scim:v2-users", | ||||||
|                 kwargs={ |                 kwargs={ | ||||||
|                     "source_slug": self.source.slug, |                     "source_slug": self.source.slug, | ||||||
|                     "user_id": str(self.user.uuid), |                     "user_id": str(user.uuid), | ||||||
|                 }, |                 }, | ||||||
|             ), |             ), | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 200) |         self.assertEqual(response.status_code, 200) | ||||||
|         SCIMUserSchema.model_validate_json(response.content, strict=True) |         SCIMUserSchema.model_validate_json(response.content, strict=True) | ||||||
|  |  | ||||||
|     def test_user_create(self): |     def test_user_create(self): | ||||||
|         """Test user create""" |         """Test user create""" | ||||||
|  |         user = create_test_user() | ||||||
|         ext_id = generate_id() |         ext_id = generate_id() | ||||||
|         response = self.client.post( |         response = self.client.post( | ||||||
|             reverse( |             reverse( | ||||||
| @ -78,13 +72,18 @@ class TestSCIMUsers(APITestCase): | |||||||
|                     "emails": [ |                     "emails": [ | ||||||
|                         { |                         { | ||||||
|                             "primary": True, |                             "primary": True, | ||||||
|                             "value": self.user.email, |                             "value": user.email, | ||||||
|                         } |                         } | ||||||
|                     ], |                     ], | ||||||
|                 } |                 } | ||||||
|             ), |             ), | ||||||
|             content_type=SCIM_CONTENT_TYPE, |             content_type=SCIM_CONTENT_TYPE, | ||||||
|             HTTP_AUTHORIZATION=f"Bearer {self.token.key}", |             HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}", | ||||||
|         ) |         ) | ||||||
|         self.assertEqual(response.status_code, 201) |         self.assertEqual(response.status_code, 201) | ||||||
|         self.assertTrue(SCIMSourceUser.objects.filter(source=self.source, id=ext_id).exists()) |         self.assertTrue(SCIMSourceUser.objects.filter(source=self.source, id=ext_id).exists()) | ||||||
|  |         self.assertTrue( | ||||||
|  |             Event.objects.filter( | ||||||
|  |                 action=EventAction.MODEL_CREATED, user__username=self.source.token.user.username | ||||||
|  |             ).exists() | ||||||
|  |         ) | ||||||
|  | |||||||
| @ -6,7 +6,6 @@ from typing import Any | |||||||
|  |  | ||||||
| from docker.types import Healthcheck | from docker.types import Healthcheck | ||||||
|  |  | ||||||
| from authentik.core.models import Token, TokenIntents, User |  | ||||||
| from authentik.lib.generators import generate_id | from authentik.lib.generators import generate_id | ||||||
| from authentik.lib.utils.http import get_http_session | from authentik.lib.utils.http import get_http_session | ||||||
| from authentik.sources.scim.models import SCIMSource | from authentik.sources.scim.models import SCIMSource | ||||||
| @ -40,18 +39,9 @@ class TestSourceSCIM(SeleniumTestCase): | |||||||
|  |  | ||||||
|     @retry() |     @retry() | ||||||
|     def test_scim_conformance(self): |     def test_scim_conformance(self): | ||||||
|         user = User.objects.create( |  | ||||||
|             username=generate_id(), |  | ||||||
|         ) |  | ||||||
|         token = Token.objects.create( |  | ||||||
|             user=user, |  | ||||||
|             intent=TokenIntents.INTENT_API, |  | ||||||
|             expiring=False, |  | ||||||
|         ) |  | ||||||
|         source = SCIMSource.objects.create( |         source = SCIMSource.objects.create( | ||||||
|             name=generate_id(), |             name=generate_id(), | ||||||
|             slug=generate_id(), |             slug=generate_id(), | ||||||
|             token=token, |  | ||||||
|         ) |         ) | ||||||
|         session = get_http_session() |         session = get_http_session() | ||||||
|         test_launch = session.post( |         test_launch = session.post( | ||||||
| @ -59,7 +49,7 @@ class TestSourceSCIM(SeleniumTestCase): | |||||||
|             data={ |             data={ | ||||||
|                 "endPoint": self.live_server_url + f"/source/scim/{source.slug}/v2", |                 "endPoint": self.live_server_url + f"/source/scim/{source.slug}/v2", | ||||||
|                 "username": "foo", |                 "username": "foo", | ||||||
|                 "password": token.key, |                 "password": source.token.key, | ||||||
|                 "jwtToken": None, |                 "jwtToken": None, | ||||||
|                 "usersCheck": 1, |                 "usersCheck": 1, | ||||||
|                 "groupsCheck": 1, |                 "groupsCheck": 1, | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Jens L
					Jens L