class TestCoreClient(unittest.TestCase): server_url = TEST_SERVER_URL def setUp(self): self.client = Client(self.server_url) self._accounts_to_delete = [] def tearDown(self): for acct in self._accounts_to_delete: acct.clear() try: stretchpwd = acct.stretchpwd except AttributeError: try: password = acct.password stretchpwd = quick_stretch_password(acct.email, password) except AttributeError: stretchpwd = DUMMY_STRETCHED_PASSWORD self.client.destroy_account(acct.email, stretchpwd=stretchpwd) def test_account_creation(self): acct = TestEmailAccount() acct.password = DUMMY_PASSWORD session = self.client.create_account(acct.email, DUMMY_PASSWORD) self._accounts_to_delete.append(acct) self.assertEqual(session.email, acct.email) self.assertFalse(session.verified) self.assertEqual(session.keys, None) self.assertEqual(session._key_fetch_token, None) with self.assertRaises(Exception): session.fetch_keys() def test_account_creation_with_key_fetch(self): acct = TestEmailAccount() session = self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, keys=True, ) self._accounts_to_delete.append(acct) self.assertEqual(session.email, acct.email) self.assertFalse(session.verified) self.assertEqual(session.keys, None) self.assertNotEqual(session._key_fetch_token, None) def test_account_login(self): acct = TestEmailAccount() session1 = self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self._accounts_to_delete.append(acct) session2 = self.client.login( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self.assertEqual(session1.email, session2.email) self.assertNotEqual(session1.token, session2.token) def test_get_random_bytes(self): b1 = self.client.get_random_bytes() b2 = self.client.get_random_bytes() self.assertTrue(isinstance(b1, binary_type)) self.assertNotEqual(b1, b2) def test_resend_verify_code(self): acct = TestEmailAccount() session = self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self._accounts_to_delete.append(acct) def is_verify_email(m): return "x-verify-code" in m["headers"] m1 = acct.wait_for_email(is_verify_email) code1 = m1["headers"]["x-verify-code"] # NOQA acct.clear() session.resend_email_code() # XXX TODO: this won't work against a live server because we # refuse to send duplicate emails within a short timespan. # m2 = acct.wait_for_email(is_verify_email) # code2 = m2["headers"]["x-verify-code"] # self.assertNotEqual(m1, m2) # self.assertEqual(code1, code2) def test_forgot_password_flow(self): acct = TestEmailAccount() self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self._accounts_to_delete.append(acct) # Initiate the password reset flow, and grab the verification code. pftok = self.client.send_reset_code(acct.email, service="foobar") m = acct.wait_for_email(lambda m: "x-recovery-code" in m["headers"]) if not m: raise RuntimeError("Password reset email was not received") acct.clear() code = m["headers"]["x-recovery-code"] # Try with an invalid code to test error handling. tries = pftok.tries_remaining self.assertTrue(tries > 1) with self.assertRaises(Exception): pftok.verify_code(mutate_one_byte(code)) pftok.get_status() self.assertEqual(pftok.tries_remaining, tries - 1) # Re-send the code, as if we've lost the email. pftok.resend_code() m = acct.wait_for_email(lambda m: "x-recovery-code" in m["headers"]) if not m: raise RuntimeError("Password reset email was not received") self.assertEqual(m["headers"]["x-recovery-code"], code) # Now verify with the actual code, and reset the account. artok = pftok.verify_code(code) self.client.reset_account(email=acct.email, token=artok, stretchpwd=DUMMY_STRETCHED_PASSWORD) def test_email_code_verification(self): self.client = Client(self.server_url) # Create a fresh testing account. self.acct = TestEmailAccount() self.client.create_account( email=self.acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) def wait_for_email(m): return "x-uid" in m["headers"] and "x-verify-code" in m["headers"] m = self.acct.wait_for_email(wait_for_email) if not m: raise RuntimeError("Verification email was not received") # If everything went well, verify_email_code should return an empty json object response = self.client.verify_email_code(m["headers"]["x-uid"], m["headers"]["x-verify-code"]) self.assertEquals(response, {}) def test_send_unblock_code(self): acct = TestEmailAccount(email="block-{uniq}@{hostname}") self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self._accounts_to_delete.append(acct) # Initiate sending unblock code response = self.client.send_unblock_code(acct.email) self.assertEquals(response, {}) m = acct.wait_for_email(lambda m: "x-unblock-code" in m["headers"]) if not m: raise RuntimeError("Unblock code email was not received") code = m["headers"]["x-unblock-code"] self.assertTrue(len(code) > 0) self.client.login(email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, unblock_code=code)
class TestCoreClient(unittest.TestCase): server_url = TEST_SERVER_URL def setUp(self): self.client = Client(self.server_url) self._accounts_to_delete = [] def tearDown(self): for acct in self._accounts_to_delete: acct.clear() try: stretchpwd = acct.stretchpwd except AttributeError: try: password = acct.password stretchpwd = quick_stretch_password(acct.email, password) except AttributeError: stretchpwd = DUMMY_STRETCHED_PASSWORD self.client.destroy_account(acct.email, stretchpwd=stretchpwd) def test_account_creation(self): acct = TestEmailAccount() acct.password = DUMMY_PASSWORD session = self.client.create_account(acct.email, DUMMY_PASSWORD) self._accounts_to_delete.append(acct) self.assertEqual(session.email, acct.email) self.assertFalse(session.verified) self.assertEqual(session.keys, None) self.assertEqual(session._key_fetch_token, None) with self.assertRaises(Exception): session.fetch_keys() def test_account_creation_with_key_fetch(self): acct = TestEmailAccount() session = self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, keys=True, ) self._accounts_to_delete.append(acct) self.assertEqual(session.email, acct.email) self.assertFalse(session.verified) self.assertEqual(session.keys, None) self.assertNotEqual(session._key_fetch_token, None) def test_account_login(self): acct = TestEmailAccount() session1 = self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self._accounts_to_delete.append(acct) session2 = self.client.login( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self.assertEqual(session1.email, session2.email) self.assertNotEqual(session1.token, session2.token) def test_get_random_bytes(self): b1 = self.client.get_random_bytes() b2 = self.client.get_random_bytes() self.assertTrue(isinstance(b1, binary_type)) self.assertNotEqual(b1, b2) def test_resend_verify_code(self): acct = TestEmailAccount() session = self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self._accounts_to_delete.append(acct) def is_verify_email(m): return "x-verify-code" in m["headers"] m1 = acct.wait_for_email(is_verify_email) code1 = m1["headers"]["x-verify-code"] # NOQA acct.clear() session.resend_email_code() # XXX TODO: this won't work against a live server because we # refuse to send duplicate emails within a short timespan. # m2 = acct.wait_for_email(is_verify_email) # code2 = m2["headers"]["x-verify-code"] # self.assertNotEqual(m1, m2) # self.assertEqual(code1, code2) def test_forgot_password_flow(self): acct = TestEmailAccount() self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self._accounts_to_delete.append(acct) # Initiate the password reset flow, and grab the verification code. pftok = self.client.send_reset_code(acct.email, service="foobar") m = acct.wait_for_email(lambda m: "x-recovery-code" in m["headers"]) if not m: raise RuntimeError("Password reset email was not received") acct.clear() code = m["headers"]["x-recovery-code"] # Try with an invalid code to test error handling. tries = pftok.tries_remaining self.assertTrue(tries > 1) with self.assertRaises(Exception): pftok.verify_code(mutate_one_byte(code)) pftok.get_status() self.assertEqual(pftok.tries_remaining, tries - 1) # Re-send the code, as if we've lost the email. pftok.resend_code() m = acct.wait_for_email(lambda m: "x-recovery-code" in m["headers"]) if not m: raise RuntimeError("Password reset email was not received") self.assertEqual(m["headers"]["x-recovery-code"], code) # Now verify with the actual code, and reset the account. artok = pftok.verify_code(code) self.client.reset_account( email=acct.email, token=artok, stretchpwd=DUMMY_STRETCHED_PASSWORD ) def test_email_code_verification(self): self.client = Client(self.server_url) # Create a fresh testing account. self.acct = TestEmailAccount() self.client.create_account( email=self.acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) def wait_for_email(m): return "x-uid" in m["headers"] and "x-verify-code" in m["headers"] m = self.acct.wait_for_email(wait_for_email) if not m: raise RuntimeError("Verification email was not received") # If everything went well, verify_email_code should return an empty json object response = self.client.verify_email_code(m["headers"]["x-uid"], m["headers"]["x-verify-code"]) self.assertEquals(response, {}) def test_send_unblock_code(self): acct = TestEmailAccount(email="block-{uniq}@{hostname}") self.client.create_account( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, ) self._accounts_to_delete.append(acct) # Initiate sending unblock code response = self.client.send_unblock_code(acct.email) self.assertEquals(response, {}) m = acct.wait_for_email(lambda m: "x-unblock-code" in m["headers"]) if not m: raise RuntimeError("Unblock code email was not received") code = m["headers"]["x-unblock-code"] self.assertTrue(len(code) > 0) self.client.login( email=acct.email, stretchpwd=DUMMY_STRETCHED_PASSWORD, unblock_code=code )