diff --git a/lib/devise/hooks/timeoutable.rb b/lib/devise/hooks/timeoutable.rb index 772eb142b7..aaabe69a4d 100644 --- a/lib/devise/hooks/timeoutable.rb +++ b/lib/devise/hooks/timeoutable.rb @@ -21,11 +21,15 @@ proxy = Devise::Hooks::Proxy.new(warden) - if !env['devise.skip_timeout'] && - record.timedout?(last_request_at) && - !proxy.remember_me_is_active?(record) - Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope) - throw :warden, scope: scope, message: :timeout + if !env['devise.skip_timeout'] && record.timedout?(last_request_at) + if proxy.remember_me_is_active?(record) + if record.respond_to?(:update_tracked_fields!) && !warden.request.env['devise.skip_trackable'] + record.update_tracked_fields!(warden.request) + end + else + Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope) + throw :warden, scope: scope, message: :timeout + end end unless env['devise.skip_trackable'] diff --git a/test/integration/timeoutable_test.rb b/test/integration/timeoutable_test.rb index d11d59105c..c9a753a963 100644 --- a/test/integration/timeoutable_test.rb +++ b/test/integration/timeoutable_test.rb @@ -177,6 +177,41 @@ def last_request_at assert warden.authenticated?(:user) end + test 'time out updates current and last sign in timestamps if remembered' do + user = sign_in_as_user remember_me: true + get expire_user_path(user) + + new_time = 2.seconds.from_now + Time.stubs(:now).returns(new_time) + + get users_path + + user.reload + assert user.current_sign_in_at > user.last_sign_in_at + end + + test 'time out updates current and last sign in remote ip if remembered' do + user = sign_in_as_user remember_me: true + get expire_user_path(user) + + arbitrary_ip = '200.121.1.69' + get users_path, headers: { 'HTTP_X_FORWARDED_FOR' => arbitrary_ip } + + user.reload + assert_equal arbitrary_ip, user.current_sign_in_ip + assert_equal '127.0.0.1', user.last_sign_in_ip + end + + test 'time out updates sign in count if remembered' do + user = sign_in_as_user remember_me: true + + get expire_user_path(user) + assert_equal 1, user.reload.sign_in_count + + get users_path + assert_equal 2, user.reload.sign_in_count + end + test 'does not crash when the last_request_at is a String' do user = sign_in_as_user