示例#1
0
    def test_token_is_created(self):
        """We test whether we are able to create a token"""

        payload = {
            'email': '*****@*****.**',
            'callback_url': 'http://www.example.com'
        }

        token = TokenHandler().create_verification_token(payload)
        # a valid token should be decoded
        self.assertTrue(TokenHandler().validate_token(token))
示例#2
0
    def test_not_alphanumeric_password(self):
        """"Tests for a request with a password that is not alphanumeric."""
        signup_data = {
            "user": {
                "username": "******",
                "email": "*****@*****.**",
                "password": "******",
                "callback_url": "https://medium.com"
            }
        }
        payload = {
            "email": "*****@*****.**",
            "callback_url": "https://www.youtube.com/"
        }
        token = TokenHandler().create_verification_token(payload)
        not_alphanumeric_password_data = {
            "user_password": {
                "password": "******",
                "confirm_password": "******",
                "token": token
            }
        }

        not_alphanumeric_password_data_response = {
            "errors": {
                "password": ["Password should be alphanumeric"]
            }
        }
        self.client.post(self.register_url, signup_data, format='json')
        response = self.client.put(self.url,
                                   not_alphanumeric_password_data,
                                   format='json')
        self.assertEqual(response.data,
                         not_alphanumeric_password_data_response)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
示例#3
0
    def test_an_invalid_token_cannot_be_decoded(self):
        """If a user passes an invalid jwt token, it should not be decoded"""

        token = ''
        res = TokenHandler().validate_token(token)

        self.assertEqual(res, 'Error. Could not decode token!')
示例#4
0
    def test_long_password(self):
        """"Tests for a request with a password longer than 128 characters."""
        signup_data = {
            "user": {
                "username": "******",
                "email": "*****@*****.**",
                "password": "******",
                "callback_url": "https://medium.com"
            }
        }
        payload = {
            "email": "*****@*****.**",
            "callback_url": "https://www.youtube.com/"
        }
        token = TokenHandler().create_verification_token(payload)
        long_password_data = {
            "user_password": {
                "password": "******" * 50,
                "confirm_password": "******" * 50,
                "token": token
            }
        }

        long_password_data_response = {
            "errors": {
                "password":
                ["Password should not be longer than 128 characters"]
            }
        }
        self.client.post(self.register_url, signup_data, format='json')
        response = self.client.put(self.url, long_password_data, format='json')
        self.assertEqual(response.data, long_password_data_response)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
示例#5
0
    def test_expired_token_results_in_an_error(self):
        """If a token expires, users should not be verified by providing it"""

        token_expiry = date.today() - timedelta(1)

        payload = {
            'email': '*****@*****.**',
            'callback_url': 'http://www.example.com'
        }

        token = jwt.encode(
            {
                'email': payload['email'],
                'callback_url': payload['callback_url'],
                'exp': int(token_expiry.strftime('%s'))
            },
            settings.SECRET_KEY,
            algorithm='HS256')

        with self.assertRaises(exceptions.AuthenticationFailed) as e:
            TokenHandler().validate_token(token)

        self.assertEqual(
            str(e.exception),
            'Your token has expired. Make a new token and try again')
示例#6
0
    def test_not_matching_passwords(self):
        """"Tests for a request with passwords that do not match."""
        signup_data = {
            "user": {
                "username": "******",
                "email": "*****@*****.**",
                "password": "******",
                "callback_url": "https://medium.com"
            }
        }
        payload = {
            "email": "*****@*****.**",
            "callback_url": "https://www.youtube.com/"
        }
        token = TokenHandler().create_verification_token(payload)
        password_data = {
            "user_password": {
                "password": "******",
                "confirm_password": "******",
                "token": token
            }
        }

        self.client.post(self.register_url, signup_data, format='json')
        user = get_object_or_404(User, email="*****@*****.**")
        user_id = user.id
        token_data = {"user": user_id, "token": token}
        serializer = PasswordResetTokenSerializer(data=token_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        password_data_response = {"message": "Passwords do not Match"}
        response = self.client.put(self.url, password_data, format='json')
        self.assertEqual(response.data, password_data_response)
示例#7
0
    def test_no_password_field(self):
        """Tests for a request with no password field."""
        signup_data = {
            "user": {
                "username": "******",
                "email": "*****@*****.**",
                "password": "******",
                "callback_url": "https://medium.com"
            }
        }
        payload = {
            "email": "*****@*****.**",
            "callback_url": "https://www.youtube.com/"
        }
        token = TokenHandler().create_verification_token(payload)
        blank_password_data = {
            "user_password": {
                "password": "",
                "confirm_password": "",
                "token": token
            }
        }

        blank_password_data_response = {
            "errors": {
                "password": ["Password field cannot be blank"]
            }
        }
        self.client.post(self.register_url, signup_data, format='json')
        response = self.client.put(self.url,
                                   blank_password_data,
                                   format='json')
        self.assertEqual(response.data, blank_password_data_response)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
示例#8
0
    def test_decoding_failure_because_payload_is_not_dictionary(self):
        """The payload to be encoded should be a dictionary"""

        payload = ['just a list']

        with self.assertRaises(TypeError) as e:
            TokenHandler().create_verification_token(payload)
        self.assertEqual(str(e.exception), 'Payload must be a dictionary!')
示例#9
0
 def post(self, request):
     data = request.data.get('payload')
     serializer = PasswordResetSerializer(data=data)
     serializer.is_valid(raise_exception=True)
     user_email = data['email']
     callback_url = data['callback_url']
     message = "A password reset link has been sent to your email."
     try:
         user = User.objects.get(email=user_email)
         user_id = user.id
         payload = {"email": user_email, "callback_url": callback_url}
         token = TokenHandler().create_verification_token(payload)
         token_data = {"user": user_id, "token": token}
         serializer = PasswordResetTokenSerializer(data=token_data)
         serializer.is_valid(raise_exception=True)
         serializer.save()
         TokenHandler().send_password_reset_link(user_email, token,
                                                 callback_url)
         return Response({"message": message}, status=status.HTTP_200_OK)
     except User.DoesNotExist:
         return Response({"message": message}, status=status.HTTP_200_OK)
示例#10
0
    def test_users_can_get_verified(self):
        """Unverified users should be able to verify their accounts"""
        user = User.objects.create_user(username='******', email='*****@*****.**', password='******')
        user.save()

        data = {'email': '*****@*****.**',
                'username': '******',
                'callback_url': 'http://www.youtube.com'}

        token = TokenHandler().create_verification_token(data)

        client = APIClient()
        res = client.get(reverse('authentication:verify email', args=(token,)))
        self.assertEqual(res.status_code, status.HTTP_302_FOUND)
示例#11
0
    def put(self, request):
        """
         put:
             Update a user's password with a new password.
         """
        try:
            data = request.data.get('user_password')
            serializer = PasswordChangeSerializer(data=data)
            serializer.is_valid(raise_exception=True)
            token = data['token']
            user = PasswordResetToken.objects.get(token=token)
            is_valid = user.is_valid
            if is_valid:
                credentials = TokenHandler().validate_token(token)
                password = data['password']
                confirm_password = data['confirm_password']

                if password != confirm_password:
                    return Response({"message": "Passwords do not Match"})

                serializer = PasswordChangeSerializer(data=data)
                serializer.is_valid(raise_exception=True)
                serializer = PasswordChangeSerializer(instance=User,
                                                      data=data,
                                                      partial=True)
                serializer = User.objects.get(email=credentials['email'])
                serializer.set_password(password)
                serializer.save()
                user.is_valid = False
                user.save()
                return Response({'message': 'Your password has been changed.'},
                                status=status.HTTP_202_ACCEPTED)

            else:
                return Response(
                    {
                        'message':
                        'Sorry, we couldn\'t find that password reset'
                        ' key in our database. Please send another request.'
                    },
                    status=status.HTTP_404_NOT_FOUND)

        except PasswordResetToken.DoesNotExist:
            return Response(
                {'message': 'A user with the given token does not exist.'},
                status=status.HTTP_404_NOT_FOUND)
示例#12
0
    def test_using_same_link_twice(self):
        """Tests for a request with an already used token."""
        signup_data = {
            "user": {
                "username": "******",
                "email": "*****@*****.**",
                "password": "******",
                "callback_url": "https://medium.com"
            }
        }
        payload = {
            "email": "*****@*****.**",
            "callback_url": "https://medium.com"
        }

        token = TokenHandler().create_verification_token(payload)

        data = {
            "user_password": {
                "password": "******",
                "confirm_password": "******",
                "token": token
            }
        }

        data_response = {
            "message":
            "Sorry, we couldn't find that password reset key in our database."
            " Please send another request."
        }

        self.client.post(self.register_url, signup_data, format='json')
        user = get_object_or_404(User, email="*****@*****.**")
        user_id = user.id
        token_data = {"user": user_id, "token": token}
        serializer = PasswordResetTokenSerializer(data=token_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        self.client.post(self.register_url, signup_data, format='json')
        self.client.put(self.url, data, format='json')
        response = self.client.put(self.url, data, format='json')
        self.assertEqual(response.data, data_response)
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
示例#13
0
    def get(self, request, token):
        decoded_token = TokenHandler().validate_token(token)

        if 'email' not in decoded_token:
            return Response({'error': 'invalid token'},
                            status=status.HTTP_400_BAD_REQUEST)
        # we check if the user exists and whether they are verified.
        # if we don't find a user we raise an error
        # if we find a registered user, we raise an error
        try:
            user = User.objects.get(email=decoded_token['email'])
        except User.DoesNotExist:
            return Response(
                {'email': 'No user with this email has been registered'},
                status=status.HTTP_404_NOT_FOUND)

        if user.is_verified is True:
            return Response({'email': 'This email has already been verified'},
                            status=status.HTTP_400_BAD_REQUEST)
        user.is_verified = True
        user.save()
        return HttpResponseRedirect(decoded_token['callback_url'])
示例#14
0
    def post(self, request):
        """This is the method that will be called when users
        want a new verification token."""
        data = request.data

        serializer = self.serializer_class(data=data)
        serializer.is_valid(raise_exception=True)
        payload = serializer.create_payload(data)

        token = TokenHandler().create_verification_token(payload)
        user_email = payload['email']
        domain = settings.DOMAIN
        template_name = 'email_verification.html'
        context = {
            'username': payload['username'],
            'token': token,
            'domain': domain
        }
        html_message = render_to_string(template_name, context)
        text_message = strip_tags(html_message)
        thread = Thread(target=mail.send_mail,
                        args=[
                            'Please verify your email', text_message,
                            settings.FROM_EMAIL, [
                                user_email,
                            ], html_message
                        ])
        thread.setDaemon(True)
        thread.start()

        message = {
            'message':
            'New verification token created. Please proceed to your email '
            +  # noqa
            user_email + ' to verify your account.'
        }
        return Response(message, status=status.HTTP_201_CREATED)
示例#15
0
    def post(self, request):
        user = request.data.get('user', {})

        # The create serializer, validate serializer, save serializer pattern
        # below is common and you will see it a lot throughout this course and
        # your own work later on. Get familiar with it.
        serializer = self.serializer_class(data=user)
        serializer.is_valid(raise_exception=True)
        user_email = serializer.validated_data['email']
        username = serializer.validated_data['username']
        callback = {'url': serializer.validated_data['callback_url']}
        token_payload = {'email': user_email, 'callback_url': callback['url']}
        domain = settings.DOMAIN
        token = TokenHandler().create_verification_token(token_payload)
        template_name = 'email_verification.html'
        context = {'username': username, 'token': token, 'domain': domain}
        # https://stackoverflow.com/questions/3005080/how-to-send-html-email-with-django-with-dynamic-content-in-it
        html_message = render_to_string(template_name, context)
        text_message = strip_tags(html_message)
        thread = Thread(target=mail.send_mail,
                        args=[
                            'Please verify your email', text_message,
                            settings.FROM_EMAIL, [
                                user_email,
                            ], html_message
                        ])
        thread.setDaemon(True)
        thread.start()

        message = {
            'message':
            'Successfully created your account. Please proceed to your email '
            +  # noqa
            user_email + ' to verify your account.'
        }
        serializer.save()
        return Response(message, status=status.HTTP_201_CREATED)
示例#16
0
    def test_valid_new_password(self):
        """Tests for a request with a valid new password."""
        signup_data = {
            "user": {
                "username": "******",
                "email": "*****@*****.**",
                "password": "******",
                "callback_url": "https://medium.com"
            }
        }

        payload = {
            "email": "*****@*****.**",
            "callback_url": "https://medium.com"
        }
        token = TokenHandler().create_verification_token(payload)

        data = {
            "user_password": {
                "password": "******",
                "confirm_password": "******",
                "token": token
            }
        }
        self.client.post(self.register_url, signup_data, format='json')
        user = get_object_or_404(User, email="*****@*****.**")
        user_id = user.id
        token_data = {"user": user_id, "token": token}
        serializer = PasswordResetTokenSerializer(data=token_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        data_response = {"message": "Your password has been changed."}
        response = self.client.put(self.url, data, format='json')
        self.assertEqual(response.data, data_response)
        self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
示例#17
0
    def test_token_can_only_be_encoded_if_neccessary_keys_are_passed(self):
        """For a token to be created, we need the `email` and `callback_url` to be provided"""

        error = TokenHandler().create_verification_token({})
        self.assertEqual(error, 'Please provide email and callback_url')