<filename>libdrf/login/tests.py
import re
from unittest import mock

from django.core import mail
from django.test import override_settings
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from .settings import login_settings

from . import factories, models

jwt_decode_handler = login_settings.JWT_DECODE_HANDLER


class RegistrationTestCase(APITestCase):

    @override_settings(USER_ACTIVATION=True)
    def test_email_registration(self):
        reg_payload = {
            'email': '<EMAIL>',
            'password': '<PASSWORD>',
        }

        outbox_size = len(mail.outbox)

        resp = self.client.post(reverse('register'), reg_payload)
        self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)

        # Check user and customer are inactive
        u = models.User.objects.get(email=reg_payload.get('email'))
        self.assertFalse(u.is_verified)

        # Get the validation code from the email
        self.assertEqual(len(mail.outbox), outbox_size + 1)
        registration_email = mail.outbox[-1]
        match = re.search(r'/activate/(.+?)/(\S+)', registration_email.body)
        self.assertIsNotNone(match)
        user_id, token = match.groups()

        # Validate
        val_payload = {
            'user_id': user_id,
            'token': token,
        }
        resp = self.client.post(reverse('activate'), val_payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertTrue(len(resp.json()['token']) > 0)

        # Check that user is active
        u.refresh_from_db()
        self.assertTrue(u.is_verified)

    @override_settings(USER_ACTIVATION=False)
    def test_email_registration_existing_email(self):
        factories.UserFactory(email='<EMAIL>')
        reg_payload = {
            'email': '<EMAIL>',
            'password': '<PASSWORD>',
        }
        resp = self.client.post(reverse('register'), reg_payload)
        self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)

    def test_email_login(self):
        user = factories.UserFactory(email='<EMAIL>')
        user.set_password('<PASSWORD>')
        user.save()
        payload = {'email': '<EMAIL>', 'password': '<PASSWORD>'}
        resp = self.client.post(reverse('login'), payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertTrue(len(resp.json()['token']) > 0)
        payload = {'email': '<EMAIL>', 'password': '<PASSWORD>'}
        resp = self.client.post(reverse('login'), payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertTrue(len(resp.json()['token']) > 0)

    def test_change_password_authenticated(self):
        user = factories.UserFactory(email='<EMAIL>')
        user.set_password('<PASSWORD>')
        user.save()
        self.client.force_authenticate(user)
        payload = {'old_password': '<PASSWORD>', 'password': '<PASSWORD>'}
        resp = self.client.post(reverse('change-password'), payload)
        self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
        payload = {'old_password': '<PASSWORD>', 'password': '<PASSWORD>'}
        resp = self.client.post(reverse('change-password'), payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertTrue(len(resp.json()['token']) > 0)

    @override_settings(USER_ACTIVATION=False)
    def test_email_case_sensitivity(self):
        reg_payload = {
            'email': '<EMAIL>',
            'password': '<PASSWORD>',
        }
        resp = self.client.post(reverse('register'), reg_payload)
        self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
        self.assertEqual(models.User.objects.count(), 1)
        self.assertEqual(models.User.objects.get().email, '<EMAIL>')

    @mock.patch.multiple(
        'libdrf.login.authentication.GoogleOauth2TokenAuthentication',
        validate_token=mock.DEFAULT,
        fetch_email=mock.DEFAULT
    )
    def test_google_registration(self, validate_token, fetch_email):
        validate_token.return_value = None
        fetch_email.return_value = '<EMAIL>'

        reg_payload = {
            'access_token': '<PASSWORD>',
        }

        resp = self.client.post(reverse('validate_google_token'), reg_payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        token = resp.json()['token']
        payload = jwt_decode_handler(token)
        u = models.User.objects.get(pk=payload.get('user_id'))
        self.assertFalse(u.has_usable_password())
        self.assertTrue(u.is_verified)

<filename>libdrf/login/tests.py
import re
from unittest import mock

from django.core import mail
from django.test import override_settings
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from .settings import login_settings

from . import factories, models

jwt_decode_handler = login_settings.JWT_DECODE_HANDLER


class RegistrationTestCase(APITestCase):

    @override_settings(USER_ACTIVATION=True)
    def test_email_registration(self):
        reg_payload = {
            'email': '<EMAIL>',
            'password': '<PASSWORD>',
        }

        outbox_size = len(mail.outbox)

        resp = self.client.post(reverse('register'), reg_payload)
        self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)

        # Check user and customer are inactive
        u = models.User.objects.get(email=reg_payload.get('email'))
        self.assertFalse(u.is_verified)

        # Get the validation code from the email
        self.assertEqual(len(mail.outbox), outbox_size + 1)
        registration_email = mail.outbox[-1]
        match = re.search(r'/activate/(.+?)/(\S+)', registration_email.body)
        self.assertIsNotNone(match)
        user_id, token = match.groups()

        # Validate
        val_payload = {
            'user_id': user_id,
            'token': token,
        }
        resp = self.client.post(reverse('activate'), val_payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertTrue(len(resp.json()['token']) > 0)

        # Check that user is active
        u.refresh_from_db()
        self.assertTrue(u.is_verified)

    @override_settings(USER_ACTIVATION=False)
    def test_email_registration_existing_email(self):
        factories.UserFactory(email='<EMAIL>')
        reg_payload = {
            'email': '<EMAIL>',
            'password': '<PASSWORD>',
        }
        resp = self.client.post(reverse('register'), reg_payload)
        self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)

    def test_email_login(self):
        user = factories.UserFactory(email='<EMAIL>')
        user.set_password('<PASSWORD>')
        user.save()
        payload = {'email': '<EMAIL>', 'password': '<PASSWORD>'}
        resp = self.client.post(reverse('login'), payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertTrue(len(resp.json()['token']) > 0)
        payload = {'email': '<EMAIL>', 'password': '<PASSWORD>'}
        resp = self.client.post(reverse('login'), payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertTrue(len(resp.json()['token']) > 0)

    def test_change_password_authenticated(self):
        user = factories.UserFactory(email='<EMAIL>')
        user.set_password('<PASSWORD>')
        user.save()
        self.client.force_authenticate(user)
        payload = {'old_password': '<PASSWORD>', 'password': '<PASSWORD>'}
        resp = self.client.post(reverse('change-password'), payload)
        self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
        payload = {'old_password': '<PASSWORD>', 'password': '<PASSWORD>'}
        resp = self.client.post(reverse('change-password'), payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertTrue(len(resp.json()['token']) > 0)

    @override_settings(USER_ACTIVATION=False)
    def test_email_case_sensitivity(self):
        reg_payload = {
            'email': '<EMAIL>',
            'password': '<PASSWORD>',
        }
        resp = self.client.post(reverse('register'), reg_payload)
        self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
        self.assertEqual(models.User.objects.count(), 1)
        self.assertEqual(models.User.objects.get().email, '<EMAIL>')

    @mock.patch.multiple(
        'libdrf.login.authentication.GoogleOauth2TokenAuthentication',
        validate_token=mock.DEFAULT,
        fetch_email=mock.DEFAULT
    )
    def test_google_registration(self, validate_token, fetch_email):
        validate_token.return_value = None
        fetch_email.return_value = '<EMAIL>'

        reg_payload = {
            'access_token': '<PASSWORD>',
        }

        resp = self.client.post(reverse('validate_google_token'), reg_payload)
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        token = resp.json()['token']
        payload = jwt_decode_handler(token)
        u = models.User.objects.get(pk=payload.get('user_id'))
        self.assertFalse(u.has_usable_password())
        self.assertTrue(u.is_verified)

# Check user and customer are inactive # Get the validation code from the email # Validate # Check that user is active