Skip to content

Commit

Permalink
Allow wrapping of lockable Warden after sign-in hook
Browse files Browse the repository at this point in the history
For applications using a primary/replica multiple database setup, Rails
6's default connection switching can lead to the `Lockable` after
sign-in hook firing on `GET` requests, getting the read-only database,
and then attempting to write while zeroing out the user's failed attempts.

This change adds a customizable wrapper proc that can allow applications
to customize this behavior. For a primary/replica setup using
ActiveRecord's default connection switching, it might look like this:

```ruby
class ConnectionWrapper
  def process(&block)
    # Use the writable DB connection no matter what
    ApplicationRecord.connected_to(role: :writing) do
      block.call
    end
  end
end

Devise.setup do |config|
  config.warden_hook_save_wrapper = ConnectionWrapper.new
end
```

Fix heartcombo#5264
  • Loading branch information
geoffharcourt committed Nov 6, 2020
1 parent f5cc775 commit be8b6b7
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 2 deletions.
8 changes: 8 additions & 0 deletions lib/devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,14 @@ module Test
mattr_accessor :sign_in_after_change_password
@@sign_in_after_change_password = true

mattr_accessor :warden_hook_save_wrapper
class EmptyWrapper
def process(&block)
block.call
end
end
@@warden_hook_save_wrapper = EmptyWrapper.new

def self.activerecord51? # :nodoc:
defined?(ActiveRecord) && ActiveRecord.gem_version >= Gem::Version.new("5.1.x")
end
Expand Down
6 changes: 4 additions & 2 deletions lib/devise/hooks/lockable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
Warden::Manager.after_set_user except: :fetch do |record, warden, options|
if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
unless record.failed_attempts.to_i.zero?
record.failed_attempts = 0
record.save(validate: false)
Devise.warden_hook_save_wrapper.process do
record.failed_attempts = 0
record.save(validate: false)
end
end
end
end

0 comments on commit be8b6b7

Please sign in to comment.