From 3122500ce0c1b1637675325161fcffec1622c437 Mon Sep 17 00:00:00 2001 From: Nicholas Staples Date: Tue, 26 Apr 2016 11:51:34 +0100 Subject: [PATCH] Failed login count set to zero with password reset. --- app/main/views/two_factor.py | 1 + app/notify_client/models.py | 3 +++ tests/app/main/views/test_two_factor.py | 28 +++++++++++++++++++++++++ tests/conftest.py | 27 ++++++++++++++++++------ 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/app/main/views/two_factor.py b/app/main/views/two_factor.py index 0c9cdefe3..fa5e22877 100644 --- a/app/main/views/two_factor.py +++ b/app/main/views/two_factor.py @@ -34,6 +34,7 @@ def two_factor(): # Check if coming from new password page if 'password' in session['user_details']: user.set_password(session['user_details']['password']) + user.reset_failed_login_count() user_api_client.update_user(user) login_user(user, remember=True) finally: diff --git a/app/notify_client/models.py b/app/notify_client/models.py index 4ce76fe94..b4e0e7143 100644 --- a/app/notify_client/models.py +++ b/app/notify_client/models.py @@ -108,6 +108,9 @@ class User(UserMixin): def failed_login_count(self, num): self._failed_login_count += num + def reset_failed_login_count(self): + self._failed_login_count = 0 + def is_locked(self): return self.failed_login_count >= self.max_failed_login_count diff --git a/tests/app/main/views/test_two_factor.py b/tests/app/main/views/test_two_factor.py index d470963c1..cad3e0882 100644 --- a/tests/app/main/views/test_two_factor.py +++ b/tests/app/main/views/test_two_factor.py @@ -177,3 +177,31 @@ def test_two_factor_should_set_password_when_new_password_exists_in_session(app_ ) api_user_active.password = 'changedpassword' mock_update_user.assert_called_once_with(api_user_active) + + +def test_two_factor_reset_login_count_called(app_, + api_user_locked, + mock_get_locked_user, + mock_update_user, + mock_check_verify_code, + mock_get_services_with_one_service): + with app_.test_request_context(): + with app_.test_client() as client: + with client.session_transaction() as session: + new_password = "1234567890" + session['user_details'] = { + 'id': api_user_locked.id, + 'email': api_user_locked.email_address, + 'password': new_password + } + response = client.post(url_for('main.two_factor'), + data={'sms_code': '12345'}) + assert response.status_code == 302 + assert response.location == url_for( + 'main.service_dashboard', + service_id=SERVICE_ONE_ID, + _external=True + ) + api_user_locked.reset_failed_login_count() + api_user_locked.password = new_password + mock_update_user.assert_called_with(api_user_locked) diff --git a/tests/conftest.py b/tests/conftest.py index 9d68c6eb9..3a12d25e7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -406,14 +406,22 @@ def mock_register_user(mocker, api_user_pending): @pytest.fixture(scope='function') -def mock_get_user(mocker, api_user_active): +def mock_get_user(mocker, user=None): + if user is None: + user = api_user_active(fake_uuid()) + def _get_user(id_): - api_user_active.id = id_ - return api_user_active + user.id = id_ + return user return mocker.patch( 'app.user_api_client.get_user', side_effect=_get_user) +@pytest.fixture(scope='function') +def mock_get_locked_user(mocker, api_user_locked): + return mock_get_user(mocker, user=api_user_locked) + + @pytest.fixture(scope='function') def mock_get_user_locked(mocker, api_user_locked): return mocker.patch( @@ -427,14 +435,21 @@ def mock_get_user_pending(mocker, api_user_pending): @pytest.fixture(scope='function') -def mock_get_user_by_email(mocker, api_user_active): +def mock_get_user_by_email(mocker, user=None): + if user is None: + user = api_user_active(fake_uuid()) def _get_user(email_address): - api_user_active._email_address = email_address - return api_user_active + user._email_address = email_address + return user return mocker.patch('app.user_api_client.get_user_by_email', side_effect=_get_user) +@pytest.fixture(scope='function') +def mock_get_locked_user_by_email(mocker, api_user_locked): + return mock_get_user_by_email(mocker, user=api_user_locked) + + @pytest.fixture(scope='function') def mock_get_user_with_permissions(mocker, api_user_active): def _get_user(id):