Commit 3938e84d by David Baumgold

Merge pull request #2526 from edx/db/refactor-student-view

Refactor student views
parents 6635233b 1dfd3310
...@@ -23,6 +23,7 @@ from external_auth.models import ExternalAuthMap ...@@ -23,6 +23,7 @@ from external_auth.models import ExternalAuthMap
TEST_DATA_MIXED_MODULESTORE = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {}) TEST_DATA_MIXED_MODULESTORE = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {})
class LoginTest(TestCase): class LoginTest(TestCase):
''' '''
Test student.views.login_user() view Test student.views.login_user() view
...@@ -224,7 +225,11 @@ class ExternalAuthShibTest(ModuleStoreTestCase): ...@@ -224,7 +225,11 @@ class ExternalAuthShibTest(ModuleStoreTestCase):
""" """
response = self.client.post(reverse('login'), {'email': self.user_w_map.email, 'password': ''}) response = self.client.post(reverse('login'), {'email': self.user_w_map.email, 'password': ''})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, json.dumps({'success': False, 'redirect': reverse('shib-login')})) obj = json.loads(response.content)
self.assertEqual(obj, {
'success': False,
'redirect': reverse('shib-login'),
})
@unittest.skipUnless(settings.FEATURES.get('AUTH_USE_SHIB'), "AUTH_USE_SHIB not set") @unittest.skipUnless(settings.FEATURES.get('AUTH_USE_SHIB'), "AUTH_USE_SHIB not set")
def test__get_course_enrollment_domain(self): def test__get_course_enrollment_domain(self):
......
...@@ -68,8 +68,11 @@ class ResetPasswordTests(TestCase): ...@@ -68,8 +68,11 @@ class ResetPasswordTests(TestCase):
bad_pwd_resp = password_reset(bad_pwd_req) bad_pwd_resp = password_reset(bad_pwd_req)
# If they've got an unusable password, we return a successful response code # If they've got an unusable password, we return a successful response code
self.assertEquals(bad_pwd_resp.status_code, 200) self.assertEquals(bad_pwd_resp.status_code, 200)
self.assertEquals(bad_pwd_resp.content, json.dumps({'success': True, obj = json.loads(bad_pwd_resp.content)
'value': "('registration/password_reset_done.html', [])"})) self.assertEquals(obj, {
'success': True,
'value': "('registration/password_reset_done.html', [])",
})
@patch('student.views.render_to_string', Mock(side_effect=mock_render_to_string, autospec=True)) @patch('student.views.render_to_string', Mock(side_effect=mock_render_to_string, autospec=True))
def test_nonexist_email_password_reset(self): def test_nonexist_email_password_reset(self):
...@@ -80,12 +83,19 @@ class ResetPasswordTests(TestCase): ...@@ -80,12 +83,19 @@ class ResetPasswordTests(TestCase):
# Note: even if the email is bad, we return a successful response code # Note: even if the email is bad, we return a successful response code
# This prevents someone potentially trying to "brute-force" find out which emails are and aren't registered with edX # This prevents someone potentially trying to "brute-force" find out which emails are and aren't registered with edX
self.assertEquals(bad_email_resp.status_code, 200) self.assertEquals(bad_email_resp.status_code, 200)
self.assertEquals(bad_email_resp.content, json.dumps({'success': True, obj = json.loads(bad_email_resp.content)
'value': "('registration/password_reset_done.html', [])"})) self.assertEquals(obj, {
'success': True,
'value': "('registration/password_reset_done.html', [])",
})
@unittest.skipIf(settings.FEATURES.get('DISABLE_RESET_EMAIL_TEST', False), @unittest.skipIf(
dedent("""Skipping Test because CMS has not provided necessary templates for password reset. settings.FEATURES.get('DISABLE_RESET_EMAIL_TEST', False),
If LMS tests print this message, that needs to be fixed.""")) dedent("""
Skipping Test because CMS has not provided necessary templates for password reset.
If LMS tests print this message, that needs to be fixed.
""")
)
@patch('django.core.mail.send_mail') @patch('django.core.mail.send_mail')
@patch('student.views.render_to_string', Mock(side_effect=mock_render_to_string, autospec=True)) @patch('student.views.render_to_string', Mock(side_effect=mock_render_to_string, autospec=True))
def test_reset_password_email(self, send_email): def test_reset_password_email(self, send_email):
...@@ -94,9 +104,11 @@ class ResetPasswordTests(TestCase): ...@@ -94,9 +104,11 @@ class ResetPasswordTests(TestCase):
good_req = self.request_factory.post('/password_reset/', {'email': self.user.email}) good_req = self.request_factory.post('/password_reset/', {'email': self.user.email})
good_resp = password_reset(good_req) good_resp = password_reset(good_req)
self.assertEquals(good_resp.status_code, 200) self.assertEquals(good_resp.status_code, 200)
self.assertEquals(good_resp.content, obj = json.loads(good_resp.content)
json.dumps({'success': True, self.assertEquals(obj, {
'value': "('registration/password_reset_done.html', [])"})) 'success': True,
'value': "('registration/password_reset_done.html', [])",
})
((subject, msg, from_addr, to_addrs), sm_kwargs) = send_email.call_args ((subject, msg, from_addr, to_addrs), sm_kwargs) = send_email.call_args
self.assertIn("Password reset", subject) self.assertIn("Password reset", subject)
......
...@@ -4,9 +4,7 @@ Student Views ...@@ -4,9 +4,7 @@ Student Views
import datetime import datetime
import json import json
import logging import logging
import random
import re import re
import string # pylint: disable=W0402
import urllib import urllib
import uuid import uuid
import time import time
...@@ -18,13 +16,11 @@ from django.contrib.auth import logout, authenticate, login ...@@ -18,13 +16,11 @@ from django.contrib.auth import logout, authenticate, login
from django.contrib.auth.models import User, AnonymousUser from django.contrib.auth.models import User, AnonymousUser
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import password_reset_confirm from django.contrib.auth.views import password_reset_confirm
# from django.contrib.sessions.models import Session
from django.core.cache import cache from django.core.cache import cache
from django.core.context_processors import csrf from django.core.context_processors import csrf
from django.core.mail import send_mail from django.core.mail import send_mail
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.validators import validate_email, validate_slug, ValidationError from django.core.validators import validate_email, validate_slug, ValidationError
from django.core.exceptions import ObjectDoesNotExist
from django.db import IntegrityError, transaction from django.db import IntegrityError, transaction
from django.http import (HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, from django.http import (HttpResponse, HttpResponseBadRequest, HttpResponseForbidden,
Http404) Http404)
...@@ -33,7 +29,6 @@ from django_future.csrf import ensure_csrf_cookie ...@@ -33,7 +29,6 @@ from django_future.csrf import ensure_csrf_cookie
from django.utils.http import cookie_date, base36_to_int from django.utils.http import cookie_date, base36_to_int
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.decorators.http import require_POST, require_GET from django.views.decorators.http import require_POST, require_GET
from django.contrib.admin.views.decorators import staff_member_required
from ratelimitbackend.exceptions import RateLimitException from ratelimitbackend.exceptions import RateLimitException
...@@ -46,6 +41,7 @@ from student.models import ( ...@@ -46,6 +41,7 @@ from student.models import (
CourseEnrollmentAllowed, UserStanding, LoginFailures CourseEnrollmentAllowed, UserStanding, LoginFailures
) )
from student.forms import PasswordResetFormNoActive from student.forms import PasswordResetFormNoActive
from student.firebase_token_generator import create_token
from verify_student.models import SoftwareSecurePhotoVerification, MidcourseReverificationWindow from verify_student.models import SoftwareSecurePhotoVerification, MidcourseReverificationWindow
from certificates.models import CertificateStatuses, certificate_status_for_student from certificates.models import CertificateStatuses, certificate_status_for_student
...@@ -69,7 +65,6 @@ import shoppingcart ...@@ -69,7 +65,6 @@ import shoppingcart
import track.views import track.views
from dogapi import dog_stats_api from dogapi import dog_stats_api
from pytz import UTC
from util.json_request import JsonResponse from util.json_request import JsonResponse
...@@ -265,7 +260,6 @@ def get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set): ...@@ -265,7 +260,6 @@ def get_course_enrollment_pairs(user, course_org_filter, org_filter_out_set):
.format(user.username, enrollment.course_id)) .format(user.username, enrollment.course_id))
def _cert_info(user, course, cert_status): def _cert_info(user, course, cert_status):
""" """
Implements the logic for cert_info -- split out for testing. Implements the logic for cert_info -- split out for testing.
...@@ -674,8 +668,10 @@ def accounts_login(request): ...@@ -674,8 +668,10 @@ def accounts_login(request):
def login_user(request, error=""): def login_user(request, error=""):
"""AJAX request to log in the user.""" """AJAX request to log in the user."""
if 'email' not in request.POST or 'password' not in request.POST: if 'email' not in request.POST or 'password' not in request.POST:
return HttpResponse(json.dumps({'success': False, return JsonResponse({
'value': _('There was an error receiving your login information. Please email us.')})) # TODO: User error message "success": False,
"value": _('There was an error receiving your login information. Please email us.'), # TODO: User error message
}) # TODO: this should be status code 400 # pylint: disable=fixme
email = request.POST['email'] email = request.POST['email']
password = request.POST['password'] password = request.POST['password']
...@@ -692,7 +688,10 @@ def login_user(request, error=""): ...@@ -692,7 +688,10 @@ def login_user(request, error=""):
try: try:
eamap = ExternalAuthMap.objects.get(user=user) eamap = ExternalAuthMap.objects.get(user=user)
if eamap.external_domain.startswith(external_auth.views.SHIBBOLETH_DOMAIN_PREFIX): if eamap.external_domain.startswith(external_auth.views.SHIBBOLETH_DOMAIN_PREFIX):
return HttpResponse(json.dumps({'success': False, 'redirect': reverse('shib-login')})) return JsonResponse({
"success": False,
"redirect": reverse('shib-login'),
}) # TODO: this should be status code 301 # pylint: disable=fixme
except ExternalAuthMap.DoesNotExist: except ExternalAuthMap.DoesNotExist:
# This is actually the common case, logging in user without external linked login # This is actually the common case, logging in user without external linked login
AUDIT_LOG.info("User %s w/o external auth attempting login", user) AUDIT_LOG.info("User %s w/o external auth attempting login", user)
...@@ -701,12 +700,10 @@ def login_user(request, error=""): ...@@ -701,12 +700,10 @@ def login_user(request, error=""):
user_found_by_email_lookup = user user_found_by_email_lookup = user
if user_found_by_email_lookup and LoginFailures.is_feature_enabled(): if user_found_by_email_lookup and LoginFailures.is_feature_enabled():
if LoginFailures.is_user_locked_out(user_found_by_email_lookup): if LoginFailures.is_user_locked_out(user_found_by_email_lookup):
return HttpResponse( return JsonResponse({
json.dumps({ "success": False,
'success': False, "value": _('This account has been temporarily locked due to excessive login failures. Try again later.'),
'value': _('This account has been temporarily locked due to excessive login failures. Try again later.') }) # TODO: this should be status code 429 # pylint: disable=fixme
})
)
# if the user doesn't exist, we want to set the username to an invalid # if the user doesn't exist, we want to set the username to an invalid
# username so that authentication is guaranteed to fail and we can take # username so that authentication is guaranteed to fail and we can take
...@@ -716,8 +713,10 @@ def login_user(request, error=""): ...@@ -716,8 +713,10 @@ def login_user(request, error=""):
user = authenticate(username=username, password=password, request=request) user = authenticate(username=username, password=password, request=request)
# this occurs when there are too many attempts from the same IP address # this occurs when there are too many attempts from the same IP address
except RateLimitException: except RateLimitException:
return HttpResponse(json.dumps({'success': False, return JsonResponse({
'value': _('Too many failed login attempts. Try again later.')})) "success": False,
"value": _('Too many failed login attempts. Try again later.'),
}) # TODO: this should be status code 429 # pylint: disable=fixme
if user is None: if user is None:
# tick the failed login counters if the user exists in the database # tick the failed login counters if the user exists in the database
if user_found_by_email_lookup and LoginFailures.is_feature_enabled(): if user_found_by_email_lookup and LoginFailures.is_feature_enabled():
...@@ -727,8 +726,10 @@ def login_user(request, error=""): ...@@ -727,8 +726,10 @@ def login_user(request, error=""):
# doesn't exist, and doesn't have a corresponding password # doesn't exist, and doesn't have a corresponding password
if username != "": if username != "":
AUDIT_LOG.warning(u"Login failed - password for {0} is invalid".format(email)) AUDIT_LOG.warning(u"Login failed - password for {0} is invalid".format(email))
return HttpResponse(json.dumps({'success': False, return JsonResponse({
'value': _('Email or password is incorrect.')})) "success": False,
"value": _('Email or password is incorrect.'),
}) # TODO: this should be status code 400 # pylint: disable=fixme
# successful login, clear failed login attempts counters, if applicable # successful login, clear failed login attempts counters, if applicable
if LoginFailures.is_feature_enabled(): if LoginFailures.is_feature_enabled():
...@@ -753,7 +754,10 @@ def login_user(request, error=""): ...@@ -753,7 +754,10 @@ def login_user(request, error=""):
redirect_url = try_change_enrollment(request) redirect_url = try_change_enrollment(request)
dog_stats_api.increment("common.student.successful_login") dog_stats_api.increment("common.student.successful_login")
response = HttpResponse(json.dumps({'success': True, 'redirect_url': redirect_url})) response = JsonResponse({
"success": True,
"redirect_url": redirect_url,
})
# set the login cookie for the edx marketing site # set the login cookie for the edx marketing site
# we want this cookie to be accessed via javascript # we want this cookie to be accessed via javascript
...@@ -767,12 +771,11 @@ def login_user(request, error=""): ...@@ -767,12 +771,11 @@ def login_user(request, error=""):
expires_time = time.time() + max_age expires_time = time.time() + max_age
expires = cookie_date(expires_time) expires = cookie_date(expires_time)
response.set_cookie(settings.EDXMKTG_COOKIE_NAME, response.set_cookie(
'true', max_age=max_age, settings.EDXMKTG_COOKIE_NAME, 'true', max_age=max_age,
expires=expires, domain=settings.SESSION_COOKIE_DOMAIN, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
path='/', path='/', secure=None, httponly=None,
secure=None, )
httponly=None)
return response return response
...@@ -780,8 +783,10 @@ def login_user(request, error=""): ...@@ -780,8 +783,10 @@ def login_user(request, error=""):
reactivation_email_for_user(user) reactivation_email_for_user(user)
not_activated_msg = _("This account has not been activated. We have sent another activation message. Please check your e-mail for the activation instructions.") not_activated_msg = _("This account has not been activated. We have sent another activation message. Please check your e-mail for the activation instructions.")
return HttpResponse(json.dumps({'success': False, return JsonResponse({
'value': not_activated_msg})) "success": False,
"value": not_activated_msg,
}) # TODO: this should be status code 400 # pylint: disable=fixme
@ensure_csrf_cookie @ensure_csrf_cookie
...@@ -799,11 +804,13 @@ def logout_user(request): ...@@ -799,11 +804,13 @@ def logout_user(request):
else: else:
target = '/' target = '/'
response = redirect(target) response = redirect(target)
response.delete_cookie(settings.EDXMKTG_COOKIE_NAME, response.delete_cookie(
path='/', settings.EDXMKTG_COOKIE_NAME,
domain=settings.SESSION_COOKIE_DOMAIN) path='/', domain=settings.SESSION_COOKIE_DOMAIN,
)
return response return response
@require_GET @require_GET
@login_required @login_required
@ensure_csrf_cookie @ensure_csrf_cookie
...@@ -890,8 +897,10 @@ def change_setting(request): ...@@ -890,8 +897,10 @@ def change_setting(request):
up.location = request.POST['location'] up.location = request.POST['location']
up.save() up.save()
return HttpResponse(json.dumps({'success': True, return JsonResponse({
'location': up.location, })) "success": True,
"location": up.location,
})
def _do_create_account(post_vars): def _do_create_account(post_vars):
...@@ -1106,8 +1115,8 @@ def create_account(request, post_override=None): ...@@ -1106,8 +1115,8 @@ def create_account(request, post_override=None):
'-' * 80 + '\n\n' + message) '-' * 80 + '\n\n' + message)
send_mail(subject, message, from_address, [dest_addr], fail_silently=False) send_mail(subject, message, from_address, [dest_addr], fail_silently=False)
else: else:
_res = user.email_user(subject, message, from_address) user.email_user(subject, message, from_address)
except: except Exception: # pylint: disable=broad-except
log.warning('Unable to send activation email to user', exc_info=True) log.warning('Unable to send activation email to user', exc_info=True)
js['value'] = _('Could not send activation e-mail.') js['value'] = _('Could not send activation e-mail.')
# What is the correct status code to use here? I think it's 500, because # What is the correct status code to use here? I think it's 500, because
...@@ -1298,8 +1307,10 @@ def password_reset(request): ...@@ -1298,8 +1307,10 @@ def password_reset(request):
from_email=settings.DEFAULT_FROM_EMAIL, from_email=settings.DEFAULT_FROM_EMAIL,
request=request, request=request,
domain_override=request.get_host()) domain_override=request.get_host())
return HttpResponse(json.dumps({'success': True, return JsonResponse({
'value': render_to_string('registration/password_reset_done.html', {})})) 'success': True,
'value': render_to_string('registration/password_reset_done.html', {}),
})
def password_reset_confirm_wrapper( def password_reset_confirm_wrapper(
...@@ -1330,23 +1341,30 @@ def reactivation_email_for_user(user): ...@@ -1330,23 +1341,30 @@ def reactivation_email_for_user(user):
try: try:
reg = Registration.objects.get(user=user) reg = Registration.objects.get(user=user)
except Registration.DoesNotExist: except Registration.DoesNotExist:
return HttpResponse(json.dumps({'success': False, return JsonResponse({
'error': _('No inactive user with this e-mail exists')})) "success": False,
"error": _('No inactive user with this e-mail exists'),
}) # TODO: this should be status code 400 # pylint: disable=fixme
d = {'name': user.profile.name, context = {
'key': reg.activation_key} 'name': user.profile.name,
'key': reg.activation_key,
}
subject = render_to_string('emails/activation_email_subject.txt', d) subject = render_to_string('emails/activation_email_subject.txt', context)
subject = ''.join(subject.splitlines()) subject = ''.join(subject.splitlines())
message = render_to_string('emails/activation_email.txt', d) message = render_to_string('emails/activation_email.txt', context)
try: try:
_res = user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL) user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
except: except Exception: # pylint: disable=broad-except
log.warning('Unable to send reactivation email', exc_info=True) log.warning('Unable to send reactivation email', exc_info=True)
return HttpResponse(json.dumps({'success': False, 'error': _('Unable to send reactivation email')})) return JsonResponse({
"success": False,
"error": _('Unable to send reactivation email')
}) # TODO: this should be status code 500 # pylint: disable=fixme
return HttpResponse(json.dumps({'success': True})) return JsonResponse({"success": True})
@ensure_csrf_cookie @ensure_csrf_cookie
...@@ -1360,20 +1378,26 @@ def change_email_request(request): ...@@ -1360,20 +1378,26 @@ def change_email_request(request):
user = request.user user = request.user
if not user.check_password(request.POST['password']): if not user.check_password(request.POST['password']):
return HttpResponse(json.dumps({'success': False, return JsonResponse({
'error': _('Invalid password')})) "success": False,
"error": _('Invalid password'),
}) # TODO: this should be status code 400 # pylint: disable=fixme
new_email = request.POST['new_email'] new_email = request.POST['new_email']
try: try:
validate_email(new_email) validate_email(new_email)
except ValidationError: except ValidationError:
return HttpResponse(json.dumps({'success': False, return JsonResponse({
'error': _('Valid e-mail address required.')})) "success": False,
"error": _('Valid e-mail address required.'),
}) # TODO: this should be status code 400 # pylint: disable=fixme
if User.objects.filter(email=new_email).count() != 0: if User.objects.filter(email=new_email).count() != 0:
## CRITICAL TODO: Handle case sensitivity for e-mails ## CRITICAL TODO: Handle case sensitivity for e-mails
return HttpResponse(json.dumps({'success': False, return JsonResponse({
'error': _('An account with this e-mail already exists.')})) "success": False,
"error": _('An account with this e-mail already exists.'),
}) # TODO: this should be status code 400 # pylint: disable=fixme
pec_list = PendingEmailChange.objects.filter(user=request.user) pec_list = PendingEmailChange.objects.filter(user=request.user)
if len(pec_list) == 0: if len(pec_list) == 0:
...@@ -1388,8 +1412,10 @@ def change_email_request(request): ...@@ -1388,8 +1412,10 @@ def change_email_request(request):
if pec.new_email == user.email: if pec.new_email == user.email:
pec.delete() pec.delete()
return HttpResponse(json.dumps({'success': False, return JsonResponse({
'error': _('Old email is the same as the new email.')})) "success": False,
"error": _('Old email is the same as the new email.'),
}) # TODO: this should be status code 400 # pylint: disable=fixme
context = { context = {
'key': pec.activation_key, 'key': pec.activation_key,
...@@ -1407,9 +1433,9 @@ def change_email_request(request): ...@@ -1407,9 +1433,9 @@ def change_email_request(request):
settings.DEFAULT_FROM_EMAIL settings.DEFAULT_FROM_EMAIL
) )
_res = send_mail(subject, message, from_address, [pec.new_email]) send_mail(subject, message, from_address, [pec.new_email])
return HttpResponse(json.dumps({'success': True})) return JsonResponse({"success": True})
@ensure_csrf_cookie @ensure_csrf_cookie
...@@ -1491,14 +1517,17 @@ def change_name_request(request): ...@@ -1491,14 +1517,17 @@ def change_name_request(request):
pnc.new_name = request.POST['new_name'] pnc.new_name = request.POST['new_name']
pnc.rationale = request.POST['rationale'] pnc.rationale = request.POST['rationale']
if len(pnc.new_name) < 2: if len(pnc.new_name) < 2:
return HttpResponse(json.dumps({'success': False, 'error': _('Name required')})) return JsonResponse({
"success": False,
"error": _('Name required'),
}) # TODO: this should be status code 400 # pylint: disable=fixme
pnc.save() pnc.save()
# The following automatically accepts name change requests. Remove this to # The following automatically accepts name change requests. Remove this to
# go back to the old system where it gets queued up for admin approval. # go back to the old system where it gets queued up for admin approval.
accept_name_change_by_id(pnc.id) accept_name_change_by_id(pnc.id)
return HttpResponse(json.dumps({'success': True})) return JsonResponse({"success": True})
@ensure_csrf_cookie @ensure_csrf_cookie
...@@ -1507,14 +1536,19 @@ def pending_name_changes(request): ...@@ -1507,14 +1536,19 @@ def pending_name_changes(request):
if not request.user.is_staff: if not request.user.is_staff:
raise Http404 raise Http404
changes = list(PendingNameChange.objects.all()) students = []
js = {'students': [{'new_name': c.new_name, for change in PendingNameChange.objects.all():
'rationale': c.rationale, profile = UserProfile.objects.get(user=change.user)
'old_name': UserProfile.objects.get(user=c.user).name, students.append({
'email': c.user.email, "new_name": change.new_name,
'uid': c.user.id, "rationale": change.rationale,
'cid': c.id} for c in changes]} "old_name": profile.name,
return render_to_response('name_changes.html', js) "email": change.user.email,
"uid": change.user.id,
"cid": change.id,
})
return render_to_response("name_changes.html", {"students": students})
@ensure_csrf_cookie @ensure_csrf_cookie
...@@ -1526,17 +1560,23 @@ def reject_name_change(request): ...@@ -1526,17 +1560,23 @@ def reject_name_change(request):
try: try:
pnc = PendingNameChange.objects.get(id=int(request.POST['id'])) pnc = PendingNameChange.objects.get(id=int(request.POST['id']))
except PendingNameChange.DoesNotExist: except PendingNameChange.DoesNotExist:
return HttpResponse(json.dumps({'success': False, 'error': _('Invalid ID')})) return JsonResponse({
"success": False,
"error": _('Invalid ID'),
}) # TODO: this should be status code 400 # pylint: disable=fixme
pnc.delete() pnc.delete()
return HttpResponse(json.dumps({'success': True})) return JsonResponse({"success": True})
def accept_name_change_by_id(id): def accept_name_change_by_id(id):
try: try:
pnc = PendingNameChange.objects.get(id=id) pnc = PendingNameChange.objects.get(id=id)
except PendingNameChange.DoesNotExist: except PendingNameChange.DoesNotExist:
return HttpResponse(json.dumps({'success': False, 'error': _('Invalid ID')})) return JsonResponse({
"success": False,
"error": _('Invalid ID'),
}) # TODO: this should be status code 400 # pylint: disable=fixme
u = pnc.user u = pnc.user
up = UserProfile.objects.get(user=u) up = UserProfile.objects.get(user=u)
...@@ -1552,7 +1592,7 @@ def accept_name_change_by_id(id): ...@@ -1552,7 +1592,7 @@ def accept_name_change_by_id(id):
up.save() up.save()
pnc.delete() pnc.delete()
return HttpResponse(json.dumps({'success': True})) return JsonResponse({"success": True})
@ensure_csrf_cookie @ensure_csrf_cookie
...@@ -1589,9 +1629,7 @@ def change_email_settings(request): ...@@ -1589,9 +1629,7 @@ def change_email_settings(request):
log.info(u"User {0} ({1}) opted out of receiving emails from course {2}".format(user.username, user.email, course_id)) log.info(u"User {0} ({1}) opted out of receiving emails from course {2}".format(user.username, user.email, course_id))
track.views.server_track(request, "change-email-settings", {"receive_emails": "no", "course": course_id}, page='dashboard') track.views.server_track(request, "change-email-settings", {"receive_emails": "no", "course": course_id}, page='dashboard')
return HttpResponse(json.dumps({'success': True})) return JsonResponse({"success": True})
from student.firebase_token_generator import create_token
@login_required @login_required
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment