Пример #1
0
class RegisterSerializerTestCase(TestCase):
    def test_ok(self):
        serializer_class = registration_settings.REGISTER_SERIALIZER_CLASS
        serializer = serializer_class(data={})
        field_names = set(serializer.get_fields())
        self.assertEqual(
            field_names,
            {
                'id', 'username', 'first_name', 'last_name', 'email',
                'password', 'password_confirm'
            },
        )

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_VERIFICATION,
            {
                'REGISTER_SERIALIZER_PASSWORD_CONFIRM': False,
            },
        ), )
    def test_no_password_ok(self):
        serializer_class = registration_settings.REGISTER_SERIALIZER_CLASS
        serializer = serializer_class(data={})
        field_names = set(serializer.get_fields())
        self.assertEqual(
            field_names,
            {'id', 'username', 'first_name', 'last_name', 'email', 'password'},
        )
class SendResetPasswordLinkViewTestCase(BaseResetPasswordViewTestCase):
    VIEW_NAME = 'send-reset-password-link'

    def test_send_link_ok(self):
        user = self.create_test_user(username='******')
        request = self.create_post_request({
            'login': user.username,
        })
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_200_OK)
        sent_email = sent_emails[0]
        self._assert_valid_send_link_email(sent_email, user, timer)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD,
            {
                'USER_VERIFICATION_ID_FIELD': 'username',
            },
        ), )
    def test_send_link_with_username_as_verification_id_ok(self):
        user = self.create_test_user(username='******')
        request = self.create_post_request({
            'login': user.username,
        })
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_200_OK)
        sent_email = sent_emails[0]
        verification_data = self._assert_valid_verification_email(
            sent_email, user)
        self.assertEqual(verification_data['user_id'], user.username)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = ResetPasswordSigner(verification_data)
        signer.verify()

    def test_send_link_but_email_not_in_login_fields(self):
        user = self.create_test_user(username='******',
                                     email='*****@*****.**')
        request = self.create_post_request({
            'login': user.email,
        })
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_404_NOT_FOUND)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD, {
                'USER_LOGIN_FIELDS': ['username', 'email'],
            }), )
    def test_send_link_via_login_username_ok(self):
        user = self.create_test_user(username='******')
        request = self.create_post_request({
            'login': user.username,
        })
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_200_OK)
        sent_email = sent_emails[0]
        self._assert_valid_send_link_email(sent_email, user, timer)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD, {
                'USER_LOGIN_FIELDS': ['username', 'email'],
            }), )
    def test_send_link_via_login_email_ok(self):
        user = self.create_test_user(username='******',
                                     email='*****@*****.**')
        request = self.create_post_request({
            'login': user.email,
        })
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_200_OK)
        sent_email = sent_emails[0]
        self._assert_valid_send_link_email(sent_email, user, timer)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD, {
                'USER_LOGIN_FIELDS': ['username', 'email'],
                'SEND_RESET_PASSWORD_LINK_SERIALIZER_USE_EMAIL': True,
            }), )
    def test_send_link_via_email_ok(self):
        user = self.create_test_user(username='******',
                                     email='*****@*****.**')
        request = self.create_post_request({
            'email': user.email,
        })
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_200_OK)
        sent_email = sent_emails[0]
        self._assert_valid_send_link_email(sent_email, user, timer)

    @skip("TODO: Issue #35")
    def test_send_link_disabled_user(self):
        pass

    def test_send_link_unverified_user(self):
        user = self.create_test_user(username='******', is_active=False)
        request = self.create_post_request({
            'login': user.username,
        })
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_200_OK)
        sent_email = sent_emails[0]
        self._assert_valid_send_link_email(sent_email, user, timer)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD, {
                'RESET_PASSWORD_VERIFICATION_ONE_TIME_USE': True,
            }), )
    def test_send_link_unverified_user_one_time_use(self):
        user = self.create_test_user(username='******', is_active=False)
        request = self.create_post_request({
            'login': user.username,
        })
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_200_OK)
        sent_email = sent_emails[0]
        self._assert_valid_send_link_email(sent_email, user, timer)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD, {
                'RESET_PASSWORD_VERIFICATION_ENABLED': False,
            }), )
    def test_reset_password_disabled(self):
        user = self.create_test_user(username='******')
        request = self.create_post_request({
            'login': user.username,
        })
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_not_found(response)

    @override_settings(
        TEMPLATES=(),
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD, {
                'RESET_PASSWORD_VERIFICATION_ENABLED': False,
            }),
    )
    def test_no_templates_reset_password_disabled(self):
        user = self.create_test_user(username='******')
        request = self.create_post_request({
            'login': user.username,
        })
        with self.capture_sent_emails() as sent_emails:
            response = self.view_func(request)
        self.assert_len_equals(sent_emails, 0)
        self.assert_response_is_not_found(response)

    def test_send_link_invalid_login(self):
        user = self.create_test_user(username='******')
        request = self.create_post_request({
            'login': user.username + 'b',
        })
        with self.assert_mails_sent(0):
            response = self.view_func(request)
            self.assert_response_is_not_found(response)

    def _assert_valid_send_link_email(self, sent_email, user, timer):
        verification_data = self._assert_valid_verification_email(
            sent_email, user)
        self._assert_valid_verification_data(verification_data, user, timer)

    def _assert_valid_verification_email(self, sent_email, user):
        self.assertEqual(
            sent_email.from_email,
            REST_REGISTRATION_WITH_RESET_PASSWORD['VERIFICATION_FROM_EMAIL'],
        )
        self.assertListEqual(sent_email.to, [user.email])
        url = self.assert_one_url_line_in_text(sent_email.body)
        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=RESET_PASSWORD_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp'},
        )
        return verification_data

    def _assert_valid_verification_data(self, verification_data, user, timer):
        self.assertEqual(int(verification_data['user_id']), user.id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = ResetPasswordSigner(verification_data)
        signer.verify()
class ResetPasswordViewTestCase(BaseResetPasswordViewTestCase):
    VIEW_NAME = 'reset-password'

    def test_reset_ok(self):
        old_password = '******'
        new_password = '******'
        user = self.create_test_user(password=old_password)
        signer = ResetPasswordSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['password'] = new_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_ok(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(new_password))

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD,
            {
                'USER_VERIFICATION_ID_FIELD': 'username',
            },
        ), )
    def test_reset_with_username_as_verification_id_ok(self):
        old_password = '******'
        new_password = '******'
        user = self.create_test_user(password=old_password)
        signer = ResetPasswordSigner({'user_id': user.username})
        data = signer.get_signed_data()
        data['password'] = new_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_ok(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(new_password))

    def test_reset_twice_ok(self):
        old_password = '******'
        new_first_password = '******'
        new_second_password = '******'
        user = self.create_test_user(password=old_password)
        signer = ResetPasswordSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['password'] = new_first_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_ok(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(new_first_password))
        data['password'] = new_second_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_ok(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(new_second_password))

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD, {
                'RESET_PASSWORD_VERIFICATION_ONE_TIME_USE': True,
            }), )
    def test_one_time_reset_twice_fail(self):
        old_password = '******'
        new_first_password = '******'
        new_second_password = '******'
        user = self.create_test_user(password=old_password)
        signer = ResetPasswordSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['password'] = new_first_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_ok(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(new_first_password))
        data['password'] = new_second_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_bad_request(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(new_first_password))

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD, {
                'RESET_PASSWORD_VERIFICATION_ENABLED': False,
            }), )
    def test_reset_password_disabled(self):
        old_password = '******'
        new_password = '******'
        user = self.create_test_user(password=old_password)
        signer = ResetPasswordSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['password'] = new_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_not_found(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(old_password))

    @skip("TODO: Issue #35")
    def test_reset_disabled_user(self):
        pass

    def test_reset_unverified_user(self):
        old_password = '******'
        new_password = '******'
        user = self.create_test_user(password=old_password, is_active=False)
        signer = ResetPasswordSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['password'] = new_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_ok(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(new_password))

    def test_reset_short_password(self):
        old_password = '******'
        new_password = '******'
        user = self.create_test_user(password=old_password)
        signer = ResetPasswordSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['password'] = new_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_bad_request(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(old_password))

    def test_reset_numeric_password(self):
        old_password = '******'
        new_password = '******'
        user = self.create_test_user(password=old_password)
        signer = ResetPasswordSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['password'] = new_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_bad_request(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(old_password))

    def test_reset_password_same_as_username(self):
        username = '******'
        old_password = '******'
        new_password = username
        user = self.create_test_user(username=username, password=old_password)
        signer = ResetPasswordSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['password'] = new_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_bad_request(response)
        user.refresh_from_db()
        self.assertTrue(user.check_password(old_password))

    def test_reset_tampered_timestamp(self):
        old_password = '******'
        new_password = '******'
        user = self.create_test_user(password=old_password)
        signer = ResetPasswordSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['timestamp'] += 1
        data['password'] = new_password
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)
        user.refresh_from_db()
        self.assertTrue(user.check_password(old_password))

    def test_reset_expired(self):
        timestamp = int(time.time())
        old_password = '******'
        new_password = '******'
        user = self.create_test_user(password=old_password)
        with patch('time.time', side_effect=lambda: timestamp):
            signer = ResetPasswordSigner({'user_id': user.pk})
            data = signer.get_signed_data()
        data['password'] = new_password
        request = self.create_post_request(data)
        with patch('time.time', side_effect=lambda: timestamp + 3600 * 24 * 8):
            response = self.view_func(request)
        self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)
        user.refresh_from_db()
        self.assertTrue(user.check_password(old_password))
Пример #4
0
class SendResetPasswordLinkViewTestCase(BaseResetPasswordViewTestCase):
    VIEW_NAME = 'send-reset-password-link'

    def test_send_link_ok(self):
        user = self.create_test_user(username='******')
        request = self.create_post_request({
            'login': user.username,
        })
        time_before = math.floor(time.time())
        with self.assert_one_mail_sent() as sent_emails:
            response = self.view_func(request)
            time_after = math.ceil(time.time())
            self.assert_valid_response(response, status.HTTP_200_OK)
        sent_email = sent_emails[0]
        self._assert_valid_send_link_email(sent_email, user, time_before,
                                           time_after)

    @skip("TODO: Issue #35")
    def test_send_link_disabled_user(self):
        pass

    def test_send_link_unverified_user(self):
        user = self.create_test_user(username='******', is_active=False)
        request = self.create_post_request({
            'login': user.username,
        })
        time_before = math.floor(time.time())
        with self.assert_one_mail_sent() as sent_emails:
            response = self.view_func(request)
            time_after = math.ceil(time.time())
            self.assert_valid_response(response, status.HTTP_200_OK)
        sent_email = sent_emails[0]
        self._assert_valid_send_link_email(sent_email, user, time_before,
                                           time_after)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_RESET_PASSWORD, {
                'RESET_PASSWORD_VERIFICATION_ENABLED': False,
            }), )
    def test_reset_password_disabled(self):
        user = self.create_test_user(username='******')
        request = self.create_post_request({
            'login': user.username,
        })
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_not_found(response)

    def test_send_link_invalid_login(self):
        user = self.create_test_user(username='******')
        request = self.create_post_request({
            'login': user.username + 'b',
        })
        with self.assert_mails_sent(0):
            response = self.view_func(request)
            self.assert_response_is_not_found(response)

    def _assert_valid_send_link_email(self, sent_email, user, time_before,
                                      time_after):
        self.assertEqual(
            sent_email.from_email,
            REST_REGISTRATION_WITH_RESET_PASSWORD['VERIFICATION_FROM_EMAIL'],
        )
        self.assertListEqual(sent_email.to, [user.email])
        url = self.assert_one_url_line_in_text(sent_email.body)
        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=RESET_PASSWORD_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp'},
        )
        self.assertEqual(int(verification_data['user_id']), user.id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, time_before)
        self.assertLessEqual(url_sig_timestamp, time_after)
        signer = ResetPasswordSigner(verification_data)
        signer.verify()
Пример #5
0
class VerifyRegistrationViewTestCase(APIViewTestCase):
    VIEW_NAME = 'verify-registration'

    def prepare_user(self):
        user = self.create_test_user(is_active=False)
        self.assertFalse(user.is_active)
        return user

    def prepare_request(self, user, session=False, data_to_sign=None):
        if data_to_sign is None:
            data_to_sign = {'user_id': user.pk}
        signer = RegisterSigner(data_to_sign)
        data = signer.get_signed_data()
        request = self.create_post_request(data)
        if session:
            self.add_session_to_request(request)
        return request

    def prepare_user_and_request(self, session=False):
        user = self.prepare_user()
        request = self.prepare_request(user, session=session)
        return user, request

    @override_settings(REST_REGISTRATION=REST_REGISTRATION_WITH_VERIFICATION)
    def test_verify_ok(self):
        user, request = self.prepare_user_and_request()
        response = self.view_func(request)
        self.assert_valid_response(response, status.HTTP_200_OK)
        user.refresh_from_db()
        self.assertTrue(user.is_active)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_VERIFICATION,
            {
                'USER_VERIFICATION_ID_FIELD': 'username',
            },
        ), )
    def test_verify_with_username_as_verification_id_ok(self):
        user = self.prepare_user()
        request = self.prepare_request(user,
                                       data_to_sign={'user_id': user.username})
        response = self.view_func(request)
        self.assert_valid_response(response, status.HTTP_200_OK)
        user.refresh_from_db()
        self.assertTrue(user.is_active)

    @override_settings(REST_REGISTRATION=REST_REGISTRATION_WITH_VERIFICATION)
    def test_verify_ok_idempotent(self):
        user = self.prepare_user()
        request1 = self.prepare_request(user)
        request2 = self.prepare_request(user)

        self.view_func(request1)

        response = self.view_func(request2)
        self.assert_valid_response(response, status.HTTP_200_OK)
        user.refresh_from_db()
        self.assertTrue(user.is_active)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_VERIFICATION,
            {
                'REGISTER_VERIFICATION_ONE_TIME_USE': True,
            },
        ), )
    def test_verify_one_time_use(self):
        user = self.prepare_user()
        request1 = self.prepare_request(user)
        request2 = self.prepare_request(user)

        self.view_func(request1)

        response = self.view_func(request2)
        self.assert_valid_response(response, status.HTTP_400_BAD_REQUEST)
        user.refresh_from_db()
        self.assertTrue(user.is_active)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_VERIFICATION,
            {
                'REGISTER_VERIFICATION_AUTO_LOGIN': True,
            },
        ), )
    def test_verify_ok_login(self):
        with patch('django.contrib.auth.login') as login_mock:
            user, request = self.prepare_user_and_request()
            response = self.view_func(request)
            login_mock.assert_called_once_with(mock.ANY, user)
        self.assert_valid_response(response, status.HTTP_200_OK)
        user.refresh_from_db()
        self.assertTrue(user.is_active)

    @override_settings(REST_REGISTRATION=REST_REGISTRATION_WITH_VERIFICATION)
    def test_verify_tampered_timestamp(self):
        user = self.create_test_user(is_active=False)
        self.assertFalse(user.is_active)
        signer = RegisterSigner({'user_id': user.pk})
        data = signer.get_signed_data()
        data['timestamp'] += 1
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)
        user.refresh_from_db()
        self.assertFalse(user.is_active)

    @override_settings(REST_REGISTRATION=REST_REGISTRATION_WITH_VERIFICATION)
    def test_verify_expired(self):
        timestamp = int(time.time())
        user = self.create_test_user(is_active=False)
        self.assertFalse(user.is_active)
        with patch('time.time', side_effect=lambda: timestamp):
            signer = RegisterSigner({'user_id': user.pk})
            data = signer.get_signed_data()
            request = self.create_post_request(data)
        with patch('time.time', side_effect=lambda: timestamp + 3600 * 24 * 8):
            response = self.view_func(request)
        self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)
        user.refresh_from_db()
        self.assertFalse(user.is_active)

    @override_settings(
        REST_REGISTRATION={
            'REGISTER_VERIFICATION_ENABLED': False,
            'REGISTER_VERIFICATION_URL': REGISTER_VERIFICATION_URL,
        })
    def test_verify_disabled(self):
        user, request = self.prepare_user_and_request()
        response = self.view_func(request)

        self.assert_invalid_response(response, status.HTTP_404_NOT_FOUND)
        user.refresh_from_db()
        self.assertFalse(user.is_active)
Пример #6
0
class RegisterViewTestCase(APIViewTestCase):
    VIEW_NAME = 'register'

    def test_register_ok(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        # Check database state.
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertFalse(user.is_active)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(sent_email.from_email, VERIFICATION_FROM_EMAIL)
        self.assertListEqual(sent_email.to, [data['email']])
        url = self.assert_one_url_line_in_text(sent_email.body)

        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp'},
        )
        url_user_id = int(verification_data['user_id'])
        self.assertEqual(url_user_id, user_id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = RegisterSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_VERIFICATION,
            {
                'USER_VERIFICATION_ID_FIELD': 'username',
            },
        ), )
    def test_register_with_username_as_verification_id_ok(self):
        # Using username is not recommended if it can change for a given user.
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        # Check database state.
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertFalse(user.is_active)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(sent_email.from_email, VERIFICATION_FROM_EMAIL)
        self.assertListEqual(sent_email.to, [data['email']])
        url = self.assert_one_url_line_in_text(sent_email.body)

        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp'},
        )
        user_verification_id = verification_data['user_id']
        self.assertEqual(user_verification_id, user.username)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = RegisterSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_VERIFICATION,
            {
                'VERIFICATION_URL_BUILDER': build_custom_verification_url,
            },
        ), )
    def test_register_with_custom_verification_url_ok(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        # Check database state.
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertFalse(user.is_active)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(sent_email.from_email, VERIFICATION_FROM_EMAIL)
        self.assertListEqual(sent_email.to, [data['email']])
        url = self.assert_one_url_line_in_text(sent_email.body)

        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_VERIFICATION_URL,
            expected_fields=['user_id', 'signature', 'timestamp'],
            url_parser=parse_custom_verification_url,
        )
        url_user_id = int(verification_data['user_id'])
        self.assertEqual(url_user_id, user_id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = RegisterSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION=REST_REGISTRATION_WITH_HTML_EMAIL_VERIFICATION, )
    def test_register_with_html_email_ok(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        # Check database state.
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertFalse(user.is_active)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(sent_email.from_email, VERIFICATION_FROM_EMAIL)
        self.assertListEqual(sent_email.to, [data['email']])
        url = self.assert_one_url_in_brackets_in_text(sent_email.body)

        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp'},
        )
        url_user_id = int(verification_data['user_id'])
        self.assertEqual(url_user_id, user_id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = RegisterSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_VERIFICATION,
            {
                'REGISTER_SERIALIZER_PASSWORD_CONFIRM': False,
            },
        ), )
    def test_register_no_password_confirm_ok(self):
        data = self._get_register_user_data(password='******')
        data.pop('password_confirm')
        request = self.create_post_request(data)
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        # Check database state.
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertFalse(user.is_active)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(sent_email.from_email, VERIFICATION_FROM_EMAIL)
        self.assertListEqual(sent_email.to, [data['email']])
        url = self.assert_one_url_line_in_text(sent_email.body)

        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp'},
        )
        url_user_id = int(verification_data['user_id'])
        self.assertEqual(url_user_id, user_id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = RegisterSigner(verification_data)
        signer.verify()

    def test_register_same_username(self):
        self.create_test_user(username='******')

        data = self._get_register_user_data(username='******',
                                            password='******')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)

    @override_settings(
        REST_REGISTRATION=REST_REGISTRATION_WITHOUT_VERIFICATION, )
    def test_register_without_verification_ok(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertTrue(user.is_active)

    @override_settings(
        TEMPLATES=(),
        REST_REGISTRATION=REST_REGISTRATION_WITHOUT_VERIFICATION,
    )
    def test_no_templates_without_verification_ok(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertTrue(user.is_active)

    def test_register_missing_email(self):
        data = self._get_register_user_data(password='******')
        del data['email']
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)

    def test_register_empty_email(self):
        data = self._get_register_user_data(password='******', email='')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    def test_register_short_password(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    def test_register_password_numeric(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    def test_register_password_same_as_username(self):
        username = '******'
        data = self._get_register_user_data(username=username,
                                            password=username)
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    def test_register_not_matching_password(self):
        data = self._get_register_user_data(password='******',
                                            password_confirm='testpassword2')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    @override_settings(
        EMAIL_BACKEND='tests.api.test_register.FailureEmailBackend', )
    def test_when_notification_failure_then_user_not_created(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        user_ids_before = {u.pk for u in self.user_class.objects.all()}
        with self.capture_sent_emails() as sent_emails, \
                pytest.raises(ConnectionRefusedError):
            self.view_func(request)
        self.assert_len_equals(sent_emails, 0)
        user_ids_after = {u.pk for u in self.user_class.objects.all()}
        self.assertSetEqual(user_ids_after, user_ids_before)

    def _get_register_user_data(self,
                                password,
                                password_confirm=None,
                                **options):
        username = '******'
        email = '*****@*****.**'
        if password_confirm is None:
            password_confirm = password
        data = {
            'username': username,
            'password': password,
            'password_confirm': password_confirm,
            'email': email,
        }
        data.update(options)
        return data
Пример #7
0
class RegisterViewTestCase(APIViewTestCase):
    VIEW_NAME = 'register'

    def test_register_ok(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        time_before = math.floor(time.time())
        with self.assert_one_mail_sent() as sent_emails:
            response = self.view_func(request)
        time_after = math.ceil(time.time())
        self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        # Check database state.
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertFalse(user.is_active)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(sent_email.from_email, VERIFICATION_FROM_EMAIL)
        self.assertListEqual(sent_email.to, [data['email']])
        url = self.assert_one_url_line_in_text(sent_email.body)

        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp'},
        )
        url_user_id = int(verification_data['user_id'])
        self.assertEqual(url_user_id, user_id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, time_before)
        self.assertLessEqual(url_sig_timestamp, time_after)
        signer = RegisterSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_VERIFICATION,
            {
                'VERIFICATION_URL_BUILDER': build_custom_verification_url,
            },
        ), )
    def test_register_with_custom_verification_url_ok(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        time_before = math.floor(time.time())
        with self.assert_one_mail_sent() as sent_emails:
            response = self.view_func(request)
        time_after = math.ceil(time.time())
        self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        # Check database state.
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertFalse(user.is_active)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(sent_email.from_email, VERIFICATION_FROM_EMAIL)
        self.assertListEqual(sent_email.to, [data['email']])
        url = self.assert_one_url_line_in_text(sent_email.body)

        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_VERIFICATION_URL,
            expected_fields=['user_id', 'signature', 'timestamp'],
            url_parser=parse_custom_verification_url,
        )
        url_user_id = int(verification_data['user_id'])
        self.assertEqual(url_user_id, user_id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, time_before)
        self.assertLessEqual(url_sig_timestamp, time_after)
        signer = RegisterSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION=REST_REGISTRATION_WITH_HTML_EMAIL_VERIFICATION, )
    def test_register_with_html_email_ok(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        time_before = math.floor(time.time())
        with self.assert_one_mail_sent() as sent_emails:
            response = self.view_func(request)
        time_after = math.ceil(time.time())
        self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        # Check database state.
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertFalse(user.is_active)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(sent_email.from_email, VERIFICATION_FROM_EMAIL)
        self.assertListEqual(sent_email.to, [data['email']])
        url = self.assert_one_url_in_brackets_in_text(sent_email.body)

        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp'},
        )
        url_user_id = int(verification_data['user_id'])
        self.assertEqual(url_user_id, user_id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, time_before)
        self.assertLessEqual(url_sig_timestamp, time_after)
        signer = RegisterSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_VERIFICATION,
            {
                'REGISTER_SERIALIZER_PASSWORD_CONFIRM': False,
            },
        ), )
    def test_register_no_password_confirm_ok(self):
        data = self._get_register_user_data(password='******')
        data.pop('password_confirm')
        request = self.create_post_request(data)
        time_before = math.floor(time.time())
        with self.assert_one_mail_sent() as sent_emails:
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_201_CREATED)
        time_after = math.ceil(time.time())
        user_id = response.data['id']
        # Check database state.
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertFalse(user.is_active)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(sent_email.from_email, VERIFICATION_FROM_EMAIL)
        self.assertListEqual(sent_email.to, [data['email']])
        url = self.assert_one_url_line_in_text(sent_email.body)

        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp'},
        )
        url_user_id = int(verification_data['user_id'])
        self.assertEqual(url_user_id, user_id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, time_before)
        self.assertLessEqual(url_sig_timestamp, time_after)
        signer = RegisterSigner(verification_data)
        signer.verify()

    def test_register_same_username(self):
        self.create_test_user(username='******')

        data = self._get_register_user_data(username='******',
                                            password='******')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)

    @override_settings(
        REST_REGISTRATION=REST_REGISTRATION_WITHOUT_VERIFICATION, )
    def test_register_without_verification_ok(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_valid_response(response, status.HTTP_201_CREATED)
        user_id = response.data['id']
        user = self.user_class.objects.get(id=user_id)
        self.assertEqual(user.username, data['username'])
        self.assertTrue(user.check_password(data['password']))
        self.assertTrue(user.is_active)

    def test_register_missing_email(self):
        data = self._get_register_user_data(password='******')
        del data['email']
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)

    def test_register_empty_email(self):
        data = self._get_register_user_data(password='******', email='')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    def test_register_short_password(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    def test_register_password_numeric(self):
        data = self._get_register_user_data(password='******')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    def test_register_password_same_as_username(self):
        username = '******'
        data = self._get_register_user_data(username=username,
                                            password=username)
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    def test_register_not_matching_password(self):
        data = self._get_register_user_data(password='******',
                                            password_confirm='testpassword2')
        request = self.create_post_request(data)
        with self.assert_no_mail_sent():
            response = self.view_func(request)
            self.assert_response_is_bad_request(response)

    def _get_register_user_data(self,
                                password,
                                password_confirm=None,
                                **options):
        username = '******'
        email = '*****@*****.**'
        if password_confirm is None:
            password_confirm = password
        data = {
            'username': username,
            'password': password,
            'password_confirm': password_confirm,
            'email': email,
        }
        data.update(options)
        return data
class VerifyEmailViewTestCase(BaseRegisterEmailViewTestCase):
    VIEW_NAME = 'verify-email'

    @override_settings(
        REST_REGISTRATION=REST_REGISTRATION_WITH_EMAIL_VERIFICATION, )
    def test_ok(self):
        self.setup_user()
        signer = RegisterEmailSigner({
            'user_id': self.user.pk,
            'email': self.new_email,
        })
        data = signer.get_signed_data()
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_valid_response(response, status.HTTP_200_OK)
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.new_email)

    @override_settings(
        REST_REGISTRATION=REST_REGISTRATION_WITH_EMAIL_VERIFICATION, )
    def test_new_email_already_in_use_ok(self):
        self.setup_user()
        self.setup_user2_with_user_new_email()
        signer = self.build_signer()
        request = self.create_post_request(signer.get_signed_data())
        response = self.view_func(request)
        self.assert_response_is_ok(response)
        self.assert_user_email_changed()

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_EMAIL_VERIFICATION,
            {
                'USER_VERIFICATION_ID_FIELD': 'username',
            },
        ), )
    def test_with_username_as_verification_id_ok(self):
        self.setup_user()
        signer = RegisterEmailSigner({
            'user_id': self.user.username,
            'email': self.new_email,
        })
        data = signer.get_signed_data()
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_valid_response(response, status.HTTP_200_OK)
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.new_email)

    @override_settings(REST_REGISTRATION={
        'REGISTER_EMAIL_VERIFICATION_URL':
        REGISTER_EMAIL_VERIFICATION_URL,
    })
    def test_inactive_user(self):
        self.setup_user()
        old_email = self.user.email
        self.user.is_active = False
        self.user.save()
        signer = RegisterEmailSigner({
            'user_id': self.user.pk,
            'email': self.new_email,
        })
        data = signer.get_signed_data()
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_response_is_not_found(response)
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, old_email)

    @override_settings(REST_REGISTRATION={
        'REGISTER_EMAIL_VERIFICATION_ENABLED': False,
    })
    def test_noverify_not_found(self):
        self.setup_user()
        signer = RegisterEmailSigner(
            {
                'user_id': self.user.pk,
                'email': self.new_email,
            }, strict=False)
        data = signer.get_signed_data()
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_invalid_response(response, status.HTTP_404_NOT_FOUND)
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.email)

    @override_settings(REST_REGISTRATION={
        'REGISTER_EMAIL_VERIFICATION_URL':
        REGISTER_EMAIL_VERIFICATION_URL,
    })
    def test_tampered_timestamp(self):
        self.setup_user()
        signer = RegisterEmailSigner({
            'user_id': self.user.pk,
            'email': self.new_email,
        })
        data = signer.get_signed_data()
        data['timestamp'] += 1
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.email)

    @override_settings(REST_REGISTRATION={
        'REGISTER_EMAIL_VERIFICATION_URL':
        REGISTER_EMAIL_VERIFICATION_URL,
    })
    def test_tampered_email(self):
        self.setup_user()
        signer = RegisterEmailSigner({
            'user_id': self.user.pk,
            'email': self.new_email,
        })
        data = signer.get_signed_data()
        data['email'] = 'p' + data['email']
        request = self.create_post_request(data)
        response = self.view_func(request)
        self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.email)

    @override_settings(REST_REGISTRATION={
        'REGISTER_EMAIL_VERIFICATION_URL':
        REGISTER_EMAIL_VERIFICATION_URL,
    })
    def test_expired(self):
        self.setup_user()
        timestamp = time.time()
        with patch('time.time', side_effect=lambda: timestamp):
            signer = RegisterEmailSigner({
                'user_id': self.user.pk,
                'email': self.new_email,
            })
            data = signer.get_signed_data()
        request = self.create_post_request(data)
        with patch('time.time', side_effect=lambda: timestamp + 3600 * 24 * 8):
            response = self.view_func(request)
        self.assert_invalid_response(response, status.HTTP_400_BAD_REQUEST)
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.email)

    @override_settings(
        AUTH_USER_MODEL='custom_users.UserWithUniqueEmail',
        REST_REGISTRATION=REST_REGISTRATION_WITH_EMAIL_VERIFICATION,
    )
    def test_user_with_unique_email_user_email_already_exists(self):
        self.setup_user()
        self.setup_user2_with_user_new_email()
        signer = self.build_signer()
        request = self.create_post_request(signer.get_signed_data())
        response = self.view_func(request)
        self.assert_response_is_bad_request(response)
        self.assert_user_email_not_changed()
class RegisterEmailViewTestCase(BaseRegisterEmailViewTestCase):
    VIEW_NAME = 'register-email'

    def _test_authenticated(self, data):
        request = self.create_authenticated_post_request(data)
        response = self.view_func(request)
        return response

    @override_settings(
        REST_REGISTRATION=REST_REGISTRATION_WITH_EMAIL_VERIFICATION, )
    def test_ok(self):
        self.setup_user()
        data = {
            'email': self.new_email,
        }
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self._test_authenticated(data)
            self.assert_valid_response(response, status.HTTP_200_OK)
        # Check database state.
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.email)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(
            sent_email.from_email,
            REST_REGISTRATION_WITH_EMAIL_VERIFICATION[
                'VERIFICATION_FROM_EMAIL'],  # noqa: E501
        )
        self.assertListEqual(sent_email.to, [self.new_email])
        url = self.assert_one_url_line_in_text(sent_email.body)
        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_EMAIL_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp', 'email'},
        )
        self.assertEqual(verification_data['email'], self.new_email)
        self.assertEqual(int(verification_data['user_id']), self.user.id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = RegisterEmailSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION=REST_REGISTRATION_WITH_EMAIL_VERIFICATION, )
    def test_email_already_in_use_ok(self):
        self.setup_user()
        self.setup_user2_with_user_new_email()
        request = self.create_authenticated_post_request({
            'email':
            self.new_email,
        })
        with self.capture_sent_emails() as sent_emails, self.timer() as timer:
            response = self.view_func(request)
        self.assert_response_is_ok(response)
        self.assert_user_email_not_changed()
        self.assert_valid_verification_email_sent(sent_emails, timer=timer)

    @override_settings(
        AUTH_USER_MODEL='custom_users.UserWithUniqueEmail',
        REST_REGISTRATION=REST_REGISTRATION_WITH_EMAIL_VERIFICATION,
    )
    def test_user_with_unique_email_ok_but_notification_already_exists(self):
        self.setup_user()
        self.setup_user2_with_user_new_email()
        request = self.create_authenticated_post_request({
            'email':
            self.new_email,
        })
        with self.capture_sent_emails() as sent_emails:
            response = self.view_func(request)
        self.assert_response_is_ok(response)
        self.assert_user_email_not_changed()
        self.assert_notification_already_exists_sent(sent_emails)

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_EMAIL_VERIFICATION,
            {
                'USER_VERIFICATION_ID_FIELD': 'username',
            },
        ), )
    def test_with_username_as_verification_id_ok(self):
        self.setup_user()
        data = {
            'email': self.new_email,
        }
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self._test_authenticated(data)
            self.assert_valid_response(response, status.HTTP_200_OK)
        # Check database state.
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.email)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(
            sent_email.from_email,
            REST_REGISTRATION_WITH_EMAIL_VERIFICATION[
                'VERIFICATION_FROM_EMAIL'],  # noqa: E501
        )
        self.assertListEqual(sent_email.to, [self.new_email])
        url = self.assert_one_url_line_in_text(sent_email.body)
        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_EMAIL_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp', 'email'},
        )
        self.assertEqual(verification_data['email'], self.new_email)
        self.assertEqual(verification_data['user_id'], self.user.username)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = RegisterEmailSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION={'REGISTER_EMAIL_VERIFICATION_ENABLED': False})
    def test_noverify_ok(self):
        self.setup_user()
        data = {
            'email': self.new_email,
        }
        with self.assert_no_mail_sent():
            response = self._test_authenticated(data)
            self.assert_valid_response(response, status.HTTP_200_OK)
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.new_email)

    @override_settings(
        TEMPLATES=(),
        REST_REGISTRATION={'REGISTER_EMAIL_VERIFICATION_ENABLED': False})
    def test_no_templates_without_verification_ok(self):
        self.setup_user()
        with self.capture_sent_emails() as sent_emails:
            response = self._test_authenticated({
                'email': self.new_email,
            })
        self.assert_response_is_ok(response)
        self.assert_len_equals(sent_emails, 0)
        self.assert_user_email_changed()
class RegisterEmailViewTestCase(BaseRegisterEmailViewTestCase):
    VIEW_NAME = 'register-email'

    def _test_authenticated(self, data):
        request = self.create_post_request(data)
        force_authenticate(request, user=self.user)
        response = self.view_func(request)
        return response

    @override_settings(
        REST_REGISTRATION=REST_REGISTRATION_WITH_EMAIL_VERIFICATION, )
    def test_ok(self):
        data = {
            'email': self.new_email,
        }
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self._test_authenticated(data)
            self.assert_valid_response(response, status.HTTP_200_OK)
        # Check database state.
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.email)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(
            sent_email.from_email,
            REST_REGISTRATION_WITH_EMAIL_VERIFICATION[
                'VERIFICATION_FROM_EMAIL'],  # noqa: E501
        )
        self.assertListEqual(sent_email.to, [self.new_email])
        url = self.assert_one_url_line_in_text(sent_email.body)
        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_EMAIL_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp', 'email'},
        )
        self.assertEqual(verification_data['email'], self.new_email)
        self.assertEqual(int(verification_data['user_id']), self.user.id)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = RegisterEmailSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION=shallow_merge_dicts(
            REST_REGISTRATION_WITH_EMAIL_VERIFICATION,
            {
                'USER_VERIFICATION_ID_FIELD': 'username',
            },
        ), )
    def test_with_username_as_verification_id_ok(self):
        data = {
            'email': self.new_email,
        }
        with self.assert_one_mail_sent() as sent_emails, self.timer() as timer:
            response = self._test_authenticated(data)
            self.assert_valid_response(response, status.HTTP_200_OK)
        # Check database state.
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.email)
        # Check verification e-mail.
        sent_email = sent_emails[0]
        self.assertEqual(
            sent_email.from_email,
            REST_REGISTRATION_WITH_EMAIL_VERIFICATION[
                'VERIFICATION_FROM_EMAIL'],  # noqa: E501
        )
        self.assertListEqual(sent_email.to, [self.new_email])
        url = self.assert_one_url_line_in_text(sent_email.body)
        verification_data = self.assert_valid_verification_url(
            url,
            expected_path=REGISTER_EMAIL_VERIFICATION_URL,
            expected_fields={'signature', 'user_id', 'timestamp', 'email'},
        )
        self.assertEqual(verification_data['email'], self.new_email)
        self.assertEqual(verification_data['user_id'], self.user.username)
        url_sig_timestamp = int(verification_data['timestamp'])
        self.assertGreaterEqual(url_sig_timestamp, timer.start_time)
        self.assertLessEqual(url_sig_timestamp, timer.end_time)
        signer = RegisterEmailSigner(verification_data)
        signer.verify()

    @override_settings(
        REST_REGISTRATION={'REGISTER_EMAIL_VERIFICATION_ENABLED': False})
    def test_noverify_ok(self):
        data = {
            'email': self.new_email,
        }
        with self.assert_no_mail_sent():
            response = self._test_authenticated(data)
            self.assert_valid_response(response, status.HTTP_200_OK)
        self.user.refresh_from_db()
        self.assertEqual(self.user.email, self.new_email)