def test_should_return_404_when_email_address_does_not_exist(app_, mock_get_user_by_email_not_found): with app_.test_request_context(): with app_.test_client() as client: data = json.dumps({'email': '*****@*****.**', 'created_at': str(datetime.utcnow())}) token = generate_token(data, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT']) response = client.get(url_for('.new_password', token=token)) assert response.status_code == 404
def test_should_throw_exception_when_token_is_tampered_with(): import uuid token = generate_token(str(uuid.uuid4()), 'secret-key', 'dangerous-salt') try: check_token(token + 'qerqwer', 'secret-key', 'dangerous-salt', 30) fail() except BadSignature: pass
def test_return_none_when_token_is_expired(): max_age = -1000 payload = 'some_payload' token = generate_token(payload, 'secret-key', 'dangerous-salt') try: assert check_token(token, 'secret-key', 'dangerous-salt', max_age) is None fail('Expected a SignatureExpired exception') except SignatureExpired: pass
def test_should_redirect_to_forgot_password_with_flash_message_when_token_is_expired( app_, mock_get_user_by_email_request_password_reset, mock_login ): with app_.test_request_context(): with app_.test_client() as client: app_.config['TOKEN_MAX_AGE_SECONDS'] = -1000 user = mock_get_user_by_email_request_password_reset.return_value token = generate_token(user.email_address, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT']) response = client.post(url_for('.new_password', token=token), data={'new_password': '******'}) assert response.status_code == 302 assert response.location == url_for('.forgot_password', _external=True) app_.config['TOKEN_MAX_AGE_SECONDS'] = 3600
def test_should_render_new_password_template(app_, api_user_active, mock_login, mock_send_verify_code, mock_get_user_by_email_request_password_reset): with app_.test_request_context(): with app_.test_client() as client: data = json.dumps({'email': api_user_active.email_address, 'created_at': str(datetime.utcnow())}) token = generate_token(data, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT']) response = client.get(url_for('.new_password', token=token)) assert response.status_code == 200 assert 'You can now create a new password for your account.' in response.get_data(as_text=True)
def test_should_redirect_index_if_user_has_already_changed_password(app_, mock_get_user_by_email_user_changed_password, mock_login, mock_send_verify_code): with app_.test_request_context(): with app_.test_client() as client: user = mock_get_user_by_email_user_changed_password.return_value data = json.dumps({'email': user.email_address, 'created_at': str(datetime.utcnow())}) token = generate_token(data, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT']) response = client.post(url_for('.new_password', token=token), data={'new_password': '******'}) assert response.status_code == 302 assert response.location == url_for('.index', _external=True) mock_get_user_by_email_user_changed_password.assert_called_once_with(user.email_address)
def test_accept_invite_returns_400_when_invited_user_does_not_exist(notify_api): with notify_api.test_request_context(): with notify_api.test_client() as client: token = generate_token(str(uuid.uuid4()), notify_api.config['SECRET_KEY'], notify_api.config['DANGEROUS_SALT']) url = '/invite/{}'.format(token) auth_header = create_authorization_header() response = client.get(url, headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 404 json_resp = json.loads(response.get_data(as_text=True)) assert json_resp['result'] == 'error' assert json_resp['message'] == 'No result found'
def test_should_redirect_to_user_profile_when_user_confirms_email_link(app_, api_user_active, mock_login, mock_update_user_attribute ): with app_.test_request_context(): with app_.test_client() as client: client.login(api_user_active) token = generate_token(payload=json.dumps({'user_id': api_user_active.id, 'email': '*****@*****.**'}), secret=app_.config['SECRET_KEY'], salt=app_.config['DANGEROUS_SALT']) response = client.get(url_for('main.user_profile_email_confirm', token=token)) assert response.status_code == 302 assert response.location == url_for('main.user_profile', _external=True)
def test_accept_invite_for_expired_token_returns_400(notify_api, sample_invited_user): with notify_api.test_request_context(): with notify_api.test_client() as client: with freeze_time('2016-01-01T12:00:00'): token = generate_token(str(sample_invited_user.id), notify_api.config['SECRET_KEY'], notify_api.config['DANGEROUS_SALT']) url = '/invite/{}'.format(token) auth_header = create_authorization_header() response = client.get(url, headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 400 json_resp = json.loads(response.get_data(as_text=True)) assert json_resp['result'] == 'error' assert json_resp['message'] == {'invitation': [ 'Your invitation to GOV.UK Notify has expired. ' 'Please ask the person that invited you to send you another one']}
def test_accept_invite_returns_200_when_token_valid(notify_api, sample_invited_user): with notify_api.test_request_context(): with notify_api.test_client() as client: token = generate_token(str(sample_invited_user.id), notify_api.config['SECRET_KEY'], notify_api.config['DANGEROUS_SALT']) url = '/invite/{}'.format(token) auth_header = create_authorization_header() response = client.get(url, headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 200 json_resp = json.loads(response.get_data(as_text=True)) assert json_resp['data']['id'] == str(sample_invited_user.id) assert json_resp['data']['email_address'] == sample_invited_user.email_address assert json_resp['data']['from_user'] == str(sample_invited_user.user_id) assert json_resp['data']['service'] == str(sample_invited_user.service_id) assert json_resp['data']['status'] == sample_invited_user.status assert json_resp['data']['permissions'] == sample_invited_user.permissions
def test_should_redirect_to_two_factor_when_password_reset_is_successful( app_, client, mock_get_user_by_email_request_password_reset, mock_login, mock_send_verify_code, mock_reset_failed_login_count): user = mock_get_user_by_email_request_password_reset.return_value data = json.dumps({ 'email': user.email_address, 'created_at': str(datetime.utcnow()) }) token = generate_token(data, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT']) response = client.post(url_for_endpoint_with_token('.new_password', token=token), data={'new_password': '******'}) assert response.status_code == 302 assert response.location == url_for('.two_factor', _external=True) mock_get_user_by_email_request_password_reset.assert_called_once_with( user.email_address)
def test_validate_invitation_token_returns_400_when_token_is_malformed(client, invitation_type): token = generate_token( str(uuid.uuid4()), current_app.config['SECRET_KEY'], current_app.config['DANGEROUS_SALT'] )[:-2] url = '/invite/{}/{}'.format(invitation_type, token) auth_header = create_authorization_header() response = client.get(url, headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 400 json_resp = json.loads(response.get_data(as_text=True)) assert json_resp['result'] == 'error' assert json_resp['message'] == { 'invitation': 'Something’s wrong with this link. Make sure you’ve copied the whole thing.' }
def test_should_redirect_index_if_user_has_already_changed_password( app_, client, mock_get_user_by_email_user_changed_password, mock_login, mock_send_verify_code, mock_reset_failed_login_count): user = mock_get_user_by_email_user_changed_password.return_value data = json.dumps({ 'email': user['email_address'], 'created_at': str(datetime.utcnow()) }) token = generate_token(data, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT']) response = client.post(url_for_endpoint_with_token('.new_password', token=token), data={'new_password': '******'}) assert response.status_code == 302 assert response.location == url_for('.index', _external=True) mock_get_user_by_email_user_changed_password.assert_called_once_with( user['email_address'])
def test_validate_invitation_token_returns_400_when_token_is_malformed( client, invitation_type): token = generate_token( str(uuid.uuid4()), current_app.config["SECRET_KEY"], current_app.config["DANGEROUS_SALT"], )[:-2] url = "/invite/{}/{}".format(invitation_type, token) auth_header = create_authorization_header() response = client.get(url, headers=[("Content-Type", "application/json"), auth_header]) assert response.status_code == 400 json_resp = json.loads(response.get_data(as_text=True)) assert json_resp["result"] == "error" assert json_resp["message"] == {"invitation": "bad invitation link"}
def test_should_render_new_password_template( app_, client, api_user_active, mock_login, mock_send_verify_code, mock_get_user_by_email_request_password_reset, ): data = json.dumps({ 'email': api_user_active.email_address, 'created_at': str(datetime.utcnow()) }) token = generate_token(data, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT']) response = client.get(url_for('.new_password', token=token)) assert response.status_code == 200 assert 'You can now create a new password for your account.' in response.get_data( as_text=True)
def test_validate_invitation_token_for_expired_token_returns_400( client, invitation_type): with freeze_time("2016-01-01T12:00:00"): token = generate_token( str(uuid.uuid4()), current_app.config["SECRET_KEY"], current_app.config["DANGEROUS_SALT"], ) url = "/invite/{}/{}".format(invitation_type, token) auth_header = create_authorization_header() response = client.get(url, headers=[("Content-Type", "application/json"), auth_header]) assert response.status_code == 400 json_resp = json.loads(response.get_data(as_text=True)) assert json_resp["result"] == "error" assert json_resp["message"] == {"invitation": "invitation expired"}
def test_should_redirect_to_user_profile_when_user_confirms_email_link( app_, logged_in_client, api_user_active, mock_update_user_attribute, ): token = generate_token(payload=json.dumps({ 'user_id': api_user_active.id, 'email': '*****@*****.**' }), secret=app_.config['SECRET_KEY'], salt=app_.config['DANGEROUS_SALT']) response = logged_in_client.get( url_for('main.user_profile_email_confirm', token=token)) assert response.status_code == 302 assert response.location == url_for('main.user_profile', _external=True)
def test_validate_invitation_token_for_expired_token_returns_400(client): with freeze_time('2016-01-01T12:00:00'): token = generate_token(str(uuid.uuid4()), current_app.config['SECRET_KEY'], current_app.config['DANGEROUS_SALT']) url = '/invite/service/{}'.format(token) auth_header = create_authorization_header() response = client.get(url, headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 400 json_resp = json.loads(response.get_data(as_text=True)) assert json_resp['result'] == 'error' assert json_resp['message'] == { 'invitation': 'Your invitation to GOV.UK Notify has expired. ' 'Please ask the person that invited you to send you another one' }
def test_should_render_new_password_template( app_, client, api_user_active, mock_login, mock_send_verify_code, mock_get_user_by_email_request_password_reset, ): data = json.dumps({ "email": api_user_active["email_address"], "created_at": str(datetime.utcnow()), }) token = generate_token(data, app_.config["SECRET_KEY"], app_.config["DANGEROUS_SALT"]) response = client.get( url_for_endpoint_with_token(".new_password", token=token)) assert response.status_code == 200 assert "You can now create a new password for your account." in response.get_data( as_text=True)
def test_should_redirect_to_user_profile_when_user_confirms_email_link( app_, logged_in_client, api_user_active, mock_update_user_attribute, ): token = generate_token( payload=json.dumps({ "user_id": api_user_active["id"], "email": "*****@*****.**" }), secret=app_.config["SECRET_KEY"], salt=app_.config["DANGEROUS_SALT"], ) response = logged_in_client.get( url_for_endpoint_with_token("main.user_profile_email_confirm", token=token)) assert response.status_code == 302 assert response.location == url_for("main.user_profile", _external=True)
def test_validate_invitation_token_returns_200_when_token_valid( client, invitation_type, sample_invited_user, sample_invited_org_user ): invited_user = sample_invited_user if invitation_type == 'service' else sample_invited_org_user token = generate_token(str(invited_user.id), current_app.config['SECRET_KEY'], current_app.config['DANGEROUS_SALT']) url = '/invite/{}/{}'.format(invitation_type, token) auth_header = create_authorization_header() response = client.get(url, headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 200 json_resp = json.loads(response.get_data(as_text=True)) if invitation_type == 'service': assert json_resp['data']['id'] == str(sample_invited_user.id) assert json_resp['data']['email_address'] == sample_invited_user.email_address assert json_resp['data']['from_user'] == str(sample_invited_user.user_id) assert json_resp['data']['service'] == str(sample_invited_user.service_id) assert json_resp['data']['status'] == sample_invited_user.status assert json_resp['data']['permissions'] == sample_invited_user.permissions if invitation_type == 'organisation': assert json_resp['data'] == sample_invited_org_user.serialize()
def test_validate_invitation_token_returns_200_when_token_valid( client, sample_invited_user, endpoint_format_str): token = generate_token(str(sample_invited_user.id), current_app.config['SECRET_KEY'], current_app.config['DANGEROUS_SALT']) url = endpoint_format_str.format(token) auth_header = create_authorization_header() response = client.get(url, headers=[('Content-Type', 'application/json'), auth_header]) assert response.status_code == 200 json_resp = json.loads(response.get_data(as_text=True)) assert json_resp['data']['id'] == str(sample_invited_user.id) assert json_resp['data'][ 'email_address'] == sample_invited_user.email_address assert json_resp['data']['from_user'] == str(sample_invited_user.user_id) assert json_resp['data']['service'] == str(sample_invited_user.service_id) assert json_resp['data']['status'] == sample_invited_user.status assert json_resp['data']['permissions'] == sample_invited_user.permissions assert json_resp['data'][ 'folder_permissions'] == sample_invited_user.folder_permissions
def test_should_redirect_index_if_user_has_already_changed_password( app_, client, mock_get_user_by_email_user_changed_password, mock_login, mock_send_verify_code, mock_reset_failed_login_count, ): user = mock_get_user_by_email_user_changed_password.return_value data = json.dumps({ "email": user["email_address"], "created_at": str(datetime.utcnow()) }) token = generate_token(data, app_.config["SECRET_KEY"], app_.config["DANGEROUS_SALT"]) response = client.post( url_for_endpoint_with_token(".new_password", token=token), data={"new_password": "******"}, ) assert response.status_code == 302 assert response.location == url_for(".index", _external=True) mock_get_user_by_email_user_changed_password.assert_called_once_with( user["email_address"])
def test_should_sign_in_when_password_reset_is_successful_for_email_auth( app_, client, mock_get_user, mock_get_user_by_email_request_password_reset, mock_login, mock_send_verify_code, mock_reset_failed_login_count, mock_update_user_password, mock_get_login_events, ): user = mock_get_user_by_email_request_password_reset.return_value user["auth_type"] = "email_auth" data = json.dumps({ "email": user["email_address"], "created_at": str(datetime.utcnow()) }) token = generate_token(data, app_.config["SECRET_KEY"], app_.config["DANGEROUS_SALT"]) response = client.post( url_for_endpoint_with_token(".new_password", token=token), data={"new_password": "******"}, ) assert response.status_code == 302 assert response.location == url_for(".show_accounts_or_dashboard", _external=True) assert mock_get_user_by_email_request_password_reset.called assert mock_reset_failed_login_count.called # the log-in flow makes a couple of calls mock_get_user.assert_called_once_with(user["id"]) mock_update_user_password.assert_called_once_with(user["id"], "a-new_password") assert not mock_send_verify_code.called
def url_with_token(data, url, config, base_url=None): from notifications_utils.url_safe_token import generate_token token = generate_token(data, config['SECRET_KEY'], config['DANGEROUS_SALT']) base_url = (base_url or config['ADMIN_BASE_URL']) + url return base_url + token
def test_should_return_payload_from_signed_token(): payload = '*****@*****.**' token = generate_token(payload, 'secret-key', 'dangerous-salt') assert payload == check_token(token, 'secret-key', 'dangerous-salt', 30)
def url_with_token(data, url, config): from notifications_utils.url_safe_token import generate_token token = generate_token(data, config['SECRET_KEY'], config['DANGEROUS_SALT']) base_url = config['ADMIN_BASE_URL'] + url return base_url + token
def test_should_return_payload_from_signed_token(): payload = '*****@*****.**' token = generate_token(payload, 'secret-key', 'dangerous-salt') token = urllib.parse.unquote(token) assert payload == check_token(token, 'secret-key', 'dangerous-salt', 30)