diff --git a/lib/devise/models/authenticatable.rb b/lib/devise/models/authenticatable.rb index c598b4fc..d4d72e90 100644 --- a/lib/devise/models/authenticatable.rb +++ b/lib/devise/models/authenticatable.rb @@ -283,28 +283,20 @@ module Devise # Find or initialize a record with group of attributes based on a list of required attributes. def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc: - attributes = if attributes.respond_to? :permit! - attributes.slice(*required_attributes).permit!.to_h.with_indifferent_access - else - attributes.with_indifferent_access.slice(*required_attributes) - end - attributes.delete_if { |key, value| value.blank? } + attributes.try(:permit!) + attributes = attributes.to_h.with_indifferent_access + .slice(*required_attributes) + .delete_if { |key, value| value.blank? } if attributes.size == required_attributes.size - record = find_first_by_auth_conditions(attributes) + record = find_first_by_auth_conditions(attributes) and return record end - unless record - record = new - + new(devise_parameter_filter.filter(attributes)).tap do |record| required_attributes.each do |key| - value = attributes[key] - record.send("#{key}=", value) - record.errors.add(key, value.present? ? error : :blank) + record.errors.add(key, attributes[key].blank? ? :blank : error) end end - - record end protected diff --git a/test/models/authenticatable_test.rb b/test/models/authenticatable_test.rb index b3cab65b..205f4ee3 100644 --- a/test/models/authenticatable_test.rb +++ b/test/models/authenticatable_test.rb @@ -13,6 +13,21 @@ class AuthenticatableTest < ActiveSupport::TestCase assert_nil User.find_first_by_auth_conditions({ email: "example@example.com" }, id: user.id.to_s.next) end + # assumes default configuration of + # config.case_insensitive_keys = [:email] + # config.strip_whitespace_keys = [:email] + test 'find_or_initialize_with_errors uses parameter filter on find' do + user = User.create!(email: "example@example.com", password: "1234567") + assert_equal User.find_or_initialize_with_errors([:email], { email: " EXAMPLE@example.com " }), user + end + + # assumes default configuration of + # config.case_insensitive_keys = [:email] + # config.strip_whitespace_keys = [:email] + test 'find_or_initialize_with_errors uses parameter filter on initialize' do + assert_equal User.find_or_initialize_with_errors([:email], { email: " EXAMPLE@example.com " }).email, "example@example.com" + end + if defined?(ActionController::Parameters) test 'does not passes an ActionController::Parameters to find_first_by_auth_conditions through find_or_initialize_with_errors' do user = create_user(email: 'example@example.com')