Commit 8761eaf3 by Will Daly

Added check for duplicate email and username

parent 7ef9ec83
"""Python API for user accounts.
Account information includes a student's username, password, and email
address, but does NOT include user profile information (i.e., demographic
information and preferences).
"""
from django.db import transaction, IntegrityError
from django.db.models import Q
from django.core.validators import validate_email, validate_slug, ValidationError
from user_api.models import User, UserProfile, Registration, PendingEmailChange
from user_api.helpers import intercept_errors
......@@ -138,6 +140,34 @@ def create_account(username, password, email):
return registration.activation_key
def check_account_exists(username=None, email=None):
"""Check whether an account with a particular username or email already exists.
Keyword Arguments:
username (unicode)
email (unicode)
Returns:
list of conflicting fields
Example Usage:
>>> account_api.check_account_exists(username="bob")
[]
>>> account_api.check_account_exists(username="ted", email="ted@example.com")
["email", "username"]
"""
conflicts = []
if email is not None and User.objects.filter(email=email).exists():
conflicts.append("email")
if username is not None and User.objects.filter(username=username).exists():
conflicts.append("username")
return conflicts
@intercept_errors(AccountInternalError, ignore_errors=[AccountRequestError])
def account_info(username):
"""Retrieve information about a user's account.
......
......@@ -1037,7 +1037,6 @@ class RegistrationViewTest(ApiTestCase):
response = self.client.post(self.url, data)
self.assertHttpBadRequest(response)
@override_settings(REGISTRATION_EXTRA_FIELDS={"country": "required"})
@ddt.data("email", "name", "username", "password", "country")
def test_register_missing_required_field(self, missing_field):
......@@ -1055,21 +1054,65 @@ class RegistrationViewTest(ApiTestCase):
response = self.client.post(self.url, data)
self.assertHttpBadRequest(response)
def test_register_already_authenticated(self):
data = {
def test_register_duplicate_email(self):
# Register the first user
response = self.client.post(self.url, {
"email": self.EMAIL,
"name": self.NAME,
"username": self.USERNAME,
"password": self.PASSWORD,
}
})
self.assertHttpOK(response)
# Register once, which will also log us in
response = self.client.post(self.url, data)
# Try to create a second user with the same email address
response = self.client.post(self.url, {
"email": self.EMAIL,
"name": "Someone Else",
"username": "someone_else",
"password": self.PASSWORD,
})
self.assertEqual(response.status_code, 409)
self.assertEqual(response.content, json.dumps(["email"]))
def test_register_duplicate_username(self):
# Register the first user
response = self.client.post(self.url, {
"email": self.EMAIL,
"name": self.NAME,
"username": self.USERNAME,
"password": self.PASSWORD,
})
self.assertHttpOK(response)
# Try to register again
response = self.client.post(self.url, data)
self.assertHttpBadRequest(response)
# Try to create a second user with the same username
response = self.client.post(self.url, {
"email": "someone+else@example.com",
"name": "Someone Else",
"username": self.USERNAME,
"password": self.PASSWORD,
})
self.assertEqual(response.status_code, 409)
self.assertEqual(response.content, json.dumps(["username"]))
def test_register_duplicate_username_and_email(self):
# Register the first user
response = self.client.post(self.url, {
"email": self.EMAIL,
"name": self.NAME,
"username": self.USERNAME,
"password": self.PASSWORD,
})
self.assertHttpOK(response)
# Try to create a second user with the same username
response = self.client.post(self.url, {
"email": self.EMAIL,
"name": "Someone Else",
"username": self.USERNAME,
"password": self.PASSWORD,
})
self.assertEqual(response.status_code, 409)
self.assertEqual(response.content, json.dumps(["email", "username"]))
def _assert_reg_field(self, extra_fields_setting, expected_field):
"""Retrieve the registration form description from the server and
......
"""HTTP end-points for the User API. """
import json
from django.conf import settings
from django.contrib.auth.models import User
......@@ -177,6 +178,7 @@ class RegistrationView(APIView):
return HttpResponse(form_desc.to_json(), content_type="application/json")
@method_decorator(ensure_csrf_cookie)
@method_decorator(require_post_params(DEFAULT_FIELDS))
def post(self, request):
"""Create the user's account.
......@@ -198,6 +200,18 @@ class RegistrationView(APIView):
request.POST["honor_code"] = "true"
request.POST["terms_of_service"] = "true"
# Handle duplicate username/email
conflicts = account_api.check_account_exists(
username=request.POST.get('username'),
email=request.POST.get('email')
)
if conflicts:
return HttpResponse(
status=409,
content=json.dumps(conflicts),
content_type="application/json"
)
# For the initial implementation, shim the existing login view
# from the student Django app.
from student.views import create_account
......
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