33"""
44
55import copy
6+ import logging
67import re
78from importlib import import_module
89
1819from eventtracking import tracker
1920
2021from common .djangoapps import third_party_auth
22+ from common .djangoapps .third_party_auth .models import SAMLProviderConfig
2123from common .djangoapps .edxmako .shortcuts import marketing_link
2224from common .djangoapps .student .models import CourseEnrollmentAllowed , UserProfile , email_exists_or_retired
2325from common .djangoapps .util .password_policy_validators import (
3638from openedx .features .enterprise_support .api import enterprise_customer_for_request
3739
3840
41+ log = logging .getLogger (__name__ )
42+
43+
3944class TrueCheckbox (widgets .CheckboxInput ):
4045 """
4146 A checkbox widget that only accepts "true" (case-insensitive) as true.
@@ -410,6 +415,56 @@ def __init__(self):
410415 field_order .extend (sorted (difference ))
411416
412417 self .field_order = field_order
418+ self .request = None # Will be set by get_registration_form
419+
420+ def _get_saml_provider_config (self ):
421+ """
422+ Get the SAML provider config for the current request's running pipeline.
423+
424+ Returns:
425+ SAMLProviderConfig or None: The SAML provider config if found, None otherwise
426+ """
427+ if not self .request or not third_party_auth .is_enabled ():
428+ return None
429+
430+ running_pipeline = third_party_auth .pipeline .get (self .request )
431+ if not running_pipeline :
432+ return None
433+
434+ try :
435+ # idp_name can be in kwargs directly or in kwargs['details']
436+ saml_provider_name = running_pipeline .get ('kwargs' , {}).get ('idp_name' )
437+ if not saml_provider_name :
438+ saml_provider_name = (
439+ running_pipeline .get ('kwargs' , {})
440+ .get ('details' , {})
441+ .get ('idp_name' )
442+ )
443+
444+ if not saml_provider_name :
445+ return None
446+
447+ try :
448+ # Try to find the SAML provider config
449+ # First try with current_set(), then fall back to direct query
450+ try :
451+ return SAMLProviderConfig .objects .current_set ().get (
452+ slug = saml_provider_name
453+ )
454+ except SAMLProviderConfig .DoesNotExist :
455+ # Fallback to direct query without current_set()
456+ return SAMLProviderConfig .objects .get (
457+ slug = saml_provider_name
458+ )
459+ except SAMLProviderConfig .DoesNotExist :
460+ log .debug (
461+ "SAML provider config not found for idp_name: %s" ,
462+ saml_provider_name
463+ )
464+ return None
465+ except Exception as exc : # pylint: disable=broad-except
466+ log .debug ("Error getting SAML provider config: %s" , str (exc ))
467+ return None
413468
414469 def get_registration_form (self , request ):
415470 """Return a description of the registration form.
@@ -426,6 +481,7 @@ def get_registration_form(self, request):
426481 Returns:
427482 HttpResponse
428483 """
484+ self .request = request
429485 form_desc = FormDescription ("post" , self ._get_registration_submit_url (request ))
430486 self ._apply_third_party_auth_overrides (request , form_desc )
431487
@@ -703,13 +759,40 @@ def _add_marketing_emails_opt_in_field(self, form_desc, required=False):
703759 platform_name = configuration_helpers .get_value ('PLATFORM_NAME' , settings .PLATFORM_NAME ),
704760 )
705761
762+ # Default: checkbox is checked
763+ default_value = True
764+ field_required = required
765+
766+ # Check if SAML provider wants to skip optional checkboxes
767+ saml_config = self ._get_saml_provider_config ()
768+ if saml_config and saml_config .skip_registration_optional_checkboxes :
769+ log .info (
770+ "SAML provider %s has skip_registration_optional_checkboxes=True, "
771+ "setting default to False and required to False" ,
772+ saml_config .slug
773+ )
774+ default_value = False # When skipped, user opts out by default
775+ field_required = False # Make field optional
776+
777+ # Set field override to ensure our SAML-specific values are used
778+ # This will override any values set by the TPA provider
779+ log .info (
780+ "Setting field override for marketing_emails_opt_in to "
781+ "defaultValue=False, required=False"
782+ )
783+ # pylint: disable=protected-access
784+ form_desc ._field_overrides ['marketing_emails_opt_in' ] = {
785+ 'defaultValue' : False ,
786+ 'required' : False
787+ }
788+
706789 form_desc .add_field (
707790 'marketing_emails_opt_in' ,
708791 label = opt_in_label ,
709792 field_type = "checkbox" ,
710793 exposed = True ,
711- default = True , # the checkbox will automatically be checked; meaning user has opted in
712- required = required ,
794+ default = default_value ,
795+ required = field_required ,
713796 )
714797
715798 def _add_field_with_configurable_select_options (self , field_name , field_label , form_desc , required = False ):
@@ -1150,22 +1233,47 @@ def _apply_third_party_auth_overrides(self, request, form_desc):
11501233
11511234 for field_name in self .DEFAULT_FIELDS + self .EXTRA_FIELDS :
11521235 if field_name in field_overrides :
1153- form_desc .override_field_properties (
1154- field_name , default = field_overrides [field_name ]
1155- )
1156-
1157- if (
1158- field_name not in ['terms_of_service' , 'honor_code' ] and
1159- field_overrides [field_name ] and
1160- hide_registration_fields_except_tos
1161- ):
1236+ # Special handling for marketing_emails_opt_in:
1237+ # If SAML provider config has skip_registration_optional_checkboxes=True,
1238+ # don't let the provider's get_register_form_data override the default
1239+ skip_override = False
1240+ if field_name == 'marketing_emails_opt_in' :
1241+ saml_config = self ._get_saml_provider_config ()
1242+ if saml_config and saml_config .skip_registration_optional_checkboxes :
1243+ log .debug (
1244+ "Skipping provider override for marketing_emails_opt_in "
1245+ "due to SAML config for provider: %s" ,
1246+ saml_config .slug
1247+ )
1248+ skip_override = True
1249+
1250+ if not skip_override :
11621251 form_desc .override_field_properties (
1163- field_name ,
1164- field_type = "hidden" ,
1165- label = "" ,
1166- instructions = "" ,
1252+ field_name , default = field_overrides [field_name ]
11671253 )
11681254
1255+ if (
1256+ field_name not in ['terms_of_service' , 'honor_code' ] and
1257+ field_overrides [field_name ] and
1258+ hide_registration_fields_except_tos
1259+ ):
1260+ # When hiding a field, set default to False for checkbox fields
1261+ # like marketing_emails_opt_in to avoid auto-opting users in
1262+ field_default = field_overrides [field_name ]
1263+ if field_name == 'marketing_emails_opt_in' :
1264+ field_default = False
1265+ log .info (
1266+ "Hiding marketing_emails_opt_in field and setting default to False"
1267+ )
1268+
1269+ form_desc .override_field_properties (
1270+ field_name ,
1271+ field_type = "hidden" ,
1272+ default = field_default ,
1273+ label = "" ,
1274+ instructions = "" ,
1275+ )
1276+
11691277 # Hide the confirm_email field
11701278 form_desc .override_field_properties (
11711279 "confirm_email" ,
0 commit comments