refactor: Ran pyupgrade on openedx/core/djangoapps/user_authn

This commit is contained in:
Usama Sadiq
2021-03-11 18:32:27 +05:00
parent bc1e9afe4b
commit d540688f8e
25 changed files with 399 additions and 420 deletions

View File

@@ -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)

View File

@@ -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',
},
},
}

View File

@@ -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

View File

@@ -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."
)

View File

@@ -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

View File

@@ -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

View File

@@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from django.conf import settings
from django.db import migrations

View File

@@ -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):

View File

@@ -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):

View File

@@ -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']

View File

@@ -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

View File

@@ -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
)
)

View File

@@ -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

View File

@@ -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 = []

View File

@@ -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)

View File

@@ -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:

View File

@@ -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
)

View File

@@ -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()

View File

@@ -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")

View File

@@ -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>')

View File

@@ -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()

View File

@@ -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)

View File

@@ -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(

View File

@@ -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
)

View File

@@ -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