Fix the user flow when the user account is locked.

The user has 10 tries at the password, after which the account is locked.
The same is true for the verify code, the user will have 10 tries before the user account is locked.
This commit is contained in:
Rebecca Law
2017-02-28 14:41:31 +00:00
parent 2d4e0a0631
commit 35f61125e8
6 changed files with 14 additions and 5 deletions
+1
View File
@@ -30,6 +30,7 @@ def new_password(token):
if form.validate_on_submit(): if form.validate_on_submit():
user_api_client.send_verify_code(user.id, 'sms', user.mobile_number) user_api_client.send_verify_code(user.id, 'sms', user.mobile_number)
user_api_client.reset_failed_login_count(user.id)
session['user_details'] = { session['user_details'] = {
'id': user.id, 'id': user.id,
'email': user.email_address, 'email': user.email_address,
-3
View File
@@ -32,9 +32,6 @@ def two_factor():
# Check if coming from new password page # Check if coming from new password page
if 'password' in session['user_details']: if 'password' in session['user_details']:
user = user_api_client.update_password(user.id, password=session['user_details']['password']) user = user_api_client.update_password(user.id, password=session['user_details']['password'])
if user.is_locked():
form.sms_code.errors.append('Code not found')
return render_template('views/two-factor.html', form=form)
activated_user = user_api_client.activate_user(user) activated_user = user_api_client.activate_user(user)
login_user(activated_user, remember=True) login_user(activated_user, remember=True)
finally: finally:
+5 -1
View File
@@ -75,6 +75,11 @@ class UserApiClient(NotifyAdminAPIClient):
user_data = self.post(url, data=data) user_data = self.post(url, data=data)
return User(user_data['data'], max_failed_login_count=self.max_failed_login_count) return User(user_data['data'], max_failed_login_count=self.max_failed_login_count)
def reset_failed_login_count(self, user_id):
url = "/user/{}/reset-failed-login-count".format(user_id)
user_data = self.post(url, data={})
return User(user_data['data'], max_failed_login_count=self.max_failed_login_count)
def update_password(self, user_id, password): def update_password(self, user_id, password):
data = {"_password": password} data = {"_password": password}
url = "/user/{}/update-password".format(user_id) url = "/user/{}/update-password".format(user_id)
@@ -152,7 +157,6 @@ class UserApiClient(NotifyAdminAPIClient):
def activate_user(self, user): def activate_user(self, user):
if user.state == 'pending': if user.state == 'pending':
user.state = 'active' user.state = 'active'
user._failed_login_count = 0
return self.update_user(user) return self.update_user(user)
else: else:
return user return user
@@ -38,6 +38,7 @@ def test_should_redirect_to_two_factor_when_password_reset_is_successful(
mock_get_user_by_email_request_password_reset, mock_get_user_by_email_request_password_reset,
mock_login, mock_login,
mock_send_verify_code, mock_send_verify_code,
mock_reset_failed_login_count
): ):
user = mock_get_user_by_email_request_password_reset.return_value user = mock_get_user_by_email_request_password_reset.return_value
data = json.dumps({'email': user.email_address, 'created_at': str(datetime.utcnow())}) data = json.dumps({'email': user.email_address, 'created_at': str(datetime.utcnow())})
@@ -54,6 +55,7 @@ def test_should_redirect_index_if_user_has_already_changed_password(
mock_get_user_by_email_user_changed_password, mock_get_user_by_email_user_changed_password,
mock_login, mock_login,
mock_send_verify_code, mock_send_verify_code,
mock_reset_failed_login_count
): ):
user = mock_get_user_by_email_user_changed_password.return_value user = mock_get_user_by_email_user_changed_password.return_value
data = json.dumps({'email': user.email_address, 'created_at': str(datetime.utcnow())}) data = json.dumps({'email': user.email_address, 'created_at': str(datetime.utcnow())})
+1 -1
View File
@@ -187,7 +187,7 @@ def test_two_factor_returns_error_when_user_is_locked(
client, client,
api_user_locked, api_user_locked,
mock_get_locked_user, mock_get_locked_user,
mock_check_verify_code, mock_check_verify_code_code_not_found,
mock_get_services_with_one_service mock_get_services_with_one_service
): ):
with client.session_transaction() as session: with client.session_transaction() as session:
+5
View File
@@ -1377,6 +1377,11 @@ def mock_update_whitelist(mocker):
) )
@pytest.fixture(scope='function')
def mock_reset_failed_login_count(mocker):
return mocker.patch('app.user_api_client.reset_failed_login_count')
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def client(app_): def client(app_):
with app_.test_request_context(), app_.test_client() as client: with app_.test_request_context(), app_.test_client() as client: