diff --git a/openedx/core/djangoapps/user_api/api.py b/openedx/core/djangoapps/user_api/api.py deleted file mode 100644 index cba96e7458..0000000000 --- a/openedx/core/djangoapps/user_api/api.py +++ /dev/null @@ -1,117 +0,0 @@ -""" -User Apis. -""" -from __future__ import absolute_import - -import copy - -import crum -import six -from django.conf import settings -from django.core.exceptions import ImproperlyConfigured -from django.urls import reverse -from django.utils.translation import ugettext as _ -from django_countries import countries - -import third_party_auth -from edxmako.shortcuts import marketing_link -from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.djangoapps.user_api import accounts -from openedx.core.djangoapps.user_api.helpers import FormDescription -from openedx.core.djangolib.markup import HTML, Text -from openedx.features.enterprise_support.api import enterprise_customer_for_request -from student.models import UserProfile -from util.password_policy_validators import ( - DEFAULT_MAX_PASSWORD_LENGTH, - password_validators_instruction_texts, - password_validators_restrictions -) - - -def get_login_session_form(request): - """Return a description of the login form. - - This decouples clients from the API definition: - if the API decides to modify the form, clients won't need - to be updated. - - See `user_api.helpers.FormDescription` for examples - of the JSON-encoded form description. - - Returns: - HttpResponse - - """ - 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. - email_label = _(u"Email") - - # Translators: This example email address is used as a placeholder in - # a field on the login form meant to hold the user's email address. - email_placeholder = _(u"username@domain.com") - - # Translators: These instructions appear on the login form, immediately - # below a field meant to hold the user's email address. - email_instructions = _(u"The email address you used to register with {platform_name}").format( - platform_name=configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) - ) - - form_desc.add_field( - "email", - field_type="email", - label=email_label, - placeholder=email_placeholder, - instructions=email_instructions, - restrictions={ - "min_length": accounts.EMAIL_MIN_LENGTH, - "max_length": accounts.EMAIL_MAX_LENGTH, - } - ) - - # Translators: This label appears above a field on the login form - # meant to hold the user's password. - password_label = _(u"Password") - - form_desc.add_field( - "password", - label=password_label, - field_type="password", - restrictions={'max_length': DEFAULT_MAX_PASSWORD_LENGTH} - ) - - 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, - } - ) diff --git a/openedx/core/djangoapps/user_api/views.py b/openedx/core/djangoapps/user_api/views.py index 60b5fe1f3e..3ceb733686 100644 --- a/openedx/core/djangoapps/user_api/views.py +++ b/openedx/core/djangoapps/user_api/views.py @@ -23,9 +23,6 @@ from six import text_type from openedx.core.djangoapps.django_comment_common.models import Role from openedx.core.djangoapps.user_api import accounts from openedx.core.djangoapps.user_api.accounts.api import check_account_exists -from openedx.core.djangoapps.user_api.api import ( - get_login_session_form, -) from openedx.core.lib.api.view_utils import require_post_params from openedx.core.djangoapps.user_api.models import UserPreference from openedx.core.djangoapps.user_api.preferences.api import get_country_time_zones, update_email_opt_in diff --git a/openedx/core/djangoapps/user_authn/views/login.py b/openedx/core/djangoapps/user_authn/views/login.py index fb5895f79d..c787f735c6 100644 --- a/openedx/core/djangoapps/user_authn/views/login.py +++ b/openedx/core/djangoapps/user_authn/views/login.py @@ -28,7 +28,7 @@ from rest_framework.views import APIView from edxmako.shortcuts import render_to_response from openedx.core.djangoapps.password_policy import compliance as password_policy_compliance from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.djangoapps.user_api.api import get_login_session_form +from openedx.core.djangoapps.user_authn.views.login_form import get_login_session_form from openedx.core.djangoapps.user_authn.cookies import refresh_jwt_cookies, set_logged_in_cookies from openedx.core.djangoapps.user_authn.exceptions import AuthFailedError from openedx.core.djangoapps.util.user_messages import PageLevelMessages diff --git a/openedx/core/djangoapps/user_authn/views/login_form.py b/openedx/core/djangoapps/user_authn/views/login_form.py index 6c7f5750bc..6397103850 100644 --- a/openedx/core/djangoapps/user_authn/views/login_form.py +++ b/openedx/core/djangoapps/user_authn/views/login_form.py @@ -7,9 +7,12 @@ import logging import six import six.moves.urllib.parse # pylint: disable=import-error +import third_party_auth + from django.conf import settings from django.contrib import messages from django.shortcuts import redirect +from django.urls import reverse from django.utils.translation import ugettext as _ from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.http import require_http_methods @@ -17,13 +20,12 @@ from django.views.decorators.http import require_http_methods import third_party_auth from edxmako.shortcuts import render_to_response from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers +from openedx.core.djangoapps.user_api import accounts from openedx.core.djangoapps.user_api.accounts.utils import ( is_secondary_email_feature_enabled, is_multiple_user_enterprises_feature_enabled ) -from openedx.core.djangoapps.user_api.api import ( - get_login_session_form, -) +from openedx.core.djangoapps.user_api.helpers import FormDescription from openedx.core.djangoapps.user_authn.cookies import are_logged_in_cookies_set from openedx.core.djangoapps.user_authn.views.registration_form import RegistrationFormFactory from openedx.core.djangoapps.user_authn.views.password_reset import get_password_reset_form @@ -36,9 +38,102 @@ from student.helpers import get_next_url_for_login_page from third_party_auth import pipeline from third_party_auth.decorators import xframe_allow_whitelisted +from util.password_policy_validators import ( + DEFAULT_MAX_PASSWORD_LENGTH, +) + log = logging.getLogger(__name__) +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, + } + ) + + +def get_login_session_form(request): + """Return a description of the login form. + + This decouples clients from the API definition: + if the API decides to modify the form, clients won't need + to be updated. + + See `user_api.helpers.FormDescription` for examples + of the JSON-encoded form description. + + Returns: + HttpResponse + + """ + 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. + email_label = _(u"Email") + + # Translators: This example email address is used as a placeholder in + # a field on the login form meant to hold the user's email address. + email_placeholder = _(u"username@domain.com") + + # Translators: These instructions appear on the login form, immediately + # below a field meant to hold the user's email address. + email_instructions = _(u"The email address you used to register with {platform_name}").format( + platform_name=configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) + ) + + form_desc.add_field( + "email", + field_type="email", + label=email_label, + placeholder=email_placeholder, + instructions=email_instructions, + restrictions={ + "min_length": accounts.EMAIL_MIN_LENGTH, + "max_length": accounts.EMAIL_MAX_LENGTH, + } + ) + + # Translators: This label appears above a field on the login form + # meant to hold the user's password. + password_label = _(u"Password") + + form_desc.add_field( + "password", + label=password_label, + field_type="password", + restrictions={'max_length': DEFAULT_MAX_PASSWORD_LENGTH} + ) + + return form_desc + + @require_http_methods(['GET']) @ensure_csrf_cookie @xframe_allow_whitelisted diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_register.py b/openedx/core/djangoapps/user_authn/views/tests/test_register.py index cbd9607397..ca871c77b4 100644 --- a/openedx/core/djangoapps/user_authn/views/tests/test_register.py +++ b/openedx/core/djangoapps/user_authn/views/tests/test_register.py @@ -585,7 +585,7 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase): provider = self.configure_google_provider(enabled=True) with simulate_running_pipeline( - "openedx.core.djangoapps.user_api.api.third_party_auth.pipeline", "google-oauth2", + "openedx.core.djangoapps.user_authn.views.login_form.third_party_auth.pipeline", "google-oauth2", email="bob@example.com", fullname="Bob", username=input_username, diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_views.py b/openedx/core/djangoapps/user_authn/views/tests/test_views.py index 9fc4988957..98eaebc99c 100644 --- a/openedx/core/djangoapps/user_authn/views/tests/test_views.py +++ b/openedx/core/djangoapps/user_authn/views/tests/test_views.py @@ -413,7 +413,6 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto self._assert_third_party_auth_data(response, None, None, [], None) @mock.patch('openedx.core.djangoapps.user_authn.views.login_form.enterprise_customer_for_request') - @mock.patch('openedx.core.djangoapps.user_api.api.enterprise_customer_for_request') @ddt.data( ("signin_user", None, None, None, False), ("register_user", None, None, None, False), @@ -443,8 +442,7 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto current_provider, expected_enterprise_customer_mock_attrs, add_user_details, - enterprise_customer_mock_1, - enterprise_customer_mock_2 + enterprise_customer_mock, ): params = [ ('course_id', 'course-v1:Org+Course+Run'), @@ -468,8 +466,7 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto 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 + enterprise_customer_mock.return_value = expected_ec # Simulate a running pipeline if current_backend is not None: