Skip to content

Commit 3780898

Browse files
committed
CH-220 fix user sync race condition
1 parent 7e8db03 commit 3780898

1 file changed

Lines changed: 13 additions & 4 deletions

File tree

  • infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django

infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/middleware.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,19 @@
33

44
from django.contrib.auth.models import User
55
from django.contrib.auth import logout
6+
from django.db import transaction
67
from keycloak.exceptions import KeycloakGetError
78

89
from cloudharness.auth.exceptions import InvalidToken
910
from cloudharness_django.services import get_user_service
1011
from .models import Member
1112
from cloudharness import log
1213
from cloudharness.auth.keycloak import get_current_user_id, User as KcUser
14+
from psycopg2.errors import UniqueViolation
1315

1416

1517
def _get_user(kc_user_id: str) -> User:
16-
18+
user = None
1719
if kc_user_id is None:
1820
return None
1921
# found bearer token get the Django user
@@ -26,15 +28,21 @@ def _get_user(kc_user_id: str) -> User:
2628
try:
2729
user = user_svc.sync_kc_user(kc_user)
2830
user_svc.sync_kc_user_groups(kc_user)
29-
except Exception as e:
30-
log.exception("User sync error, %s", kc_user.email)
31-
return None
31+
except UniqueViolation as e:
32+
# this can happen as a race condition while creating the Member object
33+
log.warning("UniqueViolation error for kc_id %s. Probably a race condition. %s", kc_user_id, str(e))
34+
return User.objects.get(member__kc_id=kc_user_id) # If it still fails, we are missing something serious
35+
3236
except User.MultipleObjectsReturned:
3337
# Race condition, multiple users created for the same kc_id
3438
log.warning("Multiple users found for kc_id %s, cleaning up...", kc_user_id)
3539
user = User.objects.filter(member__kc_id=kc_user_id).order_by('id').first()
3640
User.objects.filter(member__kc_id=kc_user_id).exclude(id=user.id).delete()
3741
return user
42+
43+
except Exception as e:
44+
log.exception("User sync error, %s", kc_user.email)
45+
return None
3846
return user
3947
except KeycloakGetError:
4048
# KC user not found
@@ -51,6 +59,7 @@ def __init__(self, get_response=None):
5159
# One-time configuration and initialization.
5260
self.get_response = get_response
5361

62+
@transaction.atomic
5463
def __call__(self, request):
5564
user = getattr(request, "user", None)
5665

0 commit comments

Comments
 (0)