From 36690f33a44a489e649022f0c56f41a38020414b Mon Sep 17 00:00:00 2001 From: Olivier Brisse Date: Fri, 15 Mar 2019 09:54:25 +1100 Subject: [PATCH] Make `#increment_failed_attempts` concurrency safe Backported from https://github.com/plataformatec/devise/pull/4996 --- lib/devise/models/lockable.rb | 4 ++-- test/models/lockable_test.rb | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/devise/models/lockable.rb b/lib/devise/models/lockable.rb index 5fc9561f96..dfea218b85 100644 --- a/lib/devise/models/lockable.rb +++ b/lib/devise/models/lockable.rb @@ -99,8 +99,8 @@ def valid_for_authentication? if super && !access_locked? true else - self.failed_attempts ||= 0 - self.failed_attempts += 1 + self.class.increment_counter(:failed_attempts, id) + reload if attempts_exceeded? lock_access! unless access_locked? else diff --git a/test/models/lockable_test.rb b/test/models/lockable_test.rb index ac86c77909..904873e978 100644 --- a/test/models/lockable_test.rb +++ b/test/models/lockable_test.rb @@ -37,6 +37,17 @@ def setup end end + test "should read failed_attempts from database when incrementing" do + user = create_user + initial_failed_attempts = user.failed_attempts + same_user = User.find(user.id) + + user.valid_for_authentication?{ false } + same_user.valid_for_authentication?{ false } + + assert_equal initial_failed_attempts + 2, user.reload.failed_attempts + end + test 'should be valid for authentication with a unlocked user' do user = create_user user.lock_access!