Skip to content

Commit

Permalink
Merge pull request #11 from andela/ft-signup-error-messages-159082306
Browse files Browse the repository at this point in the history
#159082306 Users should receive descriptive signup/Registration validation errors
  • Loading branch information
pluwum committed Jul 30, 2018
2 parents acdf14a + 47029b2 commit 4312aec
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 24 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,6 @@ db.sqlite3

# vs code
.vscode/

#DS STORE
.DS_Store
6 changes: 5 additions & 1 deletion authors/apps/authentication/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from rest_framework.renderers import JSONRenderer

from django.urls import reverse_lazy


class UserJSONRenderer(JSONRenderer):
charset = 'utf-8'
Expand All @@ -12,6 +14,7 @@ def render(self, data, media_type=None, renderer_context=None):
# the default JSONRenderer to handle rendering errors, so we need to
# check for this case.
errors = data.get('errors', None)


if errors is not None:
# As mentioned about, we will let the default JSONRenderer handle
Expand All @@ -21,5 +24,6 @@ def render(self, data, media_type=None, renderer_context=None):

# Finally, we can render our data under the "user" namespace.
return json.dumps({
'user': data
'user': data,
'message': "You were successfully registered!",
})
27 changes: 23 additions & 4 deletions authors/apps/authentication/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@

from .models import User

import re

class RegistrationSerializer(serializers.ModelSerializer):
"""Serializers registration requests and creates a new user."""

# Ensure passwords are at least 8 characters long, no longer than 128
# characters, and can not be read by the client.
password = serializers.CharField(
max_length=128,
min_length=8,
write_only=True
max_length = 128,
min_length = 8,
write_only = True,
)
email = serializers.EmailField(max_length = 255,)
username = serializers.CharField(max_length = 255, min_length = 6,)

# The client should not be able to send a token along with a registration
# request. Making `token` read-only handles that for us.
Expand All @@ -25,11 +28,27 @@ class Meta:
# or response, including fields specified explicitly above.
fields = ['email', 'username', 'password']

def validate_email(self, value):
user_qs = User.objects.filter(email=value)
if user_qs.exists():
raise serializers.ValidationError("We cannot register you because there's a user with that email already.")
return value

def validate_username(self, value):
user_qs = User.objects.filter(username=value)
if user_qs.exists():
raise serializers.ValidationError("We cannot register you because there's a user with that username already.")
return value

def validate_password(self, value):
if re.match("^[a-zA-Z0-9_]+$", value) is not None :
raise serializers.ValidationError("Please include at least a number and any of these symbols in your password @,#,!,$,%,&,*,(,) ")
return value

def create(self, validated_data):
# Use the `create_user` method we wrote earlier to create a new user.
return User.objects.create_user(**validated_data)


class LoginSerializer(serializers.Serializer):
email = serializers.CharField(max_length=255)
username = serializers.CharField(max_length=255, read_only=True)
Expand Down
16 changes: 6 additions & 10 deletions authors/apps/authentication/tests/test_login.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def setUp(self):
'user': {
'username': 'rutale',
'email': 'rutale@gmail.com',
'password': 'rutaleivan'
'password': 'rutaleivan#'
}
}
request = self.factory.post(
Expand All @@ -27,7 +27,7 @@ def test_login_wrong_email(self):
'user': {
'username': 'rutale',
'email': 'rut@gmail.com',
'password': 'rutaleivan'
'password': 'rutaleivan#'
}
}
request=self.factory.post(
Expand All @@ -54,7 +54,7 @@ def test_login_missing_email(self):
'user': {
'username': 'rutale',
'email': '',
'password': 'rutaleivan'
'password': 'rutaleivan#'
}
}
request=self.factory.post(
Expand Down Expand Up @@ -122,7 +122,7 @@ def test_datastructure_user_error_missing_email_field(self):
user = {
'user': {
'username': 'rutale',
'password': 'rutaleivan'
'password': 'rutaleivan#'
}
}
request=self.factory.post(
Expand All @@ -135,15 +135,11 @@ def test_datastructure_user_error_missing_username_field(self):
user = {
'user': {
'email': 'rutale@gmail.com',
'password': 'rutaleivan'
'password': 'rutaleivan#'
}
}
request=self.factory.post(
"/api/users/login", data=json.dumps(user), content_type='application/json')
response = LoginAPIView.as_view()(request)
self.assertEqual(response.status_code,200)





self.assertEqual(response.status_code,200)
11 changes: 6 additions & 5 deletions authors/apps/authentication/tests/test_registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ def setUp(self):
self.user = {
"user" : {
"email":"test@gmail.com",
"username":"test",
"password":"testpassword"
"username":"tester",
"password":"testpass@word"
}
}

Expand Down Expand Up @@ -43,7 +43,7 @@ def test_user_registration_with_invalid_email(self):
user = {
"user" : {
"email":"testgmail.com",
"username":"test",
"username":"tester",
"password":"testpassword"
}
}
Expand All @@ -63,8 +63,9 @@ def test_user_registration_for_email_that_already_exists(self):
request = self.factory.post('/api/users/', data = json.dumps(self.user), content_type='application/json')

response = RegistrationAPIView.as_view()(request)

self.assertEqual("We cannot register you because there's a user with that email already.",response.data["errors"]["email"][0])

self.assertIn('user with this email already exists.',response.data["errors"]["email"][0])
self.assertEqual(response.status_code, 400)


Expand All @@ -76,5 +77,5 @@ def test_user_registration_for_username_that_already_exists(self):

response = RegistrationAPIView.as_view()(request)

self.assertIn('user with this username already exists.',response.data["errors"]["username"][0])
self.assertIn("We cannot register you because there's a user with that username already.",response.data["errors"]["username"][0])
self.assertEqual(response.status_code, 400)
3 changes: 2 additions & 1 deletion authors/apps/authentication/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ def update(self, request, *args, **kwargs):
serializer.is_valid(raise_exception=True)
serializer.save()

return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.data, status=status.HTTP_200_OK)

4 changes: 2 additions & 2 deletions authors/apps/core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def _handle_generic_error(exc, context, response):
# This is about the most straightforward exception handler we can create.
# We take the response generated by DRF and wrap it in the `errors` key.
response.data = {
'errors': response.data
'errors': response.data,
"status_code": response.status_code
}

return response
1 change: 1 addition & 0 deletions authors/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,5 @@
'DEFAULT_AUTHENTICATION_CLASSES': (
'authors.apps.authentication.backends.JWTAuthentication',
),

}
3 changes: 2 additions & 1 deletion authors/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
urlpatterns = [
path('admin/', admin.site.urls),

path('api/', include('authors.apps.authentication.urls', namespace='authentication')),
path('api/', include('authors.apps.authentication.urls')),

]

0 comments on commit 4312aec

Please sign in to comment.