@@ -32,6 +32,14 @@ def run_filter(self, readonly_fields, user): # pylint: disable=arguments-differ
3232 """
3333 Add enterprise SSO-managed fields to the read-only fields set.
3434
35+ The original code migrated from openedx-platform can be distilled into 3 logical branches:
36+
37+ 1. If NO identify provider (IdP) has sync enabled → no readonly fields added.
38+ 2. If one or more IdPs have sync enabled, AND user has social auth → append ALL readonly fields.
39+ 3. If one or more IdPs have sync enabled, AND user has NO social auth → append readonly fields MINUS 'name'.
40+
41+ Each return statement below is marked with the corresponding branch number.
42+
3543 Arguments:
3644 readonly_fields (set): current set of read-only account field names.
3745 user (User): the Django User whose account settings are being updated.
@@ -46,35 +54,52 @@ def run_filter(self, readonly_fields, user): # pylint: disable=arguments-differ
4654 .first ()
4755 )
4856 if not enterprise_customer_user :
57+ # Logical branch #1 (early exit)
4958 return {"readonly_fields" : readonly_fields , "user" : user }
5059
5160 enterprise_customer = enterprise_customer_user .enterprise_customer
5261
53- idp_qs = EnterpriseCustomerIdentityProvider .objects .filter (
54- enterprise_customer = enterprise_customer
62+ idp_records = list (
63+ EnterpriseCustomerIdentityProvider .objects
64+ .filter (enterprise_customer = enterprise_customer )
5565 )
5666
57- # look for default provider in case of multiple, or default to first
58- idp_record = idp_qs .filter (default_provider = True ).first () or idp_qs .first ()
59- if not idp_record :
60- return {"readonly_fields" : readonly_fields , "user" : user }
67+ # Track whether any IdP for the customer is configured to sync learner profile data. If none are, then we can
68+ # safely allow all fields to be editable since they won't get overwritten by the sync process
69+ sync_learner_profile_data = False
6170
62- identity_provider = third_party_auth .provider .Registry .get (
63- provider_id = idp_record .provider_id
64- )
71+ # Accumulate a list of all identity providers for the customer. If the learner does NOT have any social auth
72+ # account configured with these backends, then we can safely allow them to edit the 'name' field (full name)
73+ provider_backend_names = []
74+
75+ for idp in idp_records :
76+ identity_provider = third_party_auth .provider .Registry .get (
77+ provider_id = idp .provider_id
78+ )
79+ if identity_provider and getattr (identity_provider , 'sync_learner_profile_data' , False ):
80+ sync_learner_profile_data = True
81+
82+ backend_name = getattr (identity_provider , 'backend_name' , None )
83+ if backend_name :
84+ provider_backend_names .append (backend_name )
6585
66- if not identity_provider or not getattr (identity_provider , 'sync_learner_profile_data' , False ):
86+ # If none of the IdPs for the customer are configured to sync, allow the fields to be editable
87+ if not sync_learner_profile_data :
88+ # Logical branch #1
6789 return {"readonly_fields" : readonly_fields , "user" : user }
6890
91+ # Determine if the learner has social auth configured.
92+ has_social_auth = False
93+ if provider_backend_names :
94+ has_social_auth = UserSocialAuth .objects .filter (
95+ provider__in = provider_backend_names , user = user
96+ ).exists ()
97+
6998 enterprise_readonly = set (getattr (settings , 'ENTERPRISE_READONLY_ACCOUNT_FIELDS' , []))
7099
71- if 'name' in enterprise_readonly :
72- backend_name = getattr (identity_provider , 'backend_name' , None )
73- has_social_auth = (
74- backend_name
75- and UserSocialAuth .objects .filter (provider = backend_name , user = user ).exists ()
76- )
77- if not has_social_auth :
78- enterprise_readonly = enterprise_readonly - {'name' }
100+ # If the learner does NOT have social auth configured, then at least allow them to edit their name.
101+ if not has_social_auth :
102+ enterprise_readonly = enterprise_readonly - {'name' }
79103
104+ # Logical branch #2 and #3
80105 return {"readonly_fields" : readonly_fields | enterprise_readonly , "user" : user }
0 commit comments