mirror of
https://github.com/omniauth/omniauth.git
synced 2022-11-09 12:31:49 -05:00
Small but powerful change: Strategy options now inherit from a default, are Mashes, and can be declaratively configured.
This commit is contained in:
parent
98bc2b9a4a
commit
53bc3f5741
4 changed files with 117 additions and 4 deletions
|
@ -74,6 +74,12 @@ module OmniAuth
|
||||||
self.mock_auth[provider.to_sym] = mock
|
self.mock_auth[provider.to_sym] = mock
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# This is a convenience method to be used by strategy authors
|
||||||
|
# so that they can add special cases to the camelization utility
|
||||||
|
# method that allows OmniAuth::Builder to work.
|
||||||
|
#
|
||||||
|
# @param name [String] The underscored name, e.g. `oauth`
|
||||||
|
# @param camelized [String] The properly camelized name, e.g. 'OAuth'
|
||||||
def add_camelization(name, camelized)
|
def add_camelization(name, camelized)
|
||||||
self.camelizations[name.to_s] = camelized.to_s
|
self.camelizations[name.to_s] = camelized.to_s
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
require 'omniauth'
|
require 'omniauth'
|
||||||
|
require 'hashie/mash'
|
||||||
|
|
||||||
module OmniAuth
|
module OmniAuth
|
||||||
class NoSessionError < StandardError; end
|
class NoSessionError < StandardError; end
|
||||||
|
@ -12,12 +13,58 @@ module OmniAuth
|
||||||
base.class_eval do
|
base.class_eval do
|
||||||
attr_reader :app, :name, :env, :options, :response
|
attr_reader :app, :name, :env, :options, :response
|
||||||
end
|
end
|
||||||
|
base.extend ClassMethods
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
# Returns an inherited set of default options set at the class-level
|
||||||
|
# for each strategy.
|
||||||
|
def default_options
|
||||||
|
return @default_options if @default_options
|
||||||
|
existing = superclass.respond_to?(:default_options) ? superclass.default_options : {}
|
||||||
|
@default_options = OmniAuth::Strategy::Options.new(existing)
|
||||||
|
end
|
||||||
|
|
||||||
|
# This allows for more declarative subclassing of strategies by allowing
|
||||||
|
# default options to be set using a simple configure call.
|
||||||
|
#
|
||||||
|
# @param options [Hash] If supplied, these will be the default options (deep-merged into the superclass's default options).
|
||||||
|
# @yield [Options] The options Mash that allows you to set your defaults as you'd like.
|
||||||
|
#
|
||||||
|
# @example Using a yield to configure the default options.
|
||||||
|
#
|
||||||
|
# class MyStrategy
|
||||||
|
# include OmniAuth::Strategy
|
||||||
|
#
|
||||||
|
# configure do |c|
|
||||||
|
# c.foo = 'bar'
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @example Using a hash to configure the default options.
|
||||||
|
#
|
||||||
|
# class MyStrategy
|
||||||
|
# include OmniAuth::Strategy
|
||||||
|
# configure foo: 'bar'
|
||||||
|
# end
|
||||||
|
def configure(options = nil)
|
||||||
|
yield default_options and return unless options
|
||||||
|
default_options.deep_merge!(options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Initializes the strategy by passing in the Rack endpoint,
|
||||||
|
# the unique URL segment name for this strategy, and any
|
||||||
|
# additional arguments. An `options` hash is automatically
|
||||||
|
# created from the last argument if it is a hash.
|
||||||
|
#
|
||||||
|
# @param app [Rack application] The application on which this middleware is applied.
|
||||||
|
# @param name [String] A unique URL segment to describe this particular strategy. For example, `'openid'`.
|
||||||
|
# @yield [Strategy] Yields itself for block-based configuration.
|
||||||
def initialize(app, name, *args, &block)
|
def initialize(app, name, *args, &block)
|
||||||
@app = app
|
@app = app
|
||||||
@name = name.to_sym
|
@name = name.to_s
|
||||||
@options = args.last.is_a?(Hash) ? args.pop : {}
|
@options = self.class.default_options.deep_merge(args.last.is_a?(Hash) ? args.pop : {})
|
||||||
|
|
||||||
yield self if block_given?
|
yield self if block_given?
|
||||||
end
|
end
|
||||||
|
@ -26,10 +73,17 @@ module OmniAuth
|
||||||
"#<#{self.class.to_s}>"
|
"#<#{self.class.to_s}>"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Duplicates this instance and runs #call! on it.
|
||||||
|
# @param [Hash] The Rack environment.
|
||||||
def call(env)
|
def call(env)
|
||||||
dup.call!(env)
|
dup.call!(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The logic for dispatching any additional actions that need
|
||||||
|
# to be taken. For instance, calling the request phase if
|
||||||
|
# the request path is recognized.
|
||||||
|
#
|
||||||
|
# @param env [Hash] The Rack environment.
|
||||||
def call!(env)
|
def call!(env)
|
||||||
raise OmniAuth::NoSessionError.new("You must provide a session to use OmniAuth.") unless env['rack.session']
|
raise OmniAuth::NoSessionError.new("You must provide a session to use OmniAuth.") unless env['rack.session']
|
||||||
|
|
||||||
|
@ -75,6 +129,8 @@ module OmniAuth
|
||||||
callback_phase
|
callback_phase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true if the environment recognizes either the
|
||||||
|
# request or callback path.
|
||||||
def on_auth_path?
|
def on_auth_path?
|
||||||
on_request_path? || on_callback_path?
|
on_request_path? || on_callback_path?
|
||||||
end
|
end
|
||||||
|
@ -95,6 +151,9 @@ module OmniAuth
|
||||||
request.request_method == 'OPTIONS'
|
request.request_method == 'OPTIONS'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# This is called in lieu of the normal request process
|
||||||
|
# in the event that OmniAuth has been configured to be
|
||||||
|
# in test mode.
|
||||||
def mock_call!(env)
|
def mock_call!(env)
|
||||||
return mock_request_call if on_request_path?
|
return mock_request_call if on_request_path?
|
||||||
return mock_callback_call if on_callback_path?
|
return mock_callback_call if on_callback_path?
|
||||||
|
@ -115,7 +174,7 @@ module OmniAuth
|
||||||
|
|
||||||
def mock_callback_call
|
def mock_callback_call
|
||||||
setup_phase
|
setup_phase
|
||||||
mocked_auth = OmniAuth.mock_auth_for(name.to_sym)
|
mocked_auth = OmniAuth.mock_auth_for(name.to_s)
|
||||||
if mocked_auth.is_a?(Symbol)
|
if mocked_auth.is_a?(Symbol)
|
||||||
fail!(mocked_auth)
|
fail!(mocked_auth)
|
||||||
else
|
else
|
||||||
|
@ -126,6 +185,10 @@ module OmniAuth
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The setup phase looks for the `:setup` option to exist and,
|
||||||
|
# if it is, will call either the Rack endpoint supplied to the
|
||||||
|
# `:setup` option or it will call out to the setup path of the
|
||||||
|
# underlying application. This will default to `/auth/:provider/setup`.
|
||||||
def setup_phase
|
def setup_phase
|
||||||
if options[:setup].respond_to?(:call)
|
if options[:setup].respond_to?(:call)
|
||||||
options[:setup].call(env)
|
options[:setup].call(env)
|
||||||
|
@ -183,7 +246,7 @@ module OmniAuth
|
||||||
end
|
end
|
||||||
|
|
||||||
def auth_hash
|
def auth_hash
|
||||||
AuthHash.new(:provider => name.to_s)
|
AuthHash.new(:provider => name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def full_host
|
def full_host
|
||||||
|
@ -238,5 +301,7 @@ module OmniAuth
|
||||||
|
|
||||||
OmniAuth.config.on_failure.call(self.env)
|
OmniAuth.config.on_failure.call(self.env)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class Options < Hashie::Mash; end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,6 +29,37 @@ end
|
||||||
|
|
||||||
describe OmniAuth::Strategy do
|
describe OmniAuth::Strategy do
|
||||||
let(:app){ lambda{|env| [404, {}, ['Awesome']]}}
|
let(:app){ lambda{|env| [404, {}, ['Awesome']]}}
|
||||||
|
|
||||||
|
describe '.default_options' do
|
||||||
|
it 'should be inherited from a parent class' do
|
||||||
|
superklass = Class.new
|
||||||
|
superklass.send :include, OmniAuth::Strategy
|
||||||
|
superklass.configure do |c|
|
||||||
|
c.foo = 'bar'
|
||||||
|
end
|
||||||
|
|
||||||
|
klass = Class.new(superklass)
|
||||||
|
klass.default_options.foo.should == 'bar'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.configure' do
|
||||||
|
subject { klass = Class.new; klass.send :include, OmniAuth::Strategy; klass }
|
||||||
|
it 'should take a block and allow for default options setting' do
|
||||||
|
subject.configure do |c|
|
||||||
|
c.wakka = 'doo'
|
||||||
|
end
|
||||||
|
subject.default_options.should == {"wakka" => "doo"}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should take a hash and deep merge it' do
|
||||||
|
subject.configure :abc => {:def => 123}
|
||||||
|
subject.configure :abc => {:hgi => 456}
|
||||||
|
subject.default_options.should == {'abc' => {'def' => 123, 'hgi' => 456}}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
describe '#initialize' do
|
describe '#initialize' do
|
||||||
context 'options extraction' do
|
context 'options extraction' do
|
||||||
it 'should be the last argument if the last argument is a Hash' do
|
it 'should be the last argument if the last argument is a Hash' do
|
||||||
|
@ -38,6 +69,11 @@ describe OmniAuth::Strategy do
|
||||||
it 'should be a blank hash if none are provided' do
|
it 'should be a blank hash if none are provided' do
|
||||||
ExampleStrategy.new(app, 'test').options.should == {}
|
ExampleStrategy.new(app, 'test').options.should == {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should be the default options if any are provided' do
|
||||||
|
ExampleStrategy.stub!(:default_options).and_return(OmniAuth::Strategy::Options.new(:abc => 123))
|
||||||
|
ExampleStrategy.new(app, 'test').options.abc.should == 123
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,12 @@ describe OmniAuth do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'configuration' do
|
context 'configuration' do
|
||||||
|
describe '.defaults' do
|
||||||
|
it 'should be a hash of default configuration' do
|
||||||
|
OmniAuth::Configuration.defaults.should be_kind_of(Hash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it 'should be callable from .configure' do
|
it 'should be callable from .configure' do
|
||||||
OmniAuth.configure do |c|
|
OmniAuth.configure do |c|
|
||||||
c.should be_kind_of(OmniAuth::Configuration)
|
c.should be_kind_of(OmniAuth::Configuration)
|
||||||
|
|
Loading…
Reference in a new issue