From 7dc0598b2527d338ca74358048f40f52bd265c14 Mon Sep 17 00:00:00 2001 From: cahrens Date: Thu, 26 Feb 2015 15:18:50 -0500 Subject: [PATCH 1/2] Delete ENABLE_NEW_DASHBOARD code. --- .../djangoapps/third_party_auth/pipeline.py | 8 - .../djangoapps/third_party_auth/settings.py | 7 - .../student_account/test/test_views.py | 173 ------------------ lms/djangoapps/student_account/urls.py | 8 - lms/djangoapps/student_account/views.py | 164 ----------------- lms/envs/common.py | 3 - .../student_account/email_change_failed.html | 30 --- .../email_change_successful.html | 18 -- .../message_body.txt | 21 --- .../subject_line.txt | 3 - .../email_change_request/message_body.txt | 34 ---- .../email_change_request/subject_line.txt | 3 - lms/templates/student_account/index.html | 26 --- 13 files changed, 498 deletions(-) delete mode 100644 lms/templates/student_account/email_change_failed.html delete mode 100644 lms/templates/student_account/email_change_successful.html delete mode 100644 lms/templates/student_account/emails/email_change_confirmation/message_body.txt delete mode 100644 lms/templates/student_account/emails/email_change_confirmation/subject_line.txt delete mode 100644 lms/templates/student_account/emails/email_change_request/message_body.txt delete mode 100644 lms/templates/student_account/emails/email_change_request/subject_line.txt delete mode 100644 lms/templates/student_account/index.html diff --git a/common/djangoapps/third_party_auth/pipeline.py b/common/djangoapps/third_party_auth/pipeline.py index b6561c9259..6701ee372f 100644 --- a/common/djangoapps/third_party_auth/pipeline.py +++ b/common/djangoapps/third_party_auth/pipeline.py @@ -112,7 +112,6 @@ AUTH_EMAIL_OPT_IN_KEY = 'email_opt_in' AUTH_ENTRY_DASHBOARD = 'dashboard' AUTH_ENTRY_LOGIN = 'login' -AUTH_ENTRY_PROFILE = 'profile' AUTH_ENTRY_REGISTER = 'register' # This is left-over from an A/B test @@ -143,16 +142,11 @@ AUTH_DISPATCH_URLS = { AUTH_ENTRY_LOGIN_2: '/account/login/', AUTH_ENTRY_REGISTER_2: '/account/register/', - # If linking/unlinking an account from the new student profile - # page, redirect to the profile page. Only used if - # `FEATURES['ENABLE_NEW_DASHBOARD']` is true. - AUTH_ENTRY_PROFILE: '/profile/', } _AUTH_ENTRY_CHOICES = frozenset([ AUTH_ENTRY_DASHBOARD, AUTH_ENTRY_LOGIN, - AUTH_ENTRY_PROFILE, AUTH_ENTRY_REGISTER, # This is left-over from an A/B test @@ -452,8 +446,6 @@ def parse_query_params(strategy, response, *args, **kwargs): 'is_login': auth_entry in [AUTH_ENTRY_LOGIN, AUTH_ENTRY_LOGIN_2], # Whether the auth pipeline entered from /register. 'is_register': auth_entry in [AUTH_ENTRY_REGISTER, AUTH_ENTRY_REGISTER_2], - # Whether the auth pipeline entered from /profile. - 'is_profile': auth_entry == AUTH_ENTRY_PROFILE, # Whether the auth pipeline entered from an API 'is_api': auth_entry == AUTH_ENTRY_API, } diff --git a/common/djangoapps/third_party_auth/settings.py b/common/djangoapps/third_party_auth/settings.py index 7244f05bfe..9bba287743 100644 --- a/common/djangoapps/third_party_auth/settings.py +++ b/common/djangoapps/third_party_auth/settings.py @@ -51,8 +51,6 @@ _MIDDLEWARE_CLASSES = ( 'third_party_auth.middleware.ExceptionMiddleware', ) _SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/dashboard' -_SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = '/profile' -_SOCIAL_AUTH_DISCONNECT_REDIRECT_URL = '/profile' def _merge_auth_info(django_settings, auth_info): @@ -97,11 +95,6 @@ def _set_global_settings(django_settings): # Where to send the user once social authentication is successful. django_settings.SOCIAL_AUTH_LOGIN_REDIRECT_URL = _SOCIAL_AUTH_LOGIN_REDIRECT_URL - # Change redirects to the profile page if we enable the new dashboard. - if django_settings.FEATURES.get('ENABLE_NEW_DASHBOARD', ''): - django_settings.SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = _SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL - django_settings.SOCIAL_AUTH_DISCONNECT_REDIRECT_URL = _SOCIAL_AUTH_DISCONNECT_REDIRECT_URL - # Inject our customized auth pipeline. All auth backends must work with # this pipeline. django_settings.SOCIAL_AUTH_PIPELINE = ( diff --git a/lms/djangoapps/student_account/test/test_views.py b/lms/djangoapps/student_account/test/test_views.py index c9a708a6c7..75a2354b0a 100644 --- a/lms/djangoapps/student_account/test/test_views.py +++ b/lms/djangoapps/student_account/test/test_views.py @@ -59,7 +59,6 @@ class StudentAccountUpdateTest(UrlResetMixin, TestCase): INVALID_KEY = u"123abc" - @mock.patch.dict(settings.FEATURES, {'ENABLE_NEW_DASHBOARD': True}) def setUp(self): super(StudentAccountUpdateTest, self).setUp("student_account.urls") @@ -71,141 +70,6 @@ class StudentAccountUpdateTest(UrlResetMixin, TestCase): result = self.client.login(username=self.USERNAME, password=self.OLD_PASSWORD) self.assertTrue(result) - def test_index(self): - response = self.client.get(reverse('account_index')) - self.assertContains(response, "Student Account") - - def test_change_email(self): - response = self._change_email(self.NEW_EMAIL, self.OLD_PASSWORD) - self.assertEquals(response.status_code, 200) - - # Verify that the email associated with the account remains unchanged - profile_info = profile_api.profile_info(self.USERNAME) - self.assertEquals(profile_info['email'], self.OLD_EMAIL) - - # Check that an email was sent with the activation key - self.assertEqual(len(mail.outbox), 1) - self._assert_email( - mail.outbox[0], - [self.NEW_EMAIL], - u"Email Change Request", - u"There was recently a request to change the email address" - ) - - # Retrieve the activation key from the email - email_body = mail.outbox[0].body - result = re.search('/email/confirmation/([^ \n]+)', email_body) - self.assertIsNot(result, None) - activation_key = result.group(1) - - # Attempt to activate the email - response = self.client.get(reverse('email_change_confirm', kwargs={'key': activation_key})) - self.assertEqual(response.status_code, 200) - - # Verify that the email was changed - profile_info = profile_api.profile_info(self.USERNAME) - self.assertEquals(profile_info['email'], self.NEW_EMAIL) - - # Verify that notification emails were sent - self.assertEqual(len(mail.outbox), 2) - self._assert_email( - mail.outbox[1], - [self.OLD_EMAIL, self.NEW_EMAIL], - u"Email Change Successful", - u"You successfully changed the email address" - ) - - def test_email_change_wrong_password(self): - response = self._change_email(self.NEW_EMAIL, "wrong password") - self.assertEqual(response.status_code, 401) - - def test_email_change_request_no_user(self): - # Patch account API to raise an internal error when an email change is requested - with mock.patch('student_account.views.account_api.request_email_change') as mock_call: - mock_call.side_effect = account_api.AccountUserNotFound - response = self._change_email(self.NEW_EMAIL, self.OLD_PASSWORD) - - self.assertEquals(response.status_code, 400) - - def test_email_change_request_email_taken_by_active_account(self): - # Create/activate a second user with the new email - activation_key = account_api.create_account(self.ALTERNATE_USERNAME, self.OLD_PASSWORD, self.NEW_EMAIL) - account_api.activate_account(activation_key) - - # Request to change the original user's email to the email now used by the second user - response = self._change_email(self.NEW_EMAIL, self.OLD_PASSWORD) - self.assertEquals(response.status_code, 409) - - def test_email_change_request_email_taken_by_inactive_account(self): - # Create a second user with the new email, but don't active them - account_api.create_account(self.ALTERNATE_USERNAME, self.OLD_PASSWORD, self.NEW_EMAIL) - - # Request to change the original user's email to the email used by the inactive user - response = self._change_email(self.NEW_EMAIL, self.OLD_PASSWORD) - self.assertEquals(response.status_code, 200) - - @ddt.data(*INVALID_EMAILS) - def test_email_change_request_email_invalid(self, invalid_email): - # Request to change the user's email to an invalid address - response = self._change_email(invalid_email, self.OLD_PASSWORD) - self.assertEquals(response.status_code, 400) - - def test_email_change_confirmation(self): - # Get an email change activation key - activation_key = account_api.request_email_change(self.USERNAME, self.NEW_EMAIL, self.OLD_PASSWORD) - - # Follow the link sent in the confirmation email - response = self.client.get(reverse('email_change_confirm', kwargs={'key': activation_key})) - self.assertContains(response, "Email change successful") - - # Verify that the email associated with the account has changed - profile_info = profile_api.profile_info(self.USERNAME) - self.assertEquals(profile_info['email'], self.NEW_EMAIL) - - def test_email_change_confirmation_invalid_key(self): - # Visit the confirmation page with an invalid key - response = self.client.get(reverse('email_change_confirm', kwargs={'key': self.INVALID_KEY})) - self.assertContains(response, "Something went wrong") - - # Verify that the email associated with the account has not changed - profile_info = profile_api.profile_info(self.USERNAME) - self.assertEquals(profile_info['email'], self.OLD_EMAIL) - - def test_email_change_confirmation_email_already_exists(self): - # Get an email change activation key - email_activation_key = account_api.request_email_change(self.USERNAME, self.NEW_EMAIL, self.OLD_PASSWORD) - - # Create/activate a second user with the new email - account_activation_key = account_api.create_account(self.ALTERNATE_USERNAME, self.OLD_PASSWORD, self.NEW_EMAIL) - account_api.activate_account(account_activation_key) - - # Follow the link sent to the original user - response = self.client.get(reverse('email_change_confirm', kwargs={'key': email_activation_key})) - self.assertContains(response, "address you wanted to use is already used") - - # Verify that the email associated with the original account has not changed - profile_info = profile_api.profile_info(self.USERNAME) - self.assertEquals(profile_info['email'], self.OLD_EMAIL) - - def test_email_change_confirmation_internal_error(self): - # Get an email change activation key - activation_key = account_api.request_email_change(self.USERNAME, self.NEW_EMAIL, self.OLD_PASSWORD) - - # Patch account API to return an internal error - with mock.patch('student_account.views.account_api.confirm_email_change') as mock_call: - mock_call.side_effect = account_api.AccountInternalError - response = self.client.get(reverse('email_change_confirm', kwargs={'key': activation_key})) - - self.assertContains(response, "Something went wrong") - - def test_email_change_request_missing_email_param(self): - response = self._change_email(None, self.OLD_PASSWORD) - self.assertEqual(response.status_code, 400) - - def test_email_change_request_missing_password_param(self): - response = self._change_email(self.OLD_EMAIL, None) - self.assertEqual(response.status_code, 400) - @skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') def test_password_change(self): # Request a password change while logged in, simulating @@ -316,25 +180,6 @@ class StudentAccountUpdateTest(UrlResetMixin, TestCase): self.assertEqual(response.status_code, 403) @ddt.data( - ('get', 'account_index', []), - ('post', 'email_change_request', []), - ('get', 'email_change_confirm', [123]) - ) - @ddt.unpack - def test_require_login(self, method, url_name, args): - # Access the page while logged out - self.client.logout() - url = reverse(url_name, args=args) - response = getattr(self.client, method)(url, follow=True) - - # Should have been redirected to the login page - self.assertEqual(len(response.redirect_chain), 1) - self.assertIn('accounts/login?next=', response.redirect_chain[0][0]) - - @ddt.data( - ('get', 'account_index', []), - ('post', 'email_change_request', []), - ('get', 'email_change_confirm', [123]), ('post', 'password_change_request', []), ) @ddt.unpack @@ -346,24 +191,6 @@ class StudentAccountUpdateTest(UrlResetMixin, TestCase): response = getattr(self.client, method)(url) self.assertEqual(response.status_code, 405) - def _assert_email(self, email, expected_to, expected_subject, expected_body): - """Check whether an email has the correct properties. """ - self.assertEqual(email.to, expected_to) - self.assertIn(expected_subject, email.subject) - self.assertIn(expected_body, email.body) - - def _change_email(self, new_email, password): - """Request to change the user's email. """ - data = {} - - if new_email is not None: - data['email'] = new_email - if password is not None: - # We can't pass a Unicode object to urlencode, so we encode the Unicode object - data['password'] = password.encode('utf-8') - - return self.client.post(path=reverse('email_change_request'), data=data) - def _change_password(self, email=None): """Request to change the user's password. """ data = {} diff --git a/lms/djangoapps/student_account/urls.py b/lms/djangoapps/student_account/urls.py index 945edbd9cd..4f5eba7c04 100644 --- a/lms/djangoapps/student_account/urls.py +++ b/lms/djangoapps/student_account/urls.py @@ -11,11 +11,3 @@ if settings.FEATURES.get('ENABLE_COMBINED_LOGIN_REGISTRATION'): url(r'^register/$', 'login_and_registration_form', {'initial_mode': 'register'}, name='account_register'), url(r'^password$', 'password_change_request_handler', name='password_change_request'), ) - -if settings.FEATURES.get('ENABLE_NEW_DASHBOARD'): - urlpatterns += patterns( - 'student_account.views', - url(r'^$', 'index', name='account_index'), - url(r'^email$', 'email_change_request_handler', name='email_change_request'), - url(r'^email/confirmation/(?P[^/]*)$', 'email_change_confirmation_handler', name='email_change_confirm'), - ) diff --git a/lms/djangoapps/student_account/views.py b/lms/djangoapps/student_account/views.py index 36d5aa7209..042f893422 100644 --- a/lms/djangoapps/student_account/views.py +++ b/lms/djangoapps/student_account/views.py @@ -42,31 +42,6 @@ from student_account.helpers import auth_pipeline_urls AUDIT_LOG = logging.getLogger("audit") -@login_required -@require_http_methods(['GET']) -def index(request): - """Render the account info page. - - Args: - request (HttpRequest) - - Returns: - HttpResponse: 200 if the index page was sent successfully - HttpResponse: 302 if not logged in (redirect to login page) - HttpResponse: 405 if using an unsupported HTTP method - - Example usage: - - GET /account - - """ - return render_to_response( - 'student_account/index.html', { - 'disable_courseware_js': True, - } - ) - - @require_http_methods(['GET']) @ensure_csrf_cookie def login_and_registration_form(request, initial_mode="login"): @@ -124,145 +99,6 @@ def login_and_registration_form(request, initial_mode="login"): return render_to_response('student_account/login_and_register.html', context) -@login_required -@require_http_methods(['POST']) -@ensure_csrf_cookie -def email_change_request_handler(request): - """Handle a request to change the user's email address. - - Sends an email to the newly specified address containing a link - to a confirmation page. - - Args: - request (HttpRequest) - - Returns: - HttpResponse: 200 if the confirmation email was sent successfully - HttpResponse: 302 if not logged in (redirect to login page) - HttpResponse: 400 if the format of the new email is incorrect, or if - an email change is requested for a user which does not exist - HttpResponse: 401 if the provided password (in the form) is incorrect - HttpResponse: 405 if using an unsupported HTTP method - HttpResponse: 409 if the provided email is already in use - - Example usage: - - POST /account/email - - """ - username = request.user.username - password = request.POST.get('password') - new_email = request.POST.get('email') - - if new_email is None: - return HttpResponseBadRequest("Missing param 'email'") - if password is None: - return HttpResponseBadRequest("Missing param 'password'") - - old_email = profile_api.profile_info(username)['email'] - - try: - key = account_api.request_email_change(username, new_email, password) - except (account_api.AccountEmailInvalid, account_api.AccountUserNotFound): - return HttpResponseBadRequest() - except account_api.AccountEmailAlreadyExists: - return HttpResponse(status=409) - except account_api.AccountNotAuthorized: - return HttpResponse(status=401) - - context = { - 'key': key, - 'old_email': old_email, - 'new_email': new_email, - } - - subject = render_to_string('student_account/emails/email_change_request/subject_line.txt', context) - subject = ''.join(subject.splitlines()) - message = render_to_string('student_account/emails/email_change_request/message_body.txt', context) - - from_address = microsite.get_value( - 'email_from_address', - settings.DEFAULT_FROM_EMAIL - ) - - # Send a confirmation email to the new address containing the activation key - send_mail(subject, message, from_address, [new_email]) - - return HttpResponse(status=200) - - -@login_required -@require_http_methods(['GET']) -def email_change_confirmation_handler(request, key): - """Complete a change of the user's email address. - - This is called when the activation link included in the confirmation - email is clicked. - - Args: - request (HttpRequest) - - Returns: - HttpResponse: 200 if the email change is successful, the activation key - is invalid, the new email is already in use, or the - user to which the email change will be applied does - not exist - HttpResponse: 302 if not logged in (redirect to login page) - HttpResponse: 405 if using an unsupported HTTP method - - Example usage: - - GET /account/email/confirmation/{key} - - """ - try: - old_email, new_email = account_api.confirm_email_change(key) - except account_api.AccountNotAuthorized: - return render_to_response( - 'student_account/email_change_failed.html', { - 'disable_courseware_js': True, - 'error': 'key_invalid', - } - ) - except account_api.AccountEmailAlreadyExists: - return render_to_response( - 'student_account/email_change_failed.html', { - 'disable_courseware_js': True, - 'error': 'email_used', - } - ) - except account_api.AccountInternalError: - return render_to_response( - 'student_account/email_change_failed.html', { - 'disable_courseware_js': True, - 'error': 'internal', - } - ) - - context = { - 'old_email': old_email, - 'new_email': new_email, - } - - subject = render_to_string('student_account/emails/email_change_confirmation/subject_line.txt', context) - subject = ''.join(subject.splitlines()) - message = render_to_string('student_account/emails/email_change_confirmation/message_body.txt', context) - - from_address = microsite.get_value( - 'email_from_address', - settings.DEFAULT_FROM_EMAIL - ) - - # Notify both old and new emails of the change - send_mail(subject, message, from_address, [old_email, new_email]) - - return render_to_response( - 'student_account/email_change_successful.html', { - 'disable_courseware_js': True, - } - ) - - @require_http_methods(['POST']) def password_change_request_handler(request): """Handle password change requests originating from the account page. diff --git a/lms/envs/common.py b/lms/envs/common.py index d35f902666..fdf7b6aaef 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -313,9 +313,6 @@ FEATURES = { # ENABLE_OAUTH2_PROVIDER to True 'ENABLE_MOBILE_REST_API': False, - # Enable the new dashboard, account, and profile pages - 'ENABLE_NEW_DASHBOARD': False, - # Enable the combined login/registration form 'ENABLE_COMBINED_LOGIN_REGISTRATION': False, diff --git a/lms/templates/student_account/email_change_failed.html b/lms/templates/student_account/email_change_failed.html deleted file mode 100644 index 5b24f9c262..0000000000 --- a/lms/templates/student_account/email_change_failed.html +++ /dev/null @@ -1,30 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> -<%! from django.core.urlresolvers import reverse %> -<%inherit file="../main.html" /> - -
-
-

${_("Email change failed.")}

-
- -

- % if error is 'key_invalid' or error is 'internal': - ${_("Something went wrong. Please contact {support} for help.").format( - support="{support_email}".format( - support_email=settings.TECH_SUPPORT_EMAIL - ) - )} - % elif error is 'email_used': - ${_("The email address you wanted to use is already used by another " - "{platform_name} account.").format(platform_name=settings.PLATFORM_NAME)} - % endif -

- -

- ${_("You can try again from the {link_start}account settings{link_end} page.").format( - link_start="".format(url=reverse('account_index')), - link_end="" - )} -

-
-
diff --git a/lms/templates/student_account/email_change_successful.html b/lms/templates/student_account/email_change_successful.html deleted file mode 100644 index 5cc4d17444..0000000000 --- a/lms/templates/student_account/email_change_successful.html +++ /dev/null @@ -1,18 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> -<%! from django.core.urlresolvers import reverse %> -<%inherit file="../main.html" /> - -
-
-

${_("Email change successful!")}

-
- -

- ${_("You should see your new email address listed on the " - "{link_start}account settings{link_end} page.").format( - link_start="".format(url=reverse('account_index')), - link_end="", - )} -

-
-
diff --git a/lms/templates/student_account/emails/email_change_confirmation/message_body.txt b/lms/templates/student_account/emails/email_change_confirmation/message_body.txt deleted file mode 100644 index 8608aa6d8d..0000000000 --- a/lms/templates/student_account/emails/email_change_confirmation/message_body.txt +++ /dev/null @@ -1,21 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -## TODO: Get sign-off from Product on new copy, and think about -## turning this into a large, multi-line message for i18n purposes. -## Greeting -${_("Hi there,")} - -## Preamble -${_("You successfully changed the email address associated with your " - "{platform_name} account from {old_email} to {new_email}.").format( - platform_name=settings.PLATFORM_NAME, - old_email=old_email, - new_email=new_email - ) -} - -## Translators: This is the signature of an email. "\n" is a newline character, -## and should be placed between the closing word and the signing team's name. -${_("Thanks,\n - The {platform_name} Team").format( - platform_name=settings.PLATFORM_NAME, -)} diff --git a/lms/templates/student_account/emails/email_change_confirmation/subject_line.txt b/lms/templates/student_account/emails/email_change_confirmation/subject_line.txt deleted file mode 100644 index 57eeadc97c..0000000000 --- a/lms/templates/student_account/emails/email_change_confirmation/subject_line.txt +++ /dev/null @@ -1,3 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("{platform_name} Email Change Successful").format(platform_name=settings.PLATFORM_NAME)} diff --git a/lms/templates/student_account/emails/email_change_request/message_body.txt b/lms/templates/student_account/emails/email_change_request/message_body.txt deleted file mode 100644 index ab7a6999ef..0000000000 --- a/lms/templates/student_account/emails/email_change_request/message_body.txt +++ /dev/null @@ -1,34 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -## TODO: Get sign-off from Product on new copy, and think about -## turning this into a large, multi-line message for i18n purposes. -## Greeting -${_("Hi there,")} - -## Preamble -${_("There was recently a request to change the email address associated " - "with your {platform_name} account from {old_email} to {new_email}. " - "If you requested this change, please confirm your new email address " - "by following the link below:").format( - platform_name=settings.PLATFORM_NAME, - old_email=old_email, - new_email=new_email - ) -} - -## Confirmation link -% if is_secure: -https://${site}/account/email/confirmation/${key} -% else: -http://${site}/account/email/confirmation/${key} -% endif - -## Closing -${_("If you don't want to change the email address associated with your " - "account, ignore this message.")} - -## Translators: This is the signature of an email. "\n" is a newline character, -## and should be placed between the closing word and the signing team's name. -${_("Thanks,\n - The {platform_name} Team").format( - platform_name=settings.PLATFORM_NAME, -)} diff --git a/lms/templates/student_account/emails/email_change_request/subject_line.txt b/lms/templates/student_account/emails/email_change_request/subject_line.txt deleted file mode 100644 index a409534d94..0000000000 --- a/lms/templates/student_account/emails/email_change_request/subject_line.txt +++ /dev/null @@ -1,3 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("{platform_name} Email Change Request").format(platform_name=settings.PLATFORM_NAME)} diff --git a/lms/templates/student_account/index.html b/lms/templates/student_account/index.html deleted file mode 100644 index 0b9ed36aa5..0000000000 --- a/lms/templates/student_account/index.html +++ /dev/null @@ -1,26 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> -<%namespace name='static' file='/static_content.html'/> - -<%inherit file="../main.html" /> - -<%block name="pagetitle">${_("Student Account")} - -<%block name="js_extra"> - - - <%static:js group='student_account'/> - - -<%block name="header_extras"> -% for template_name in ["account"]: - -% endfor - - -

Student Account

- -

This is a placeholder for the student's account page.

- -
From 61a108d3771e32bc26692ba1e2d036dde08a8ce6 Mon Sep 17 00:00:00 2001 From: cahrens Date: Fri, 27 Feb 2015 13:20:57 -0500 Subject: [PATCH 2/2] Delete unused code for changing email. --- common/djangoapps/student/models.py | 26 --- .../core/djangoapps/user_api/api/account.py | 121 -------------- .../user_api/tests/test_account_api.py | 153 ------------------ 3 files changed, 300 deletions(-) diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index e18b078696..7f26eac7b1 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -309,32 +309,6 @@ class UserProfile(models.Model): self.name = new_name self.save() - @transaction.commit_on_success - def update_email(self, new_email): - """Update the user's email and save the change in the history. - - Implicitly saves the model. - If the new email is the same as the old email, do not update the history. - - Arguments: - new_email (unicode): The new email for the user. - - Returns: - None - """ - if self.user.email == new_email: - return - - meta = self.get_meta() - if 'old_emails' not in meta: - meta['old_emails'] = [] - meta['old_emails'].append([self.user.email, datetime.now(UTC).isoformat()]) - self.set_meta(meta) - self.save() - - self.user.email = new_email - self.user.save() - class UserSignupSource(models.Model): """ diff --git a/openedx/core/djangoapps/user_api/api/account.py b/openedx/core/djangoapps/user_api/api/account.py index 92a7e9a4fc..f2cf4a2a62 100644 --- a/openedx/core/djangoapps/user_api/api/account.py +++ b/openedx/core/djangoapps/user_api/api/account.py @@ -45,11 +45,6 @@ class AccountUsernameAlreadyExists(AccountUserAlreadyExists): pass -class AccountEmailAlreadyExists(AccountUserAlreadyExists): - """An account already exists with the requested email. """ - pass - - class AccountUsernameInvalid(AccountRequestError): """The requested username is not in a valid format. """ pass @@ -216,122 +211,6 @@ def activate_account(activation_key): # This implicitly saves the registration registration.activate() - -@intercept_errors(AccountInternalError, ignore_errors=[AccountRequestError]) -def request_email_change(username, new_email, password): - """Request an email change. - - Users must confirm the change before we update their information. - - Args: - username (unicode): The username associated with the account. - new_email (unicode): The user's new email address. - password (unicode): The password the user entered to authorize the change. - - Returns: - unicode: an activation key for the account. - - Raises: - AccountUserNotFound - AccountEmailAlreadyExists - AccountEmailInvalid - AccountNotAuthorized - - """ - try: - user = User.objects.get(username=username) - except User.DoesNotExist: - raise AccountUserNotFound - - # Check the user's credentials - if not user.check_password(password): - raise AccountNotAuthorized - - # Validate the email, raising an exception if it is not in the correct format - _validate_email(new_email) - - # Verify that no active account has taken the email in between - # the request and the activation. - # We'll check again before confirming and persisting the change, - # but if the email is already taken by an active account, we should - # let the user know as soon as possible. - if User.objects.filter(email=new_email, is_active=True).exists(): - raise AccountEmailAlreadyExists - - try: - pending_change = PendingEmailChange.objects.get(user=user) - except PendingEmailChange.DoesNotExist: - pending_change = PendingEmailChange(user=user) - - # Update the change (re-using the same record if it already exists) - # This will generate a new activation key and save the record. - return pending_change.request_change(new_email) - - -@intercept_errors(AccountInternalError, ignore_errors=[AccountRequestError]) -@transaction.commit_on_success -def confirm_email_change(activation_key): - """Confirm an email change. - - Users can confirm the change by providing an activation key - they received via email. - - Args: - activation_key (unicode): The activation key the user received - when he/she requested the email change. - - Returns: - Tuple: (old_email, new_email) - - Raises: - AccountNotAuthorized: The activation code is invalid. - AccountEmailAlreadyExists: Someone else has already taken the email address. - AccountInternalError - - """ - - try: - # Activation key has a uniqueness constraint, so we're guaranteed to get - # at most one pending change. - pending_change = PendingEmailChange.objects.select_related('user').get( - activation_key=activation_key - ) - except PendingEmailChange.DoesNotExist: - # If there are no changes, then the activation key is invalid - raise AccountNotAuthorized - else: - old_email = pending_change.user.email - new_email = pending_change.new_email - - # Verify that no one else has taken the email in between - # the request and the activation. - # In our production database, email has a uniqueness constraint, - # so there is no danger of a race condition here. - if User.objects.filter(email=new_email).exists(): - raise AccountEmailAlreadyExists - - # Update the email history (in the user profile) - try: - profile = UserProfile.objects.get(user=pending_change.user) - except UserProfile.DoesNotExist: - raise AccountInternalError( - "No profile exists for the user '{username}'".format( - username=pending_change.user.username - ) - ) - else: - profile.update_email(new_email) - - # Delete the pending change, so that the activation code - # will be single-use - pending_change.delete() - - # Return the old and new email - # This allows the caller of the function to notify users at both - # the new and old email, which is necessary for security reasons. - return (old_email, new_email) - - @intercept_errors(AccountInternalError, ignore_errors=[AccountRequestError]) def request_password_change(email, orig_host, is_secure): """Email a single-use link for performing a password reset. diff --git a/openedx/core/djangoapps/user_api/tests/test_account_api.py b/openedx/core/djangoapps/user_api/tests/test_account_api.py index 506487e56d..3040708dfc 100644 --- a/openedx/core/djangoapps/user_api/tests/test_account_api.py +++ b/openedx/core/djangoapps/user_api/tests/test_account_api.py @@ -76,40 +76,6 @@ class AccountApiTest(TestCase): account = account_api.account_info(self.USERNAME) self.assertTrue(account['is_active']) - def test_change_email(self): - # Request an email change - account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - activation_key = account_api.request_email_change( - self.USERNAME, u'new+email@example.com', self.PASSWORD - ) - - # Verify that the email has not yet changed - account = account_api.account_info(self.USERNAME) - self.assertEqual(account['email'], self.EMAIL) - - # Confirm the change, using the activation code - old_email, new_email = account_api.confirm_email_change(activation_key) - self.assertEqual(old_email, self.EMAIL) - self.assertEqual(new_email, u'new+email@example.com') - - # Verify that the email is changed - account = account_api.account_info(self.USERNAME) - self.assertEqual(account['email'], u'new+email@example.com') - - def test_confirm_email_change_repeat(self): - account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - activation_key = account_api.request_email_change( - self.USERNAME, u'new+email@example.com', self.PASSWORD - ) - - # Confirm the change once - account_api.confirm_email_change(activation_key) - - # Confirm the change again. The activation code should be - # single-use, so this should raise an error. - with self.assertRaises(account_api.AccountNotAuthorized): - account_api.confirm_email_change(activation_key) - def test_create_account_duplicate_username(self): account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) with self.assertRaises(account_api.AccountUserAlreadyExists): @@ -155,125 +121,6 @@ class AccountApiTest(TestCase): def test_activate_account_invalid_key(self): account_api.activate_account(u'invalid') - @raises(account_api.AccountUserNotFound) - def test_request_email_change_no_user(self): - account_api.request_email_change(u'no_such_user', self.EMAIL, self.PASSWORD) - - @ddt.data(*INVALID_EMAILS) - def test_request_email_change_invalid_email(self, invalid_email): - # Create an account with a valid email address - account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - - # Attempt to change the account to an invalid email - with self.assertRaises(account_api.AccountEmailInvalid): - account_api.request_email_change(self.USERNAME, invalid_email, self.PASSWORD) - - def test_request_email_change_already_exists(self): - # Create two accounts, both activated - activation_key = account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - account_api.activate_account(activation_key) - activation_key = account_api.create_account(u'another_user', u'password', u'another+user@example.com') - account_api.activate_account(activation_key) - - # Try to change the first user's email to the same as the second user's - with self.assertRaises(account_api.AccountEmailAlreadyExists): - account_api.request_email_change(self.USERNAME, u'another+user@example.com', self.PASSWORD) - - def test_request_email_change_duplicates_unactivated_account(self): - # Create two accounts, but the second account is inactive - activation_key = account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - account_api.activate_account(activation_key) - account_api.create_account(u'another_user', u'password', u'another+user@example.com') - - # Try to change the first user's email to the same as the second user's - # Since the second user has not yet activated, this should succeed. - account_api.request_email_change(self.USERNAME, u'another+user@example.com', self.PASSWORD) - - def test_request_email_change_same_address(self): - # Create and activate the account - activation_key = account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - account_api.activate_account(activation_key) - - # Try to change the email address to the current address - with self.assertRaises(account_api.AccountEmailAlreadyExists): - account_api.request_email_change(self.USERNAME, self.EMAIL, self.PASSWORD) - - def test_request_email_change_wrong_password(self): - account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - - # Use the wrong password - with self.assertRaises(account_api.AccountNotAuthorized): - account_api.request_email_change(self.USERNAME, u'new+email@example.com', u'wrong password') - - def test_confirm_email_change_invalid_activation_key(self): - account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - account_api.request_email_change(self.USERNAME, u'new+email@example.com', self.PASSWORD) - - with self.assertRaises(account_api.AccountNotAuthorized): - account_api.confirm_email_change(u'invalid') - - def test_confirm_email_change_no_request_pending(self): - account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - - def test_confirm_email_already_exists(self): - account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - - # Request a change - activation_key = account_api.request_email_change( - self.USERNAME, u'new+email@example.com', self.PASSWORD - ) - - # Another use takes the email before we confirm the change - account_api.create_account(u'other_user', u'password', u'new+email@example.com') - - # When we try to confirm our change, we get an error because the email is taken - with self.assertRaises(account_api.AccountEmailAlreadyExists): - account_api.confirm_email_change(activation_key) - - # Verify that the email was NOT changed - self.assertEqual(account_api.account_info(self.USERNAME)['email'], self.EMAIL) - - def test_confirm_email_no_user_profile(self): - account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - activation_key = account_api.request_email_change( - self.USERNAME, u'new+email@example.com', self.PASSWORD - ) - - # This should never happen, but just in case... - UserProfile.objects.get(user__username=self.USERNAME).delete() - - with self.assertRaises(account_api.AccountInternalError): - account_api.confirm_email_change(activation_key) - - def test_record_email_change_history(self): - account_api.create_account(self.USERNAME, self.PASSWORD, self.EMAIL) - - # Change the email once - activation_key = account_api.request_email_change( - self.USERNAME, u'new+email@example.com', self.PASSWORD - ) - account_api.confirm_email_change(activation_key) - - # Verify that the old email appears in the history - meta = UserProfile.objects.get(user__username=self.USERNAME).get_meta() - self.assertEqual(len(meta['old_emails']), 1) - email, timestamp = meta['old_emails'][0] - self.assertEqual(email, self.EMAIL) - self._assert_is_datetime(timestamp) - - # Change the email again - activation_key = account_api.request_email_change( - self.USERNAME, u'another_new+email@example.com', self.PASSWORD - ) - account_api.confirm_email_change(activation_key) - - # Verify that both emails appear in the history - meta = UserProfile.objects.get(user__username=self.USERNAME).get_meta() - self.assertEqual(len(meta['old_emails']), 2) - email, timestamp = meta['old_emails'][1] - self.assertEqual(email, 'new+email@example.com') - self._assert_is_datetime(timestamp) - @skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS') def test_request_password_change(self): # Create and activate an account