diff --git a/authors/apps/authentication/serializers.py b/authors/apps/authentication/serializers.py index e0a3a98..c75d990 100644 --- a/authors/apps/authentication/serializers.py +++ b/authors/apps/authentication/serializers.py @@ -17,8 +17,14 @@ class RegistrationSerializer(serializers.ModelSerializer): # Ensure passwords are at least 8 characters long, no longer than 30 # Password has no spaces + # Ensure password has two uppercase letters + # Ensure password has one special case letter. + # Ensure password has two digits + # Ensure password has three lowercase letters + password = serializers.RegexField( - regex=("^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)\S{8,}$"), + regex=( + "^(?=.*[A-Z].*[A-Z])(?=.*[!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8,}$"), max_length=30, min_length=8, write_only=True, @@ -27,7 +33,7 @@ class RegistrationSerializer(serializers.ModelSerializer): 'required': 'Password is a required field', 'min_length': 'Password must be at least 8 characters long', 'max_length': 'Password cannot be more than 30 characters', - 'invalid': 'Password must have alphanumeric characters with no space', + 'invalid': 'Password must have three lowercase, two upercase, one special case letters and two digits eg 12aaaAA@', } ) @@ -36,7 +42,7 @@ class RegistrationSerializer(serializers.ModelSerializer): # Email should have no spaces email = serializers.RegexField( regex=( - "^[^<>()[\]\\,;:\%=#^\s@\"$&!@]+@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z0-9]+\.)+[a-zA-Z]{2,}))$"), + "^([a-zA-Z0-9_\-\.@#]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$"), required=True, validators=[ UniqueValidator( @@ -45,25 +51,26 @@ class RegistrationSerializer(serializers.ModelSerializer): ) ], error_messages={ - 'invalid': 'Email must be of the format name@domain.com and should not contain any special characters before @', + 'invalid': 'Email must be of the format name@domain.com', 'required': 'Email is a required field' } ) # Username should be unique # Username should not have spaces or special characters - # Underscores and hyphens are allowed + # Username should be atleast 3 characters and maximum length of 15 + # Only Underscores and hyphens are allowed username = serializers.RegexField( - regex='^(?!.*\ )[A-Za-z\d\-\_]+$', + regex='^[a-z0-9._-]{3,15}$', required=True, validators=[ UniqueValidator( queryset=User.objects.all(), - message='username already taken', + message='user with this username already exists', ) ], error_messages={ - 'invalid': 'Username should have no spaces or special characters only', + 'invalid': 'Username should be at least 3 characters, have no spaces or special characters except hyphen-, fullstop. and underscore_', 'required': 'Username is a required field' } ) @@ -214,6 +221,8 @@ class SocialAuthSerializer(serializers.Serializer): allow_blank=True, default="" ) + + class PasswordResetSerializer(serializers.Serializer): """ Serializer for password reset diff --git a/authors/apps/authentication/tests/basetests.py b/authors/apps/authentication/tests/basetests.py index 8994ef8..34d9167 100644 --- a/authors/apps/authentication/tests/basetests.py +++ b/authors/apps/authentication/tests/basetests.py @@ -28,7 +28,7 @@ def setUp(self): self.user = User.objects.create_user( username="adam", email="adam@gmail.com", - password="@Us3r.com", + password="@UUss35r.com", ) self.user.is_verified=True self.user.save() @@ -36,7 +36,7 @@ def setUp(self): self.user1 = User.objects.create_user( username="ian", email="ian@gmail.com", - password="Maina9176", + password="@UUss35r.com", ) self.user1.is_verified=True self.user1 = User.objects.get(username='ian') @@ -46,19 +46,19 @@ def setUp(self): self.user2 = User.objects.create_user( username="theonly", email="ianissa@gmail.com", - password="Maina9176", + password="@UUss35r.com", ) self.user3 = User.objects.create_user( username="Escobar", email="pablo@escobar.com", - password="Maina9176", + password="@UUss35r.com", ) self.user4 = User.objects.create_user( username="Elchapo", email="el@chapo.com", - password="Maina9176", + password="@UUss35r.com", ) self.user4.is_verified=True diff --git a/authors/apps/authentication/tests/test_jwt_authentication.py b/authors/apps/authentication/tests/test_jwt_authentication.py index 7b65ae4..20161bb 100644 --- a/authors/apps/authentication/tests/test_jwt_authentication.py +++ b/authors/apps/authentication/tests/test_jwt_authentication.py @@ -14,14 +14,14 @@ def test_get_jwt_with_unverified_user_after_login(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_get_jwt_after_login(self): - self.signup_user('issa', 'issamwangi@gmail.com', 'Maina9176') + self.signup_user('issa', 'issamwangi@gmail.com', '@UUss35r.com') self.verify_user('issamwangi@gmail.com') - response = self.login_user('issamwangi@gmail.com', 'Maina9176') + response = self.login_user('issamwangi@gmail.com', '@UUss35r.com') self.assertEqual(response.status_code, status.HTTP_200_OK) def test_get_jwt_after_signup(self): response = self.signup_user( - 'issa', 'issamwangi@gmail.com', 'Maina9176') + 'issa', 'issamwangi@gmail.com', '@UUss35r.com') self.assertEqual(response.status_code, status.HTTP_201_CREATED) def test_invalid_authorization_header(self): diff --git a/authors/apps/authentication/tests/test_users.py b/authors/apps/authentication/tests/test_users.py index 243533e..6a82b38 100644 --- a/authors/apps/authentication/tests/test_users.py +++ b/authors/apps/authentication/tests/test_users.py @@ -32,21 +32,21 @@ def test_successful_signup(self): """ Test user signup with the correct credentials """ - response = self.signup_user("eve", "eve@gmail.com", "@Us3r.com") + response = self.signup_user("eve", "eve@gmail.com", "@UUss35r.com") self.assertEqual(response.status_code, status.HTTP_201_CREATED) def test_signup_without_value(self): """ Test user signup with the missing value credentials """ - response = self.signup_user("", "eve@gmail.com", "@Us3r.com") + response = self.signup_user("", "eve@gmail.com", "@UUss3r.com") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_signup_with_invalid_value(self): """ Test user signup with invalid value credentials """ - response = self.signup_user("evegirl", "evegmail.com", "@Us3r.com") + response = self.signup_user("evegirl", "evegmail.com", "@UUss3r.com") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) response = self.signup_user("evegirl", "eve@gmail.com", "@Us") @@ -56,7 +56,7 @@ def test_signup_with_existing_user(self): """ Test user signup with credentials that exist """ - response = self.signup_user("adam", "adam@gmail.com", "@Us3r.com") + response = self.signup_user("adam", "adam@gmail.com", "@UUss3r.com") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_signup_without_key(self): @@ -78,7 +78,7 @@ def test_login_with_correct_credentials(self): """ Test user login with the correct credentials """ - response = self.login_user("adam@gmail.com", "@Us3r.com") + response = self.login_user("adam@gmail.com", "@UUss35r.com") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIn('token', str(response.data)) @@ -86,7 +86,7 @@ def test_login_with_incorrect_credentials(self): """ Test user login with the incorrect credentials """ - response = self.login_user("dam@gmail.com", "@Us3r.com") + response = self.login_user("dam@gmail.com", "@UUss35r.com") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -100,15 +100,15 @@ def test_update_with_user_login(self): """ Test user update with the correct credentials """ - self.authenticate_user("adam@gmail.com", "@Us3r.com") - response = self.update_user("admin1", "adam@gmail.com", "@Us3r.com") + self.authenticate_user("adam@gmail.com", "@UUss35r.com") + response = self.update_user("admin1", "adam@gmail.com", "@UUss35r.com") self.assertEqual(response.status_code, status.HTTP_200_OK) def test_update_with_user_logged_out(self): """ Test user update with user not logged in """ - response = self.update_user("admin1", "adam@gmail.com", "@Us3r.com") + response = self.update_user("admin1", "adam@gmail.com", "@UUss35r.com") self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_update_with_user_details_exist(self): @@ -116,7 +116,7 @@ def test_update_with_user_details_exist(self): Test user update with user details that exist """ self.authenticate_user("admin@authors.com", "adm123Pass!!") - response = self.update_user("admin1", "adam@gmail.com", "@Us3r.com") + response = self.update_user("admin1", "adam@gmail.com", "@UUss35r.com") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) def test_update_with_invalid_value(self): @@ -124,7 +124,7 @@ def test_update_with_invalid_value(self): Test user update with invalid credentials """ self.authenticate_user("admin@authors.com", "adm123Pass!!") - response = self.update_user("admin1", "adamgmail.com", "@Us3r.com") + response = self.update_user("admin1", "adamgmail.com", "@UUss35r.com") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) response = self.update_user("evegirl", "eve@gmail.com", "@Us") @@ -141,7 +141,7 @@ def test_with_logged_in_user(self): """ Test get user with the correct login credentials """ - self.authenticate_user("adam@gmail.com", "@Us3r.com") + self.authenticate_user("adam@gmail.com", "@UUss35r.com") response = self.get_user() self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/authors/apps/authentication/tests/test_validations.py b/authors/apps/authentication/tests/test_validations.py index 9e65b69..4af3240 100644 --- a/authors/apps/authentication/tests/test_validations.py +++ b/authors/apps/authentication/tests/test_validations.py @@ -14,7 +14,7 @@ def test_invalid_username(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) errors = response.data['errors'] self.assertEqual( - errors['username'][0], "Username should have no spaces or special characters only") + errors['username'][0], "Username should be at least 3 characters, have no spaces or special characters except hyphen-, fullstop. and underscore_") def test_empty_username(self): """ @@ -33,7 +33,8 @@ def test_existing_username(self): response = self.signup_user("adam", "test@gmail.com", "12qQqetfdt") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) errors = response.data['errors'] - self.assertEqual(errors['username'][0], "username already taken") + self.assertEqual(errors['username'][0], + "user with this username already exists") def test_invalid_email(self): """ @@ -43,7 +44,7 @@ def test_invalid_email(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) errors = response.data['errors'] self.assertEqual( - errors['email'][0], "Email must be of the format name@domain.com and should not contain any special characters before @") + errors['email'][0], "Email must be of the format name@domain.com") def test_existing_email(self): """ @@ -65,14 +66,4 @@ def test_short_password(self): self.assertEqual(errors['password'][0], "Password must be at least 8 characters long") self.assertEqual( - errors['password'][1], "Password must have alphanumeric characters with no space") - - def test_non_alphanumeric_password(self): - """ - Test user signup with the special characters as password - """ - response = self.signup_user("test", "test@gmail.com", "@@@@@@@@@@") - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - errors = response.data['errors'] - self.assertEqual( - errors['password'][0], "Password must have alphanumeric characters with no space") + errors['password'][1], "Password must have three lowercase, two upercase, one special case letters and two digits eg 12aaaAA@") diff --git a/authors/apps/profiles/serializers.py b/authors/apps/profiles/serializers.py index 6a7ca74..c518924 100644 --- a/authors/apps/profiles/serializers.py +++ b/authors/apps/profiles/serializers.py @@ -11,12 +11,14 @@ class UserProfileSerializer(serializers.ModelSerializer): username = serializers.ReadOnlyField(source='fetch_username') img_url = serializers.ReadOnlyField(source='fetch_image') created_at = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S") + class Meta: model = Profile fields = ( 'username', 'first_name', 'last_name', 'bio', 'img_url', 'created_at' ) + class UpdateUserProfileSerializer(serializers.ModelSerializer): """ Serializer class for updating user profile @@ -36,10 +38,14 @@ class FollowingSerializer(serializers.ModelSerializer): class Meta: model = Followers fields = ('profile', 'followed') + + class UserListSerializer(serializers.ModelSerializer): """ Serializer class for getting user profile """ + username = serializers.ReadOnlyField(source='fetch_username') + class Meta: model = Profile - fields = '__all__' + exclude = ('user', 'id', )