def test_reset_view(self): with capture_reset_password_requests() as requests: r = self._post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) t = requests[0]['token'] r = self._get('/reset/' + t) self.assertIn(b'<h1>Reset password</h1>', r.data)
def test_expired_reset_token(client, get_message): with capture_reset_password_requests() as requests: client.post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) user = requests[0]["user"] token = requests[0]["token"] time.sleep(1) with capture_flashes() as flashes: msg = get_message("PASSWORD_RESET_EXPIRED", within="1 milliseconds", email=user.email) # Test getting reset form with expired token response = client.get("/reset/" + token, follow_redirects=True) assert msg in response.data # Test trying to reset password with expired token response = client.post( "/reset/" + token, data={ "password": "******", "password_confirm": "newpassword" }, follow_redirects=True, ) assert msg in response.data assert len(flashes) == 2
def test_used_reset_token(client, get_message): with capture_reset_password_requests() as requests: client.post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) token = requests[0]["token"] # use the token response = client.post( "/reset/" + token, data={ "password": "******", "password_confirm": "awesome sunset" }, follow_redirects=True, ) assert get_message("PASSWORD_RESET") in response.data logout(client) # attempt to use it a second time response2 = client.post( "/reset/" + token, data={ "password": "******", "password_confirm": "otherpassword" }, follow_redirects=True, ) msg = get_message("INVALID_RESET_PASSWORD_TOKEN") assert msg in response2.data
def test_reset_token_deleted_user(app, client, get_message, sqlalchemy_datastore): with capture_reset_password_requests() as requests: client.post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) token = requests[0]["token"] # Delete user with app.app_context(): # load user (and role) to get into session so cascade delete works. user = app.security.datastore.find_user(email="*****@*****.**") sqlalchemy_datastore.delete(user) sqlalchemy_datastore.commit() response = client.post( "/reset/" + token, data={ "password": "******", "password_confirm": "newpassword" }, follow_redirects=True, ) msg = get_message("INVALID_RESET_PASSWORD_TOKEN") assert msg in response.data
def test_bc_password(app, client_nc): # Test behavior of BACKWARDS_COMPAT_AUTH_TOKEN_INVALID response = json_authenticate(client_nc, email="*****@*****.**") token = response.json["response"]["user"]["authentication_token"] verify_token(client_nc, token) json_logout(client_nc, token) with capture_reset_password_requests() as requests: response = client_nc.post( "/reset", json=dict(email="*****@*****.**"), headers={"Content-Type": "application/json"}, ) assert response.status_code == 200 reset_token = requests[0]["token"] data = dict(password="******", password_confirm="awesome sunset") response = client_nc.post( "/reset/" + reset_token + "?include_auth_token=1", json=data, headers={"Content-Type": "application/json"}, ) assert response.status_code == 200 assert "authentication_token" in response.json["response"]["user"] # changing password should have rendered existing auth tokens invalid verify_token(client_nc, token, status=401) # but new auth token should work token = response.json["response"]["user"]["authentication_token"] verify_token(client_nc, token)
def test_used_reset_token(client, get_message): with capture_reset_password_requests() as requests: client.post( '/reset', data=dict( email='*****@*****.**'), follow_redirects=True) token = requests[0]['token'] # use the token response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert get_message('PASSWORD_RESET') in response.data logout(client) # attempt to use it a second time response2 = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'otherpassword' }, follow_redirects=True) msg = get_message('INVALID_RESET_PASSWORD_TOKEN') assert msg in response2.data
def test_used_reset_token(client, get_message): with capture_reset_password_requests() as requests: client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) token = requests[0]['token'] # use the token response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert get_message('PASSWORD_RESET') in response.data logout(client) # attempt to use it a second time response2 = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'otherpassword' }, follow_redirects=True) msg = get_message('INVALID_RESET_PASSWORD_TOKEN') assert msg in response2.data
def test_reset_password(self): with capture_reset_password_requests() as requests: self._post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) token = requests[0]['token'] r = self._get('/reset/' + token) self.assertIn(b"My Reset Password Submit Field", r.data)
def test_custom_reset_templates(client): response = client.get("/reset") assert b"CUSTOM FORGOT PASSWORD" in response.data with capture_reset_password_requests() as requests: client.post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) token = requests[0]["token"] response = client.get("/reset/" + token) assert b"CUSTOM RESET PASSWORD" in response.data
def test_custom_reset_templates(client): response = client.get('/reset') assert b'CUSTOM FORGOT PASSWORD' in response.data with capture_reset_password_requests() as requests: client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) token = requests[0]['token'] response = client.get('/reset/' + token) assert b'CUSTOM RESET PASSWORD' in response.data
def test_reset_password_template(self): with capture_reset_password_requests() as requests: r = self._post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) t = requests[0]['token'] r = self._get('/reset/' + t) self.assertIn(b'CUSTOM RESET PASSWORD', r.data)
def test_basic_custom_forms(app, sqlalchemy_datastore): class MyLoginForm(LoginForm): email = StringField('My Login Email Address Field') class MyRegisterForm(RegisterForm): email = StringField('My Register Email Address Field') class MyForgotPasswordForm(ForgotPasswordForm): email = StringField( 'My Forgot Email Address Field', validators=[ email_required, email_validator, valid_user_email]) class MyResetPasswordForm(ResetPasswordForm): password = StringField('My Reset Password Field') class MyChangePasswordForm(ChangePasswordForm): password = PasswordField('My Change Password Field') app.security = Security(app, datastore=sqlalchemy_datastore, login_form=MyLoginForm, register_form=MyRegisterForm, forgot_password_form=MyForgotPasswordForm, reset_password_form=MyResetPasswordForm, change_password_form=MyChangePasswordForm) populate_data(app) client = app.test_client() response = client.get('/login') assert b'My Login Email Address Field' in response.data response = client.get('/register') assert b'My Register Email Address Field' in response.data response = client.get('/reset') assert b'My Forgot Email Address Field' in response.data with capture_reset_password_requests() as requests: response = client.post('/reset', data=dict(email='*****@*****.**')) token = requests[0]['token'] response = client.get('/reset/' + token) assert b'My Reset Password Field' in response.data authenticate(client) response = client.get('/change') assert b'My Change Password Field' in response.data
def test_basic_custom_forms(app, sqlalchemy_datastore): class MyLoginForm(LoginForm): email = StringField("My Login Email Address Field") class MyRegisterForm(RegisterForm): email = StringField("My Register Email Address Field") class MyForgotPasswordForm(ForgotPasswordForm): email = StringField( "My Forgot Email Address Field", validators=[email_required, email_validator, valid_user_email], ) class MyResetPasswordForm(ResetPasswordForm): password = StringField("My Reset Password Field") class MyChangePasswordForm(ChangePasswordForm): password = PasswordField("My Change Password Field") app.security = Security( app, datastore=sqlalchemy_datastore, login_form=MyLoginForm, register_form=MyRegisterForm, forgot_password_form=MyForgotPasswordForm, reset_password_form=MyResetPasswordForm, change_password_form=MyChangePasswordForm, ) populate_data(app) client = app.test_client() response = client.get("/login") assert b"My Login Email Address Field" in response.data response = client.get("/register") assert b"My Register Email Address Field" in response.data response = client.get("/reset") assert b"My Forgot Email Address Field" in response.data with capture_reset_password_requests() as requests: response = client.post("/reset", data=dict(email="*****@*****.**")) token = requests[0]["token"] response = client.get("/reset/" + token) assert b"My Reset Password Field" in response.data authenticate(client) response = client.get("/change") assert b"My Change Password Field" in response.data
def test_reset_passwordless_user(client, get_message): with capture_reset_password_requests() as requests: client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) token = requests[0]['token'] # use the token response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert get_message('PASSWORD_RESET') in response.data
def test_reset_password(self): with capture_reset_password_requests() as requests: self._post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) token = requests[0]["token"] with capture_signals() as mocks: data = dict(password="******", password_confirm="newpassword") self._post("/reset/" + token, data, follow_redirects=True) self.assertEqual(mocks.signals_sent(), set([password_reset])) user = self.app.security.datastore.find_user(email="*****@*****.**") calls = mocks[password_reset] self.assertEqual(len(calls), 1) args, kwargs = calls[0] self.assertTrue(compare_user(kwargs["user"], user)) self.assertEqual(args[0], self.app)
def test_reset_password_with_expired_token(self): with capture_reset_password_requests() as requests: r = self._post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) t = requests[0]['token'] time.sleep(1) r = self._post('/reset/' + t, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) self.assertIn(b'You did not reset your password within', r.data)
def test_reset_password_with_valid_token(self): with capture_reset_password_requests() as requests: r = self._post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) t = requests[0]['token'] r = self._post('/reset/' + t, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) r = self.logout() r = self.authenticate('*****@*****.**', 'newpassword') self.assertIn(b'Hello [email protected]', r.data)
def test_reset_passwordless_user(client, get_message): with capture_reset_password_requests() as requests: client.post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) token = requests[0]["token"] # use the token response = client.post( "/reset/" + token, data={"password": "******", "password_confirm": "awesome sunset"}, follow_redirects=True, ) assert get_message("PASSWORD_RESET") in response.data
def test_easy_password(client, get_message): with capture_reset_password_requests() as requests: client.post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) token = requests[0]["token"] # use the token response = client.post( "/reset/" + token, data={"password": "******", "password_confirm": "mypassword"}, follow_redirects=True, ) assert b"This is a very common password" in response.data
def test_reset_password(self): with capture_reset_password_requests() as requests: self._post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) token = requests[0]['token'] with capture_signals() as mocks: data = dict(password='******', password_confirm='newpassword') self._post('/reset/' + token, data, follow_redirects=True) self.assertEqual(mocks.signals_sent(), set([password_reset])) user = self.app.security.datastore.find_user(email='*****@*****.**') calls = mocks[password_reset] self.assertEqual(len(calls), 1) args, kwargs = calls[0] self.assertTrue(compare_user(kwargs['user'], user)) self.assertEqual(args[0], self.app)
def test_reset_password(self): with capture_reset_password_requests() as requests: self._post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) token = requests[0]['token'] with capture_signals() as mocks: data = dict(password='******', password_confirm='newpassword') self._post('/reset/' + token, data, follow_redirects=True) self.assertEqual(mocks.signals_sent(), set([password_reset])) user = self.app.security.datastore.find_user(email='*****@*****.**') calls = mocks[password_reset] self.assertEqual(len(calls), 1) args, kwargs = calls[0] self.assertTrue(compare_user(args[0], user)) self.assertEqual(kwargs['app'], self.app)
def test_reset_token_redirect_to_post_reset(client, get_message): with capture_reset_password_requests() as requests: client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) token = requests[0]['token'] response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert b'Post Reset' in response.data
def test_expired_reset_token(client, get_message): with capture_reset_password_requests() as requests: client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) user = requests[0]['user'] token = requests[0]['token'] time.sleep(1) response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) msg = get_message('PASSWORD_RESET_EXPIRED', within='1 milliseconds', email=user.email) assert msg in response.data
def test_spa_get_bad_token(app, client, get_message): """ Test expired and invalid token""" with capture_flashes() as flashes: with capture_reset_password_requests() as requests: response = client.post( "/reset", data='{"email": "*****@*****.**"}', headers={"Content-Type": "application/json"}, ) assert response.headers["Content-Type"] == "application/json" assert "user" not in response.jdata["response"] token = requests[0]["token"] time.sleep(1) response = client.get("/reset/" + token) assert response.status_code == 302 split = urlsplit(response.headers["Location"]) assert "localhost:8081" == split.netloc assert "/reset-error" == split.path qparams = dict(parse_qsl(split.query)) assert len(qparams) == 2 assert all(k in qparams for k in ["email", "error"]) msg = get_message( "PASSWORD_RESET_EXPIRED", within="1 milliseconds", email="*****@*****.**" ) assert msg == qparams["error"].encode("utf-8") # Test mangled token token = ( "WyIxNjQ2MzYiLCIxMzQ1YzBlZmVhM2VhZjYwODgwMDhhZGU2YzU0MzZjMiJd." "BZEw_Q.lQyo3npdPZtcJ_sNHVHP103syjM" "&url_id=fbb89a8328e58c181ea7d064c2987874bc54a23d" ) response = client.get("/reset/" + token) assert response.status_code == 302 split = urlsplit(response.headers["Location"]) assert "localhost:8081" == split.netloc assert "/reset-error" == split.path qparams = dict(parse_qsl(split.query)) assert len(qparams) == 1 assert all(k in qparams for k in ["error"]) msg = get_message("INVALID_RESET_PASSWORD_TOKEN") assert msg == qparams["error"].encode("utf-8") assert len(flashes) == 0
def test_reset_token_redirect(client, get_message): with capture_reset_password_requests() as requests: client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) token = requests[0]['token'] response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }) assert 'location' in response.headers assert '/login' in response.location response = client.get(response.location) assert get_message('PASSWORD_RESET') in response.data
def test_can_add_password(app, client, get_message): # Test that if register w/o a password, can use 'recover password' to assign one data = dict(email="*****@*****.**", password="") response = client.post("/register", data=data, follow_redirects=True) assert b"Welcome [email protected]" in response.data logout(client) with capture_reset_password_requests() as requests: client.post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) token = requests[0]["token"] response = client.post( "/reset/" + token, data={ "password": "******", "password_confirm": "awesome sunset" }, follow_redirects=True, ) assert get_message("PASSWORD_RESET") in response.data # authenticate with new password using standard/old login endpoint. response = authenticate(client, "*****@*****.**", "awesome sunset", follow_redirects=True) assert b"Welcome [email protected]" in response.data logout(client) # authenticate with password and us-signin endpoint response = client.post( "/us-signin", data=dict(identity="*****@*****.**", passcode="awesome sunset"), follow_redirects=True, ) assert b"Welcome [email protected]" in response.data
def test_spa_get(app, client): """ Test 'single-page-application' style redirects This uses json only. """ with capture_reset_password_requests() as requests: response = client.post( "/reset", json=dict(email="*****@*****.**"), headers={"Content-Type": "application/json"}, ) assert response.headers["Content-Type"] == "application/json" assert "user" not in response.json["response"] token = requests[0]["token"] response = client.get("/reset/" + token) assert response.status_code == 302 split = urlsplit(response.headers["Location"]) assert "localhost:8081" == split.netloc assert "/reset-redirect" == split.path qparams = dict(parse_qsl(split.query)) assert qparams["email"] == "*****@*****.**" assert qparams["token"] == token
def test_reset_token_deleted_user(app, client, get_message, sqlalchemy_datastore): with capture_reset_password_requests() as requests: client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) user = requests[0]['user'] token = requests[0]['token'] # Delete user with app.app_context(): sqlalchemy_datastore.delete(user) sqlalchemy_datastore.commit() response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) msg = get_message('INVALID_RESET_PASSWORD_TOKEN') assert msg in response.data
def test_reset_token_deleted_user(app, client, get_message, sqlalchemy_datastore): with capture_reset_password_requests() as requests: client.post( '/reset', data=dict( email='*****@*****.**'), follow_redirects=True) user = requests[0]['user'] token = requests[0]['token'] # Delete user with app.app_context(): sqlalchemy_datastore.delete(user) sqlalchemy_datastore.commit() response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) msg = get_message('INVALID_RESET_PASSWORD_TOKEN') assert msg in response.data
def test_recoverable_flag(app, client, get_message): recorded_resets = [] recorded_instructions_sent = [] @password_reset.connect_via(app) def on_password_reset(app, user): recorded_resets.append(user) @reset_password_instructions_sent.connect_via(app) def on_instructions_sent(app, user, token): assert isinstance(app, Flask) assert isinstance(user, UserMixin) assert isinstance(token, str) recorded_instructions_sent.append(user) # Test the reset view response = client.get('/reset') assert b'<h1>Send password reset instructions</h1>' in response.data # Test submitting email to reset password creates a token and sends email with capture_reset_password_requests() as requests: with app.mail.record_messages() as outbox: response = client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) assert len(recorded_instructions_sent) == 1 assert len(outbox) == 1 assert response.status_code == 200 assert get_message('PASSWORD_RESET_REQUEST', email='*****@*****.**') in response.data token = requests[0]['token'] # Test view for reset token response = client.get('/reset/' + token) assert b'<h1>Reset password</h1>' in response.data # Test submitting a new password response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert get_message('PASSWORD_RESET') in response.data assert len(recorded_resets) == 1 logout(client) # Test logging in with the new password response = authenticate(client, '*****@*****.**', 'newpassword', follow_redirects=True) assert b'Hello [email protected]' in response.data logout(client) # Test invalid email response = client.post('/reset', data=dict(email='*****@*****.**'), follow_redirects=True) assert get_message('USER_DOES_NOT_EXIST') in response.data logout(client) # Test invalid token response = client.post('/reset/bogus', data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert get_message('INVALID_RESET_PASSWORD_TOKEN') in response.data # Test mangled token token = ("WyIxNjQ2MzYiLCIxMzQ1YzBlZmVhM2VhZjYwODgwMDhhZGU2YzU0MzZjMiJd." "BZEw_Q.lQyo3npdPZtcJ_sNHVHP103syjM" "&url_id=fbb89a8328e58c181ea7d064c2987874bc54a23d") response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert get_message('INVALID_RESET_PASSWORD_TOKEN') in response.data
def test_forgot_post_sends_email(self): with capture_reset_password_requests(): with self.app.extensions['mail'].record_messages() as outbox: self._post('/reset', data=dict(email='*****@*****.**')) self.assertEqual(len(outbox), 1)
def test_recoverable_json(app, client, get_message): recorded_resets = [] recorded_instructions_sent = [] @password_reset.connect_via(app) def on_password_reset(app, user): recorded_resets.append(user) @reset_password_instructions_sent.connect_via(app) def on_instructions_sent(app, user, token): recorded_instructions_sent.append(user) with capture_flashes() as flashes: # Test reset password creates a token and sends email with capture_reset_password_requests() as requests: with app.mail.record_messages() as outbox: response = client.post( "/reset", json=dict(email="*****@*****.**"), headers={"Content-Type": "application/json"}, ) assert response.headers["Content-Type"] == "application/json" assert len(recorded_instructions_sent) == 1 assert len(outbox) == 1 assert response.status_code == 200 token = requests[0]["token"] # Test invalid email response = client.post( "/reset", json=dict(email="*****@*****.**"), headers={"Content-Type": "application/json"}, ) assert response.status_code == 400 assert response.json["response"]["errors"]["email"][0].encode( "utf-8") == get_message("USER_DOES_NOT_EXIST") # Test submitting a new password but leave out 'confirm' response = client.post( "/reset/" + token, data='{"password": "******"}', headers={"Content-Type": "application/json"}, ) assert response.status_code == 400 assert response.json["response"]["errors"]["password_confirm"][ 0].encode("utf-8") == get_message("PASSWORD_NOT_PROVIDED") # Test submitting a new password response = client.post( "/reset/" + token + "?include_auth_token", json=dict(password="******", password_confirm="awesome sunset"), headers={"Content-Type": "application/json"}, ) assert all(k in response.json["response"]["user"] for k in ["id", "authentication_token"]) assert len(recorded_resets) == 1 # reset automatically logs user in logout(client) # Test logging in with the new password response = client.post( "/login?include_auth_token", json=dict(email="*****@*****.**", password="******"), headers={"Content-Type": "application/json"}, ) assert all(k in response.json["response"]["user"] for k in ["id", "authentication_token"]) logout(client) # Use token again - should fail since already have set new password. response = client.post( "/reset/" + token, json=dict(password="******", password_confirm="newpassword"), headers={"Content-Type": "application/json"}, ) assert response.status_code == 400 assert len(recorded_resets) == 1 # Test invalid token response = client.post( "/reset/bogus", json=dict(password="******", password_confirm="newpassword"), headers={"Content-Type": "application/json"}, ) assert response.json["response"]["error"].encode( "utf-8") == get_message("INVALID_RESET_PASSWORD_TOKEN") assert len(flashes) == 0
def test_recoverable_flag(app, client, get_message): recorded_resets = [] recorded_instructions_sent = [] @password_reset.connect_via(app) def on_password_reset(app, user): recorded_resets.append(user) @reset_password_instructions_sent.connect_via(app) def on_instructions_sent(app, user, token): assert isinstance(app, Flask) assert isinstance(user, UserMixin) assert isinstance(token, string_types) recorded_instructions_sent.append(user) # Test the reset view response = client.get("/reset") assert b"<h1>Send password reset instructions</h1>" in response.data # Test submitting email to reset password creates a token and sends email with capture_reset_password_requests() as requests: with app.mail.record_messages() as outbox: response = client.post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) assert len(recorded_instructions_sent) == 1 assert len(outbox) == 1 assert response.status_code == 200 assert get_message("PASSWORD_RESET_REQUEST", email="*****@*****.**") in response.data token = requests[0]["token"] # Test view for reset token response = client.get("/reset/" + token) assert b"<h1>Reset password</h1>" in response.data # Test submitting a new password but leave out confirm response = client.post("/reset/" + token, data={"password": "******"}, follow_redirects=True) assert get_message("PASSWORD_NOT_PROVIDED") in response.data assert len(recorded_resets) == 0 # Test submitting a new password response = client.post( "/reset/" + token, data={ "password": "******", "password_confirm": "awesome sunset" }, follow_redirects=True, ) assert get_message("PASSWORD_RESET") in response.data assert len(recorded_resets) == 1 logout(client) # Test logging in with the new password response = authenticate(client, "*****@*****.**", "awesome sunset", follow_redirects=True) assert b"Welcome [email protected]" in response.data logout(client) # Test invalid email response = client.post("/reset", data=dict(email="*****@*****.**"), follow_redirects=True) assert get_message("USER_DOES_NOT_EXIST") in response.data logout(client) # Test invalid token response = client.post( "/reset/bogus", data={ "password": "******", "password_confirm": "awesome sunset" }, follow_redirects=True, ) assert get_message("INVALID_RESET_PASSWORD_TOKEN") in response.data # Test mangled token token = ("WyIxNjQ2MzYiLCIxMzQ1YzBlZmVhM2VhZjYwODgwMDhhZGU2YzU0MzZjMiJd." "BZEw_Q.lQyo3npdPZtcJ_sNHVHP103syjM" "&url_id=fbb89a8328e58c181ea7d064c2987874bc54a23d") response = client.post( "/reset/" + token, data={ "password": "******", "password_confirm": "newpassword" }, follow_redirects=True, ) assert get_message("INVALID_RESET_PASSWORD_TOKEN") in response.data
def test_recoverable_flag(app, client, get_message): recorded_resets = [] recorded_instructions_sent = [] @password_reset.connect_via(app) def on_password_reset(app, user): recorded_resets.append(user) @reset_password_instructions_sent.connect_via(app) def on_instructions_sent(app, user, token): assert isinstance(app, Flask) assert isinstance(user, UserMixin) assert isinstance(token, string_types) recorded_instructions_sent.append(user) # Test the reset view response = client.get('/reset') assert b'<h1>Send password reset instructions</h1>' in response.data # Test submitting email to reset password creates a token and sends email with capture_reset_password_requests() as requests: with app.mail.record_messages() as outbox: response = client.post( '/reset', data=dict( email='*****@*****.**'), follow_redirects=True) assert len(recorded_instructions_sent) == 1 assert len(outbox) == 1 assert response.status_code == 200 assert get_message( 'PASSWORD_RESET_REQUEST', email='*****@*****.**') in response.data token = requests[0]['token'] # Test view for reset token response = client.get('/reset/' + token) assert b'<h1>Reset password</h1>' in response.data # Test submitting a new password response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert get_message('PASSWORD_RESET') in response.data assert len(recorded_resets) == 1 logout(client) # Test logging in with the new password response = authenticate( client, '*****@*****.**', 'newpassword', follow_redirects=True) assert b'Hello [email protected]' in response.data logout(client) # Test submitting JSON response = client.post('/reset', data='{"email": "*****@*****.**"}', headers={ 'Content-Type': 'application/json' }) assert response.headers['Content-Type'] == 'application/json' assert 'user' not in response.jdata['response'] logout(client) # Test invalid email response = client.post( '/reset', data=dict( email='*****@*****.**'), follow_redirects=True) assert get_message('USER_DOES_NOT_EXIST') in response.data logout(client) # Test invalid token response = client.post('/reset/bogus', data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert get_message('INVALID_RESET_PASSWORD_TOKEN') in response.data # Test mangled token token = ( "WyIxNjQ2MzYiLCIxMzQ1YzBlZmVhM2VhZjYwODgwMDhhZGU2YzU0MzZjMiJd." "BZEw_Q.lQyo3npdPZtcJ_sNHVHP103syjM" "&url_id=fbb89a8328e58c181ea7d064c2987874bc54a23d") response = client.post('/reset/' + token, data={ 'password': '******', 'password_confirm': 'newpassword' }, follow_redirects=True) assert get_message('INVALID_RESET_PASSWORD_TOKEN') in response.data