Merge pull request #16950 from edx/asadiqbal08/ENT-772-Update-singin-UI
ENT-772 - UI Updated to Support Ent Data Synchronization message
This commit is contained in:
@@ -362,15 +362,16 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
self._assert_third_party_auth_data(response, None, None, [], None)
|
||||
|
||||
@mock.patch('student_account.views.enterprise_customer_for_request')
|
||||
@mock.patch('openedx.core.djangoapps.user_api.api.enterprise_customer_for_request')
|
||||
@ddt.data(
|
||||
("signin_user", None, None, None),
|
||||
("register_user", None, None, None),
|
||||
("signin_user", "google-oauth2", "Google", None),
|
||||
("register_user", "google-oauth2", "Google", None),
|
||||
("signin_user", "facebook", "Facebook", None),
|
||||
("register_user", "facebook", "Facebook", None),
|
||||
("signin_user", "dummy", "Dummy", None),
|
||||
("register_user", "dummy", "Dummy", None),
|
||||
("signin_user", None, None, None, False),
|
||||
("register_user", None, None, None, False),
|
||||
("signin_user", "google-oauth2", "Google", None, False),
|
||||
("register_user", "google-oauth2", "Google", None, False),
|
||||
("signin_user", "facebook", "Facebook", None, False),
|
||||
("register_user", "facebook", "Facebook", None, False),
|
||||
("signin_user", "dummy", "Dummy", None, False),
|
||||
("register_user", "dummy", "Dummy", None, False),
|
||||
(
|
||||
"signin_user",
|
||||
"google-oauth2",
|
||||
@@ -379,7 +380,8 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
'name': 'FakeName',
|
||||
'logo': 'https://host.com/logo.jpg',
|
||||
'welcome_msg': 'No message'
|
||||
}
|
||||
},
|
||||
True
|
||||
)
|
||||
)
|
||||
@ddt.unpack
|
||||
@@ -389,7 +391,9 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
current_backend,
|
||||
current_provider,
|
||||
expected_enterprise_customer_mock_attrs,
|
||||
enterprise_customer_mock
|
||||
add_user_details,
|
||||
enterprise_customer_mock_1,
|
||||
enterprise_customer_mock_2
|
||||
):
|
||||
params = [
|
||||
('course_id', 'course-v1:Org+Course+Run'),
|
||||
@@ -400,24 +404,26 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
]
|
||||
|
||||
if expected_enterprise_customer_mock_attrs:
|
||||
expected_ec = mock.MagicMock(
|
||||
branding_configuration=mock.MagicMock(
|
||||
logo=mock.MagicMock(
|
||||
url=expected_enterprise_customer_mock_attrs['logo']
|
||||
),
|
||||
welcome_message=expected_enterprise_customer_mock_attrs['welcome_msg']
|
||||
)
|
||||
)
|
||||
expected_ec.name = expected_enterprise_customer_mock_attrs['name']
|
||||
expected_ec = {
|
||||
'name': expected_enterprise_customer_mock_attrs['name'],
|
||||
'branding_configuration': {
|
||||
'logo': 'https://host.com/logo.jpg',
|
||||
'welcome_message': expected_enterprise_customer_mock_attrs['welcome_msg']
|
||||
}
|
||||
}
|
||||
else:
|
||||
expected_ec = None
|
||||
|
||||
enterprise_customer_mock.return_value = expected_ec
|
||||
email = None
|
||||
if add_user_details:
|
||||
email = 'test@test.com'
|
||||
enterprise_customer_mock_1.return_value = expected_ec
|
||||
enterprise_customer_mock_2.return_value = expected_ec
|
||||
|
||||
# Simulate a running pipeline
|
||||
if current_backend is not None:
|
||||
pipeline_target = "student_account.views.third_party_auth.pipeline"
|
||||
with simulate_running_pipeline(pipeline_target, current_backend):
|
||||
with simulate_running_pipeline(pipeline_target, current_backend, email=email):
|
||||
response = self.client.get(reverse(url_name), params, HTTP_ACCEPT="text/html")
|
||||
|
||||
# Do NOT simulate a running pipeline
|
||||
@@ -456,7 +462,8 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
current_backend,
|
||||
current_provider,
|
||||
expected_providers,
|
||||
expected_ec
|
||||
expected_ec,
|
||||
add_user_details
|
||||
)
|
||||
|
||||
def _configure_testshib_provider(self, provider_name, idp_slug):
|
||||
@@ -477,16 +484,12 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
|
||||
@mock.patch('django.conf.settings.MESSAGE_STORAGE', 'django.contrib.messages.storage.cookie.CookieStorage')
|
||||
@mock.patch('lms.djangoapps.student_account.views.enterprise_customer_for_request')
|
||||
@mock.patch('openedx.core.djangoapps.user_api.api.enterprise_customer_for_request')
|
||||
@ddt.data(
|
||||
(
|
||||
'signin_user',
|
||||
'tpa-saml',
|
||||
'TestShib',
|
||||
{
|
||||
'name': 'FakeName',
|
||||
'logo': 'https://host.com/logo.jpg',
|
||||
'welcome_msg': 'No message'
|
||||
}
|
||||
)
|
||||
)
|
||||
@ddt.unpack
|
||||
@@ -495,8 +498,8 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
url_name,
|
||||
current_backend,
|
||||
current_provider,
|
||||
expected_enterprise_customer_mock_attrs,
|
||||
enterprise_customer_mock,
|
||||
enterprise_customer_mock_1,
|
||||
enterprise_customer_mock_2,
|
||||
):
|
||||
params = []
|
||||
request = RequestFactory().get(reverse(url_name), params, HTTP_ACCEPT='text/html')
|
||||
@@ -506,21 +509,13 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
self.enable_saml()
|
||||
dummy_idp = 'testshib'
|
||||
self._configure_testshib_provider(current_provider, dummy_idp)
|
||||
expected_ec = mock.MagicMock(
|
||||
branding_configuration=mock.MagicMock(
|
||||
logo=mock.MagicMock(
|
||||
url=expected_enterprise_customer_mock_attrs['logo']
|
||||
),
|
||||
welcome_message=expected_enterprise_customer_mock_attrs['welcome_msg']
|
||||
)
|
||||
)
|
||||
expected_ec.name = expected_enterprise_customer_mock_attrs['name']
|
||||
enterprise_customer_data = {
|
||||
'uuid': '72416e52-8c77-4860-9584-15e5b06220fb',
|
||||
'name': 'Dummy Enterprise',
|
||||
'identity_provider': dummy_idp,
|
||||
}
|
||||
enterprise_customer_mock.return_value = enterprise_customer_data
|
||||
enterprise_customer_mock_1.return_value = enterprise_customer_data
|
||||
enterprise_customer_mock_2.return_value = enterprise_customer_data
|
||||
dummy_error_message = 'Authentication failed: SAML login failed ' \
|
||||
'["invalid_response"] [SAML Response must contain 1 assertion]'
|
||||
|
||||
@@ -739,7 +734,8 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
|
||||
self.assertEqual(resp['X-Frame-Options'], 'ALLOW')
|
||||
|
||||
def _assert_third_party_auth_data(self, response, current_backend, current_provider, providers, expected_ec):
|
||||
def _assert_third_party_auth_data(self, response, current_backend, current_provider, providers, expected_ec,
|
||||
add_user_details=False):
|
||||
"""Verify that third party auth info is rendered correctly in a DOM data attribute. """
|
||||
finish_auth_url = None
|
||||
if current_backend:
|
||||
@@ -753,6 +749,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
"errorMessage": None,
|
||||
"registerFormSubmitButtonText": "Create Account",
|
||||
"syncLearnerProfileData": False,
|
||||
"pipeline_user_details": {"email": "test@test.com"} if add_user_details else None
|
||||
}
|
||||
if expected_ec is not None:
|
||||
# If we set an EnterpriseCustomer, third-party auth providers ought to be hidden.
|
||||
@@ -782,6 +779,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
'errorMessage': expected_error_message,
|
||||
'registerFormSubmitButtonText': 'Create Account',
|
||||
'syncLearnerProfileData': False,
|
||||
'pipeline_user_details': {'response': {'idp_name': 'testshib'}}
|
||||
}
|
||||
auth_info = dump_js_escaped_json(auth_info)
|
||||
|
||||
|
||||
@@ -250,6 +250,7 @@ def _third_party_auth_context(request, redirect_to, tpa_hint=None):
|
||||
"errorMessage": None,
|
||||
"registerFormSubmitButtonText": _("Create Account"),
|
||||
"syncLearnerProfileData": False,
|
||||
"pipeline_user_details": None
|
||||
}
|
||||
|
||||
if third_party_auth.is_enabled():
|
||||
@@ -275,6 +276,9 @@ def _third_party_auth_context(request, redirect_to, tpa_hint=None):
|
||||
running_pipeline = pipeline.get(request)
|
||||
if running_pipeline is not None:
|
||||
current_provider = third_party_auth.provider.Registry.get_from_pipeline(running_pipeline)
|
||||
user_details = running_pipeline['kwargs']['details']
|
||||
if user_details:
|
||||
context['pipeline_user_details'] = user_details
|
||||
|
||||
if current_provider is not None:
|
||||
context["currentProvider"] = current_provider.name
|
||||
@@ -309,7 +313,7 @@ def _get_form_descriptions(request):
|
||||
|
||||
return {
|
||||
'password_reset': get_password_reset_form().to_json(),
|
||||
'login': get_login_session_form().to_json(),
|
||||
'login': get_login_session_form(request).to_json(),
|
||||
'registration': RegistrationFormFactory().get_registration_form(request).to_json()
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@
|
||||
this.passwordResetSupportUrl = options.password_reset_support_link;
|
||||
this.createAccountOption = options.account_creation_allowed;
|
||||
this.hideAuthWarnings = options.hide_auth_warnings || false;
|
||||
this.pipelineUserDetails = options.third_party_auth.pipeline_user_details;
|
||||
this.enterpriseName = options.enterprise_name || '';
|
||||
|
||||
// The login view listens for 'sync' events from the reset model
|
||||
this.resetModel = new PasswordResetModel({}, {
|
||||
@@ -133,7 +135,9 @@
|
||||
supportURL: this.supportURL,
|
||||
passwordResetSupportUrl: this.passwordResetSupportUrl,
|
||||
createAccountOption: this.createAccountOption,
|
||||
hideAuthWarnings: this.hideAuthWarnings
|
||||
hideAuthWarnings: this.hideAuthWarnings,
|
||||
pipelineUserDetails: this.pipelineUserDetails,
|
||||
enterpriseName: this.enterpriseName
|
||||
});
|
||||
|
||||
// Listen for 'password-help' event to toggle sub-views
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
this.createAccountOption = data.createAccountOption;
|
||||
this.accountActivationMessages = data.accountActivationMessages;
|
||||
this.hideAuthWarnings = data.hideAuthWarnings;
|
||||
this.pipelineUserDetails = data.pipelineUserDetails;
|
||||
this.enterpriseName = data.enterpriseName;
|
||||
|
||||
this.listenTo(this.model, 'sync', this.saveSuccess);
|
||||
this.listenTo(this.resetModel, 'sync', this.resetEmail);
|
||||
@@ -68,7 +70,9 @@
|
||||
providers: this.providers,
|
||||
hasSecondaryProviders: this.hasSecondaryProviders,
|
||||
platformName: this.platformName,
|
||||
createAccountOption: this.createAccountOption
|
||||
createAccountOption: this.createAccountOption,
|
||||
pipelineUserDetails: this.pipelineUserDetails,
|
||||
enterpriseName: this.enterpriseName
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
<% } %>
|
||||
<% if ( restrictions.min_length ) { %> minlength="<%- restrictions.min_length %>"<% } %>
|
||||
<% if ( restrictions.max_length ) { %> maxlength="<%- restrictions.max_length %>"<% } %>
|
||||
<% if ( restrictions.readonly ) { %> readonly <% } %>
|
||||
<% if ( required ) { %> required<% } %>
|
||||
<% if ( typeof errorMessages !== 'undefined' ) {
|
||||
_.each(errorMessages, function( msg, type ) {%>
|
||||
|
||||
@@ -1,14 +1,30 @@
|
||||
<div class="js-form-feedback" aria-live="assertive" tabindex="-1">
|
||||
</div>
|
||||
|
||||
<% if ( context.createAccountOption !== false && !context.syncLearnerProfileData) { %>
|
||||
<% if ( context.createAccountOption !== false && !context.syncLearnerProfileData && !context.enterpriseName) { %>
|
||||
<div class="toggle-form">
|
||||
<span class="text"><%- gettext("First time here?") %></span>
|
||||
<a href="#login" class="form-toggle" data-type="register"><%- gettext("Create an Account.") %></a>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<h2><%- gettext("Sign In") %></h2>
|
||||
<% if (context.enterpriseName) { %>
|
||||
<% if (context.pipelineUserDetails.email) { %>
|
||||
<h2><%- gettext("Sign in to continue learning as {email}").replace("{email}", context.pipelineUserDetails.email) %></h2>
|
||||
<% } else { %>
|
||||
<h2><%- gettext("Sign in to continue learning") %></h2>
|
||||
<% } %>
|
||||
<p>
|
||||
<%- gettext("You already have an edX account with your {enterprise_name} email address.").replace(/{enterprise_name}/g, context.enterpriseName) %>
|
||||
<% if (context.syncLearnerProfileData) {
|
||||
%><%- gettext("Going forward, your account information will be updated and maintained by {enterprise_name}.").replace(/{enterprise_name}/g, context.enterpriseName) %>
|
||||
<% } %>
|
||||
<%- gettext("You can view your information or unlink from {enterprise_name} anytime in your Account Settings.").replace(/{enterprise_name}/g, context.enterpriseName) %>
|
||||
</p>
|
||||
<p><%- gettext("To continue learning with this account, sign in below.") %></p>
|
||||
<% } else { %>
|
||||
<h2><%- gettext("Sign In") %></h2>
|
||||
<% } %>
|
||||
|
||||
<form id="login" class="login-form" tabindex="-1" method="POST">
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ def get_password_reset_form():
|
||||
return form_desc
|
||||
|
||||
|
||||
def get_login_session_form():
|
||||
def get_login_session_form(request):
|
||||
"""Return a description of the login form.
|
||||
|
||||
This decouples clients from the API definition:
|
||||
@@ -77,6 +77,7 @@ def get_login_session_form():
|
||||
|
||||
"""
|
||||
form_desc = FormDescription("post", reverse("user_api_login_session"))
|
||||
_apply_third_party_auth_overrides(request, form_desc)
|
||||
|
||||
# Translators: This label appears above a field on the login form
|
||||
# meant to hold the user's email address.
|
||||
@@ -128,6 +129,38 @@ def get_login_session_form():
|
||||
return form_desc
|
||||
|
||||
|
||||
def _apply_third_party_auth_overrides(request, form_desc):
|
||||
"""Modify the login form if the user has authenticated with a third-party provider.
|
||||
If a user has successfully authenticated with a third-party provider,
|
||||
and an email is associated with it then we fill in the email field with readonly property.
|
||||
Arguments:
|
||||
request (HttpRequest): The request for the registration form, used
|
||||
to determine if the user has successfully authenticated
|
||||
with a third-party provider.
|
||||
form_desc (FormDescription): The registration form description
|
||||
"""
|
||||
if third_party_auth.is_enabled():
|
||||
running_pipeline = third_party_auth.pipeline.get(request)
|
||||
if running_pipeline:
|
||||
current_provider = third_party_auth.provider.Registry.get_from_pipeline(running_pipeline)
|
||||
if current_provider and enterprise_customer_for_request(request):
|
||||
pipeline_kwargs = running_pipeline.get('kwargs')
|
||||
|
||||
# Details about the user sent back from the provider.
|
||||
details = pipeline_kwargs.get('details')
|
||||
email = details.get('email', '')
|
||||
|
||||
# override the email field.
|
||||
form_desc.override_field_properties(
|
||||
"email",
|
||||
default=email,
|
||||
restrictions={"readonly": "readonly"} if email else {
|
||||
"min_length": accounts.EMAIL_MIN_LENGTH,
|
||||
"max_length": accounts.EMAIL_MAX_LENGTH,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class RegistrationFormFactory(object):
|
||||
"""HTTP end-points for creating a new user. """
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ class FormDescription(object):
|
||||
ALLOWED_RESTRICTIONS = {
|
||||
"text": ["min_length", "max_length"],
|
||||
"password": ["min_length", "max_length"],
|
||||
"email": ["min_length", "max_length"],
|
||||
"email": ["min_length", "max_length", "readonly"],
|
||||
}
|
||||
|
||||
FIELD_TYPE_MAP = {
|
||||
|
||||
@@ -43,7 +43,7 @@ class LoginSessionView(APIView):
|
||||
|
||||
@method_decorator(ensure_csrf_cookie)
|
||||
def get(self, request):
|
||||
return HttpResponse(get_login_session_form().to_json(), content_type="application/json")
|
||||
return HttpResponse(get_login_session_form(request).to_json(), content_type="application/json")
|
||||
|
||||
@method_decorator(require_post_params(["email", "password"]))
|
||||
@method_decorator(csrf_protect)
|
||||
|
||||
@@ -61,6 +61,7 @@ def update_logistration_context_for_enterprise(request, context, enterprise_cust
|
||||
context.update(sidebar_context)
|
||||
context['enable_enterprise_sidebar'] = True
|
||||
context['data']['hide_auth_warnings'] = True
|
||||
context['data']['enterprise_name'] = enterprise_customer['name']
|
||||
else:
|
||||
context['enable_enterprise_sidebar'] = False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user