33
44from django .contrib .auth .models import User
55from django .contrib .auth import logout
6+ from django .db import transaction
67from keycloak .exceptions import KeycloakGetError
78
89from cloudharness .auth .exceptions import InvalidToken
910from cloudharness_django .services import get_user_service
1011from .models import Member
1112from cloudharness import log
1213from cloudharness .auth .keycloak import get_current_user_id , User as KcUser
14+ from psycopg2 .errors import UniqueViolation
1315
1416
1517def _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