Merge pull request #43779 from jonathanhefner/authenticate_by-call-attributes-to_h

Convert attributes to Hash in authenticate_by
This commit is contained in:
Rafael Mendonça França 2021-12-06 12:30:38 -05:00 committed by GitHub
commit d301b3b02b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 6 deletions

View File

@ -1,7 +1,5 @@
# frozen_string_literal: true
require "active_support/core_ext/hash/except"
module ActiveRecord
module SecurePassword
extend ActiveSupport::Concern
@ -37,15 +35,17 @@ module ActiveRecord
# User.authenticate_by(email: "jdoe@example.com") # => ArgumentError
# User.authenticate_by(password: "abc123") # => ArgumentError
def authenticate_by(attributes)
passwords = attributes.select { |name, value| !has_attribute?(name) && has_attribute?("#{name}_digest") }
passwords, identifiers = attributes.to_h.partition do |name, value|
!has_attribute?(name) && has_attribute?("#{name}_digest")
end.map(&:to_h)
raise ArgumentError, "One or more password arguments are required" if passwords.empty?
raise ArgumentError, "One or more finder arguments are required" if passwords.size == attributes.size
raise ArgumentError, "One or more finder arguments are required" if identifiers.empty?
if record = find_by(attributes.except(*passwords.keys))
if record = find_by(identifiers)
record if passwords.count { |name, value| record.public_send(:"authenticate_#{name}", value) } == passwords.size
else
self.new(passwords)
new(passwords)
nil
end
end

View File

@ -64,4 +64,16 @@ class SecurePasswordTest < ActiveRecord::TestCase
User.authenticate_by(password: @user.password)
end
end
test "authenticate_by accepts any object that implements to_h" do
params = Enumerator.new { raise "must access via to_h" }
assert_called_with(params, :to_h, [[]], returns: { token: @user.token, password: @user.password }) do
assert_equal @user, User.authenticate_by(params)
end
assert_called_with(params, :to_h, [[]], returns: { token: "wrong", password: @user.password }) do
assert_nil User.authenticate_by(params)
end
end
end