refactor: Ran pyupgrade on openedx/core/djangoapps/user_authn
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
"""
|
||||
Logistration API View Tests
|
||||
"""
|
||||
from unittest.mock import patch
|
||||
from urllib.parse import urlencode
|
||||
import ddt
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from mock import patch
|
||||
from rest_framework.test import APITestCase
|
||||
from six.moves.urllib.parse import urlencode
|
||||
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
from common.djangoapps.third_party_auth import pipeline
|
||||
@@ -24,7 +24,7 @@ class TPAContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
"""
|
||||
Test Setup
|
||||
"""
|
||||
super(TPAContextViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.url = reverse('third_party_auth_context')
|
||||
self.query_params = {'next': '/dashboard'}
|
||||
@@ -42,7 +42,7 @@ class TPAContextViewTest(ThirdPartyAuthTestMixin, APITestCase):
|
||||
"""
|
||||
Construct the login URL to start third party authentication
|
||||
"""
|
||||
return u'{url}?auth_entry={auth_entry}&{param_str}'.format(
|
||||
return '{url}?auth_entry={auth_entry}&{param_str}'.format(
|
||||
url=reverse('social:begin', kwargs={'backend': backend_name}),
|
||||
auth_entry=auth_entry,
|
||||
param_str=urlencode(params)
|
||||
|
||||
@@ -12,14 +12,14 @@ class UserAuthnConfig(AppConfig):
|
||||
"""
|
||||
Application Configuration for User Authentication.
|
||||
"""
|
||||
name = u'openedx.core.djangoapps.user_authn'
|
||||
name = 'openedx.core.djangoapps.user_authn'
|
||||
|
||||
plugin_app = {
|
||||
PluginURLs.CONFIG: {
|
||||
ProjectType.LMS: {
|
||||
PluginURLs.NAMESPACE: u'',
|
||||
PluginURLs.REGEX: u'',
|
||||
PluginURLs.RELATIVE_PATH: u'urls',
|
||||
PluginURLs.NAMESPACE: '',
|
||||
PluginURLs.REGEX: '',
|
||||
PluginURLs.RELATIVE_PATH: 'urls',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ Waffle flags and switches for user authn.
|
||||
|
||||
from edx_toggles.toggles import LegacyWaffleSwitch, LegacyWaffleSwitchNamespace
|
||||
|
||||
_WAFFLE_NAMESPACE = u'user_authn'
|
||||
_WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace(name=_WAFFLE_NAMESPACE, log_prefix=u'UserAuthN: ')
|
||||
_WAFFLE_NAMESPACE = 'user_authn'
|
||||
_WAFFLE_SWITCH_NAMESPACE = LegacyWaffleSwitchNamespace(name=_WAFFLE_NAMESPACE, log_prefix='UserAuthN: ')
|
||||
|
||||
# .. toggle_name: user_authn.enable_login_using_thirdparty_auth_only
|
||||
# .. toggle_implementation: WaffleSwitch
|
||||
|
||||
@@ -7,7 +7,6 @@ import json
|
||||
import logging
|
||||
import time
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.dispatch import Signal
|
||||
@@ -223,7 +222,7 @@ def _set_deprecated_logged_in_cookie(response, cookie_settings):
|
||||
|
||||
def _convert_to_absolute_uris(request, urls_obj):
|
||||
""" Convert relative URL paths to absolute URIs """
|
||||
for url_name, url_path in six.iteritems(urls_obj):
|
||||
for url_name, url_path in urls_obj.items():
|
||||
urls_obj[url_name] = request.build_absolute_uri(url_path)
|
||||
|
||||
return urls_obj
|
||||
@@ -350,5 +349,5 @@ def _get_login_oauth_client():
|
||||
return Application.objects.get(client_id=login_client_id)
|
||||
except Application.DoesNotExist:
|
||||
raise AuthFailedError( # lint-amnesty, pylint: disable=raise-missing-from
|
||||
u"OAuth Client for the Login service, '{}', is not configured.".format(login_client_id)
|
||||
f"OAuth Client for the Login service, '{login_client_id}', is not configured."
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ class AuthFailedError(Exception):
|
||||
def __init__( # lint-amnesty, pylint: disable=dangerous-default-value
|
||||
self, value=None, redirect=None, redirect_url=None, error_code=None, context={},
|
||||
):
|
||||
super(AuthFailedError, self).__init__() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__()
|
||||
self.value = Text(value)
|
||||
self.redirect = redirect
|
||||
self.redirect_url = redirect_url
|
||||
|
||||
@@ -10,7 +10,7 @@ class PasswordReset(BaseMessageType):
|
||||
A message to the user with password reset link.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PasswordReset, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# pylint: disable=unsupported-assignment-operation
|
||||
self.options['transactional'] = True
|
||||
@@ -22,5 +22,5 @@ class PasswordResetSuccess(BaseMessageType):
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PasswordResetSuccess, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
self.options['transactional'] = True
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
|
||||
from datetime import date
|
||||
import json
|
||||
import six
|
||||
from unittest.mock import MagicMock, patch
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponse
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.urls import reverse
|
||||
from edx_rest_framework_extensions.auth.jwt.decoder import jwt_decode_handler
|
||||
from edx_rest_framework_extensions.auth.jwt.middleware import JwtAuthCookieMiddleware
|
||||
from mock import MagicMock, patch
|
||||
|
||||
from openedx.core.djangoapps.user_api.accounts.utils import retrieve_last_sitewide_block_completed
|
||||
from openedx.core.djangoapps.user_authn import cookies as cookies_api
|
||||
@@ -24,7 +23,7 @@ from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_
|
||||
|
||||
class CookieTests(TestCase):
|
||||
def setUp(self):
|
||||
super(CookieTests, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create()
|
||||
self.user.profile = UserProfileFactory.create(user=self.user)
|
||||
self.request = RequestFactory().get('/')
|
||||
@@ -38,7 +37,7 @@ class CookieTests(TestCase):
|
||||
|
||||
def _convert_to_absolute_uris(self, request, urls_obj):
|
||||
""" Convert relative URL paths to absolute URIs """
|
||||
for url_name, url_path in six.iteritems(urls_obj):
|
||||
for url_name, url_path in urls_obj.items():
|
||||
urls_obj[url_name] = request.build_absolute_uri(url_path)
|
||||
|
||||
return urls_obj
|
||||
@@ -70,7 +69,7 @@ class CookieTests(TestCase):
|
||||
def _copy_cookies_to_request(self, response, request):
|
||||
request.COOKIES = {
|
||||
key: val.value
|
||||
for key, val in six.iteritems(response.cookies)
|
||||
for key, val in response.cookies.items()
|
||||
}
|
||||
|
||||
def _set_use_jwt_cookie_header(self, request):
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
|
||||
from collections import namedtuple
|
||||
from urllib.parse import urlencode # pylint: disable=import-error
|
||||
import pytest
|
||||
import ddt
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from six.moves.urllib.parse import urlencode # pylint: disable=import-error
|
||||
|
||||
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory
|
||||
from openedx.core.djangoapps.user_authn.utils import (
|
||||
@@ -20,7 +20,7 @@ class TestRedirectUtils(TestCase):
|
||||
"""Test redirect utility methods."""
|
||||
|
||||
def setUp(self):
|
||||
super(TestRedirectUtils, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.request = RequestFactory()
|
||||
|
||||
RedirectCase = namedtuple('RedirectCase', ['url', 'host', 'req_is_secure', 'expected_is_safe'])
|
||||
@@ -79,8 +79,8 @@ class GeneratePasswordTest(TestCase):
|
||||
def test_default_args(self):
|
||||
password = generate_password()
|
||||
assert 12 == len(password)
|
||||
assert any((c.isdigit for c in password))
|
||||
assert any((c.isalpha for c in password))
|
||||
assert any(c.isdigit for c in password)
|
||||
assert any(c.isalpha for c in password)
|
||||
|
||||
def test_length(self):
|
||||
length = 25
|
||||
@@ -90,8 +90,8 @@ class GeneratePasswordTest(TestCase):
|
||||
char = '!'
|
||||
password = generate_password(length=12, chars=(char,))
|
||||
|
||||
assert any((c.isdigit for c in password))
|
||||
assert any((c.isalpha for c in password))
|
||||
assert any(c.isdigit for c in password)
|
||||
assert any(c.isalpha for c in password)
|
||||
assert (char * 10) == password[2:]
|
||||
|
||||
def test_min_length(self):
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from enum import Enum
|
||||
from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from mock import patch
|
||||
from oauth2_provider import models as dot_models
|
||||
from rest_framework import status
|
||||
|
||||
@@ -46,7 +46,7 @@ def utcnow():
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class AuthAndScopesTestMixin(object):
|
||||
class AuthAndScopesTestMixin:
|
||||
"""
|
||||
Mixin class to test authentication and oauth scopes for an API.
|
||||
Test classes that use this Mixin need to define:
|
||||
@@ -61,7 +61,7 @@ class AuthAndScopesTestMixin(object):
|
||||
user_password = 'test'
|
||||
|
||||
def setUp(self):
|
||||
super(AuthAndScopesTestMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.student = UserFactory.create(password=self.user_password)
|
||||
self.other_student = UserFactory.create(password=self.user_password)
|
||||
self.global_staff = UserFactory.create(password=self.user_password, is_staff=True)
|
||||
@@ -84,12 +84,12 @@ class AuthAndScopesTestMixin(object):
|
||||
elif auth_type == AuthType.oauth:
|
||||
if not token:
|
||||
token = self._create_oauth_token(requesting_user)
|
||||
auth_header = u"Bearer {0}".format(token)
|
||||
auth_header = f"Bearer {token}"
|
||||
else:
|
||||
assert auth_type in JWT_AUTH_TYPES
|
||||
if not token:
|
||||
token = self._create_jwt_token(requesting_user, auth_type)
|
||||
auth_header = u"JWT {0}".format(token)
|
||||
auth_header = f"JWT {token}"
|
||||
|
||||
extra = dict(HTTP_AUTHORIZATION=auth_header) if auth_header else {}
|
||||
return self.client.get(
|
||||
@@ -119,7 +119,7 @@ class AuthAndScopesTestMixin(object):
|
||||
""" Creates and returns a JWT token for the given user with the given parameters. """
|
||||
filters = []
|
||||
if include_org_filter:
|
||||
filters += ['content_org:{}'.format(self.course.id.org)]
|
||||
filters += [f'content_org:{self.course.id.org}']
|
||||
if include_me_filter:
|
||||
filters += ['user:me']
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ Utility functions used during user authentication.
|
||||
|
||||
import random
|
||||
import string
|
||||
from urllib.parse import urlparse # pylint: disable=import-error
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils import http
|
||||
from oauth2_provider.models import Application
|
||||
from six.moves.urllib.parse import urlparse # pylint: disable=import-error
|
||||
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import json
|
||||
import logging
|
||||
import hashlib
|
||||
import re
|
||||
import urllib
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import authenticate
|
||||
from django.contrib.auth import login as django_login
|
||||
@@ -71,17 +71,17 @@ def _do_third_party_auth(request):
|
||||
return pipeline.get_authenticated_user(requested_provider, username, third_party_uid)
|
||||
except User.DoesNotExist:
|
||||
AUDIT_LOG.info(
|
||||
u"Login failed - user with username {username} has no social auth "
|
||||
u"with backend_name {backend_name}".format(
|
||||
"Login failed - user with username {username} has no social auth "
|
||||
"with backend_name {backend_name}".format(
|
||||
username=username, backend_name=backend_name)
|
||||
)
|
||||
message = Text(_(
|
||||
u"You've successfully signed in to your {provider_name} account, "
|
||||
u"but this account isn't linked with your {platform_name} account yet. {blank_lines}"
|
||||
u"Use your {platform_name} username and password to sign in to {platform_name} below, "
|
||||
u"and then link your {platform_name} account with {provider_name} from your dashboard. {blank_lines}"
|
||||
u"If you don't have an account on {platform_name} yet, "
|
||||
u"click {register_label_strong} at the top of the page."
|
||||
"You've successfully signed in to your {provider_name} account, "
|
||||
"but this account isn't linked with your {platform_name} account yet. {blank_lines}"
|
||||
"Use your {platform_name} username and password to sign in to {platform_name} below, "
|
||||
"and then link your {platform_name} account with {provider_name} from your dashboard. {blank_lines}"
|
||||
"If you don't have an account on {platform_name} yet, "
|
||||
"click {register_label_strong} at the top of the page."
|
||||
)).format(
|
||||
blank_lines=HTML('<br/><br/>'),
|
||||
platform_name=platform_name,
|
||||
@@ -149,12 +149,12 @@ def _enforce_password_policy_compliance(request, user): # lint-amnesty, pylint:
|
||||
password_policy_compliance.enforce_compliance_on_login(user, request.POST.get('password'))
|
||||
except password_policy_compliance.NonCompliantPasswordWarning as e:
|
||||
# Allow login, but warn the user that they will be required to reset their password soon.
|
||||
PageLevelMessages.register_warning_message(request, six.text_type(e))
|
||||
PageLevelMessages.register_warning_message(request, str(e))
|
||||
except password_policy_compliance.NonCompliantPasswordException as e:
|
||||
AUDIT_LOG.info("Password reset initiated for email %s.", user.email)
|
||||
send_password_reset_email_for_user(user, request)
|
||||
# Prevent the login attempt.
|
||||
raise AuthFailedError(HTML(six.text_type(e)), error_code=e.__class__.__name__) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise AuthFailedError(HTML(str(e)), error_code=e.__class__.__name__) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
|
||||
def _log_and_raise_inactive_user_auth_error(unauthenticated_user):
|
||||
@@ -309,8 +309,8 @@ def _create_message(site, root_url, allowed_domain):
|
||||
through allowed domain SSO provider.
|
||||
"""
|
||||
msg = Text(_(
|
||||
u'As {allowed_domain} user, You must login with your {allowed_domain} '
|
||||
u'{link_start}{provider} account{link_end}.'
|
||||
'As {allowed_domain} user, You must login with your {allowed_domain} '
|
||||
'{link_start}{provider} account{link_end}.'
|
||||
)).format(
|
||||
allowed_domain=allowed_domain,
|
||||
link_start=HTML("<a href='{root_url}{tpa_provider_link}'>").format(
|
||||
@@ -404,7 +404,7 @@ def enterprise_selection_page(request, user, next_url):
|
||||
|
||||
# Check to see if next url has an enterprise in it. In this case if user is associated with
|
||||
# that enterprise, activate that enterprise and bypass the selection page.
|
||||
if re.match(ENTERPRISE_ENROLLMENT_URL_REGEX, six.moves.urllib.parse.unquote(next_url)):
|
||||
if re.match(ENTERPRISE_ENROLLMENT_URL_REGEX, urllib.parse.unquote(next_url)):
|
||||
enterprise_in_url = re.search(UUID4_REGEX, next_url).group(0)
|
||||
for enterprise in response:
|
||||
if enterprise_in_url == str(enterprise['enterprise_customer']['uuid']):
|
||||
@@ -614,7 +614,7 @@ class LoginSessionView(APIView):
|
||||
|
||||
@method_decorator(sensitive_post_parameters("password"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super(LoginSessionView, self).dispatch(request, *args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
def _parse_analytics_param_for_course_id(request):
|
||||
@@ -642,7 +642,7 @@ def _parse_analytics_param_for_course_id(request):
|
||||
except (ValueError, TypeError):
|
||||
set_custom_attribute('shim_analytics_course_id', 'parse-error')
|
||||
log.error(
|
||||
u"Could not parse analytics object sent to user API: {analytics}".format(
|
||||
"Could not parse analytics object sent to user API: {analytics}".format(
|
||||
analytics=analytics
|
||||
)
|
||||
)
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
import json
|
||||
import logging
|
||||
import urllib
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.shortcuts import redirect
|
||||
@@ -115,7 +115,7 @@ def get_login_session_form(request):
|
||||
|
||||
# Translators: This label appears above a field on the login form
|
||||
# meant to hold the user's password.
|
||||
password_label = _(u"Password")
|
||||
password_label = _("Password")
|
||||
|
||||
form_desc.add_field(
|
||||
"password",
|
||||
@@ -166,7 +166,7 @@ def login_and_registration_form(request, initial_mode="login"):
|
||||
third_party_auth_hint = None
|
||||
if '?' in redirect_to: # lint-amnesty, pylint: disable=too-many-nested-blocks
|
||||
try:
|
||||
next_args = six.moves.urllib.parse.parse_qs(six.moves.urllib.parse.urlparse(redirect_to).query)
|
||||
next_args = urllib.parse.parse_qs(urllib.parse.urlparse(redirect_to).query)
|
||||
if 'tpa_hint' in next_args:
|
||||
provider_id = next_args['tpa_hint'][0]
|
||||
tpa_hint_provider = third_party_auth.provider.Registry.get(provider_id=provider_id)
|
||||
@@ -184,7 +184,7 @@ def login_and_registration_form(request, initial_mode="login"):
|
||||
third_party_auth_hint = provider_id
|
||||
initial_mode = "hinted_login"
|
||||
except (KeyError, ValueError, IndexError) as ex:
|
||||
log.exception(u"Unknown tpa_hint provider: %s", ex)
|
||||
log.exception("Unknown tpa_hint provider: %s", ex)
|
||||
|
||||
# Redirect to authn MFE if it is enabled or user is not an enterprise user or not coming from a SAML IDP.
|
||||
saml_provider = False
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
|
||||
import re
|
||||
import urllib.parse as parse # pylint: disable=import-error
|
||||
from urllib.parse import parse_qs, urlsplit, urlunsplit # pylint: disable=import-error
|
||||
|
||||
import six.moves.urllib.parse as parse # pylint: disable=import-error
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import logout
|
||||
from django.utils.http import urlencode
|
||||
from django.views.generic import TemplateView
|
||||
from oauth2_provider.models import Application
|
||||
from six.moves.urllib.parse import parse_qs, urlsplit, urlunsplit # pylint: disable=import-error
|
||||
|
||||
from openedx.core.djangoapps.user_authn.cookies import delete_logged_in_cookies
|
||||
from openedx.core.djangoapps.user_authn.utils import is_safe_login_or_logout_redirect
|
||||
@@ -76,7 +76,7 @@ class LogoutView(TemplateView):
|
||||
|
||||
logout(request)
|
||||
|
||||
response = super(LogoutView, self).dispatch(request, *args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
response = super().dispatch(request, *args, **kwargs)
|
||||
|
||||
# Clear the cookie used by the edx.org marketing site
|
||||
delete_logged_in_cookies(response)
|
||||
@@ -123,7 +123,7 @@ class LogoutView(TemplateView):
|
||||
return False
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(LogoutView, self).get_context_data(**kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
# Create a list of URIs that must be called to log the user out of all of the IDAs.
|
||||
uris = []
|
||||
|
||||
@@ -85,16 +85,16 @@ def get_password_reset_form():
|
||||
|
||||
# Translators: This label appears above a field on the password reset
|
||||
# form meant to hold the user's email address.
|
||||
email_label = _(u"Email")
|
||||
email_label = _("Email")
|
||||
|
||||
# Translators: This example email address is used as a placeholder in
|
||||
# a field on the password reset form meant to hold the user's email address.
|
||||
email_placeholder = _(u"username@domain.com")
|
||||
email_placeholder = _("username@domain.com")
|
||||
|
||||
# Translators: These instructions appear on the password reset form,
|
||||
# immediately below a field meant to hold the user's email address.
|
||||
# pylint: disable=no-member
|
||||
email_instructions = _(u"The email address you used to register with {platform_name}").format(
|
||||
email_instructions = _("The email address you used to register with {platform_name}").format(
|
||||
platform_name=configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME)
|
||||
)
|
||||
|
||||
@@ -124,7 +124,7 @@ def send_password_reset_success_email(user, request):
|
||||
message_context, user_language_preference = get_user_default_email_params(user)
|
||||
lms_root_url = configuration_helpers.get_value('LMS_ROOT_URL', settings.LMS_ROOT_URL)
|
||||
message_context.update(
|
||||
{'login_link': '{}/login'.format(lms_root_url), 'request': request, }
|
||||
{'login_link': f'{lms_root_url}/login', 'request': request, }
|
||||
)
|
||||
|
||||
msg = PasswordResetSuccess(context=message_context).personalize(
|
||||
@@ -392,8 +392,7 @@ class PasswordResetConfirmWrapper(PasswordResetConfirmView):
|
||||
except (ValueError, User.DoesNotExist):
|
||||
# if there's any error getting a user, just let django's
|
||||
# password_reset_confirm function handle it.
|
||||
return super(PasswordResetConfirmWrapper, self).dispatch(request, uidb64=self.uidb64, token=self.token, # lint-amnesty, pylint: disable=super-with-arguments
|
||||
extra_context=self.platform_name)
|
||||
return super().dispatch(request, uidb64=self.uidb64, token=self.token, extra_context=self.platform_name)
|
||||
|
||||
def _handle_retired_user(self, request):
|
||||
"""
|
||||
@@ -430,8 +429,8 @@ class PasswordResetConfirmWrapper(PasswordResetConfirmView):
|
||||
form_valid = response.context_data['form'].is_valid() if response.context_data['form'] else False
|
||||
if not form_valid:
|
||||
log.warning(
|
||||
u'Unable to reset password for user [%s] because form is not valid. '
|
||||
u'A possible cause is that the user had an invalid reset token',
|
||||
'Unable to reset password for user [%s] because form is not valid. '
|
||||
'A possible cause is that the user had an invalid reset token',
|
||||
self.user.username,
|
||||
)
|
||||
response.context_data['err_msg'] = _('Error in resetting your password. Please try again.')
|
||||
@@ -459,8 +458,8 @@ class PasswordResetConfirmWrapper(PasswordResetConfirmView):
|
||||
messages.success(
|
||||
request,
|
||||
HTML(_(
|
||||
u'{html_start}Password Creation Complete{html_end}'
|
||||
u'Your password has been created. {bold_start}{email}{bold_end} is now your primary login email.'
|
||||
'{html_start}Password Creation Complete{html_end}'
|
||||
'Your password has been created. {bold_start}{email}{bold_end} is now your primary login email.'
|
||||
)).format(
|
||||
support_url=configuration_helpers.get_value('SUPPORT_SITE_LINK', settings.SUPPORT_SITE_LINK),
|
||||
html_start=HTML('<p class="message-title">'),
|
||||
@@ -532,7 +531,7 @@ class PasswordResetConfirmWrapper(PasswordResetConfirmView):
|
||||
self.token = self._get_token_from_session(self.request)
|
||||
return self.post(self.request, *args, **kwargs)
|
||||
else:
|
||||
response = super(PasswordResetConfirmWrapper, self).dispatch( # lint-amnesty, pylint: disable=super-with-arguments
|
||||
response = super().dispatch(
|
||||
self.request,
|
||||
uidb64=self.uidb64,
|
||||
token=self.token,
|
||||
@@ -634,7 +633,7 @@ def password_change_request_handler(request):
|
||||
)
|
||||
ace.send(msg)
|
||||
except errors.UserAPIInternalError as err:
|
||||
log.exception(u'Error occured during password change for user {email}: {error}'
|
||||
log.exception('Error occured during password change for user {email}: {error}'
|
||||
.format(email=email, error=err))
|
||||
return HttpResponse(_("Some error occured during password change. Please try again"), status=500)
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ from ratelimit.decorators import ratelimit
|
||||
from requests import HTTPError
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from six import text_type
|
||||
from social_core.exceptions import AuthAlreadyAssociated, AuthException
|
||||
from social_django import utils as social_utils
|
||||
|
||||
@@ -106,8 +105,8 @@ REGISTER_USER = Signal(providing_args=["user", "registration"])
|
||||
# .. toggle_target_removal_date: 2020-06-01
|
||||
# .. toggle_warnings: This temporary feature toggle does not have a target removal date.
|
||||
REGISTRATION_FAILURE_LOGGING_FLAG = LegacyWaffleFlag(
|
||||
waffle_namespace=LegacyWaffleFlagNamespace(name=u'registration'),
|
||||
flag_name=u'enable_failure_logging',
|
||||
waffle_namespace=LegacyWaffleFlagNamespace(name='registration'),
|
||||
flag_name='enable_failure_logging',
|
||||
module_name=__name__,
|
||||
)
|
||||
REAL_IP_KEY = 'openedx.core.djangoapps.util.ratelimit.real_ip'
|
||||
@@ -179,7 +178,7 @@ def create_account_with_params(request, params):
|
||||
raise ValidationError(
|
||||
{
|
||||
'session_expired': [
|
||||
_(u"Registration using {provider} has timed out.").format(
|
||||
_("Registration using {provider} has timed out.").format(
|
||||
provider=params.get('social_auth_provider'))
|
||||
],
|
||||
'error_code': 'tpa-session-expired',
|
||||
@@ -240,7 +239,7 @@ def create_account_with_params(request, params):
|
||||
try:
|
||||
enable_notifications(user)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
log.exception(u"Enable discussion notifications failed for user {id}.".format(id=user.id))
|
||||
log.exception(f"Enable discussion notifications failed for user {user.id}.")
|
||||
|
||||
_track_user_registration(user, profile, params, third_party_provider)
|
||||
|
||||
@@ -258,7 +257,7 @@ def create_account_with_params(request, params):
|
||||
# TODO: there is no error checking here to see that the user actually logged in successfully,
|
||||
# and is not yet an active user.
|
||||
if new_user is not None:
|
||||
AUDIT_LOG.info(u"Login success on new account creation - {0}".format(new_user.username))
|
||||
AUDIT_LOG.info(f"Login success on new account creation - {new_user.username}")
|
||||
|
||||
return new_user
|
||||
|
||||
@@ -287,7 +286,7 @@ def _link_user_to_third_party_provider(
|
||||
if not social_access_token:
|
||||
raise ValidationError({
|
||||
'access_token': [
|
||||
_(u"An access_token is required when passing value ({}) for provider.").format(
|
||||
_("An access_token is required when passing value ({}) for provider.").format(
|
||||
params['provider']
|
||||
)
|
||||
],
|
||||
@@ -333,7 +332,7 @@ def _track_user_registration(user, profile, params, third_party_provider):
|
||||
'education': profile.level_of_education_display,
|
||||
'address': profile.mailing_address,
|
||||
'gender': profile.gender_display,
|
||||
'country': text_type(profile.country),
|
||||
'country': str(profile.country),
|
||||
}
|
||||
]
|
||||
# .. pii: Many pieces of PII are sent to Segment here. Retired directly through Segment API call in Tubular.
|
||||
@@ -409,7 +408,7 @@ def _skip_activation_email(user, running_pipeline, third_party_provider):
|
||||
# log the cases where skip activation email flag is set, but email validity check fails
|
||||
if third_party_provider and third_party_provider.skip_email_verification and not valid_email:
|
||||
log.info(
|
||||
u'[skip_email_verification=True][user=%s][pipeline-email=%s][identity_provider=%s][provider_type=%s] '
|
||||
'[skip_email_verification=True][user=%s][pipeline-email=%s][identity_provider=%s][provider_type=%s] '
|
||||
'Account activation email sent as user\'s system email differs from SSO email.',
|
||||
user.email,
|
||||
sso_pipeline_email,
|
||||
@@ -483,7 +482,7 @@ class RegistrationView(APIView):
|
||||
@method_decorator(transaction.non_atomic_requests)
|
||||
@method_decorator(sensitive_post_parameters("password"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super(RegistrationView, self).dispatch(request, *args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
@method_decorator(ensure_csrf_cookie)
|
||||
def get(self, request):
|
||||
@@ -573,7 +572,7 @@ class RegistrationView(APIView):
|
||||
user = create_account_with_params(request, data)
|
||||
except AccountValidationError as err:
|
||||
errors = {
|
||||
err.field: [{"user_message": text_type(err)}]
|
||||
err.field: [{"user_message": str(err)}]
|
||||
}
|
||||
response = self._create_response(request, errors, status_code=409, error_code=err.error_code)
|
||||
except ValidationError as err:
|
||||
|
||||
@@ -6,8 +6,6 @@ import copy
|
||||
from importlib import import_module
|
||||
import re
|
||||
|
||||
import six
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
@@ -69,7 +67,7 @@ def validate_username(username):
|
||||
message = accounts.USERNAME_INVALID_CHARS_ASCII
|
||||
|
||||
if settings.FEATURES.get("ENABLE_UNICODE_USERNAME"):
|
||||
username_re = r"^{regex}$".format(regex=settings.USERNAME_REGEX_PARTIAL)
|
||||
username_re = fr"^{settings.USERNAME_REGEX_PARTIAL}$"
|
||||
flags = re.UNICODE
|
||||
message = accounts.USERNAME_INVALID_CHARS_UNICODE
|
||||
|
||||
@@ -109,7 +107,7 @@ class UsernameField(forms.CharField):
|
||||
default_validators = [validate_username]
|
||||
|
||||
def __init__(self, *args, **kwargs): # lint-amnesty, pylint: disable=unused-argument
|
||||
super(UsernameField, self).__init__( # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(
|
||||
min_length=accounts.USERNAME_MIN_LENGTH,
|
||||
max_length=accounts.USERNAME_MAX_LENGTH,
|
||||
error_messages={
|
||||
@@ -127,7 +125,7 @@ class UsernameField(forms.CharField):
|
||||
"""
|
||||
|
||||
value = self.to_python(value).strip()
|
||||
return super(UsernameField, self).clean(value) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().clean(value)
|
||||
|
||||
|
||||
class AccountCreationForm(forms.Form):
|
||||
@@ -136,8 +134,8 @@ class AccountCreationForm(forms.Form):
|
||||
validation, not rendering.
|
||||
"""
|
||||
|
||||
_EMAIL_INVALID_MSG = _(u"A properly formatted e-mail is required")
|
||||
_NAME_TOO_SHORT_MSG = _(u"Your legal name must be a minimum of one character long")
|
||||
_EMAIL_INVALID_MSG = _("A properly formatted e-mail is required")
|
||||
_NAME_TOO_SHORT_MSG = _("Your legal name must be a minimum of one character long")
|
||||
|
||||
# TODO: Resolve repetition
|
||||
|
||||
@@ -149,7 +147,7 @@ class AccountCreationForm(forms.Form):
|
||||
error_messages={
|
||||
"required": _EMAIL_INVALID_MSG,
|
||||
"invalid": _EMAIL_INVALID_MSG,
|
||||
"max_length": _(u"Email cannot be more than %(limit_value)s characters long"),
|
||||
"max_length": _("Email cannot be more than %(limit_value)s characters long"),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -172,7 +170,7 @@ class AccountCreationForm(forms.Form):
|
||||
do_third_party_auth=True,
|
||||
tos_required=True
|
||||
):
|
||||
super(AccountCreationForm, self).__init__(data) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(data)
|
||||
|
||||
extra_fields = extra_fields or {}
|
||||
self.extended_profile_fields = extended_profile_fields or {}
|
||||
@@ -245,11 +243,11 @@ class AccountCreationForm(forms.Form):
|
||||
# they may have been manually invited by an instructor and if not,
|
||||
# reject the registration.
|
||||
if not CourseEnrollmentAllowed.objects.filter(email=email).exists():
|
||||
raise ValidationError(_(u"Unauthorized email address."))
|
||||
raise ValidationError(_("Unauthorized email address."))
|
||||
if email_exists_or_retired(email):
|
||||
raise ValidationError(
|
||||
_(
|
||||
u"It looks like {email} belongs to an existing account. Try again with a different email address."
|
||||
"It looks like {email} belongs to an existing account. Try again with a different email address."
|
||||
).format(email=email)
|
||||
)
|
||||
return email
|
||||
@@ -290,7 +288,7 @@ def get_registration_extension_form(*args, **kwargs):
|
||||
return getattr(module, klass)(*args, **kwargs)
|
||||
|
||||
|
||||
class RegistrationFormFactory(object):
|
||||
class RegistrationFormFactory:
|
||||
"""
|
||||
Construct Registration forms and associated fields.
|
||||
"""
|
||||
@@ -338,14 +336,14 @@ class RegistrationFormFactory(object):
|
||||
# Check that the setting is configured correctly
|
||||
for field_name in self.EXTRA_FIELDS:
|
||||
if self._extra_fields_setting.get(field_name, "hidden") not in ["required", "optional", "hidden"]:
|
||||
msg = u"Setting REGISTRATION_EXTRA_FIELDS values must be either required, optional, or hidden."
|
||||
msg = "Setting REGISTRATION_EXTRA_FIELDS values must be either required, optional, or hidden."
|
||||
raise ImproperlyConfigured(msg)
|
||||
|
||||
# Map field names to the instance method used to add the field to the form
|
||||
self.field_handlers = {}
|
||||
valid_fields = self.DEFAULT_FIELDS + self.EXTRA_FIELDS
|
||||
for field_name in valid_fields:
|
||||
handler = getattr(self, "_add_{field_name}_field".format(field_name=field_name))
|
||||
handler = getattr(self, f"_add_{field_name}_field")
|
||||
self.field_handlers[field_name] = handler
|
||||
|
||||
field_order = configuration_helpers.get_value('REGISTRATION_FIELD_ORDER')
|
||||
@@ -397,7 +395,7 @@ class RegistrationFormFactory(object):
|
||||
field_type = field_options.get('field_type', FormDescription.FIELD_TYPE_MAP.get(field.__class__))
|
||||
if not field_type:
|
||||
raise ImproperlyConfigured(
|
||||
u"Field type '{}' not recognized for registration extension field '{}'.".format(
|
||||
"Field type '{}' not recognized for registration extension field '{}'.".format(
|
||||
field_type,
|
||||
field_name
|
||||
)
|
||||
@@ -450,11 +448,11 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# meant to hold the user's email address.
|
||||
email_label = _(u"Email")
|
||||
email_label = _("Email")
|
||||
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's email address.
|
||||
email_instructions = _(u"This is what you will use to login.")
|
||||
email_instructions = _("This is what you will use to login.")
|
||||
|
||||
form_desc.add_field(
|
||||
"email",
|
||||
@@ -477,7 +475,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# meant to confirm the user's email address.
|
||||
email_label = _(u"Confirm Email")
|
||||
email_label = _("Confirm Email")
|
||||
|
||||
error_msg = accounts.REQUIRED_FIELD_CONFIRM_EMAIL_MSG
|
||||
|
||||
@@ -500,11 +498,11 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# meant to hold the user's full name.
|
||||
name_label = _(u"Full Name")
|
||||
name_label = _("Full Name")
|
||||
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's full name.
|
||||
name_instructions = _(u"This name will be used on any certificates that you earn.")
|
||||
name_instructions = _("This name will be used on any certificates that you earn.")
|
||||
|
||||
form_desc.add_field(
|
||||
"name",
|
||||
@@ -525,13 +523,13 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# meant to hold the user's public username.
|
||||
username_label = _(u"Public Username")
|
||||
username_label = _("Public Username")
|
||||
|
||||
username_instructions = _(
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's public username.
|
||||
u"The name that will identify you in your courses. "
|
||||
u"It cannot be changed later."
|
||||
"The name that will identify you in your courses. "
|
||||
"It cannot be changed later."
|
||||
)
|
||||
form_desc.add_field(
|
||||
"username",
|
||||
@@ -553,7 +551,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# meant to hold the user's password.
|
||||
password_label = _(u"Password")
|
||||
password_label = _("Password")
|
||||
|
||||
form_desc.add_field(
|
||||
"password",
|
||||
@@ -573,7 +571,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a dropdown menu on the registration
|
||||
# form used to select the user's highest completed level of education.
|
||||
education_level_label = _(u"Highest level of education completed")
|
||||
education_level_label = _("Highest level of education completed")
|
||||
error_msg = accounts.REQUIRED_FIELD_LEVEL_OF_EDUCATION_MSG
|
||||
|
||||
# The labels are marked for translation in UserProfile model definition.
|
||||
@@ -600,7 +598,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a dropdown menu on the registration
|
||||
# form used to select the user's gender.
|
||||
gender_label = _(u"Gender")
|
||||
gender_label = _("Gender")
|
||||
|
||||
# The labels are marked for translation in UserProfile model definition.
|
||||
# pylint: disable=translation-of-non-string
|
||||
@@ -623,9 +621,9 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a dropdown menu on the registration
|
||||
# form used to select the user's year of birth.
|
||||
yob_label = _(u"Year of birth")
|
||||
yob_label = _("Year of birth")
|
||||
|
||||
options = [(six.text_type(year), six.text_type(year)) for year in UserProfile.VALID_YEARS]
|
||||
options = [(str(year), str(year)) for year in UserProfile.VALID_YEARS]
|
||||
form_desc.add_field(
|
||||
"year_of_birth",
|
||||
label=yob_label,
|
||||
@@ -656,14 +654,14 @@ class RegistrationFormFactory(object):
|
||||
include_default_option = False
|
||||
options = None
|
||||
error_msg = ''
|
||||
error_msg = getattr(accounts, u'REQUIRED_FIELD_{}_TEXT_MSG'.format(field_name.upper()))
|
||||
error_msg = getattr(accounts, f'REQUIRED_FIELD_{field_name.upper()}_TEXT_MSG')
|
||||
else:
|
||||
field_type = "select"
|
||||
include_default_option = True
|
||||
field_options = extra_field_options.get(field_name)
|
||||
options = [(six.text_type(option.lower()), option) for option in field_options]
|
||||
options = [(str(option.lower()), option) for option in field_options]
|
||||
error_msg = ''
|
||||
error_msg = getattr(accounts, u'REQUIRED_FIELD_{}_SELECT_MSG'.format(field_name.upper()))
|
||||
error_msg = getattr(accounts, f'REQUIRED_FIELD_{field_name.upper()}_SELECT_MSG')
|
||||
|
||||
form_desc.add_field(
|
||||
field_name,
|
||||
@@ -718,7 +716,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# meant to hold the user's mailing address.
|
||||
mailing_address_label = _(u"Mailing address")
|
||||
mailing_address_label = _("Mailing address")
|
||||
error_msg = accounts.REQUIRED_FIELD_MAILING_ADDRESS_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
@@ -740,7 +738,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This phrase appears above a field on the registration form
|
||||
# meant to hold the user's reasons for registering with edX.
|
||||
goals_label = _(u"Tell us why you're interested in {platform_name}").format(
|
||||
goals_label = _("Tell us why you're interested in {platform_name}").format(
|
||||
platform_name=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME)
|
||||
)
|
||||
error_msg = accounts.REQUIRED_FIELD_GOALS_MSG
|
||||
@@ -764,7 +762,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the city in which they live.
|
||||
city_label = _(u"City")
|
||||
city_label = _("City")
|
||||
error_msg = accounts.REQUIRED_FIELD_CITY_MSG
|
||||
|
||||
form_desc.add_field(
|
||||
@@ -785,7 +783,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the State/Province/Region in which they live.
|
||||
state_label = _(u"State/Province/Region")
|
||||
state_label = _("State/Province/Region")
|
||||
|
||||
form_desc.add_field(
|
||||
"state",
|
||||
@@ -802,7 +800,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the Company
|
||||
company_label = _(u"Company")
|
||||
company_label = _("Company")
|
||||
|
||||
form_desc.add_field(
|
||||
"company",
|
||||
@@ -819,7 +817,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the Title
|
||||
title_label = _(u"Title")
|
||||
title_label = _("Title")
|
||||
|
||||
form_desc.add_field(
|
||||
"title",
|
||||
@@ -836,7 +834,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the Job Title
|
||||
job_title_label = _(u"Job Title")
|
||||
job_title_label = _("Job Title")
|
||||
|
||||
form_desc.add_field(
|
||||
"job_title",
|
||||
@@ -853,7 +851,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the First Name
|
||||
first_name_label = _(u"First Name")
|
||||
first_name_label = _("First Name")
|
||||
|
||||
form_desc.add_field(
|
||||
"first_name",
|
||||
@@ -870,7 +868,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# which allows the user to input the First Name
|
||||
last_name_label = _(u"Last Name")
|
||||
last_name_label = _("Last Name")
|
||||
|
||||
form_desc.add_field(
|
||||
"last_name",
|
||||
@@ -887,7 +885,7 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This label appears above a dropdown menu on the registration
|
||||
# form used to select the country in which the user lives.
|
||||
country_label = _(u"Country or Region of Residence")
|
||||
country_label = _("Country or Region of Residence")
|
||||
|
||||
error_msg = accounts.REQUIRED_FIELD_COUNTRY_MSG
|
||||
|
||||
@@ -898,7 +896,7 @@ class RegistrationFormFactory(object):
|
||||
country_instructions = _(
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's country.
|
||||
u"The country or region where you live."
|
||||
"The country or region where you live."
|
||||
)
|
||||
if default_country:
|
||||
form_desc.override_field_properties(
|
||||
@@ -930,24 +928,24 @@ class RegistrationFormFactory(object):
|
||||
separate_honor_and_tos = self._is_field_visible("terms_of_service")
|
||||
# Separate terms of service and honor code checkboxes
|
||||
if separate_honor_and_tos:
|
||||
terms_label = _(u"Honor Code")
|
||||
terms_label = _("Honor Code")
|
||||
terms_link = marketing_link("HONOR")
|
||||
|
||||
# Combine terms of service and honor code checkboxes
|
||||
else:
|
||||
# Translators: This is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
terms_label = _(u"Terms of Service and Honor Code")
|
||||
terms_label = _("Terms of Service and Honor Code")
|
||||
terms_link = marketing_link("HONOR")
|
||||
|
||||
# Translators: "Terms of Service" is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
label = Text(_(
|
||||
u"I agree to the {platform_name} {terms_of_service_link_start}{terms_of_service}{terms_of_service_link_end}"
|
||||
"I agree to the {platform_name} {terms_of_service_link_start}{terms_of_service}{terms_of_service_link_end}"
|
||||
)).format(
|
||||
platform_name=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label,
|
||||
terms_of_service_link_start=HTML(u"<a href='{terms_link}' rel='noopener' target='_blank'>").format(
|
||||
terms_of_service_link_start=HTML("<a href='{terms_link}' rel='noopener' target='_blank'>").format(
|
||||
terms_link=terms_link
|
||||
),
|
||||
terms_of_service_link_end=HTML("</a>"),
|
||||
@@ -955,7 +953,7 @@ class RegistrationFormFactory(object):
|
||||
|
||||
# Translators: "Terms of Service" is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
error_msg = _(u"You must agree to the {platform_name} {terms_of_service}").format(
|
||||
error_msg = _("You must agree to the {platform_name} {terms_of_service}").format(
|
||||
platform_name=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
@@ -966,18 +964,18 @@ class RegistrationFormFactory(object):
|
||||
|
||||
pp_link = marketing_link("PRIVACY")
|
||||
label = Text(_(
|
||||
u"By creating an account, you agree to the \
|
||||
"By creating an account, you agree to the \
|
||||
{terms_of_service_link_start}{terms_of_service}{terms_of_service_link_end} \
|
||||
and you acknowledge that {platform_name} and each Member process your personal data in accordance \
|
||||
with the {privacy_policy_link_start}Privacy Policy{privacy_policy_link_end}."
|
||||
)).format(
|
||||
platform_name=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label,
|
||||
terms_of_service_link_start=HTML(u"<a href='{terms_url}' rel='noopener' target='_blank'>").format(
|
||||
terms_of_service_link_start=HTML("<a href='{terms_url}' rel='noopener' target='_blank'>").format(
|
||||
terms_url=terms_link
|
||||
),
|
||||
terms_of_service_link_end=HTML("</a>"),
|
||||
privacy_policy_link_start=HTML(u"<a href='{pp_url}' rel='noopener' target='_blank'>").format(
|
||||
privacy_policy_link_start=HTML("<a href='{pp_url}' rel='noopener' target='_blank'>").format(
|
||||
pp_url=pp_link
|
||||
),
|
||||
privacy_policy_link_end=HTML("</a>"),
|
||||
@@ -1003,15 +1001,15 @@ class RegistrationFormFactory(object):
|
||||
"""
|
||||
# Translators: This is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
terms_label = _(u"Terms of Service")
|
||||
terms_label = _("Terms of Service")
|
||||
terms_link = marketing_link("TOS")
|
||||
|
||||
# Translators: "Terms of service" is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
label = Text(_(u"I agree to the {platform_name} {tos_link_start}{terms_of_service}{tos_link_end}")).format(
|
||||
label = Text(_("I agree to the {platform_name} {tos_link_start}{terms_of_service}{tos_link_end}")).format(
|
||||
platform_name=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label,
|
||||
tos_link_start=HTML(u"<a href='{terms_link}' rel='noopener' target='_blank'>").format(
|
||||
tos_link_start=HTML("<a href='{terms_link}' rel='noopener' target='_blank'>").format(
|
||||
terms_link=terms_link
|
||||
),
|
||||
tos_link_end=HTML("</a>"),
|
||||
@@ -1019,7 +1017,7 @@ class RegistrationFormFactory(object):
|
||||
|
||||
# Translators: "Terms of service" is a legal document users must agree to
|
||||
# in order to register a new account.
|
||||
error_msg = _(u"You must agree to the {platform_name} {terms_of_service}").format(
|
||||
error_msg = _("You must agree to the {platform_name} {terms_of_service}").format(
|
||||
platform_name=configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME),
|
||||
terms_of_service=terms_label
|
||||
)
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
|
||||
|
||||
import json
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import ddt
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.test import TestCase
|
||||
from django.test.client import Client
|
||||
from mock import Mock, patch
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
|
||||
from common.djangoapps.student.models import CourseAccessRole, CourseEnrollment, UserProfile, anonymous_id_for_user
|
||||
@@ -51,7 +50,7 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase, ModuleStoreTestCase):
|
||||
# of the UrlResetMixin)
|
||||
|
||||
self.CREATE_USER = False # no need to add a user from modulestore setup
|
||||
super(AutoAuthEnabledTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = '/auto_auth'
|
||||
self.client = Client()
|
||||
|
||||
@@ -148,7 +147,7 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase, ModuleStoreTestCase):
|
||||
@ddt.unpack
|
||||
def test_set_roles(self, course_id, course_key):
|
||||
seed_permissions_roles(course_key)
|
||||
course_roles = dict((r.name, r) for r in Role.objects.filter(course_id=course_key))
|
||||
course_roles = {r.name: r for r in Role.objects.filter(course_id=course_key)}
|
||||
assert len(course_roles) == 5
|
||||
# sanity check
|
||||
|
||||
@@ -163,13 +162,13 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase, ModuleStoreTestCase):
|
||||
self._auto_auth({'username': 'a_moderator', 'course_id': course_id, 'roles': 'Moderator'})
|
||||
user = User.objects.get(username='a_moderator')
|
||||
user_roles = user.roles.all()
|
||||
assert set(user_roles) == set([course_roles[FORUM_ROLE_STUDENT], course_roles[FORUM_ROLE_MODERATOR]])
|
||||
assert set(user_roles) == {course_roles[FORUM_ROLE_STUDENT], course_roles[FORUM_ROLE_MODERATOR]}
|
||||
|
||||
# check multiple roles work.
|
||||
self.client.logout()
|
||||
self._auto_auth({
|
||||
'username': 'an_admin', 'course_id': course_id,
|
||||
'roles': '{},{}'.format(FORUM_ROLE_MODERATOR, FORUM_ROLE_ADMINISTRATOR)
|
||||
'roles': f'{FORUM_ROLE_MODERATOR},{FORUM_ROLE_ADMINISTRATOR}'
|
||||
})
|
||||
user = User.objects.get(username='an_admin')
|
||||
user_roles = user.roles.all()
|
||||
@@ -211,7 +210,7 @@ class AutoAuthEnabledTestCase(AutoAuthTestCase, ModuleStoreTestCase):
|
||||
if settings.ROOT_URLCONF == 'lms.urls':
|
||||
url_pattern = '/course/'
|
||||
else:
|
||||
url_pattern = '/course/{}'.format(six.text_type(course_key))
|
||||
url_pattern = '/course/{}'.format(str(course_key))
|
||||
|
||||
assert response.url.endswith(url_pattern)
|
||||
|
||||
@@ -306,7 +305,7 @@ class AutoAuthDisabledTestCase(AutoAuthTestCase):
|
||||
# value affects the contents of urls.py,
|
||||
# so we need to call super.setUp() which reloads urls.py (because
|
||||
# of the UrlResetMixin)
|
||||
super(AutoAuthDisabledTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = '/auto_auth'
|
||||
self.client = Client()
|
||||
|
||||
@@ -330,7 +329,7 @@ class AutoAuthRestrictedTestCase(AutoAuthTestCase):
|
||||
# value affects the contents of urls.py,
|
||||
# so we need to call super.setUp() which reloads urls.py (because
|
||||
# of the UrlResetMixin)
|
||||
super(AutoAuthRestrictedTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = '/auto_auth'
|
||||
self.client = Client()
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# coding:utf-8
|
||||
"""
|
||||
Tests for student activation and login
|
||||
"""
|
||||
@@ -8,9 +7,9 @@ import datetime
|
||||
import hashlib
|
||||
import json
|
||||
import unicodedata
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import ddt
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.core import mail
|
||||
@@ -21,7 +20,6 @@ from django.test.utils import override_settings
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag, override_waffle_switch
|
||||
from freezegun import freeze_time
|
||||
from mock import Mock, patch
|
||||
from common.djangoapps.student.tests.factories import RegistrationFactory, UserFactory, UserProfileFactory
|
||||
|
||||
from openedx.core.djangoapps.password_policy.compliance import (
|
||||
@@ -59,7 +57,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Setup a test user along with its registration and profile"""
|
||||
super(LoginTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = self._create_user(self.username, self.user_email)
|
||||
|
||||
RegistrationFactory(user=self.user)
|
||||
@@ -81,7 +79,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
self.user_email, self.password, patched_audit_log='common.djangoapps.student.models.AUDIT_LOG'
|
||||
)
|
||||
self._assert_response(response, success=True)
|
||||
self._assert_audit_log(mock_audit_log, 'info', [u'Login success', self.user_email])
|
||||
self._assert_audit_log(mock_audit_log, 'info', ['Login success', self.user_email])
|
||||
|
||||
FEATURES_WITH_AUTHN_MFE_ENABLED = settings.FEATURES.copy()
|
||||
FEATURES_WITH_AUTHN_MFE_ENABLED['ENABLE_AUTHN_MICROFRONTEND'] = True
|
||||
@@ -291,11 +289,11 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
self.user_email, self.password, patched_audit_log='common.djangoapps.student.models.AUDIT_LOG'
|
||||
)
|
||||
self._assert_response(response, success=True)
|
||||
self._assert_audit_log(mock_audit_log, 'info', [u'Login success'])
|
||||
self._assert_audit_log(mock_audit_log, 'info', ['Login success'])
|
||||
self._assert_not_in_audit_log(mock_audit_log, 'info', [self.user_email])
|
||||
|
||||
def test_login_success_unicode_email(self):
|
||||
unicode_email = u'test' + six.unichr(40960) + u'@edx.org'
|
||||
unicode_email = 'test' + chr(40960) + '@edx.org'
|
||||
self.user.email = unicode_email
|
||||
self.user.save()
|
||||
|
||||
@@ -303,10 +301,10 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
unicode_email, self.password, patched_audit_log='common.djangoapps.student.models.AUDIT_LOG'
|
||||
)
|
||||
self._assert_response(response, success=True)
|
||||
self._assert_audit_log(mock_audit_log, 'info', [u'Login success', unicode_email])
|
||||
self._assert_audit_log(mock_audit_log, 'info', ['Login success', unicode_email])
|
||||
|
||||
def test_login_fail_no_user_exists(self):
|
||||
nonexistent_email = u'not_a_user@edx.org'
|
||||
nonexistent_email = 'not_a_user@edx.org'
|
||||
# pylint: disable=too-many-function-args
|
||||
email_hash = hashlib.shake_128(nonexistent_email.encode('utf-8')).hexdigest(16)
|
||||
response, mock_audit_log = self._login_response(
|
||||
@@ -316,17 +314,17 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
self._assert_response(
|
||||
response, success=False, value=self.LOGIN_FAILED_WARNING, status_code=400
|
||||
)
|
||||
self._assert_audit_log(mock_audit_log, 'warning', [u'Login failed', u'Unknown user email', email_hash])
|
||||
self._assert_audit_log(mock_audit_log, 'warning', ['Login failed', 'Unknown user email', email_hash])
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {'SQUELCH_PII_IN_LOGS': True})
|
||||
def test_login_fail_no_user_exists_no_pii(self):
|
||||
nonexistent_email = u'not_a_user@edx.org'
|
||||
nonexistent_email = 'not_a_user@edx.org'
|
||||
response, mock_audit_log = self._login_response(
|
||||
nonexistent_email,
|
||||
self.password,
|
||||
)
|
||||
self._assert_response(response, success=False, value=self.LOGIN_FAILED_WARNING)
|
||||
self._assert_audit_log(mock_audit_log, 'warning', [u'Login failed', u'Unknown user email'])
|
||||
self._assert_audit_log(mock_audit_log, 'warning', ['Login failed', 'Unknown user email'])
|
||||
self._assert_not_in_audit_log(mock_audit_log, 'warning', [nonexistent_email])
|
||||
|
||||
def test_login_fail_wrong_password(self):
|
||||
@@ -336,14 +334,14 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
)
|
||||
self._assert_response(response, success=False, value=self.LOGIN_FAILED_WARNING)
|
||||
self._assert_audit_log(mock_audit_log, 'warning',
|
||||
[u'Login failed', u'password for', str(self.user.id), u'invalid'])
|
||||
['Login failed', 'password for', str(self.user.id), 'invalid'])
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {'SQUELCH_PII_IN_LOGS': True})
|
||||
def test_login_fail_wrong_password_no_pii(self):
|
||||
response, mock_audit_log = self._login_response(self.user_email, 'wrong_password')
|
||||
self._assert_response(response, success=False, value=self.LOGIN_FAILED_WARNING)
|
||||
self._assert_audit_log(
|
||||
mock_audit_log, 'warning', [u'Login failed', u'password for', str(self.user.id), u'invalid']
|
||||
mock_audit_log, 'warning', ['Login failed', 'password for', str(self.user.id), 'invalid']
|
||||
)
|
||||
self._assert_not_in_audit_log(mock_audit_log, 'warning', [self.user_email])
|
||||
|
||||
@@ -358,8 +356,8 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
self.password
|
||||
)
|
||||
self._assert_response(response, success=False, error_code="inactive-user")
|
||||
self._assert_audit_log(mock_audit_log, 'warning', [u'Login failed', u'Account not active for user'])
|
||||
self._assert_not_in_audit_log(mock_audit_log, 'warning', [u'test'])
|
||||
self._assert_audit_log(mock_audit_log, 'warning', ['Login failed', 'Account not active for user'])
|
||||
self._assert_not_in_audit_log(mock_audit_log, 'warning', ['test'])
|
||||
|
||||
def test_login_not_activated_with_correct_credentials(self):
|
||||
"""
|
||||
@@ -374,7 +372,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
self.password,
|
||||
)
|
||||
self._assert_response(response, success=False, error_code="inactive-user")
|
||||
self._assert_audit_log(mock_audit_log, 'warning', [u'Login failed', u'Account not active for user'])
|
||||
self._assert_audit_log(mock_audit_log, 'warning', ['Login failed', 'Account not active for user'])
|
||||
|
||||
@patch('openedx.core.djangoapps.user_authn.views.login._log_and_raise_inactive_user_auth_error')
|
||||
def test_login_inactivated_user_with_incorrect_credentials(self, mock_inactive_user_email_and_error):
|
||||
@@ -391,10 +389,10 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
|
||||
assert not mock_inactive_user_email_and_error.called
|
||||
self._assert_response(response, success=False, value=self.LOGIN_FAILED_WARNING)
|
||||
self._assert_audit_log(mock_audit_log, 'warning', [u'Login failed', u'Unknown user email', email_hash])
|
||||
self._assert_audit_log(mock_audit_log, 'warning', ['Login failed', 'Unknown user email', email_hash])
|
||||
|
||||
def test_login_unicode_email(self):
|
||||
unicode_email = self.user_email + six.unichr(40960)
|
||||
unicode_email = self.user_email + chr(40960)
|
||||
# pylint: disable=too-many-function-args
|
||||
email_hash = hashlib.shake_128(unicode_email.encode('utf-8')).hexdigest(16)
|
||||
response, mock_audit_log = self._login_response(
|
||||
@@ -402,17 +400,17 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
self.password,
|
||||
)
|
||||
self._assert_response(response, success=False)
|
||||
self._assert_audit_log(mock_audit_log, 'warning', [u'Login failed', email_hash])
|
||||
self._assert_audit_log(mock_audit_log, 'warning', ['Login failed', email_hash])
|
||||
|
||||
def test_login_unicode_password(self):
|
||||
unicode_password = self.password + six.unichr(1972)
|
||||
unicode_password = self.password + chr(1972)
|
||||
response, mock_audit_log = self._login_response(
|
||||
self.user_email,
|
||||
unicode_password,
|
||||
)
|
||||
self._assert_response(response, success=False)
|
||||
self._assert_audit_log(mock_audit_log, 'warning',
|
||||
[u'Login failed', u'password for', str(self.user.id), u'invalid'])
|
||||
['Login failed', 'password for', str(self.user.id), 'invalid'])
|
||||
|
||||
def test_logout_logging(self):
|
||||
response, _ = self._login_response(self.user_email, self.password)
|
||||
@@ -421,7 +419,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
with patch('common.djangoapps.student.models.AUDIT_LOG') as mock_audit_log:
|
||||
response = self.client.post(logout_url)
|
||||
assert response.status_code == 200
|
||||
self._assert_audit_log(mock_audit_log, 'info', [u'Logout', u'test'])
|
||||
self._assert_audit_log(mock_audit_log, 'info', ['Logout', 'test'])
|
||||
|
||||
def test_login_user_info_cookie(self):
|
||||
response, _ = self._login_response(self.user_email, self.password)
|
||||
@@ -457,8 +455,8 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
assert '01 Jan 1970' in cookie.get('expires').replace('-', ' ')
|
||||
|
||||
@override_settings(
|
||||
EDXMKTG_LOGGED_IN_COOKIE_NAME=u"unicode-logged-in",
|
||||
EDXMKTG_USER_INFO_COOKIE_NAME=u"unicode-user-info",
|
||||
EDXMKTG_LOGGED_IN_COOKIE_NAME="unicode-logged-in",
|
||||
EDXMKTG_USER_INFO_COOKIE_NAME="unicode-user-info",
|
||||
)
|
||||
def test_unicode_mktg_cookie_names(self):
|
||||
# When logged in cookie names are loaded from JSON files, they may
|
||||
@@ -481,15 +479,15 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
with patch('common.djangoapps.student.models.AUDIT_LOG') as mock_audit_log:
|
||||
response = self.client.post(logout_url)
|
||||
assert response.status_code == 200
|
||||
self._assert_audit_log(mock_audit_log, 'info', [u'Logout'])
|
||||
self._assert_not_in_audit_log(mock_audit_log, 'info', [u'test'])
|
||||
self._assert_audit_log(mock_audit_log, 'info', ['Logout'])
|
||||
self._assert_not_in_audit_log(mock_audit_log, 'info', ['test'])
|
||||
|
||||
@override_settings(RATELIMIT_ENABLE=False)
|
||||
def test_excessive_login_attempts_success(self):
|
||||
# Try (and fail) logging in with fewer attempts than the limit of 30
|
||||
# and verify that you can still successfully log in afterwards.
|
||||
for i in range(20):
|
||||
password = u'test_password{0}'.format(i)
|
||||
password = f'test_password{i}'
|
||||
response, _audit_log = self._login_response(self.user_email, password)
|
||||
self._assert_response(response, success=False)
|
||||
# now try logging in with a valid password
|
||||
@@ -506,7 +504,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
# are not predictable and we don't want the test to be flaky.
|
||||
with freeze_time():
|
||||
for i in range(6):
|
||||
password = u'test_password{0}'.format(i)
|
||||
password = f'test_password{i}'
|
||||
# Provide unique IPs so we don't get ip rate limited.
|
||||
real_ip_mock.return_value = f'192.168.1.{i}'
|
||||
self._login_response(self.user_email, password)
|
||||
@@ -692,12 +690,12 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
|
||||
@ddt.data(
|
||||
('test_password', 'test_password', True),
|
||||
(unicodedata.normalize('NFKD', u'Ṗŕệṿïệẅ Ṯệẍt'),
|
||||
unicodedata.normalize('NFKC', u'Ṗŕệṿïệẅ Ṯệẍt'), False),
|
||||
(unicodedata.normalize('NFKC', u'Ṗŕệṿïệẅ Ṯệẍt'),
|
||||
unicodedata.normalize('NFKD', u'Ṗŕệṿïệẅ Ṯệẍt'), True),
|
||||
(unicodedata.normalize('NFKD', u'Ṗŕệṿïệẅ Ṯệẍt'),
|
||||
unicodedata.normalize('NFKD', u'Ṗŕệṿïệẅ Ṯệẍt'), False),
|
||||
(unicodedata.normalize('NFKD', 'Ṗŕệṿïệẅ Ṯệẍt'),
|
||||
unicodedata.normalize('NFKC', 'Ṗŕệṿïệẅ Ṯệẍt'), False),
|
||||
(unicodedata.normalize('NFKC', 'Ṗŕệṿïệẅ Ṯệẍt'),
|
||||
unicodedata.normalize('NFKD', 'Ṗŕệṿïệẅ Ṯệẍt'), True),
|
||||
(unicodedata.normalize('NFKD', 'Ṗŕệṿïệẅ Ṯệẍt'),
|
||||
unicodedata.normalize('NFKD', 'Ṗŕệṿïệẅ Ṯệẍt'), False),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_password_unicode_normalization_login(self, password, password_entered, login_success):
|
||||
@@ -741,7 +739,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
try:
|
||||
response_dict = json.loads(response.content.decode('utf-8'))
|
||||
except ValueError:
|
||||
self.fail(u"Could not parse response content as JSON: %s"
|
||||
self.fail("Could not parse response content as JSON: %s"
|
||||
% str(response.content))
|
||||
|
||||
if success is not None:
|
||||
@@ -751,8 +749,8 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
assert response_dict['error_code'] == error_code
|
||||
|
||||
if value is not None:
|
||||
msg = (u"'%s' did not contain '%s'" %
|
||||
(six.text_type(response_dict['value']), six.text_type(value)))
|
||||
msg = ("'%s' did not contain '%s'" %
|
||||
(str(response_dict['value']), str(value)))
|
||||
assert value in response_dict['value'], msg
|
||||
|
||||
def _assert_redirect_url(self, response, expected_redirect_url):
|
||||
@@ -877,7 +875,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
provider = 'Google'
|
||||
provider_tpa_hint = 'saml-test'
|
||||
username = 'batman'
|
||||
user_email = '{username}@{domain}'.format(username=username, domain=user_domain)
|
||||
user_email = f'{username}@{user_domain}'
|
||||
user = self._create_user(username, user_email)
|
||||
default_site_configuration_values = {
|
||||
'SITE_NAME': allowed_domain,
|
||||
@@ -898,7 +896,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
if success:
|
||||
value = None
|
||||
else:
|
||||
value = u'As {0} user, You must login with your {0} <a href=\'{1}\'>{2} account</a>.'.format(
|
||||
value = 'As {0} user, You must login with your {0} <a href=\'{1}\'>{2} account</a>.'.format(
|
||||
allowed_domain,
|
||||
'{}?tpa_hint={}'.format(reverse("dashboard"), provider_tpa_hint),
|
||||
provider,
|
||||
@@ -958,7 +956,7 @@ class LoginSessionViewTest(ApiTestCase):
|
||||
PASSWORD = "password"
|
||||
|
||||
def setUp(self):
|
||||
super(LoginSessionViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("user_api_login_session")
|
||||
|
||||
@ddt.data("get", "post")
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" Tests for Logistration views. """
|
||||
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from http.cookies import SimpleCookie
|
||||
from urllib.parse import urlencode
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
@@ -45,13 +44,13 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
""" Tests for Login and Registration. """
|
||||
USERNAME = "bob"
|
||||
EMAIL = "bob@example.com"
|
||||
PASSWORD = u"password"
|
||||
PASSWORD = "password"
|
||||
|
||||
URLCONF_MODULES = ['openedx.core.djangoapps.embargo']
|
||||
|
||||
@mock.patch.dict(settings.FEATURES, {'EMBARGO': True})
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super(LoginAndRegistrationTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# Several third party auth providers are created for these tests:
|
||||
self.google_provider = self.configure_google_provider(enabled=True, visible=True)
|
||||
@@ -125,7 +124,7 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
@ddt.unpack
|
||||
def test_login_and_registration_form(self, url_name, initial_mode):
|
||||
response = self.client.get(reverse(url_name))
|
||||
expected_data = u'"initial_mode": "{mode}"'.format(mode=initial_mode)
|
||||
expected_data = f'"initial_mode": "{initial_mode}"'
|
||||
self.assertContains(response, expected_data)
|
||||
|
||||
def test_login_and_registration_form_ratelimited(self):
|
||||
@@ -399,10 +398,10 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
response = login_and_registration_form(request)
|
||||
|
||||
expected_error_message = Text(_(
|
||||
u'We are sorry, you are not authorized to access {platform_name} via this channel. '
|
||||
u'Please contact your learning administrator or manager in order to access {platform_name}.'
|
||||
u'{line_break}{line_break}'
|
||||
u'Error Details:{line_break}{error_message}')
|
||||
'We are sorry, you are not authorized to access {platform_name} via this channel. '
|
||||
'Please contact your learning administrator or manager in order to access {platform_name}.'
|
||||
'{line_break}{line_break}'
|
||||
'Error Details:{line_break}{error_message}')
|
||||
).format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
error_message=dummy_error_message,
|
||||
@@ -421,12 +420,12 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
self.assertContains(response, '"third_party_auth_hint": "oa2-google-oauth2"')
|
||||
|
||||
tpa_hint = self.hidden_enabled_provider.provider_id
|
||||
params = [("next", "/courses/something/?tpa_hint={0}".format(tpa_hint))]
|
||||
params = [("next", f"/courses/something/?tpa_hint={tpa_hint}")]
|
||||
response = self.client.get(reverse('signin_user'), params, HTTP_ACCEPT="text/html")
|
||||
self.assertContains(response, u'"third_party_auth_hint": "{0}"'.format(tpa_hint))
|
||||
self.assertContains(response, f'"third_party_auth_hint": "{tpa_hint}"')
|
||||
|
||||
tpa_hint = self.hidden_disabled_provider.provider_id
|
||||
params = [("next", "/courses/something/?tpa_hint={0}".format(tpa_hint))]
|
||||
params = [("next", f"/courses/something/?tpa_hint={tpa_hint}")]
|
||||
response = self.client.get(reverse('signin_user'), params, HTTP_ACCEPT="text/html")
|
||||
assert response.content.decode('utf-8') not in tpa_hint
|
||||
|
||||
@@ -464,13 +463,13 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
|
||||
# THIRD_PARTY_AUTH_HINT can be overridden via the query string
|
||||
tpa_hint = self.hidden_enabled_provider.provider_id
|
||||
params = [("next", "/courses/something/?tpa_hint={0}".format(tpa_hint))]
|
||||
params = [("next", f"/courses/something/?tpa_hint={tpa_hint}")]
|
||||
response = self.client.get(reverse(url_name), params, HTTP_ACCEPT="text/html")
|
||||
self.assertContains(response, u'"third_party_auth_hint": "{0}"'.format(tpa_hint))
|
||||
self.assertContains(response, f'"third_party_auth_hint": "{tpa_hint}"')
|
||||
|
||||
# Even disabled providers in the query string will override THIRD_PARTY_AUTH_HINT
|
||||
tpa_hint = self.hidden_disabled_provider.provider_id
|
||||
params = [("next", "/courses/something/?tpa_hint={0}".format(tpa_hint))]
|
||||
params = [("next", f"/courses/something/?tpa_hint={tpa_hint}")]
|
||||
response = self.client.get(reverse(url_name), params, HTTP_ACCEPT="text/html")
|
||||
assert response.content.decode('utf-8') not in tpa_hint
|
||||
|
||||
@@ -525,7 +524,7 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
|
||||
response = self.client.get(reverse(url_name), params, HTTP_ACCEPT="text/html")
|
||||
|
||||
enterprise_sidebar_div_id = u'enterprise-content-container'
|
||||
enterprise_sidebar_div_id = 'enterprise-content-container'
|
||||
|
||||
if not ec_present:
|
||||
self.assertNotContains(response, text=enterprise_sidebar_div_id)
|
||||
@@ -541,7 +540,7 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
line_break=HTML('<br/>'),
|
||||
enterprise_name=ec_name,
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
privacy_policy_link_start=HTML(u"<a href='{pp_url}' rel='noopener' target='_blank'>").format(
|
||||
privacy_policy_link_start=HTML("<a href='{pp_url}' rel='noopener' target='_blank'>").format(
|
||||
pp_url=get_privacy_url()
|
||||
),
|
||||
privacy_policy_link_end=HTML("</a>"),
|
||||
@@ -607,7 +606,7 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
auth_info['providers'] = []
|
||||
auth_info = dump_js_escaped_json(auth_info)
|
||||
|
||||
expected_data = u'"third_party_auth": {auth_info}'.format(
|
||||
expected_data = '"third_party_auth": {auth_info}'.format(
|
||||
auth_info=auth_info
|
||||
)
|
||||
self.assertContains(response, expected_data)
|
||||
@@ -635,14 +634,14 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
}
|
||||
auth_info = dump_js_escaped_json(auth_info)
|
||||
|
||||
expected_data = u'"third_party_auth": {auth_info}'.format(
|
||||
expected_data = '"third_party_auth": {auth_info}'.format(
|
||||
auth_info=auth_info
|
||||
)
|
||||
self.assertContains(response, expected_data)
|
||||
|
||||
def _third_party_login_url(self, backend_name, auth_entry, login_params):
|
||||
"""Construct the login URL to start third party authentication. """
|
||||
return u"{url}?auth_entry={auth_entry}&{param_str}".format(
|
||||
return "{url}?auth_entry={auth_entry}&{param_str}".format(
|
||||
url=reverse("social:begin", kwargs={"backend": backend_name}),
|
||||
auth_entry=auth_entry,
|
||||
param_str=self._finish_auth_url_param(login_params),
|
||||
@@ -689,7 +688,7 @@ class AccountCreationTestCaseWithSiteOverrides(SiteMixin, TestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Set up the tests"""
|
||||
super(AccountCreationTestCaseWithSiteOverrides, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
# Set the feature flag ALLOW_PUBLIC_ACCOUNT_CREATION to False
|
||||
self.site_configuration_values = {
|
||||
@@ -704,4 +703,4 @@ class AccountCreationTestCaseWithSiteOverrides(SiteMixin, TestCase):
|
||||
ALLOW_PUBLIC_ACCOUNT_CREATION flag is turned off
|
||||
"""
|
||||
response = self.client.get(reverse('signin_user'))
|
||||
self.assertNotContains(response, u'<a class="btn-neutral" href="/register?next=%2Fdashboard">Register</a>')
|
||||
self.assertNotContains(response, '<a class="btn-neutral" href="/register?next=%2Fdashboard">Register</a>')
|
||||
|
||||
@@ -4,10 +4,9 @@ Tests for logout
|
||||
|
||||
|
||||
import unittest
|
||||
|
||||
import urllib
|
||||
from unittest import mock
|
||||
import ddt
|
||||
import mock
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
@@ -24,7 +23,7 @@ class LogoutTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
""" Create a course and user, then log in. """
|
||||
super(LogoutTests, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory()
|
||||
self.client.login(username=self.user.username, password='test')
|
||||
|
||||
@@ -75,7 +74,7 @@ class LogoutTests(TestCase):
|
||||
)
|
||||
response = self.client.get(url, HTTP_HOST=host)
|
||||
expected = {
|
||||
'target': six.moves.urllib.parse.unquote(redirect_url),
|
||||
'target': urllib.parse.unquote(redirect_url),
|
||||
}
|
||||
self.assertDictContainsSubset(expected, response.context_data)
|
||||
|
||||
@@ -180,7 +179,7 @@ class LogoutTests(TestCase):
|
||||
Test when learner logout from learner portal having active SSO session
|
||||
logout page should have link to logout url IdP.
|
||||
"""
|
||||
learner_portal_logout_url = '{}/logout'.format(settings.LEARNER_PORTAL_URL_ROOT)
|
||||
learner_portal_logout_url = f'{settings.LEARNER_PORTAL_URL_ROOT}/logout'
|
||||
idp_logout_url = 'http://mock-idp.com/logout'
|
||||
client = self._create_oauth_client()
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tests for user authorization password-related functionality.
|
||||
"""
|
||||
@@ -6,6 +5,7 @@ import json
|
||||
import logging
|
||||
import re
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
import ddt
|
||||
@@ -17,7 +17,6 @@ from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.urls import reverse
|
||||
from freezegun import freeze_time
|
||||
from mock import Mock, patch
|
||||
from oauth2_provider.models import AccessToken as dot_access_token
|
||||
from oauth2_provider.models import RefreshToken as dot_refresh_token
|
||||
from pytz import UTC
|
||||
@@ -38,9 +37,9 @@ class TestRequestPasswordChange(CreateAccountMixin, TestCase):
|
||||
"""
|
||||
Tests for users who request a password change.
|
||||
"""
|
||||
USERNAME = u'claire-underwood'
|
||||
PASSWORD = u'ṕáśśẃőŕd'
|
||||
EMAIL = u'claire+underwood@example.com'
|
||||
USERNAME = 'claire-underwood'
|
||||
PASSWORD = 'ṕáśśẃőŕd'
|
||||
EMAIL = 'claire+underwood@example.com'
|
||||
|
||||
IS_SECURE = False
|
||||
|
||||
@@ -97,19 +96,19 @@ class TestRequestPasswordChange(CreateAccountMixin, TestCase):
|
||||
class TestPasswordChange(CreateAccountMixin, CacheIsolationTestCase):
|
||||
""" Tests for views that change the user's password. """
|
||||
|
||||
USERNAME = u"heisenberg"
|
||||
ALTERNATE_USERNAME = u"walt"
|
||||
OLD_PASSWORD = u"ḅḷüëṡḳÿ"
|
||||
NEW_PASSWORD = u"B🄸🄶B🄻🅄🄴"
|
||||
OLD_EMAIL = u"walter@graymattertech.com"
|
||||
NEW_EMAIL = u"walt@savewalterwhite.com"
|
||||
USERNAME = "heisenberg"
|
||||
ALTERNATE_USERNAME = "walt"
|
||||
OLD_PASSWORD = "ḅḷüëṡḳÿ"
|
||||
NEW_PASSWORD = "B🄸🄶B🄻🅄🄴"
|
||||
OLD_EMAIL = "walter@graymattertech.com"
|
||||
NEW_EMAIL = "walt@savewalterwhite.com"
|
||||
|
||||
INVALID_KEY = u"123abc"
|
||||
INVALID_KEY = "123abc"
|
||||
|
||||
ENABLED_CACHES = ['default']
|
||||
|
||||
def setUp(self):
|
||||
super(TestPasswordChange, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.create_account(self.USERNAME, self.OLD_PASSWORD, self.OLD_EMAIL)
|
||||
result = self.client.login(username=self.USERNAME, password=self.OLD_PASSWORD)
|
||||
@@ -204,11 +203,11 @@ class TestPasswordChange(CreateAccountMixin, CacheIsolationTestCase):
|
||||
html_body = sent_message.alternatives[0][0]
|
||||
|
||||
for email_body in [text_body, html_body]:
|
||||
msg = u'However, there is currently no user account associated with your email address: {email}'.format(
|
||||
msg = 'However, there is currently no user account associated with your email address: {email}'.format(
|
||||
email=bad_email
|
||||
)
|
||||
|
||||
assert u'reset for your user account at {}'.format(settings.PLATFORM_NAME) in email_body
|
||||
assert f'reset for your user account at {settings.PLATFORM_NAME}' in email_body
|
||||
assert 'password_reset_confirm' not in email_body, 'The link should not be added if user was not found'
|
||||
assert msg in email_body
|
||||
|
||||
@@ -270,7 +269,7 @@ class TestPasswordChange(CreateAccountMixin, CacheIsolationTestCase):
|
||||
assert response.status_code == 200
|
||||
|
||||
expected_logs = (
|
||||
(LOGGER_NAME, 'INFO', 'Password reset initiated for email {}.'.format(self.NEW_EMAIL)),
|
||||
(LOGGER_NAME, 'INFO', f'Password reset initiated for email {self.NEW_EMAIL}.'),
|
||||
(LOGGER_NAME, 'INFO', 'Invalid password reset attempt')
|
||||
)
|
||||
logger.check(*expected_logs)
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests for account creation"""
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
from unittest import skipIf, skipUnless
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
import httpretty
|
||||
import mock
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.core import mail
|
||||
@@ -18,7 +16,6 @@ from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from pytz import UTC
|
||||
from six.moves import range
|
||||
from social_django.models import Partial, UserSocialAuth
|
||||
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
@@ -90,7 +87,7 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
GOALS = "Learn all the things!"
|
||||
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super(RegistrationViewValidationErrorTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("user_api_registration")
|
||||
|
||||
@mock.patch.dict(settings.FEATURES, {
|
||||
@@ -143,7 +140,7 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
{
|
||||
"email": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different email address."
|
||||
).format(
|
||||
self.EMAIL
|
||||
@@ -188,7 +185,7 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
{
|
||||
"username": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different username."
|
||||
).format(
|
||||
self.USERNAME
|
||||
@@ -226,7 +223,7 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
{
|
||||
"email": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different email address."
|
||||
).format(
|
||||
self.EMAIL
|
||||
@@ -264,7 +261,7 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
{
|
||||
"email": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different email address."
|
||||
).format(
|
||||
self.EMAIL
|
||||
@@ -301,7 +298,7 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
{
|
||||
"username": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different username."
|
||||
).format(
|
||||
self.USERNAME
|
||||
@@ -338,7 +335,7 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
{
|
||||
"username": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different username."
|
||||
).format(
|
||||
self.USERNAME
|
||||
@@ -346,7 +343,7 @@ class RegistrationViewValidationErrorTest(ThirdPartyAuthTestMixin, UserAPITestCa
|
||||
}],
|
||||
"email": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different email address."
|
||||
).format(
|
||||
self.EMAIL
|
||||
@@ -376,31 +373,31 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
GOALS = "Learn all the things!"
|
||||
PROFESSION_OPTIONS = [
|
||||
{
|
||||
"name": u'--',
|
||||
"value": u'',
|
||||
"name": '--',
|
||||
"value": '',
|
||||
"default": True
|
||||
|
||||
},
|
||||
{
|
||||
"value": u'software engineer',
|
||||
"name": u'Software Engineer',
|
||||
"value": 'software engineer',
|
||||
"name": 'Software Engineer',
|
||||
"default": False
|
||||
},
|
||||
{
|
||||
"value": u'teacher',
|
||||
"name": u'Teacher',
|
||||
"value": 'teacher',
|
||||
"name": 'Teacher',
|
||||
"default": False
|
||||
},
|
||||
{
|
||||
"value": u'other',
|
||||
"name": u'Other',
|
||||
"value": 'other',
|
||||
"name": 'Other',
|
||||
"default": False
|
||||
}
|
||||
]
|
||||
SPECIALTY_OPTIONS = [
|
||||
{
|
||||
"name": u'--',
|
||||
"value": u'',
|
||||
"name": '--',
|
||||
"value": '',
|
||||
"default": True
|
||||
|
||||
},
|
||||
@@ -410,20 +407,20 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
"default": False
|
||||
},
|
||||
{
|
||||
"value": u'early education',
|
||||
"name": u'Early Education',
|
||||
"value": 'early education',
|
||||
"name": 'Early Education',
|
||||
"default": False
|
||||
},
|
||||
{
|
||||
"value": u'n/a',
|
||||
"name": u'N/A',
|
||||
"value": 'n/a',
|
||||
"name": 'N/A',
|
||||
"default": False
|
||||
}
|
||||
]
|
||||
link_template = u"<a href='/honor' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
link_template = "<a href='/honor' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super(RegistrationViewTestV1, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("user_api_registration")
|
||||
|
||||
@ddt.data("get", "post")
|
||||
@@ -451,12 +448,12 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"name": u"email",
|
||||
u"type": u"email",
|
||||
u"required": True,
|
||||
u"label": u"Email",
|
||||
u"instructions": u"This is what you will use to login.",
|
||||
u"restrictions": {
|
||||
"name": "email",
|
||||
"type": "email",
|
||||
"required": True,
|
||||
"label": "Email",
|
||||
"instructions": "This is what you will use to login.",
|
||||
"restrictions": {
|
||||
"min_length": EMAIL_MIN_LENGTH,
|
||||
"max_length": EMAIL_MAX_LENGTH
|
||||
},
|
||||
@@ -466,12 +463,12 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"name": u"name",
|
||||
u"type": u"text",
|
||||
u"required": True,
|
||||
u"label": u"Full Name",
|
||||
u"instructions": u"This name will be used on any certificates that you earn.",
|
||||
u"restrictions": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"required": True,
|
||||
"label": "Full Name",
|
||||
"instructions": "This name will be used on any certificates that you earn.",
|
||||
"restrictions": {
|
||||
"max_length": 255
|
||||
},
|
||||
}
|
||||
@@ -480,13 +477,12 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"name": u"username",
|
||||
u"type": u"text",
|
||||
u"required": True,
|
||||
u"label": u"Public Username",
|
||||
u"instructions": u"The name that will identify you in your courses. "
|
||||
u"It cannot be changed later.",
|
||||
u"restrictions": {
|
||||
"name": "username",
|
||||
"type": "text",
|
||||
"required": True,
|
||||
"label": "Public Username",
|
||||
"instructions": "The name that will identify you in your courses. It cannot be changed later.",
|
||||
"restrictions": {
|
||||
"min_length": USERNAME_MIN_LENGTH,
|
||||
"max_length": USERNAME_MAX_LENGTH
|
||||
},
|
||||
@@ -496,13 +492,13 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"placeholder": "",
|
||||
u"name": u"password",
|
||||
u"type": u"password",
|
||||
u"required": True,
|
||||
u"label": u"Password",
|
||||
u"instructions": password_validators_instruction_texts(),
|
||||
u"restrictions": password_validators_restrictions(),
|
||||
"placeholder": "",
|
||||
"name": "password",
|
||||
"type": "password",
|
||||
"required": True,
|
||||
"label": "Password",
|
||||
"instructions": password_validators_instruction_texts(),
|
||||
"restrictions": password_validators_restrictions(),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -524,22 +520,22 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u'name': u'password',
|
||||
u'label': u'Password',
|
||||
u"instructions": password_validators_instruction_texts(),
|
||||
u"restrictions": password_validators_restrictions(),
|
||||
'name': 'password',
|
||||
'label': 'Password',
|
||||
"instructions": password_validators_instruction_texts(),
|
||||
"restrictions": password_validators_restrictions(),
|
||||
}
|
||||
)
|
||||
|
||||
msg = u'Your password must contain at least 2 characters, including ' \
|
||||
u'3 uppercase letters & 1 symbol.'
|
||||
msg = 'Your password must contain at least 2 characters, including ' \
|
||||
'3 uppercase letters & 1 symbol.'
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u'name': u'password',
|
||||
u'label': u'Password',
|
||||
u'instructions': msg,
|
||||
u"restrictions": password_validators_restrictions(),
|
||||
'name': 'password',
|
||||
'label': 'Password',
|
||||
'instructions': msg,
|
||||
"restrictions": password_validators_restrictions(),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -551,12 +547,12 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"name": u"email",
|
||||
u"type": u"email",
|
||||
u"required": True,
|
||||
u"label": u"Email",
|
||||
u"instructions": u"This is what you will use to login.",
|
||||
u"restrictions": {
|
||||
"name": "email",
|
||||
"type": "email",
|
||||
"required": True,
|
||||
"label": "Email",
|
||||
"instructions": "This is what you will use to login.",
|
||||
"restrictions": {
|
||||
"min_length": EMAIL_MIN_LENGTH,
|
||||
"max_length": EMAIL_MAX_LENGTH
|
||||
},
|
||||
@@ -566,15 +562,15 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"name": u"favorite_editor",
|
||||
u"type": u"select",
|
||||
u"required": False,
|
||||
u"label": u"Favorite Editor",
|
||||
u"placeholder": u"cat",
|
||||
u"defaultValue": u"vim",
|
||||
u"errorMessages": {
|
||||
u'required': u'This field is required.',
|
||||
u'invalid_choice': u'Select a valid choice. %(value)s is not one of the available choices.',
|
||||
"name": "favorite_editor",
|
||||
"type": "select",
|
||||
"required": False,
|
||||
"label": "Favorite Editor",
|
||||
"placeholder": "cat",
|
||||
"defaultValue": "vim",
|
||||
"errorMessages": {
|
||||
'required': 'This field is required.',
|
||||
'invalid_choice': 'Select a valid choice. %(value)s is not one of the available choices.',
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -582,17 +578,17 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"name": u"favorite_movie",
|
||||
u"type": u"text",
|
||||
u"required": True,
|
||||
u"label": u"Fav Flick",
|
||||
u"placeholder": None,
|
||||
u"defaultValue": None,
|
||||
u"errorMessages": {
|
||||
u'required': u'Please tell us your favorite movie.',
|
||||
u'invalid': u"We're pretty sure you made that movie up."
|
||||
"name": "favorite_movie",
|
||||
"type": "text",
|
||||
"required": True,
|
||||
"label": "Fav Flick",
|
||||
"placeholder": None,
|
||||
"defaultValue": None,
|
||||
"errorMessages": {
|
||||
'required': 'Please tell us your favorite movie.',
|
||||
'invalid': "We're pretty sure you made that movie up."
|
||||
},
|
||||
u"restrictions": {
|
||||
"restrictions": {
|
||||
"min_length": TestCaseForm.MOVIE_MIN_LEN,
|
||||
"max_length": TestCaseForm.MOVIE_MAX_LEN,
|
||||
}
|
||||
@@ -620,7 +616,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
] + [
|
||||
{
|
||||
"value": country_code,
|
||||
"name": six.text_type(country_name),
|
||||
"name": str(country_name),
|
||||
"default": country_code == expected_country_code
|
||||
}
|
||||
for country_code, country_name in SORTED_COUNTRIES
|
||||
@@ -642,13 +638,13 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"name": u"email",
|
||||
u"defaultValue": u"bob@example.com",
|
||||
u"type": u"email",
|
||||
u"required": True,
|
||||
u"label": u"Email",
|
||||
u"instructions": u"This is what you will use to login.",
|
||||
u"restrictions": {
|
||||
"name": "email",
|
||||
"defaultValue": "bob@example.com",
|
||||
"type": "email",
|
||||
"required": True,
|
||||
"label": "Email",
|
||||
"instructions": "This is what you will use to login.",
|
||||
"restrictions": {
|
||||
"min_length": EMAIL_MIN_LENGTH,
|
||||
"max_length": EMAIL_MAX_LENGTH
|
||||
},
|
||||
@@ -659,13 +655,13 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"name": u"name",
|
||||
u"defaultValue": u"Bob",
|
||||
u"type": u"text",
|
||||
u"required": True,
|
||||
u"label": u"Full Name",
|
||||
u"instructions": u"This name will be used on any certificates that you earn.",
|
||||
u"restrictions": {
|
||||
"name": "name",
|
||||
"defaultValue": "Bob",
|
||||
"type": "text",
|
||||
"required": True,
|
||||
"label": "Full Name",
|
||||
"instructions": "This name will be used on any certificates that you earn.",
|
||||
"restrictions": {
|
||||
"max_length": NAME_MAX_LENGTH,
|
||||
}
|
||||
}
|
||||
@@ -675,14 +671,13 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
no_extra_fields_setting,
|
||||
{
|
||||
u"name": u"username",
|
||||
u"defaultValue": expected_username,
|
||||
u"type": u"text",
|
||||
u"required": True,
|
||||
u"label": u"Public Username",
|
||||
u"instructions": u"The name that will identify you in your courses. "
|
||||
u"It cannot be changed later.",
|
||||
u"restrictions": {
|
||||
"name": "username",
|
||||
"defaultValue": expected_username,
|
||||
"type": "text",
|
||||
"required": True,
|
||||
"label": "Public Username",
|
||||
"instructions": "The name that will identify you in your courses. It cannot be changed later.",
|
||||
"restrictions": {
|
||||
"min_length": USERNAME_MIN_LENGTH,
|
||||
"max_length": USERNAME_MAX_LENGTH
|
||||
}
|
||||
@@ -691,17 +686,17 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
|
||||
# Country should be filled in.
|
||||
self._assert_reg_field(
|
||||
{u"country": u"required"},
|
||||
{"country": "required"},
|
||||
{
|
||||
u"label": u"Country or Region of Residence",
|
||||
u"name": u"country",
|
||||
u"defaultValue": expected_country_code,
|
||||
u"type": u"select",
|
||||
u"required": True,
|
||||
u"options": country_options,
|
||||
u"instructions": u"The country or region where you live.",
|
||||
u"errorMessages": {
|
||||
u"required": u"Select your country or region of residence."
|
||||
"label": "Country or Region of Residence",
|
||||
"name": "country",
|
||||
"defaultValue": expected_country_code,
|
||||
"type": "select",
|
||||
"required": True,
|
||||
"options": country_options,
|
||||
"instructions": "The country or region where you live.",
|
||||
"errorMessages": {
|
||||
"required": "Select your country or region of residence."
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -809,8 +804,8 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
}
|
||||
] + [
|
||||
{
|
||||
"value": six.text_type(year),
|
||||
"name": six.text_type(year),
|
||||
"value": str(year),
|
||||
"name": str(year),
|
||||
"default": False
|
||||
}
|
||||
for year in range(this_year, this_year - 120, -1)
|
||||
@@ -916,7 +911,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
"name": "goals",
|
||||
"type": "textarea",
|
||||
"required": False,
|
||||
"label": u"Tell us why you're interested in {platform_name}".format(
|
||||
"label": "Tell us why you're interested in {platform_name}".format(
|
||||
platform_name=settings.PLATFORM_NAME
|
||||
),
|
||||
"errorMessages": {
|
||||
@@ -961,7 +956,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
] + [
|
||||
{
|
||||
"value": country_code,
|
||||
"name": six.text_type(country_name),
|
||||
"name": str(country_name),
|
||||
"default": False
|
||||
}
|
||||
for country_code, country_name in SORTED_COUNTRIES
|
||||
@@ -991,17 +986,17 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
@mock.patch.dict(settings.FEATURES, {"ENABLE_MKTG_SITE": True})
|
||||
def test_registration_honor_code_mktg_site_enabled(self):
|
||||
link_template = "<a href='https://www.test.com/honor' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
link_template2 = u"<a href='#' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
link_template2 = "<a href='#' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
link_label = "Terms of Service and Honor Code"
|
||||
link_label2 = "Privacy Policy"
|
||||
self._assert_reg_field(
|
||||
{"honor_code": "required"},
|
||||
{
|
||||
"label": (u"By creating an account, you agree to the {spacing}"
|
||||
u"{link_label} {spacing}"
|
||||
u"and you acknowledge that {platform_name} and each Member process your "
|
||||
u"personal data in accordance {spacing}"
|
||||
u"with the {link_label2}.").format(
|
||||
"label": ("By creating an account, you agree to the {spacing}"
|
||||
"{link_label} {spacing}"
|
||||
"and you acknowledge that {platform_name} and each Member process your "
|
||||
"personal data in accordance {spacing}"
|
||||
"with the {link_label2}.").format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=link_template.format(link_label=link_label),
|
||||
link_label2=link_template2.format(link_label=link_label2),
|
||||
@@ -1012,7 +1007,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
"type": "plaintext",
|
||||
"required": True,
|
||||
"errorMessages": {
|
||||
"required": u"You must agree to the {platform_name} {link_label}".format(
|
||||
"required": "You must agree to the {platform_name} {link_label}".format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=link_label
|
||||
)
|
||||
@@ -1029,11 +1024,11 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
{"honor_code": "required"},
|
||||
{
|
||||
"label": (u"By creating an account, you agree to the {spacing}"
|
||||
u"{link_label} {spacing}"
|
||||
u"and you acknowledge that {platform_name} and each Member process your "
|
||||
u"personal data in accordance {spacing}"
|
||||
u"with the {link_label2}.").format(
|
||||
"label": ("By creating an account, you agree to the {spacing}"
|
||||
"{link_label} {spacing}"
|
||||
"and you acknowledge that {platform_name} and each Member process your "
|
||||
"personal data in accordance {spacing}"
|
||||
"with the {link_label2}.").format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=self.link_template.format(link_label=link_label),
|
||||
link_label2=link_template.format(link_label=link_label2),
|
||||
@@ -1044,7 +1039,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
"type": "plaintext",
|
||||
"required": True,
|
||||
"errorMessages": {
|
||||
"required": u"You must agree to the {platform_name} {link_label}".format(
|
||||
"required": "You must agree to the {platform_name} {link_label}".format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=link_label
|
||||
)
|
||||
@@ -1062,11 +1057,11 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
# Honor code field should say ONLY honor code,
|
||||
# not "terms of service and honor code"
|
||||
link_label = 'Honor Code'
|
||||
link_template = u"<a href='https://www.test.com/honor' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
link_template = "<a href='https://www.test.com/honor' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
self._assert_reg_field(
|
||||
{"honor_code": "required", "terms_of_service": "required"},
|
||||
{
|
||||
"label": u"I agree to the {platform_name} {link_label}".format(
|
||||
"label": "I agree to the {platform_name} {link_label}".format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=link_template.format(link_label=link_label)
|
||||
),
|
||||
@@ -1075,7 +1070,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
"type": "checkbox",
|
||||
"required": True,
|
||||
"errorMessages": {
|
||||
"required": u"You must agree to the {platform_name} {link_label}".format(
|
||||
"required": "You must agree to the {platform_name} {link_label}".format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=link_label
|
||||
)
|
||||
@@ -1085,11 +1080,11 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
|
||||
# Terms of service field should also be present
|
||||
link_label = "Terms of Service"
|
||||
link_template = u"<a href='https://www.test.com/tos' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
link_template = "<a href='https://www.test.com/tos' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
self._assert_reg_field(
|
||||
{"honor_code": "required", "terms_of_service": "required"},
|
||||
{
|
||||
"label": u"I agree to the {platform_name} {link_label}".format(
|
||||
"label": "I agree to the {platform_name} {link_label}".format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=link_template.format(link_label=link_label)
|
||||
),
|
||||
@@ -1098,7 +1093,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
"type": "checkbox",
|
||||
"required": True,
|
||||
"errorMessages": {
|
||||
"required": u"You must agree to the {platform_name} {link_label}".format(
|
||||
"required": "You must agree to the {platform_name} {link_label}".format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=link_label
|
||||
)
|
||||
@@ -1115,7 +1110,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self._assert_reg_field(
|
||||
{"honor_code": "required", "terms_of_service": "required"},
|
||||
{
|
||||
"label": u"I agree to the {platform_name} {link_label}".format(
|
||||
"label": "I agree to the {platform_name} {link_label}".format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=self.link_template.format(link_label=link_label)
|
||||
),
|
||||
@@ -1124,7 +1119,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
"type": "checkbox",
|
||||
"required": True,
|
||||
"errorMessages": {
|
||||
"required": u"You must agree to the {platform_name} Honor Code".format(
|
||||
"required": "You must agree to the {platform_name} Honor Code".format(
|
||||
platform_name=settings.PLATFORM_NAME
|
||||
)
|
||||
}
|
||||
@@ -1133,11 +1128,11 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
|
||||
link_label = 'Terms of Service'
|
||||
# Terms of service field should also be present
|
||||
link_template = u"<a href='/tos' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
link_template = "<a href='/tos' rel='noopener' target='_blank'>{link_label}</a>"
|
||||
self._assert_reg_field(
|
||||
{"honor_code": "required", "terms_of_service": "required"},
|
||||
{
|
||||
"label": u"I agree to the {platform_name} {link_label}".format(
|
||||
"label": "I agree to the {platform_name} {link_label}".format(
|
||||
platform_name=settings.PLATFORM_NAME,
|
||||
link_label=link_template.format(link_label=link_label)
|
||||
),
|
||||
@@ -1146,7 +1141,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
"type": "checkbox",
|
||||
"required": True,
|
||||
"errorMessages": {
|
||||
"required": u"You must agree to the {platform_name} Terms of Service".format(
|
||||
"required": "You must agree to the {platform_name} Terms of Service".format(
|
||||
platform_name=settings.PLATFORM_NAME
|
||||
)
|
||||
}
|
||||
@@ -1390,8 +1385,8 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
sent_email = mail.outbox[0]
|
||||
assert sent_email.to == [self.EMAIL]
|
||||
assert sent_email.subject ==\
|
||||
u'Action Required: Activate your {platform} account'.format(platform=settings.PLATFORM_NAME)
|
||||
assert u'high-quality {platform} courses'.format(platform=settings.PLATFORM_NAME) in sent_email.body
|
||||
f'Action Required: Activate your {settings.PLATFORM_NAME} account'
|
||||
assert f'high-quality {settings.PLATFORM_NAME} courses' in sent_email.body
|
||||
|
||||
@ddt.data(
|
||||
{"email": ""},
|
||||
@@ -1461,7 +1456,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
{
|
||||
"email": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different email address."
|
||||
).format(
|
||||
self.EMAIL
|
||||
@@ -1498,7 +1493,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
{
|
||||
"username": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different username."
|
||||
).format(
|
||||
self.USERNAME
|
||||
@@ -1535,7 +1530,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
{
|
||||
"username": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different username."
|
||||
).format(
|
||||
self.USERNAME
|
||||
@@ -1543,7 +1538,7 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
}],
|
||||
"email": [{
|
||||
"user_message": (
|
||||
u"It looks like {} belongs to an existing account. "
|
||||
"It looks like {} belongs to an existing account. "
|
||||
"Try again with a different email address."
|
||||
).format(
|
||||
self.EMAIL
|
||||
@@ -1577,8 +1572,8 @@ class RegistrationViewTestV1(ThirdPartyAuthTestMixin, UserAPITestCase):
|
||||
self.assertDictEqual(
|
||||
response_json,
|
||||
{
|
||||
"username": [{u"user_message": USERNAME_BAD_LENGTH_MSG}],
|
||||
"password": [{u"user_message": u"This field is required."}],
|
||||
"username": [{"user_message": USERNAME_BAD_LENGTH_MSG}],
|
||||
"password": [{"user_message": "This field is required."}],
|
||||
"error_code": "validation-error"
|
||||
}
|
||||
)
|
||||
@@ -1988,11 +1983,11 @@ class ThirdPartyRegistrationTestMixin(ThirdPartyOAuthTestMixin, CacheIsolationTe
|
||||
__test__ = False
|
||||
|
||||
def setUp(self):
|
||||
super(ThirdPartyRegistrationTestMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse('user_api_registration')
|
||||
|
||||
def tearDown(self):
|
||||
super(ThirdPartyRegistrationTestMixin, self).tearDown() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().tearDown()
|
||||
Partial.objects.all().delete()
|
||||
|
||||
def data(self, user=None):
|
||||
@@ -2114,7 +2109,7 @@ class ThirdPartyRegistrationTestMixin(ThirdPartyOAuthTestMixin, CacheIsolationTe
|
||||
response = self.client.post(self.url, data)
|
||||
self._assert_access_token_error(
|
||||
response,
|
||||
u"An access_token is required when passing value ({}) for provider.".format(self.BACKEND),
|
||||
f"An access_token is required when passing value ({self.BACKEND}) for provider.",
|
||||
"tpa-missing-access-token"
|
||||
)
|
||||
self._verify_user_existence(user_exists=False, social_link_exists=False)
|
||||
@@ -2136,7 +2131,7 @@ class ThirdPartyRegistrationTestMixin(ThirdPartyOAuthTestMixin, CacheIsolationTe
|
||||
response = self.client.post(self.url, data)
|
||||
self._assert_third_party_session_expired_error(
|
||||
response,
|
||||
u"Registration using {provider} has timed out.".format(provider="Google")
|
||||
"Registration using {provider} has timed out.".format(provider="Google")
|
||||
)
|
||||
self._verify_user_existence(user_exists=False, social_link_exists=False)
|
||||
|
||||
@@ -2177,7 +2172,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
|
||||
path = reverse(endpoint_name)
|
||||
|
||||
def setUp(self):
|
||||
super(RegistrationValidationViewTests, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
cache.clear()
|
||||
|
||||
def get_validation_decision(self, data):
|
||||
@@ -2293,7 +2288,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
|
||||
def test_confirm_email_doesnt_equal_email(self, confirm_email):
|
||||
self.assertValidationDecision(
|
||||
{'email': 'user@email.com', 'confirm_email': confirm_email},
|
||||
{'email': '', 'confirm_email': six.text_type(REQUIRED_FIELD_CONFIRM_EMAIL_MSG)}
|
||||
{'email': '', 'confirm_email': str(REQUIRED_FIELD_CONFIRM_EMAIL_MSG)}
|
||||
)
|
||||
|
||||
@ddt.data(
|
||||
@@ -2303,7 +2298,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
|
||||
def test_username_bad_length_validation_decision(self, username):
|
||||
self.assertValidationDecision(
|
||||
{'username': username},
|
||||
{'username': six.text_type(USERNAME_BAD_LENGTH_MSG)}
|
||||
{'username': str(USERNAME_BAD_LENGTH_MSG)}
|
||||
)
|
||||
|
||||
@skipUnless(settings.FEATURES.get("ENABLE_UNICODE_USERNAME"), "Unicode usernames disabled.")
|
||||
@@ -2311,7 +2306,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
|
||||
def test_username_invalid_unicode_validation_decision(self, username):
|
||||
self.assertValidationDecision(
|
||||
{'username': username},
|
||||
{'username': six.text_type(USERNAME_INVALID_CHARS_UNICODE)}
|
||||
{'username': str(USERNAME_INVALID_CHARS_UNICODE)}
|
||||
)
|
||||
|
||||
@skipIf(settings.FEATURES.get("ENABLE_UNICODE_USERNAME"), "Unicode usernames enabled.")
|
||||
@@ -2319,13 +2314,13 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
|
||||
def test_username_invalid_ascii_validation_decision(self, username):
|
||||
self.assertValidationDecision(
|
||||
{'username': username},
|
||||
{"username": six.text_type(USERNAME_INVALID_CHARS_ASCII)}
|
||||
{"username": str(USERNAME_INVALID_CHARS_ASCII)}
|
||||
)
|
||||
|
||||
def test_password_empty_validation_decision(self):
|
||||
# 2 is the default setting for minimum length found in lms/envs/common.py
|
||||
# under AUTH_PASSWORD_VALIDATORS.MinimumLengthValidator
|
||||
msg = u'This password is too short. It must contain at least 2 characters.'
|
||||
msg = 'This password is too short. It must contain at least 2 characters.'
|
||||
self.assertValidationDecision(
|
||||
{'password': ''},
|
||||
{"password": msg}
|
||||
@@ -2335,7 +2330,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
|
||||
password = 'p'
|
||||
# 2 is the default setting for minimum length found in lms/envs/common.py
|
||||
# under AUTH_PASSWORD_VALIDATORS.MinimumLengthValidator
|
||||
msg = u'This password is too short. It must contain at least 2 characters.'
|
||||
msg = 'This password is too short. It must contain at least 2 characters.'
|
||||
self.assertValidationDecision(
|
||||
{'password': password},
|
||||
{"password": msg}
|
||||
@@ -2345,7 +2340,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
|
||||
password = 'p' * DEFAULT_MAX_PASSWORD_LENGTH
|
||||
# 75 is the default setting for maximum length found in lms/envs/common.py
|
||||
# under AUTH_PASSWORD_VALIDATORS.MaximumLengthValidator
|
||||
msg = u'This password is too long. It must contain no more than 75 characters.'
|
||||
msg = 'This password is too long. It must contain no more than 75 characters.'
|
||||
self.assertValidationDecision(
|
||||
{'password': password},
|
||||
{"password": msg}
|
||||
@@ -2354,7 +2349,7 @@ class RegistrationValidationViewTests(test_utils.ApiTestCase):
|
||||
def test_password_equals_username_validation_decision(self):
|
||||
self.assertValidationDecision(
|
||||
{"username": "somephrase", "password": "somephrase"},
|
||||
{"username": "", "password": u"The password is too similar to the username."}
|
||||
{"username": "", "password": "The password is too similar to the username."}
|
||||
)
|
||||
|
||||
@override_settings(
|
||||
|
||||
@@ -7,6 +7,7 @@ import re
|
||||
import unicodedata
|
||||
import unittest
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import Mock, patch
|
||||
import ddt
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.hashers import UNUSABLE_PASSWORD_PREFIX, make_password
|
||||
@@ -23,7 +24,6 @@ from django.urls import reverse
|
||||
from django.utils.http import int_to_base36
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
from freezegun import freeze_time
|
||||
from mock import Mock, patch
|
||||
from oauth2_provider import models as dot_models
|
||||
from pytz import UTC
|
||||
|
||||
@@ -290,7 +290,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
|
||||
assert self.user.email in sent_message.to
|
||||
|
||||
self.assert_event_emitted(
|
||||
SETTING_CHANGE_INITIATED, user_id=self.user.id, setting=u'password', old=None, new=None,
|
||||
SETTING_CHANGE_INITIATED, user_id=self.user.id, setting='password', old=None, new=None,
|
||||
)
|
||||
|
||||
# Test that the user is not active
|
||||
@@ -321,7 +321,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
|
||||
assert expected_msg in msg
|
||||
|
||||
self.assert_event_emitted(
|
||||
SETTING_CHANGE_INITIATED, user_id=self.user.id, setting=u'password', old=None, new=None
|
||||
SETTING_CHANGE_INITIATED, user_id=self.user.id, setting='password', old=None, new=None
|
||||
)
|
||||
|
||||
@override_settings(FEATURES=ENABLE_AUTHN_MICROFRONTEND)
|
||||
@@ -345,17 +345,17 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
|
||||
sent_message = mail.outbox[0]
|
||||
msg = sent_message.body
|
||||
|
||||
reset_msg = u"you requested a password reset for your user account at {}"
|
||||
reset_msg = "you requested a password reset for your user account at {}"
|
||||
reset_msg = reset_msg.format(site_name)
|
||||
|
||||
assert reset_msg in msg
|
||||
assert settings.AUTHN_MICROFRONTEND_URL in msg
|
||||
|
||||
sign_off = u"The {} Team".format(platform_name)
|
||||
sign_off = f"The {platform_name} Team"
|
||||
assert sign_off in msg
|
||||
|
||||
self.assert_event_emitted(
|
||||
SETTING_CHANGE_INITIATED, user_id=self.user.id, setting=u'password', old=None, new=None
|
||||
SETTING_CHANGE_INITIATED, user_id=self.user.id, setting='password', old=None, new=None
|
||||
)
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', "Test only valid in LMS")
|
||||
@@ -384,14 +384,14 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
|
||||
|
||||
body = bodies[body_type]
|
||||
|
||||
reset_msg = u"you requested a password reset for your user account at {}".format(
|
||||
reset_msg = "you requested a password reset for your user account at {}".format(
|
||||
fake_get_value('PLATFORM_NAME')
|
||||
)
|
||||
|
||||
assert reset_msg in body
|
||||
|
||||
self.assert_event_emitted(
|
||||
SETTING_CHANGE_INITIATED, user_id=self.user.id, setting=u'password', old=None, new=None
|
||||
SETTING_CHANGE_INITIATED, user_id=self.user.id, setting='password', old=None, new=None
|
||||
)
|
||||
assert sent_message.from_email == 'no-reply@fakeuniversity.com'
|
||||
|
||||
@@ -516,7 +516,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
|
||||
method of NFKC.
|
||||
In this test, the input password is u'p\u212bssword'. It should be normalized to u'p\xc5ssword'
|
||||
"""
|
||||
password = u'p\u212bssword'
|
||||
password = 'p\u212bssword'
|
||||
request_params = {'new_password1': password, 'new_password2': password}
|
||||
confirm_request = self.request_factory.post(self.password_reset_confirm_url, data=request_params)
|
||||
process_request(confirm_request)
|
||||
@@ -527,7 +527,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
|
||||
|
||||
user = User.objects.get(pk=self.user.pk)
|
||||
salt_val = user.password.split('$')[1]
|
||||
expected_user_password = make_password(unicodedata.normalize('NFKC', u'p\u212bssword'), salt_val)
|
||||
expected_user_password = make_password(unicodedata.normalize('NFKC', 'p\u212bssword'), salt_val)
|
||||
assert expected_user_password == user.password
|
||||
|
||||
self.assert_email_sent_successfully({
|
||||
@@ -618,7 +618,7 @@ class PasswordResetViewTest(UserAPITestCase):
|
||||
"""Tests of the user API's password reset endpoint. """
|
||||
|
||||
def setUp(self):
|
||||
super(PasswordResetViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.url = reverse("user_api_password_reset")
|
||||
|
||||
@ddt.data("get", "post")
|
||||
@@ -652,7 +652,7 @@ class PasswordResetViewTest(UserAPITestCase):
|
||||
assert form_desc['fields'] ==\
|
||||
[{'name': 'email', 'defaultValue': '', 'type': 'email', 'required': True,
|
||||
'label': 'Email', 'placeholder': 'username@domain.com',
|
||||
'instructions': u'The email address you used to register with {platform_name}'
|
||||
'instructions': 'The email address you used to register with {platform_name}'
|
||||
.format(platform_name=settings.PLATFORM_NAME),
|
||||
'restrictions': {'min_length': EMAIL_MIN_LENGTH,
|
||||
'max_length': EMAIL_MAX_LENGTH},
|
||||
@@ -666,7 +666,7 @@ class PasswordResetTokenValidateViewTest(UserAPITestCase):
|
||||
"""Tests of the user API's password reset endpoint. """
|
||||
|
||||
def setUp(self):
|
||||
super(PasswordResetTokenValidateViewTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory.create()
|
||||
self.user.is_active = False
|
||||
self.user.save()
|
||||
@@ -822,7 +822,7 @@ class ResetPasswordAPITests(EventTestMixin, CacheIsolationTestCase):
|
||||
self.assert_event_emitted(
|
||||
SETTING_CHANGE_INITIATED,
|
||||
user_id=self.user.id,
|
||||
setting=u'email',
|
||||
setting='email',
|
||||
old=self.user.email,
|
||||
new=updated_user.email
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"""
|
||||
User Auth Views Utils
|
||||
"""
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.utils.translation import ugettext as _
|
||||
@@ -12,7 +11,7 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_
|
||||
|
||||
|
||||
UUID4_REGEX = '[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}'
|
||||
ENTERPRISE_ENROLLMENT_URL_REGEX = r'/enterprise/{}/course/{}/enroll'.format(UUID4_REGEX, settings.COURSE_KEY_REGEX)
|
||||
ENTERPRISE_ENROLLMENT_URL_REGEX = fr'/enterprise/{UUID4_REGEX}/course/{settings.COURSE_KEY_REGEX}/enroll'
|
||||
|
||||
|
||||
def third_party_auth_context(request, redirect_to, tpa_hint=None):
|
||||
@@ -84,7 +83,7 @@ def third_party_auth_context(request, redirect_to, tpa_hint=None):
|
||||
for msg in messages.get_messages(request):
|
||||
if msg.extra_tags.split()[0] == "social-auth":
|
||||
# msg may or may not be translated. Try translating [again] in case we are able to:
|
||||
context["errorMessage"] = _(six.text_type(msg)) # pylint: disable=E7610
|
||||
context["errorMessage"] = _(str(msg)) # pylint: disable=E7610
|
||||
break
|
||||
|
||||
return context
|
||||
|
||||
Reference in New Issue
Block a user