Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: openedx/edx-platform
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 712fabfbebd277b94e44dcc3a4d63365bd8fa67f
Choose a base ref
..
head repository: openedx/edx-platform
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5812d7f6a25cc1d35c0757538fe1548cf4200387
Choose a head ref
4 changes: 4 additions & 0 deletions lms/djangoapps/bulk_email/signals.py
Original file line number Diff line number Diff line change
@@ -44,6 +44,8 @@ def ace_email_sent_handler(sender, **kwargs):
user_id = recipient.get('user_id', None)
channel = message.get('channel', None)
course_id = context.get('course_id', None)
message_language = message.get('message_language', None)
translation_language = message.get('translation_language', None)
if not course_id:
course_email = context.get('course_email', None)
course_id = course_email.course_id if course_email else None
@@ -56,5 +58,7 @@ def ace_email_sent_handler(sender, **kwargs):
'course_id': course_id,
'user_id': user_id,
'user_email': email_address,
'message_language': message_language,
'translation_language': translation_language,
}
)
2 changes: 1 addition & 1 deletion lms/envs/common.py
Original file line number Diff line number Diff line change
@@ -4952,7 +4952,7 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring
# .. setting_description: Set the format a retired user username field gets transformed into, where {}
# is replaced with the hash of the original username. This is a derived setting that depends on
# RETIRED_USERNAME_PREFIX value.
RETIRED_USERNAME_FMT = Derived(lambda settings: settings.RETIRED_USERNAME_PREFIX + '{}'),
RETIRED_USERNAME_FMT = Derived(lambda settings: settings.RETIRED_USERNAME_PREFIX + '{}')
# .. setting_name: RETIRED_EMAIL_FMT
# .. setting_default: retired__user_{}@retired.invalid
# .. setting_description: Set the format a retired user email field gets transformed into, where {} is
14 changes: 7 additions & 7 deletions openedx/core/lib/derived.py
Original file line number Diff line number Diff line change
@@ -55,9 +55,9 @@ def _match_every_key(_key: str) -> bool:

def _derive_recursively(settings: Settings, value: t.Any) -> t.Any:
"""
Recursively evaluate `Derive` objects` in `value` and any child containers. Return the evaluated version of `value`.
Recursively evaluate `Derived` objects` in `value` and any child containers. Return the evaluated version of `value`.
* If `value` is a `Derive` object, then use `settings` to calculate and return its value.
* If `value` is a `Derived` object, then use `settings` to calculate and return its value.
* If `value` is a mutable container, then recursively evaluate it in-place.
* If `value` is an immutable container, then recursively evalute a shallow copy of it.
Keep in mind that immutable containers (particularly: tuples) can contain mutable containers. In such a case, the
@@ -79,7 +79,7 @@ def _derive_recursively(settings: Settings, value: t.Any) -> t.Any:

def _derive_dict(settings: Settings, the_dict: dict, key_filter: t.Callable[[str], bool] = _match_every_key) -> dict:
"""
Recursively evaluate `Derive` objects in `the_dict` and any child containers. Modifies `the_dict` in place.
Recursively evaluate `Derived` objects in `the_dict` and any child containers. Modifies `the_dict` in place.
Optionally takes a `key_filter`. Items that do not match the provided `key_filter` will be left alone.
"""
@@ -91,7 +91,7 @@ def _derive_dict(settings: Settings, the_dict: dict, key_filter: t.Callable[[str

def _derive_list(settings: Settings, the_list: list) -> list:
"""
Recursively evaluate `Derive` objects in `the_list` and any child containers. Modifies `the_list` in place.
Recursively evaluate `Derived` objects in `the_list` and any child containers. Modifies `the_list` in place.
"""
for ix in range(len(the_list)):
the_list[ix] = _derive_recursively(settings, the_list[ix])
@@ -100,14 +100,14 @@ def _derive_list(settings: Settings, the_list: list) -> list:

def _derive_tuple(settings: Settings, tup: tuple) -> tuple:
"""
Recursively evaluate `Derive` objects in `tup` and any child containers. Returns a shallow copy of `tup`.
Recursively evaluate `Derived` objects in `tup` and any child containers. Returns a shallow copy of `tup`.
"""
return tuple(_derive_recursively(settings, item) for item in tup)


def _derive_set(settings: Settings, the_set: set) -> set:
"""
Recursively evaluate `Derive` objects in `the_set` and any child containers. Modifies `the_set` in-place.
Recursively evaluate `Derived` objects in `the_set` and any child containers. Modifies `the_set` in-place.
"""
for original in the_set:
derived = _derive_recursively(settings, original)
@@ -119,6 +119,6 @@ def _derive_set(settings: Settings, the_set: set) -> set:

def _derive_frozenset(settings: Settings, the_set: frozenset) -> frozenset:
"""
Recursively evaluate `Derive` objects in `the_set` and any child containers. Returns a shallow copy of `the_set`.
Recursively evaluate `Derived` objects in `the_set` and any child containers. Returns a shallow copy of `the_set`.
"""
return frozenset(_derive_recursively(settings, item) for item in the_set)
49 changes: 49 additions & 0 deletions openedx/features/enterprise_support/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@
)
from openedx.features.enterprise_support.utils import (
ENTERPRISE_HEADER_LINKS,
_user_has_social_auth_record,
clear_data_consent_share_cache,
enterprise_fields_only,
fetch_enterprise_customer_by_id,
@@ -539,6 +540,54 @@ def test_get_provider_login_url_with_redirect_url(self, mock_tpa, mock_next_logi
)
assert not mock_next_login_url.called

@mock.patch('openedx.features.enterprise_support.utils.UserSocialAuth')
@mock.patch('openedx.features.enterprise_support.utils.third_party_auth')
def test_user_has_social_auth_record(self, mock_tpa, mock_user_social_auth):
user = mock.Mock()
enterprise_customer = {
'identity_providers': [
{'provider_id': 'mock-idp'},
],
}
mock_idp = mock.MagicMock(backend_name='mock-backend')
mock_tpa.provider.Registry.get.return_value = mock_idp
mock_user_social_auth.objects.select_related.return_value.filter.return_value.exists.return_value = True

result = _user_has_social_auth_record(user, enterprise_customer)
assert result is True

mock_tpa.provider.Registry.get.assert_called_once_with(provider_id='mock-idp')
mock_user_social_auth.objects.select_related.assert_called_once_with('user')
mock_user_social_auth.objects.select_related.return_value.filter.assert_called_once_with(
provider__in=['mock-backend'], user=user
)

@mock.patch('openedx.features.enterprise_support.utils.UserSocialAuth')
@mock.patch('openedx.features.enterprise_support.utils.third_party_auth')
def test_user_has_social_auth_record_no_providers(self, mock_tpa, mock_user_social_auth):
user = mock.Mock()
enterprise_customer = {
'identity_providers': [],
}

result = _user_has_social_auth_record(user, enterprise_customer)
assert result is False

assert not mock_tpa.provider.Registry.get.called
assert not mock_user_social_auth.objects.select_related.called

@mock.patch('openedx.features.enterprise_support.utils.UserSocialAuth')
@mock.patch('openedx.features.enterprise_support.utils.third_party_auth')
def test_user_has_social_auth_record_no_enterprise_customer(self, mock_tpa, mock_user_social_auth):
user = mock.Mock()
enterprise_customer = None

result = _user_has_social_auth_record(user, enterprise_customer)
assert result is False

assert not mock_tpa.provider.Registry.get.called
assert not mock_user_social_auth.objects.select_related.called


@override_settings(FEATURES=FEATURES_WITH_ENTERPRISE_ENABLED)
@skip_unless_lms
9 changes: 6 additions & 3 deletions openedx/features/enterprise_support/utils.py
Original file line number Diff line number Diff line change
@@ -294,9 +294,12 @@ def _user_has_social_auth_record(user, enterprise_customer):
identity_provider = third_party_auth.provider.Registry.get(
provider_id=idp['provider_id']
)
provider_backend_names.append(identity_provider.backend_name)
return UserSocialAuth.objects.select_related('user').\
filter(provider__in=provider_backend_names, user=user).exists()
if identity_provider and hasattr(identity_provider, 'backend_name'):
provider_backend_names.append(identity_provider.backend_name)

if provider_backend_names:
return UserSocialAuth.objects.select_related('user').\
filter(provider__in=provider_backend_names, user=user).exists()
return False


2 changes: 1 addition & 1 deletion requirements/edx/base.txt
Original file line number Diff line number Diff line change
@@ -401,7 +401,7 @@ drf-yasg==1.21.8
# via
# django-user-tasks
# edx-api-doc-tools
edx-ace==1.11.3
edx-ace==1.11.4
# via -r requirements/edx/kernel.in
edx-api-doc-tools==2.0.0
# via
2 changes: 1 addition & 1 deletion requirements/edx/development.txt
Original file line number Diff line number Diff line change
@@ -661,7 +661,7 @@ drf-yasg==1.21.8
# -r requirements/edx/testing.txt
# django-user-tasks
# edx-api-doc-tools
edx-ace==1.11.3
edx-ace==1.11.4
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
2 changes: 1 addition & 1 deletion requirements/edx/doc.txt
Original file line number Diff line number Diff line change
@@ -486,7 +486,7 @@ drf-yasg==1.21.8
# -r requirements/edx/base.txt
# django-user-tasks
# edx-api-doc-tools
edx-ace==1.11.3
edx-ace==1.11.4
# via -r requirements/edx/base.txt
edx-api-doc-tools==2.0.0
# via
2 changes: 1 addition & 1 deletion requirements/edx/testing.txt
Original file line number Diff line number Diff line change
@@ -508,7 +508,7 @@ drf-yasg==1.21.8
# -r requirements/edx/base.txt
# django-user-tasks
# edx-api-doc-tools
edx-ace==1.11.3
edx-ace==1.11.4
# via -r requirements/edx/base.txt
edx-api-doc-tools==2.0.0
# via