|
1 | 1 | """User client"""
|
2 | 2 |
|
| 3 | +from django.db import transaction |
| 4 | +from django.utils.http import urlencode |
3 | 5 | from pydantic import ValidationError
|
4 | 6 |
|
5 | 7 | from authentik.core.models import User
|
6 | 8 | from authentik.lib.sync.mapper import PropertyMappingManager
|
7 |
| -from authentik.lib.sync.outgoing.exceptions import StopSync |
| 9 | +from authentik.lib.sync.outgoing.exceptions import ObjectExistsSyncException, StopSync |
8 | 10 | from authentik.policies.utils import delete_none_values
|
9 | 11 | from authentik.providers.scim.clients.base import SCIMClient
|
10 | 12 | from authentik.providers.scim.clients.schema import SCIM_USER_SCHEMA
|
@@ -55,18 +57,35 @@ def delete(self, obj: User):
|
55 | 57 | def create(self, user: User):
|
56 | 58 | """Create user from scratch and create a connection object"""
|
57 | 59 | scim_user = self.to_schema(user, None)
|
58 |
| - response = self._request( |
59 |
| - "POST", |
60 |
| - "/Users", |
61 |
| - json=scim_user.model_dump( |
62 |
| - mode="json", |
63 |
| - exclude_unset=True, |
64 |
| - ), |
65 |
| - ) |
66 |
| - scim_id = response.get("id") |
67 |
| - if not scim_id or scim_id == "": |
68 |
| - raise StopSync("SCIM Response with missing or invalid `id`") |
69 |
| - return SCIMProviderUser.objects.create(provider=self.provider, user=user, scim_id=scim_id) |
| 60 | + with transaction.atomic(): |
| 61 | + try: |
| 62 | + response = self._request( |
| 63 | + "POST", |
| 64 | + "/Users", |
| 65 | + json=scim_user.model_dump( |
| 66 | + mode="json", |
| 67 | + exclude_unset=True, |
| 68 | + ), |
| 69 | + ) |
| 70 | + except ObjectExistsSyncException as exc: |
| 71 | + if not self._config.filter.supported: |
| 72 | + raise exc |
| 73 | + users = self._request( |
| 74 | + "GET", f"/Users?{urlencode({'filter': f'userName eq {scim_user.userName}'})}" |
| 75 | + ) |
| 76 | + users_res = users.get("Resources", []) |
| 77 | + if len(users_res) < 1: |
| 78 | + raise exc |
| 79 | + return SCIMProviderUser.objects.create( |
| 80 | + provider=self.provider, user=user, scim_id=users_res[0]["id"] |
| 81 | + ) |
| 82 | + else: |
| 83 | + scim_id = response.get("id") |
| 84 | + if not scim_id or scim_id == "": |
| 85 | + raise StopSync("SCIM Response with missing or invalid `id`") |
| 86 | + return SCIMProviderUser.objects.create( |
| 87 | + provider=self.provider, user=user, scim_id=scim_id |
| 88 | + ) |
70 | 89 |
|
71 | 90 | def update(self, user: User, connection: SCIMProviderUser):
|
72 | 91 | """Update existing user"""
|
|
0 commit comments