@@ -85,7 +85,7 @@ def test_determine_username_from_uid(
8585 # Use different log levels based on the scenario
8686 log_level = 'warning' if related_authenticator == 'ldap' else 'info'
8787 with expected_log (self .logger , log_level , info_message ):
88- new_username = authentication .determine_username_from_uid (uid , "" , local_authenticator )
88+ new_username = authentication .determine_username_from_uid (uid = uid , email = "" , authenticator = local_authenticator )
8989 if expected_username :
9090 assert new_username == random_user .username
9191 else :
@@ -173,7 +173,7 @@ def test_external_system_user_login(self, request, auth_fixture):
173173 uid = settings .SYSTEM_USERNAME
174174 authenticator = request .getfixturevalue (auth_fixture )
175175 with pytest .raises (AuthException ):
176- authentication .determine_username_from_uid (uid , "" , authenticator )
176+ authentication .determine_username_from_uid (uid = uid , email = "" , authenticator = authenticator )
177177 with pytest .raises (AuthException ):
178178 authentication .get_or_create_authenticator_user (uid = uid , email = "" , authenticator = authenticator , user_details = {}, extra_data = {})
179179
@@ -249,27 +249,6 @@ def test_determine_username_from_uid_social_happy_path(self, ldap_authenticator)
249249 )
250250 assert response == {'username' : 'Bob' }
251251
252- @pytest .mark .parametrize (
253- "auth_fixture, expected_username, uid_param, details_username" ,
254- [
255- # SAML authenticator uses uid parameter (line 141)
256- ("saml_authenticator" , "SamlUser" , "SamlUser" , "should_not_be_used" ),
257- # Non-SAML authenticators use details['username'] (line 143)
258- ("ldap_authenticator" , "LdapUser" , "should_not_be_used" , "LdapUser" ),
259- ("oidc_authenticator" , "OidcUser" , "should_not_be_used" , "OidcUser" ),
260- ("keycloak_authenticator" , "KeycloakUser" , "should_not_be_used" , "KeycloakUser" ),
261- ],
262- )
263- def test_determine_username_from_uid_social_authenticator_types (self , request , auth_fixture , expected_username , uid_param , details_username ):
264- """Test username selection logic for different authenticator types (lines 140-143)"""
265- authenticator = request .getfixturevalue (auth_fixture )
266- response = authentication .determine_username_from_uid_social (
267- details = {'username' : details_username },
268- backend = get_authenticator_class (authenticator .type )(database_instance = authenticator ),
269- uid = uid_param ,
270- )
271- assert response == {'username' : expected_username }
272-
273252 def test_raise_auth_exception (self ):
274253 try :
275254 authentication .raise_auth_exception ('testing' )
@@ -288,3 +267,113 @@ def test_raise_auth_exception_in_logs(self, local_authenticator, expected_log):
288267 )
289268 except AuthException :
290269 pass
270+
271+ @pytest .mark .parametrize (
272+ "uid_param, expected_uid_filter" ,
273+ [
274+ ("user123" , ["testuser" , "user123" ]), # When uid is provided, should include both selected_username and uid
275+ (None , ["testuser" ]), # When uid is None, should only include selected_username
276+ ("" , ["testuser" ]), # When uid is empty string, should only include selected_username
277+ ],
278+ )
279+ def test_determine_username_from_uid_social_uid_filter_construction (self , ldap_authenticator , uid_param , expected_uid_filter ):
280+ """Test that uid_filter is constructed correctly in determine_username_from_uid_social."""
281+ from unittest .mock import patch
282+
283+ authenticator_class = get_authenticator_class (ldap_authenticator .type )(database_instance = ldap_authenticator )
284+
285+ # Mock migrate_from_existing_authenticator to return None (no migration)
286+ # Mock determine_username_from_uid to capture the uid_filter parameter
287+ with patch ('ansible_base.authentication.utils.authentication.migrate_from_existing_authenticator' ) as mock_migrate :
288+ mock_migrate .return_value = None
289+
290+ with patch ('ansible_base.authentication.utils.authentication.determine_username_from_uid' ) as mock_determine_uid :
291+ mock_determine_uid .return_value = 'testuser'
292+
293+ kwargs = {
294+ 'details' : {
'username' :
'testuser' ,
'email' :
'[email protected] ' },
295+ 'backend' : authenticator_class ,
296+ }
297+ if uid_param is not None :
298+ kwargs ['uid' ] = uid_param
299+
300+ response = authentication .determine_username_from_uid_social (** kwargs )
301+
302+ # Verify determine_username_from_uid was called with correct uid_filter
303+ mock_determine_uid .assert_called_once_with (
304+ uid = 'testuser' ,
uid_filter = expected_uid_filter ,
email = '[email protected] ' ,
authenticator = ldap_authenticator 305+ )
306+ assert response == {'username' : 'testuser' }
307+
308+ def test_determine_username_from_uid_social_uid_filter_with_email_username (self , ldap_authenticator ):
309+ """Test uid_filter construction when USERNAME_IS_FULL_EMAIL is True."""
310+ from unittest .mock import patch
311+
312+ authenticator_class = get_authenticator_class (ldap_authenticator .type )(database_instance = ldap_authenticator )
313+
314+ # Mock migrate_from_existing_authenticator to return None (no migration)
315+ # Mock the setting method to return True for USERNAME_IS_FULL_EMAIL
316+ with patch ('ansible_base.authentication.utils.authentication.migrate_from_existing_authenticator' ) as mock_migrate :
317+ mock_migrate .return_value = None
318+
319+ with patch .object (authenticator_class , 'setting' ) as mock_setting :
320+ mock_setting .return_value = True
321+
322+ with patch ('ansible_base.authentication.utils.authentication.determine_username_from_uid' ) as mock_determine_uid :
323+ mock_determine_uid .
return_value = '[email protected] ' 324+
325+ response = authentication .determine_username_from_uid_social (
326+ details = {
'username' :
'testuser' ,
'email' :
'[email protected] ' },
backend = authenticator_class ,
uid = 'uid123' 327+ )
328+
329+ # When USERNAME_IS_FULL_EMAIL is True, selected_username should be the email
330+ mock_determine_uid .assert_called_once_with (
331+ uid = '[email protected] ' ,
uid_filter = [
'[email protected] ' ,
'uid123' ],
email = '[email protected] ' ,
authenticator = ldap_authenticator 332+ )
333+ assert response == {
'username' :
'[email protected] ' }
334+
335+ def test_determine_username_from_uid_social_uid_filter_no_migration (self , ldap_authenticator ):
336+ """Test that uid_filter is passed to determine_username_from_uid when migration doesn't occur."""
337+ from unittest .mock import patch
338+
339+ authenticator_class = get_authenticator_class (ldap_authenticator .type )(database_instance = ldap_authenticator )
340+
341+ with patch ('ansible_base.authentication.utils.authentication.migrate_from_existing_authenticator' ) as mock_migrate :
342+ mock_migrate .return_value = None # No migration
343+
344+ with patch ('ansible_base.authentication.utils.authentication.determine_username_from_uid' ) as mock_determine_uid :
345+ mock_determine_uid .return_value = 'finaluser'
346+
347+ response = authentication .determine_username_from_uid_social (
348+ details = {
'username' :
'originaluser' ,
'email' :
'[email protected] ' },
backend = authenticator_class ,
uid = 'uid456' 349+ )
350+
351+ # Verify migration was attempted first
352+ mock_migrate .assert_called_once_with (uid = 'uid456' , alt_uid = None , authenticator = ldap_authenticator , preferred_username = 'originaluser' )
353+
354+ # Verify determine_username_from_uid was called with correct uid_filter
355+ mock_determine_uid .assert_called_once_with (
356+ uid = 'originaluser' ,
uid_filter = [
'originaluser' ,
'uid456' ],
email = '[email protected] ' ,
authenticator = ldap_authenticator 357+ )
358+ assert response == {'username' : 'finaluser' }
359+
360+ def test_determine_username_from_uid_social_uid_filter_with_migration (self , ldap_authenticator ):
361+ """Test that determine_username_from_uid is not called when migration succeeds."""
362+ from unittest .mock import patch
363+
364+ authenticator_class = get_authenticator_class (ldap_authenticator .type )(database_instance = ldap_authenticator )
365+
366+ with patch ('ansible_base.authentication.utils.authentication.migrate_from_existing_authenticator' ) as mock_migrate :
367+ mock_migrate .return_value = 'migrated_user' # Migration succeeded
368+
369+ with patch ('ansible_base.authentication.utils.authentication.determine_username_from_uid' ) as mock_determine_uid :
370+ response = authentication .determine_username_from_uid_social (
371+ details = {
'username' :
'originaluser' ,
'email' :
'[email protected] ' },
backend = authenticator_class ,
uid = 'uid789' 372+ )
373+
374+ # Verify migration was attempted
375+ mock_migrate .assert_called_once_with (uid = 'uid789' , alt_uid = None , authenticator = ldap_authenticator , preferred_username = 'originaluser' )
376+
377+ # determine_username_from_uid should NOT be called when migration succeeds
378+ mock_determine_uid .assert_not_called ()
379+ assert response == {'username' : 'migrated_user' }
0 commit comments