from rest_framework import status from rest_framework.test import APITestCase from django.test.utils import override_settings from django.test import RequestFactory from pingcap_sso.models import SecurityCode, User from pingcap_sso.lib.sso import sync_cookie_url from pingcap_sso.forms.signup import SignupForm @override_settings( SMS_BACKEND='sms.backends.dummy.SmsBackend', TRUSTED_HOSTS=['tidb.io'], # Just for disable django-rest-framework's throttle CACHES={ 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', } } ) class SingupTest(APITestCase): SIGNUP_SEND_CODE_PATH = '/api/signup/send-code' SIGNUP_PATH = '/api/signup' def setUp(self): self.user = User( username=User.generate_random_username(), company_name='company_name', phone='13333333333', ) self.user.set_password(None) self.user.save() def test_normal_signup_process(self): phone = '13688888888' company_name = 'pingcap' email = 'user@mail.com' redirect_to = 'https://tidb.io/test' # Send Code response = self.client.post( self.SIGNUP_SEND_CODE_PATH, data={ 'phone': phone, 're_token_v3': 'dummy' } ) self.assertEquals(response.status_code, status.HTTP_200_OK) self.assertTrue( SecurityCode.objects.filter( deliver_address=phone, deliver_channel=SecurityCode.DELIVER_BY_PHONE, confirmed=False ).exists() ) code = SecurityCode.objects.get( deliver_address=phone, deliver_channel=SecurityCode.DELIVER_BY_PHONE, confirmed=False).code # Post signup form response = self.client.post( self.SIGNUP_PATH, data={ 'company': company_name, 'email': email, 'phone': phone, 'code': code, 're_token_v3': 'dummy', 'redirect_to': redirect_to } ) self.assertEquals(response.status_code, status.HTTP_200_OK) new_user = User.objects.get(phone=phone) self.assertEquals(new_user.signup_email, email) self.assertEquals(new_user.email, None) self.assertEquals(new_user.email_verified, False) self.assertEquals(new_user.company_name, company_name) self.assertEquals(new_user.phone, phone) self.assertEquals(response.data['data']['redirect_to'], sync_cookie_url(redirect_to)) def test_signup_with_hong_kong_and_macao_phone(self): for phone in ('+85251234567', '+85361234567'): with self.subTest(phone=phone): response = self.client.post( self.SIGNUP_SEND_CODE_PATH, data={'phone': phone, 're_token_v3': 'dummy'} ) self.assertEqual(response.status_code, status.HTTP_200_OK) code = SecurityCode.objects.get( deliver_address=phone, deliver_channel=SecurityCode.DELIVER_BY_PHONE, confirmed=False, ).code form = SignupForm( RequestFactory().post('/'), data={ 'company': 'pingcap', 'email': '{}@mail.com'.format(phone[1:4]), 'phone': phone, 'code': code, 're_token_v3': 'dummy', 'redirect_to': 'https://tidb.io/test', }, ) self.assertTrue(form.is_valid(), form.errors) form.save() self.assertTrue(User.objects.filter(phone=phone).exists()) def test_signup_normalizes_mainland_country_code(self): phone = '+8613688888888' normalized_phone = '13688888888' response = self.client.post( self.SIGNUP_SEND_CODE_PATH, data={'phone': phone, 're_token_v3': 'dummy'} ) self.assertEqual(response.status_code, status.HTTP_200_OK) code = SecurityCode.objects.get( deliver_address=normalized_phone, deliver_channel=SecurityCode.DELIVER_BY_PHONE, confirmed=False, ).code form = SignupForm( RequestFactory().post('/'), data={ 'company': 'pingcap', 'email': 'normalized@mail.com', 'phone': phone, 'code': code, 're_token_v3': 'dummy', 'redirect_to': 'https://tidb.io/test', }, ) self.assertTrue(form.is_valid(), form.errors) form.save() self.assertTrue(User.objects.filter(phone=normalized_phone).exists()) def test_country_code_cannot_bypass_duplicate_phone_check(self): response = self.client.post( self.SIGNUP_SEND_CODE_PATH, data={'phone': '+8613333333333', 're_token_v3': 'dummy'} ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn('phone', response.data['errors']) def test_send_code_rate_limit(self): phone = '13688888888' response = self.client.post( self.SIGNUP_SEND_CODE_PATH, data={ 'phone': phone, 're_token_v3': 'dummy' } ) self.assertEquals(response.status_code, status.HTTP_200_OK) self.assertTrue( SecurityCode.objects.filter( deliver_address=phone, deliver_channel=SecurityCode.DELIVER_BY_PHONE, confirmed=False ).exists() ) response = self.client.post( self.SIGNUP_SEND_CODE_PATH, data={ 'phone': phone, 're_token_v3': 'dummy' } ) self.assertEquals(response.status_code, status.HTTP_429_TOO_MANY_REQUESTS) self.assertEquals( SecurityCode.objects.filter( deliver_address=phone, deliver_channel=SecurityCode.DELIVER_BY_PHONE, confirmed=False ).count(), 1 ) def test_signup_form_invalid_code(self): phone = '13688888888' company_name = 'pingcap' email = 'user@mail.com' redirect_to = 'https://tidb.io/test' response = self.client.post( self.SIGNUP_PATH, data={ 'company': company_name, 'email': email, 'phone': phone, 'code': 'invalid_code', 're_token_v3': 'dummy', 'redirect_to': redirect_to } ) self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn('code', response.data['errors']) def test_signup_form_empty_fields(self): response = self.client.post( self.SIGNUP_PATH, data={ 'company': '', 'email': '', 'phone': '', 'code': '', 're_token_v3': 'dummy', 'redirect_to': '' } ) self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn('company', response.data['errors']) self.assertIn('email', response.data['errors']) self.assertIn('phone', response.data['errors']) self.assertIn('code', response.data['errors']) self.assertNotIn('redirect_to', response.data['errors']) def test_signup_with_registered_phone(self): company_name = 'pingcap' email = 'user@mail.com' redirect_to = 'https://tidb.io/test' response = self.client.post( self.SIGNUP_PATH, data={ 'company': company_name, 'email': email, 'phone': self.user.phone, 'code': '111111', 're_token_v3': 'dummy', 'redirect_to': redirect_to } ) self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn('phone', response.data['errors']) def test_send_code_invalid_phone(self): response = self.client.post( self.SIGNUP_SEND_CODE_PATH, data={ 'phone': 'invalid', 're_token_v3': 'dummy' } ) self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn('phone', response.data['errors']) def test_send_code_registered_phone(self): response = self.client.post( self.SIGNUP_SEND_CODE_PATH, data={ 'phone': self.user.phone, 're_token_v3': 'dummy' } ) self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn('phone', response.data['errors'])