Merge pull request #22086 from edx/arch/user-authn-delete-deprecated
User Authn: Remove deprecated, ENABLE_COMBINED_LOGIN_REGISTRATION
This commit is contained in:
@@ -395,8 +395,6 @@ def get_registration_extension_form(*args, **kwargs):
|
||||
|
||||
An example form app for this can be found at http://github.com/open-craft/custom-form-app
|
||||
"""
|
||||
if not settings.FEATURES.get("ENABLE_COMBINED_LOGIN_REGISTRATION"):
|
||||
return None
|
||||
if not getattr(settings, 'REGISTRATION_EXTENSION_FORM', None):
|
||||
return None
|
||||
module, klass = settings.REGISTRATION_EXTENSION_FORM.rsplit('.', 1)
|
||||
|
||||
@@ -220,40 +220,6 @@ def check_verify_status_by_course(user, course_enrollments):
|
||||
return status_by_course
|
||||
|
||||
|
||||
def auth_pipeline_urls(auth_entry, redirect_url=None):
|
||||
"""Retrieve URLs for each enabled third-party auth provider.
|
||||
|
||||
These URLs are used on the "sign up" and "sign in" buttons
|
||||
on the login/registration forms to allow users to begin
|
||||
authentication with a third-party provider.
|
||||
|
||||
Optionally, we can redirect the user to an arbitrary
|
||||
url after auth completes successfully. We use this
|
||||
to redirect the user to a page that required login,
|
||||
or to send users to the payment flow when enrolling
|
||||
in a course.
|
||||
|
||||
Args:
|
||||
auth_entry (string): Either `pipeline.AUTH_ENTRY_LOGIN` or `pipeline.AUTH_ENTRY_REGISTER`
|
||||
|
||||
Keyword Args:
|
||||
redirect_url (unicode): If provided, send users to this URL
|
||||
after they successfully authenticate.
|
||||
|
||||
Returns:
|
||||
dict mapping provider IDs to URLs
|
||||
|
||||
"""
|
||||
if not third_party_auth.is_enabled():
|
||||
return {}
|
||||
|
||||
return {
|
||||
provider.provider_id: third_party_auth.pipeline.get_login_url(
|
||||
provider.provider_id, auth_entry, redirect_url=redirect_url
|
||||
) for provider in third_party_auth.provider.Registry.displayed_for_login()
|
||||
}
|
||||
|
||||
|
||||
# Query string parameters that can be passed to the "finish_auth" view to manage
|
||||
# things like auto-enrollment.
|
||||
POST_AUTH_PARAMS = ('course_id', 'enrollment_action', 'course_mode', 'email_opt_in', 'purchase_workflow')
|
||||
|
||||
@@ -37,13 +37,13 @@ class TestLongUsernameEmail(TestCase):
|
||||
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['username'][0]['user_message'],
|
||||
USERNAME_BAD_LENGTH_MSG,
|
||||
)
|
||||
|
||||
def test_spoffed_name(self):
|
||||
"""
|
||||
Test name cannot contains html.
|
||||
Test name cannot contain html.
|
||||
"""
|
||||
self.url_params['name'] = '<p style="font-size:300px; color:green;"></br>Name<input type="text"></br>Content spoof'
|
||||
response = self.client.post(self.url, self.url_params)
|
||||
@@ -65,6 +65,6 @@ class TestLongUsernameEmail(TestCase):
|
||||
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['email'][0]['user_message'],
|
||||
"Email cannot be more than 254 characters long",
|
||||
)
|
||||
|
||||
@@ -14,7 +14,6 @@ from django.urls import reverse
|
||||
from mock import patch
|
||||
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
||||
from openedx.core.djangoapps.user_authn.views.deprecated import create_account
|
||||
from util.password_policy_validators import create_validator_config
|
||||
|
||||
|
||||
@@ -43,7 +42,7 @@ class TestPasswordPolicy(TestCase):
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['password'][0]['user_message'],
|
||||
"This password is too short. It must contain at least 6 characters.",
|
||||
)
|
||||
|
||||
@@ -66,7 +65,7 @@ class TestPasswordPolicy(TestCase):
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['password'][0]['user_message'],
|
||||
"This password is too long. It must contain no more than 12 characters.",
|
||||
)
|
||||
|
||||
@@ -79,7 +78,7 @@ class TestPasswordPolicy(TestCase):
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['password'][0]['user_message'],
|
||||
"This password must contain at least 3 uppercase letters.",
|
||||
)
|
||||
|
||||
@@ -102,7 +101,7 @@ class TestPasswordPolicy(TestCase):
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['password'][0]['user_message'],
|
||||
"This password must contain at least 3 lowercase letters.",
|
||||
)
|
||||
|
||||
@@ -125,7 +124,7 @@ class TestPasswordPolicy(TestCase):
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['password'][0]['user_message'],
|
||||
"This password must contain at least 3 punctuation marks.",
|
||||
)
|
||||
|
||||
@@ -149,7 +148,7 @@ class TestPasswordPolicy(TestCase):
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['password'][0]['user_message'],
|
||||
"This password must contain at least 3 numbers.",
|
||||
)
|
||||
|
||||
@@ -173,7 +172,7 @@ class TestPasswordPolicy(TestCase):
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['password'][0]['user_message'],
|
||||
"This password must contain at least 3 letters.",
|
||||
)
|
||||
|
||||
@@ -198,12 +197,13 @@ class TestPasswordPolicy(TestCase):
|
||||
response = self.client.post(self.url, self.url_params)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
errstring = (
|
||||
"This password must contain at least 3 uppercase letters. "
|
||||
"This password must contain at least 3 numbers. "
|
||||
"This password must contain at least 3 punctuation marks."
|
||||
)
|
||||
self.assertEqual(obj['value'], errstring)
|
||||
error_strings = [
|
||||
"This password must contain at least 3 uppercase letters.",
|
||||
"This password must contain at least 3 numbers.",
|
||||
"This password must contain at least 3 punctuation marks.",
|
||||
]
|
||||
for i in range(3):
|
||||
self.assertEqual(obj['password'][i]['user_message'], error_strings[i])
|
||||
|
||||
@override_settings(AUTH_PASSWORD_VALIDATORS=[
|
||||
create_validator_config('util.password_policy_validators.MinimumLengthValidator', {'min_length': 3}),
|
||||
@@ -228,7 +228,7 @@ class TestPasswordPolicy(TestCase):
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['password'][0]['user_message'],
|
||||
"This password is too common.",
|
||||
)
|
||||
|
||||
@@ -280,7 +280,7 @@ class TestUsernamePasswordNonmatch(TestCase):
|
||||
self.assertEquals(response.status_code, 400)
|
||||
obj = json.loads(response.content.decode('utf-8'))
|
||||
self.assertEqual(
|
||||
obj['value'],
|
||||
obj['password'][0]['user_message'],
|
||||
"The password is too similar to the username.",
|
||||
)
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ class ProviderConfig(ConfigurationModel):
|
||||
def get_register_form_data(cls, pipeline_kwargs):
|
||||
"""Gets dict of data to display on the register form.
|
||||
|
||||
openedx.core.djangoapps.user_authn.views.deprecated.register_user uses this to populate
|
||||
register_user uses this to populate
|
||||
the new account creation form with values supplied by the user's chosen
|
||||
provider, preventing duplicate data entry.
|
||||
|
||||
|
||||
@@ -21,8 +21,9 @@ from social_django import utils as social_utils
|
||||
from social_django import views as social_views
|
||||
|
||||
from lms.djangoapps.commerce.tests import TEST_API_URL
|
||||
from openedx.core.djangoapps.user_authn.views.deprecated import signin_user, create_account, register_user
|
||||
from openedx.core.djangoapps.user_api.views import RegistrationView
|
||||
from openedx.core.djangoapps.user_authn.views.login import login_user
|
||||
from openedx.core.djangoapps.user_authn.views.login_form import login_and_registration_form
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
||||
from openedx.core.djangoapps.user_api.accounts.settings_views import account_settings_context
|
||||
from student import models as student_models
|
||||
@@ -32,6 +33,10 @@ from third_party_auth import middleware, pipeline
|
||||
from third_party_auth.tests import testutil
|
||||
|
||||
|
||||
def create_account(request):
|
||||
return RegistrationView().post(request)
|
||||
|
||||
|
||||
class HelperMixin(object):
|
||||
"""
|
||||
Contains helper methods for IntegrationTestMixin and IntegrationTest classes below.
|
||||
@@ -65,14 +70,18 @@ class HelperMixin(object):
|
||||
# Check that the correct provider was selected.
|
||||
self.assertContains(
|
||||
response,
|
||||
u'successfully signed in with <strong>%s</strong>' % self.provider.name,
|
||||
u'"errorMessage": null'
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
u'"currentProvider": "{}"'.format(self.provider.name),
|
||||
)
|
||||
# Expect that each truthy value we've prepopulated the register form
|
||||
# with is actually present.
|
||||
form_field_data = self.provider.get_register_form_data(pipeline_kwargs)
|
||||
for prepopulated_form_data in form_field_data:
|
||||
if prepopulated_form_data in required_fields:
|
||||
self.assertIn(form_field_data[prepopulated_form_data], response.content.decode('utf-8'))
|
||||
self.assertContains(response, form_field_data[prepopulated_form_data])
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
def assert_account_settings_context_looks_correct(self, context, duplicate=False, linked=None):
|
||||
@@ -129,17 +138,18 @@ class HelperMixin(object):
|
||||
|
||||
def assert_json_failure_response_is_username_collision(self, response):
|
||||
"""Asserts the json response indicates a username collision."""
|
||||
self.assertEqual(400, response.status_code)
|
||||
self.assertEqual(409, response.status_code)
|
||||
payload = json.loads(response.content.decode('utf-8'))
|
||||
self.assertFalse(payload.get('success'))
|
||||
self.assertIn('belongs to an existing account', payload.get('value'))
|
||||
self.assertIn('belongs to an existing account', payload['username'][0]['user_message'])
|
||||
|
||||
def assert_json_success_response_looks_correct(self, response):
|
||||
def assert_json_success_response_looks_correct(self, response, verify_redirect_url):
|
||||
"""Asserts the json response indicates success and redirection."""
|
||||
self.assertEqual(200, response.status_code)
|
||||
payload = json.loads(response.content.decode('utf-8'))
|
||||
self.assertTrue(payload.get('success'))
|
||||
self.assertEqual(pipeline.get_complete_url(self.provider.backend_name), payload.get('redirect_url'))
|
||||
if verify_redirect_url:
|
||||
self.assertEqual(pipeline.get_complete_url(self.provider.backend_name), payload.get('redirect_url'))
|
||||
|
||||
def assert_login_response_before_pipeline_looks_correct(self, response):
|
||||
"""Asserts a GET of /login not in the pipeline looks correct."""
|
||||
@@ -285,7 +295,6 @@ class HelperMixin(object):
|
||||
"""Creates user, profile, registration, and (usually) social auth.
|
||||
|
||||
This synthesizes what happens during /register.
|
||||
See student.views.register and student.helpers.do_create_account.
|
||||
"""
|
||||
response_data = self.get_response_data()
|
||||
uid = strategy.request.backend.get_user_id(response_data, response_data)
|
||||
@@ -541,7 +550,6 @@ class IntegrationTest(testutil.TestCase, test.TestCase, HelperMixin):
|
||||
actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access
|
||||
request=request)
|
||||
|
||||
signin_user(strategy.request)
|
||||
login_user(strategy.request)
|
||||
actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access
|
||||
request=request)
|
||||
@@ -598,7 +606,6 @@ class IntegrationTest(testutil.TestCase, test.TestCase, HelperMixin):
|
||||
request=request)
|
||||
|
||||
with self._patch_edxmako_current_request(strategy.request):
|
||||
signin_user(strategy.request)
|
||||
login_user(strategy.request)
|
||||
actions.do_complete(request.backend, social_views._do_login, user=user, # pylint: disable=protected-access
|
||||
request=request)
|
||||
@@ -665,7 +672,6 @@ class IntegrationTest(testutil.TestCase, test.TestCase, HelperMixin):
|
||||
request=request)
|
||||
|
||||
with self._patch_edxmako_current_request(strategy.request):
|
||||
signin_user(strategy.request)
|
||||
login_user(strategy.request)
|
||||
actions.do_complete(request.backend, social_views._do_login, # pylint: disable=protected-access
|
||||
user=user, request=request)
|
||||
@@ -710,12 +716,12 @@ class IntegrationTest(testutil.TestCase, test.TestCase, HelperMixin):
|
||||
# At this point we know the pipeline has resumed correctly. Next we
|
||||
# fire off the view that displays the login form and posts it via JS.
|
||||
with self._patch_edxmako_current_request(strategy.request):
|
||||
self.assert_login_response_in_pipeline_looks_correct(signin_user(strategy.request))
|
||||
self.assert_login_response_in_pipeline_looks_correct(login_user(strategy.request))
|
||||
|
||||
# Next, we invoke the view that handles the POST, and expect it
|
||||
# redirects to /auth/complete. In the browser ajax handlers will
|
||||
# redirect the user to the dashboard; we invoke it manually here.
|
||||
self.assert_json_success_response_looks_correct(login_user(strategy.request))
|
||||
self.assert_json_success_response_looks_correct(login_user(strategy.request), verify_redirect_url=True)
|
||||
|
||||
# We should be redirected back to the complete page, setting
|
||||
# the "logged in" cookie for the marketing site.
|
||||
@@ -806,7 +812,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase, HelperMixin):
|
||||
# fire off the view that displays the registration form.
|
||||
with self._patch_edxmako_current_request(request):
|
||||
self.assert_register_response_in_pipeline_looks_correct(
|
||||
register_user(strategy.request),
|
||||
login_and_registration_form(strategy.request, initial_mode='register'),
|
||||
pipeline.get(request)['kwargs'],
|
||||
['name', 'username', 'email']
|
||||
)
|
||||
@@ -828,7 +834,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase, HelperMixin):
|
||||
# ...but when we invoke create_account the existing edX view will make
|
||||
# it, but not social auths. The pipeline creates those later.
|
||||
with self._patch_edxmako_current_request(strategy.request):
|
||||
self.assert_json_success_response_looks_correct(create_account(strategy.request))
|
||||
self.assert_json_success_response_looks_correct(create_account(strategy.request), verify_redirect_url=False)
|
||||
# We've overridden the user's password, so authenticate() with the old
|
||||
# value won't work:
|
||||
created_user = self.get_user_by_email(strategy, email)
|
||||
@@ -881,7 +887,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase, HelperMixin):
|
||||
|
||||
with self._patch_edxmako_current_request(request):
|
||||
self.assert_register_response_in_pipeline_looks_correct(
|
||||
register_user(strategy.request),
|
||||
login_and_registration_form(strategy.request, initial_mode='register'),
|
||||
pipeline.get(request)['kwargs'],
|
||||
['name', 'username', 'email']
|
||||
)
|
||||
|
||||
@@ -22,7 +22,6 @@ from social_django.models import UserSocialAuth
|
||||
from testfixtures import LogCapture
|
||||
|
||||
from enterprise.models import EnterpriseCustomerIdentityProvider, EnterpriseCustomerUser
|
||||
from openedx.core.djangoapps.user_authn.views.deprecated import signin_user
|
||||
from openedx.core.djangoapps.user_authn.views.login import login_user
|
||||
from openedx.core.djangoapps.user_api.accounts.settings_views import account_settings_context
|
||||
from openedx.features.enterprise_support.tests.factories import EnterpriseCustomerFactory
|
||||
@@ -210,7 +209,6 @@ class TestShibIntegrationTest(SamlIntegrationTestUtilities, IntegrationTestMixin
|
||||
request=request)
|
||||
|
||||
with self._patch_edxmako_current_request(strategy.request):
|
||||
signin_user(strategy.request)
|
||||
login_user(strategy.request)
|
||||
actions.do_complete(request.backend, social_views._do_login, user=user, # pylint: disable=protected-access
|
||||
request=request)
|
||||
|
||||
@@ -110,10 +110,6 @@ class ResetPasswordPage(PageObject):
|
||||
class CombinedLoginAndRegisterPage(PageObject):
|
||||
"""Interact with combined login and registration page.
|
||||
|
||||
This page is currently hidden behind the feature flag
|
||||
`ENABLE_COMBINED_LOGIN_REGISTRATION`, which is enabled
|
||||
in the bok choy settings.
|
||||
|
||||
When enabled, the new page is available from either
|
||||
`/login` or `/register`; the new page is also served at
|
||||
`/account/login/` or `/account/register/`, where it was
|
||||
|
||||
Reference in New Issue
Block a user