diff --git a/lib/devise/omniauth/config.rb b/lib/devise/omniauth/config.rb index b39be236..3f9f628b 100644 --- a/lib/devise/omniauth/config.rb +++ b/lib/devise/omniauth/config.rb @@ -2,25 +2,44 @@ module Devise module OmniAuth class Config attr_accessor :strategy - attr_reader :args + attr_reader :args, :options, :provider def initialize(provider, args) @provider = provider @args = args @strategy = nil + @options = @args.last.is_a?(Hash) ? @args.last : {} end # open_id strategy can have configurable name def strategy_name - options = @args.last.is_a?(Hash) && @args.last - options && options[:name] ? options[:name] : @provider + options[:name] || @provider end def strategy_class - # NOTE: this could be bad if a third-party plugin does not define its strategy - # under the OmniaAuth::Strategies namespace. May be better to search through - # OmniAuth.strategies instead of autoloading. - ::OmniAuth::Strategies.const_get("#{::OmniAuth::Utils.camelize(@provider.to_s)}") + find_strategy || require_strategy + end + + def find_strategy + ::OmniAuth.strategies.find do |strategy_class| + strategy_class.to_s =~ /#{::OmniAuth::Utils.camelize(strategy_name)}$/ || + strategy_class.default_options[:name] == strategy_name + end + end + + def require_strategy + if [:facebook, :github, :twitter].include?(provider.to_sym) + require "omniauth/strategies/#{provider}" + elsif options[:require] + require options[:require] + else + require "omniauth-#{provider}" + end + find_strategy || autoload_strategy + end + + def autoload_strategy + ::OmniAuth::Strategies.const_get(::OmniAuth::Utils.camelize(provider.to_s)) end end end diff --git a/test/omniauth/config_test.rb b/test/omniauth/config_test.rb new file mode 100644 index 00000000..3e1fd60f --- /dev/null +++ b/test/omniauth/config_test.rb @@ -0,0 +1,58 @@ +require 'test_helper' + +class OmniAuthConfigTest < ActiveSupport::TestCase + def self.context(name, &block) + instance_eval(&block) + end + + setup do + $: << File.dirname(__FILE__) + end + + context 'Devise::OmniAuth::Config#strategy_name' do + test 'returns provider if no options given' do + config = Devise::OmniAuth::Config.new :facebook, [{}] + assert_equal :facebook, config.strategy_name + end + test 'returns provider if no name option given' do + config = Devise::OmniAuth::Config.new :facebook, [{ :other => :option }] + assert_equal :facebook, config.strategy_name + end + test 'returns name option' do + config = Devise::OmniAuth::Config.new :facebook, [{ :name => :github }] + assert_equal :github, config.strategy_name + end + end + + context 'Devise::OmniAuth::Config#strategy_class' do + test "finds contrib strategies" do + config = Devise::OmniAuth::Config.new :facebook, [{}] + assert_equal OmniAuth::Strategies::Facebook, config.strategy_class + end + test "finds the strategy in OmniAuth's list by name" do + NamedTestStrategy = Class.new + NamedTestStrategy.send :include, OmniAuth::Strategy + NamedTestStrategy.option :name, :the_one + + config = Devise::OmniAuth::Config.new :the_one, [{}] + assert_equal NamedTestStrategy, config.strategy_class + end + test "finds the strategy in OmniAuth's list by class name" do + UnNamedTestStrategy = Class.new + UnNamedTestStrategy.send :include, OmniAuth::Strategy + + config = Devise::OmniAuth::Config.new :un_named_test_strategy, [{}] + assert_equal UnNamedTestStrategy, config.strategy_class + end + test 'attempts to load an as-yet not loaded plugin' do + config = Devise::OmniAuth::Config.new :my_strategy, [{}] + config_class = config.strategy_class + assert_equal MyStrategy, config_class + end + test 'allows the user to define a custom require path' do + config = Devise::OmniAuth::Config.new :my_other_strategy, [{:require => 'my_other_strategy'}] + config_class = config.strategy_class + assert_equal MyOtherStrategy, config_class + end + end +end diff --git a/test/omniauth/my_other_strategy.rb b/test/omniauth/my_other_strategy.rb new file mode 100644 index 00000000..116e65eb --- /dev/null +++ b/test/omniauth/my_other_strategy.rb @@ -0,0 +1,5 @@ +require 'omniauth' + +class MyOtherStrategy + include OmniAuth::Strategy +end diff --git a/test/omniauth/omniauth-my_strategy.rb b/test/omniauth/omniauth-my_strategy.rb new file mode 100644 index 00000000..d1e8b2a0 --- /dev/null +++ b/test/omniauth/omniauth-my_strategy.rb @@ -0,0 +1,5 @@ +require 'omniauth' + +class MyStrategy + include OmniAuth::Strategy +end