Skip to content

Commit ed32cac

Browse files
authored
AAP-49736 Fix SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL (#779)
This setting causes social auth to use the user's email as their username if set to True (fixed)
1 parent 2ee8ba9 commit ed32cac

File tree

3 files changed

+68
-8
lines changed

3 files changed

+68
-8
lines changed

ansible_base/authentication/authenticator_plugins/ldap.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,9 @@ def process_login_messages(self, ldap_user, username: str) -> None:
583583
def update_settings(self, database_authenticator: Authenticator) -> None:
584584
self.settings = LDAPSettings(defaults=database_authenticator.configuration)
585585

586+
def setting(self, name, default=None):
587+
return getattr(self.settings, name, default)
588+
586589
def get_or_build_user(self, username, ldap_user):
587590
"""
588591
This gets called by _LDAPUser to create the user in the database.

ansible_base/authentication/utils/authentication.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import importlib
12
import logging
23
from typing import Optional, Tuple, Union
34

@@ -20,8 +21,24 @@
2021

2122

2223
class FakeBackend:
23-
def setting(self, *args, **kwargs):
24-
return ["username", "email"]
24+
def __init__(self):
25+
self.settings = {}
26+
fq_function_name = getattr(settings, 'ANSIBLE_BASE_SOCIAL_AUTH_STRATEGY_SETTINGS_FUNCTION', None)
27+
if fq_function_name:
28+
try:
29+
module_name, _, function_name = fq_function_name.rpartition('.')
30+
the_function = getattr(importlib.import_module(module_name), function_name)
31+
self.settings = the_function()
32+
except Exception as e:
33+
logger.error(f"FakeBackend: Failed to run {fq_function_name} to get additional settings: {e}")
34+
35+
self.settings["USER_FIELDS"] = ["username", "email"]
36+
37+
def setting(self, name, default=None):
38+
for name in [name, f"SOCIAL_AUTH_{name}"]:
39+
if name in self.settings:
40+
return self.settings[name]
41+
return default
2542

2643

2744
def raise_auth_exception(message: str, backend: Optional[Authenticator] = None):
@@ -87,7 +104,6 @@ def get_local_username(user_details: dict) -> str:
87104
from other auth backends.
88105
"""
89106
username = get_username(strategy=AuthenticatorStrategy(AuthenticatorStorage()), details=user_details, backend=FakeBackend())
90-
91107
return username['username']
92108

93109

@@ -118,8 +134,10 @@ def determine_username_from_uid_social(**kwargs) -> dict:
118134
authenticator = kwargs.get('backend')
119135
if not authenticator:
120136
raise_auth_exception(_('Unable to get backend from kwargs'))
121-
122-
selected_username = kwargs.get('details', {}).get('username', None)
137+
if authenticator.setting('USERNAME_IS_FULL_EMAIL', False):
138+
selected_username = kwargs.get('details', {}).get('email', None)
139+
else:
140+
selected_username = kwargs.get('details', {}).get('username', None)
123141
if not selected_username:
124142
raise_auth_exception(
125143
_('Unable to get associated username from details, expected entry "username". Full user details: %(details)s')

test_app/tests/authentication/utils/test_authentication.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pytest
22
from django.conf import settings
3+
from django.test import override_settings
34
from social_core.exceptions import AuthException
45

56
from ansible_base.authentication.authenticator_plugins.utils import get_authenticator_class
@@ -9,14 +10,36 @@
910
from test_app.models import User
1011

1112

13+
def load_social_auth_settings():
14+
return {"SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL": settings.SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL}
15+
16+
1217
@pytest.mark.django_db
1318
class TestAuthenticationUtilsAuthentication:
1419
logger = 'ansible_base.authentication.utils.authentication.logger'
1520

16-
def test_fake_backend_settings(self):
21+
@pytest.mark.parametrize(
22+
"name, exp_val, username_is_full_email_setting",
23+
[
24+
("USER_FIELDS", ["username", "email"], False),
25+
("SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL", True, True),
26+
("SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL", False, False),
27+
("BOGUS", None, False),
28+
],
29+
)
30+
def test_fake_backend_settings(self, name, exp_val, username_is_full_email_setting):
31+
with override_settings(SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL=username_is_full_email_setting):
32+
with override_settings(
33+
ANSIBLE_BASE_SOCIAL_AUTH_STRATEGY_SETTINGS_FUNCTION="test_app.tests.authentication.utils.test_authentication.load_social_auth_settings"
34+
):
35+
backend = authentication.FakeBackend()
36+
response = backend.setting(name)
37+
assert response == exp_val
38+
39+
def test_fake_backend_settings_with_default(self):
1740
backend = authentication.FakeBackend()
18-
response = backend.setting()
19-
assert response == ["username", "email"]
41+
response = backend.setting("BOGUS", "bogus_default")
42+
assert response == "bogus_default"
2043

2144
def test_get_local_username_no_input(self):
2245
response = authentication.get_local_username({})
@@ -26,6 +49,22 @@ def test_get_local_user_username_existing_user(self, random_user):
2649
response = authentication.get_local_username({'username': random_user.username})
2750
assert len(response) > len(random_user.username)
2851

52+
@pytest.mark.parametrize(
53+
"username_is_full_email_setting, expected_username",
54+
[
55+
(True, "[email protected]"),
56+
(False, "new-user"),
57+
],
58+
)
59+
def test_get_local_username_with_email(self, username_is_full_email_setting, expected_username):
60+
user_details = {'username': 'new-user', 'email': '[email protected]'}
61+
with override_settings(SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL=username_is_full_email_setting):
62+
with override_settings(
63+
ANSIBLE_BASE_SOCIAL_AUTH_STRATEGY_SETTINGS_FUNCTION="test_app.tests.authentication.utils.test_authentication.load_social_auth_settings"
64+
):
65+
response = authentication.get_local_username(user_details)
66+
assert response == expected_username
67+
2968
@pytest.mark.parametrize(
3069
"related_authenticator,info_message,expected_username",
3170
[

0 commit comments

Comments
 (0)