diff --git a/lib/devise/passwordless.rb b/lib/devise/passwordless.rb index 19548bc..7fddc99 100644 --- a/lib/devise/passwordless.rb +++ b/lib/devise/passwordless.rb @@ -23,5 +23,21 @@ def self.secret_key Devise.secret_key end end + + FILTER_PARAMS_WARNING = "[DEVISE-PASSWORDLESS] We have detected that your Rails configuration does not " \ + "filter :token parameters out of your logs. You should append :token to your " \ + "config.filter_parameters Rails setting so that magic link tokens don't " \ + "leak out of your logs." + + def self.check_filter_parameters(params) + begin + unless params.find{|p| p.to_sym == :token} + warn FILTER_PARAMS_WARNING + end + # Cancel the check if filter_parameters contains regular expressions or other exotic values + rescue NoMethodError + return + end + end end end diff --git a/lib/devise/passwordless/rails.rb b/lib/devise/passwordless/rails.rb index 911fd19..2d0c66a 100644 --- a/lib/devise/passwordless/rails.rb +++ b/lib/devise/passwordless/rails.rb @@ -14,12 +14,7 @@ class Engine < Rails::Engine initializer "devise_passwordless.log_filter_check" do params = Rails.try(:application).try(:config).try(:filter_parameters) || [] - unless params.map(&:to_sym).include?(:token) - warn "[DEVISE-PASSWORDLESS] We have detected that your Rails configuration does not " \ - "filter :token parameters out of your logs. You should append :token to your " \ - "config.filter_parameters Rails setting so that magic link tokens don't " \ - "leak out of your logs." - end + ::Devise::Passwordless.check_filter_parameters(params) end end end diff --git a/spec/devise/passwordless_spec.rb b/spec/devise/passwordless_spec.rb index fcb9ad5..1bce508 100644 --- a/spec/devise/passwordless_spec.rb +++ b/spec/devise/passwordless_spec.rb @@ -2,4 +2,44 @@ it "has a version number" do expect(Devise::Passwordless::VERSION).not_to be nil end + + context "check_filter_parameters" do + let(:warn_msg) { Devise::Passwordless::FILTER_PARAMS_WARNING + "\n" } + + context "symbol keys" do + it "warns if :token is not filtered" do + params = [:password, :password_confirmation] + expect { Devise::Passwordless.check_filter_parameters(params) }.to output(warn_msg).to_stderr + end + + it "doesn't warn if :token is filtered" do + params = [:token, :password, :password_confirmation] + expect { Devise::Passwordless.check_filter_parameters(params) }.not_to output(warn_msg).to_stderr + end + end + + context "string keys" do + it "warns if :token is not filtered" do + params = ["password", "password_confirmation"] + expect { Devise::Passwordless.check_filter_parameters(params) }.to output(warn_msg).to_stderr + end + + it "doesn't warn if :token is filtered" do + params = ["token", "password", "password_confirmation"] + expect { Devise::Passwordless.check_filter_parameters(params) }.not_to output(warn_msg).to_stderr + end + end + + context "regex keys" do + it "doesn't warn if :token is not filtered" do + params = [:password, :password_confirmation, /foo/] + expect { Devise::Passwordless.check_filter_parameters(params) }.not_to output(warn_msg).to_stderr + end + + it "doesn't warn if :token is filtered" do + params = [:token, "token", :password, :password_confirmation, /foo/] + expect { Devise::Passwordless.check_filter_parameters(params) }.not_to output(warn_msg).to_stderr + end + end + end end