Skip to content

Commit 186d67a

Browse files
authored
Merge branch 'pwnage101/ENT-11510' of github.com:openedx/edx-enterprise into pwnage101/ENT-11510
2 parents 7682420 + 6408c56 commit 186d67a

File tree

7 files changed

+78
-34
lines changed

7 files changed

+78
-34
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ Unreleased
2121
---------------------
2222
* feat: add AccountSettingsReadOnlyFieldsStep pipeline step (ENT-11510)
2323

24+
[6.8.3] - 2026-03-27
25+
---------------------
26+
* fix: Move settings reads out of AppConfig, into consumers
27+
2428
[6.8.2] - 2026-03-26
2529
---------------------
2630
* feat: add admin invite reminder emails (ENT-11581)

enterprise/api/v1/views/coupon_codes.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST, HTTP_500_INTERNAL_SERVER_ERROR
1313
from rest_framework.views import APIView
1414

15-
from django.apps import apps
15+
from django.conf import settings
1616
from django.core import mail
1717
from django.utils.translation import gettext as _
1818

@@ -97,9 +97,8 @@ def post(self, request):
9797
token_enterprise_name=enterprise_name
9898
)
9999
body_msg = create_message_body(email, enterprise_name, number_of_codes, notes)
100-
app_config = apps.get_app_config("enterprise")
101-
from_email_address = app_config.enterprise_integrations_email
102-
cs_email = app_config.customer_success_email
100+
from_email_address = settings.ENTERPRISE_INTEGRATIONS_EMAIL
101+
cs_email = settings.ENTERPRISE_CUSTOMER_SUCCESS_EMAIL
103102
data = {
104103
self.REQUIRED_PARAM_EMAIL: email,
105104
self.REQUIRED_PARAM_ENTERPRISE_NAME: enterprise_name,

enterprise/api_client/client.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from edx_rest_api_client.auth import SuppliedJwtAuth
1111
from edx_rest_api_client.client import OAuthAPIClient
1212

13-
from django.apps import apps
1413
from django.conf import settings
1514

1615
from enterprise.utils import NotConnectedToOpenEdX # pylint: disable=cyclic-import
@@ -49,11 +48,10 @@ class BackendServiceAPIClient(APIClientMixin):
4948
Uses the backend service user to make requests.
5049
"""
5150
def __init__(self):
52-
app_config = apps.get_app_config("enterprise")
5351
self.client = OAuthAPIClient(
54-
app_config.backend_service_edx_oauth2_provider_url,
55-
app_config.backend_service_edx_oauth2_key,
56-
app_config.backend_service_edx_oauth2_secret
52+
base_url=settings.ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_PROVIDER_URL,
53+
client_id=settings.ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_KEY,
54+
client_secret=settings.ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_SECRET,
5755
)
5856

5957

enterprise/apps.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"""
44

55
from django.apps import AppConfig, apps
6-
from django.conf import settings
76

87
from enterprise.constants import USER_POST_SAVE_DISPATCH_UID
98

@@ -28,23 +27,6 @@ class EnterpriseConfig(AppConfig):
2827

2928
name = "enterprise"
3029
valid_image_extensions = [".png", ]
31-
valid_max_image_size = getattr(settings, 'ENTERPRISE_CUSTOMER_LOGO_IMAGE_SIZE', 512) # Value in KB's
32-
customer_success_email = getattr(settings, 'ENTERPRISE_CUSTOMER_SUCCESS_EMAIL', 'customersuccess@edx.org')
33-
enterprise_integrations_email = getattr(
34-
settings,
35-
'ENTERPRISE_INTEGRATIONS_EMAIL',
36-
'enterprise-integrations@edx.org'
37-
)
38-
39-
backend_service_edx_oauth2_key = getattr(
40-
settings, "ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_KEY", "enterprise-backend-service-key"
41-
)
42-
backend_service_edx_oauth2_secret = getattr(
43-
settings, "ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_SECRET", "enterprise-backend-service-secret"
44-
)
45-
backend_service_edx_oauth2_provider_url = getattr(
46-
settings, "ENTERPRISE_BACKEND_SERVICE_EDX_OAUTH2_PROVIDER_URL", "http://127.0.0.1:8000/oauth2"
47-
)
4830

4931
@property
5032
def auth_user_model(self):

enterprise/settings/test.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,6 @@ def root(*args):
415415
ADMIN_INVITE_REMINDER_CADENCE_DAYS = 3
416416
ADMIN_INVITE_REMINDER_MAX_COUNT = 1
417417
ADMIN_INVITE_REMINDER_BATCH_SIZE = 500
418+
419+
ENTERPRISE_CUSTOMER_SUCCESS_EMAIL = 'customersuccess@edx.org'
420+
ENTERPRISE_INTEGRATIONS_EMAIL = 'enterprise-integrations@edx.org'

enterprise/validators.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import pgpy
99

1010
from django.apps import apps
11+
from django.conf import settings
1112
from django.core.exceptions import ValidationError
1213
from django.utils.translation import gettext_lazy as _
1314

@@ -45,11 +46,11 @@ def validate_image_size(image):
4546
"""
4647
Validate that a particular image size.
4748
"""
48-
config = get_app_config()
49-
valid_max_image_size_in_bytes = config.valid_max_image_size * 1024
50-
if config and not image.size <= valid_max_image_size_in_bytes:
49+
valid_max_image_size_in_kb = getattr(settings, 'ENTERPRISE_CUSTOMER_LOGO_IMAGE_SIZE', 512)
50+
valid_max_image_size_in_bytes = valid_max_image_size_in_kb * 1024
51+
if not image.size <= valid_max_image_size_in_bytes:
5152
raise ValidationError(
52-
_("The logo image file size must be less than or equal to %s KB.") % config.valid_max_image_size)
53+
_("The logo image file size must be less than or equal to %s KB.") % valid_max_image_size_in_kb)
5354

5455

5556
def validate_content_filter_fields(content_filter):

tests/filters/test_accounts.py

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from django.test import TestCase, override_settings
77

88
from enterprise.filters.accounts import AccountSettingsReadOnlyFieldsStep
9-
from enterprise.models import EnterpriseCustomerUser
9+
from enterprise.models import EnterpriseCustomerIdentityProvider, EnterpriseCustomerUser
1010

1111

1212
class TestAccountSettingsReadOnlyFieldsStep(TestCase):
@@ -33,8 +33,9 @@ def test_returns_unchanged_readonly_fields_when_no_enterprise_user(self, mock_ob
3333
mock_objects.select_related.return_value.get.side_effect = EnterpriseCustomerUser.DoesNotExist
3434
step = self._make_step()
3535
fields = set()
36-
result = step.run_filter(readonly_fields=fields, user=self._mock_user())
37-
self.assertEqual(result, {"readonly_fields": fields})
36+
user = self._mock_user()
37+
result = step.run_filter(readonly_fields=fields, user=user)
38+
self.assertEqual(result, {"readonly_fields": fields, "user": user})
3839

3940
@patch('enterprise.filters.accounts.UserSocialAuth')
4041
@patch('enterprise.filters.accounts.EnterpriseCustomerIdentityProvider.objects')
@@ -100,3 +101,59 @@ def test_name_not_added_without_social_auth_record(
100101

101102
self.assertNotIn("name", result["readonly_fields"])
102103
self.assertIn("email", result["readonly_fields"])
104+
105+
@patch('enterprise.filters.accounts.EnterpriseCustomerIdentityProvider.objects')
106+
@patch('enterprise.filters.accounts.EnterpriseCustomerUser.objects')
107+
def test_returns_unchanged_readonly_fields_when_no_idp_record(
108+
self, mock_ecu_objects, mock_idp_objects
109+
):
110+
"""
111+
When the enterprise customer has no linked identity provider,
112+
readonly_fields is returned unchanged.
113+
"""
114+
user = self._mock_user()
115+
mock_ecu_objects.select_related.return_value.get.return_value = MagicMock()
116+
mock_idp_objects.get.side_effect = EnterpriseCustomerIdentityProvider.DoesNotExist
117+
step = self._make_step()
118+
fields = {'existing_field'}
119+
result = step.run_filter(readonly_fields=fields, user=user)
120+
self.assertEqual(result["readonly_fields"], fields)
121+
122+
@patch('enterprise.filters.accounts.EnterpriseCustomerIdentityProvider.objects')
123+
@patch('enterprise.filters.accounts.EnterpriseCustomerUser.objects')
124+
def test_returns_unchanged_readonly_fields_when_third_party_auth_unavailable(
125+
self, mock_ecu_objects, mock_idp_objects
126+
):
127+
"""
128+
When third_party_auth is not installed (None), readonly_fields is returned unchanged.
129+
"""
130+
user = self._mock_user()
131+
mock_ecu_objects.select_related.return_value.get.return_value = MagicMock()
132+
mock_idp_objects.get.return_value = MagicMock(provider_id='saml-test')
133+
step = self._make_step()
134+
fields = {'existing_field'}
135+
with patch('enterprise.filters.accounts.third_party_auth', None):
136+
result = step.run_filter(readonly_fields=fields, user=user)
137+
self.assertEqual(result["readonly_fields"], fields)
138+
139+
@patch('enterprise.filters.accounts.EnterpriseCustomerIdentityProvider.objects')
140+
@patch('enterprise.filters.accounts.EnterpriseCustomerUser.objects')
141+
def test_returns_unchanged_readonly_fields_when_sync_not_enabled(
142+
self, mock_ecu_objects, mock_idp_objects
143+
):
144+
"""
145+
When the identity provider exists but sync_learner_profile_data is False,
146+
readonly_fields is returned unchanged.
147+
"""
148+
user = self._mock_user()
149+
mock_ecu_objects.select_related.return_value.get.return_value = MagicMock()
150+
mock_idp_objects.get.return_value = MagicMock(provider_id='saml-test')
151+
mock_identity_provider = MagicMock()
152+
mock_identity_provider.sync_learner_profile_data = False
153+
mock_tpa = MagicMock()
154+
mock_tpa.provider.Registry.get.return_value = mock_identity_provider
155+
step = self._make_step()
156+
fields = {'existing_field'}
157+
with patch('enterprise.filters.accounts.third_party_auth', mock_tpa):
158+
result = step.run_filter(readonly_fields=fields, user=user)
159+
self.assertEqual(result["readonly_fields"], fields)

0 commit comments

Comments
 (0)