Do not depend on silence_missing_strategies! anymore. This speeds up strategies matching because we don't need to check if the model duck types to the strategy and it doesn't trigger uneeded strategies.
This commit is contained in:
parent
066c6e8771
commit
033db1ca7c
|
@ -27,7 +27,7 @@ module Devise
|
|||
ALL = []
|
||||
CONTROLLERS = {}
|
||||
ROUTES = []
|
||||
STRATEGIES = []
|
||||
STRATEGIES = ActiveSupport::OrderedHash.new
|
||||
FLASH_MESSAGES = [:unauthenticated]
|
||||
|
||||
# True values used to check params
|
||||
|
@ -122,49 +122,73 @@ module Devise
|
|||
mattr_accessor :token_authentication_key
|
||||
@@token_authentication_key = :auth_token
|
||||
|
||||
# The realm used in Http Basic Authentication
|
||||
# The realm used in Http Basic Authentication.
|
||||
mattr_accessor :http_authentication_realm
|
||||
@@http_authentication_realm = "Application"
|
||||
|
||||
# Private methods to interface with Warden.
|
||||
mattr_reader :warden_config
|
||||
@@warden_config = nil
|
||||
@@warden_config_block = nil
|
||||
|
||||
# Default way to setup Devise. Run rails generate devise_install to create
|
||||
# a fresh initializer with all configuration values.
|
||||
def self.setup
|
||||
yield self
|
||||
end
|
||||
|
||||
# Register a model in Devise. You can call this manually if you don't want
|
||||
# to use devise routes. Check devise_for in routes to know which options
|
||||
# are available.
|
||||
def self.register(resource, options)
|
||||
mapping = Devise::Mapping.new(resource, options)
|
||||
self.mappings[mapping.name] = mapping
|
||||
self.default_scope ||= mapping.name
|
||||
|
||||
warden_config.default_scope ||= mapping.name
|
||||
warden_config.scope_defaults mapping.name, :strategies => mapping.strategies
|
||||
mapping
|
||||
end
|
||||
|
||||
# Make Devise aware of an 3rd party Devise-module. For convenience.
|
||||
#
|
||||
# == Options:
|
||||
#
|
||||
# +strategy+ - Boolean value representing if this module got a custom *strategy*.
|
||||
# Default is +false+. Note: Devise will auto-detect this in such case if this is true.
|
||||
# +model+ - String representing the load path to a custom *model* for this module (to autoload.)
|
||||
# Default is +nil+ (i.e. +false+).
|
||||
# +controller+ - Symbol representing the name of an exisiting or custom *controller* for this module.
|
||||
# Default is +nil+ (i.e. +false+).
|
||||
# +route+ - Symbol representing the named *router* helper for this module.
|
||||
# Default is +nil+ (i.e. +false+).
|
||||
# +flash+ - Symbol representing the *flash messages* used by this helper.
|
||||
# Default is +nil+ (i.e. +false+).
|
||||
# +model+ - String representing the load path to a custom *model* for this module (to autoload.)
|
||||
# +controller+ - Symbol representing the name of an exisiting or custom *controller* for this module.
|
||||
# +route+ - Symbol representing the named *route* helper for this module.
|
||||
# +flash+ - Symbol representing the *flash messages* used by this helper.
|
||||
# +strategy+ - Symbol representing if this module got a custom *strategy*.
|
||||
#
|
||||
# All values, except :model, accept also a boolean and will have the same name as the given module
|
||||
# name.
|
||||
#
|
||||
# == Examples:
|
||||
#
|
||||
# Devise.add_module(:party_module)
|
||||
# Devise.add_module(:party_module, :strategy => true, :controller => :sessions)
|
||||
# Devise.add_module(:party_module, :autoload => 'party_module/model')
|
||||
# Devise.add_module(:party_module, :model => 'party_module/model')
|
||||
#
|
||||
def self.add_module(module_name, options = {})
|
||||
ALL << module_name
|
||||
options.assert_valid_keys(:strategy, :model, :controller, :route, :flash)
|
||||
options.assert_valid_keys(:strategy, :model, :controller, :route, :flash, :passive_strategy)
|
||||
|
||||
{ :strategy => STRATEGIES, :flash => FLASH_MESSAGES, :route => ROUTES }.each do |key, value|
|
||||
config = {
|
||||
:strategy => STRATEGIES,
|
||||
:flash => FLASH_MESSAGES,
|
||||
:route => ROUTES,
|
||||
:controller => CONTROLLERS
|
||||
}
|
||||
|
||||
config.each do |key, value|
|
||||
next unless options[key]
|
||||
name = (options[key] == true ? module_name : options[key])
|
||||
value.unshift(name) unless value.include?(name)
|
||||
end
|
||||
|
||||
if options[:controller]
|
||||
Devise::CONTROLLERS[module_name] = options[:controller].to_sym
|
||||
if value.is_a?(Hash)
|
||||
value[module_name] = name
|
||||
else
|
||||
value << name unless value.include?(name)
|
||||
end
|
||||
end
|
||||
|
||||
if options[:model]
|
||||
|
@ -172,7 +196,7 @@ module Devise
|
|||
Devise::Models.send(:autoload, module_name.to_s.camelize.to_sym, model_path)
|
||||
end
|
||||
|
||||
Devise::Mapping.register module_name
|
||||
Devise::Mapping.add_module module_name
|
||||
end
|
||||
|
||||
# Sets warden configuration using a block that will be invoked on warden
|
||||
|
@ -187,19 +211,17 @@ module Devise
|
|||
# end
|
||||
# end
|
||||
def self.warden(&block)
|
||||
@warden_config = block
|
||||
@@warden_config_block = block
|
||||
end
|
||||
|
||||
# A method used internally to setup warden manager from the Rails initialize
|
||||
# block.
|
||||
def self.configure_warden(config) #:nodoc:
|
||||
config.default_strategies *Devise::STRATEGIES
|
||||
config.failure_app = Devise::FailureApp
|
||||
config.silence_missing_strategies!
|
||||
config.failure_app = Devise::FailureApp
|
||||
config.default_scope = Devise.default_scope
|
||||
|
||||
# If the user provided a warden hook, call it now.
|
||||
@warden_config.try :call, config
|
||||
@@warden_config = config
|
||||
@@warden_config_block.try :call, config
|
||||
end
|
||||
|
||||
# Generate a friendly string randomically to be used as token.
|
||||
|
|
|
@ -77,6 +77,10 @@ module Devise
|
|||
klass
|
||||
end
|
||||
|
||||
def strategies
|
||||
@strategies ||= STRATEGIES.values_at(*self.modules).compact.reverse
|
||||
end
|
||||
|
||||
# Keep a list of allowed controllers for this mapping. It's useful to ensure
|
||||
# that an Admin cannot access the registrations controller unless it has
|
||||
# :registerable in the model.
|
||||
|
@ -104,7 +108,7 @@ module Devise
|
|||
# self.modules.include?(:confirmable)
|
||||
# end
|
||||
#
|
||||
def self.register(m)
|
||||
def self.add_module(m)
|
||||
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
||||
def #{m}?
|
||||
self.modules.include?(:#{m})
|
||||
|
|
|
@ -92,17 +92,14 @@ module ActionDispatch::Routing
|
|||
resources.map!(&:to_sym)
|
||||
|
||||
resources.each do |resource|
|
||||
mapping = Devise::Mapping.new(resource, options)
|
||||
mapping = Devise.register(resource, options)
|
||||
|
||||
unless mapping.to.respond_to?(:devise)
|
||||
raise "#{mapping.to.name} does not respond to 'devise' method. This usually means you haven't " <<
|
||||
"loaded your ORM file or it's being loaded to late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " <<
|
||||
"loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " <<
|
||||
"inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb'"
|
||||
end
|
||||
|
||||
Devise.default_scope ||= mapping.name
|
||||
Devise.mappings[mapping.name] = mapping
|
||||
|
||||
routes_modules = mapping.modules - Array(options.delete(:skip))
|
||||
routes_modules.each do |mod|
|
||||
send(mod, mapping, mapping.controllers) if self.respond_to?(mod, true)
|
||||
|
|
|
@ -6,7 +6,7 @@ module Devise
|
|||
# Redirects to sign_in page if it's not authenticated
|
||||
class Authenticatable < Base
|
||||
def valid?
|
||||
valid_controller? && valid_params? && mapping.to.respond_to?(:authenticate)
|
||||
valid_controller? && valid_params?
|
||||
end
|
||||
|
||||
# Authenticate a user based on email and password params, returning to warden
|
||||
|
|
|
@ -5,7 +5,7 @@ module Devise
|
|||
# Sign in an user using HTTP authentication.
|
||||
class HttpAuthenticatable < Base
|
||||
def valid?
|
||||
request.authorization && mapping.to.respond_to?(:authenticate_with_http)
|
||||
request.authorization
|
||||
end
|
||||
|
||||
def authenticate!
|
||||
|
|
|
@ -10,7 +10,7 @@ module Devise
|
|||
|
||||
# A valid strategy for rememberable needs a remember token in the cookies.
|
||||
def valid?
|
||||
remember_me_cookie.present? && mapping.to.respond_to?(:serialize_from_cookie)
|
||||
remember_me_cookie.present?
|
||||
end
|
||||
|
||||
# To authenticate a user we deserialize the cookie and attempt finding
|
||||
|
|
|
@ -6,7 +6,7 @@ module Devise
|
|||
# Redirects to sign_in page if it's not authenticated.
|
||||
class TokenAuthenticatable < Base
|
||||
def valid?
|
||||
mapping.to.respond_to?(:authenticate_with_token) && authentication_token(scope).present?
|
||||
authentication_token(scope).present?
|
||||
end
|
||||
|
||||
# Authenticate a user based on authenticatable token params, returning to warden
|
||||
|
|
|
@ -15,7 +15,7 @@ module Devise
|
|||
def initialize(controller)
|
||||
@controller = controller
|
||||
manager = Warden::Manager.new(nil) do |config|
|
||||
Devise.configure_warden(config)
|
||||
config.merge! Devise.warden_config
|
||||
end
|
||||
super(controller.request.env, manager)
|
||||
end
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
require 'test_helper'
|
||||
|
||||
module Devise
|
||||
def self.clean_warden_config!
|
||||
@warden_config = nil
|
||||
def self.yield_and_restore
|
||||
c, b = @@warden_config, @@warden_config_block
|
||||
yield
|
||||
ensure
|
||||
@@warden_config, @@warden_config_block = c, b
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -21,17 +24,17 @@ class DeviseTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
test 'warden manager configuration' do
|
||||
config = Warden::Config.new
|
||||
Devise.configure_warden(config)
|
||||
Devise.yield_and_restore do
|
||||
config = Warden::Config.new
|
||||
Devise.configure_warden(config)
|
||||
|
||||
assert_equal Devise::FailureApp, config.failure_app
|
||||
assert_equal [:rememberable, :token_authenticatable, :http_authenticatable, :authenticatable], config.default_strategies
|
||||
assert_equal :user, config.default_scope
|
||||
assert config.silence_missing_strategies?
|
||||
assert_equal Devise::FailureApp, config.failure_app
|
||||
assert_equal :user, config.default_scope
|
||||
end
|
||||
end
|
||||
|
||||
test 'warden manager user configuration through a block' do
|
||||
begin
|
||||
Devise.yield_and_restore do
|
||||
@executed = false
|
||||
Devise.warden do |config|
|
||||
@executed = true
|
||||
|
@ -40,8 +43,6 @@ class DeviseTest < ActiveSupport::TestCase
|
|||
|
||||
Devise.configure_warden(Warden::Config.new)
|
||||
assert @executed
|
||||
ensure
|
||||
Devise.clean_warden_config!
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -52,8 +53,8 @@ class DeviseTest < ActiveSupport::TestCase
|
|||
assert_not defined?(Devise::Models::Coconut)
|
||||
Devise::ALL.delete(:coconut)
|
||||
|
||||
assert_nothing_raised(Exception) { Devise.add_module(:banana, :strategy => true) }
|
||||
assert_equal 1, Devise::STRATEGIES.select { |v| v == :banana }.size
|
||||
assert_nothing_raised(Exception) { Devise.add_module(:banana, :strategy => :fruits) }
|
||||
assert_equal :fruits, Devise::STRATEGIES[:banana]
|
||||
Devise::ALL.delete(:banana)
|
||||
Devise::STRATEGIES.delete(:banana)
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ class MappingTest < ActiveSupport::TestCase
|
|||
assert_equal :admin_area, Devise.mappings[:admin].as
|
||||
end
|
||||
|
||||
test 'allow custom scope to be given' do
|
||||
test 'allows custom scope to be given' do
|
||||
assert_equal :accounts, Devise.mappings[:manager].as
|
||||
end
|
||||
|
||||
|
@ -29,6 +29,12 @@ class MappingTest < ActiveSupport::TestCase
|
|||
assert_not allowed.include?("devise/unlocks")
|
||||
end
|
||||
|
||||
test 'has strategies depending on the model declaration' do
|
||||
assert_equal [:rememberable, :token_authenticatable,
|
||||
:http_authenticatable, :authenticatable], Devise.mappings[:user].strategies
|
||||
assert_equal [:authenticatable], Devise.mappings[:admin].strategies
|
||||
end
|
||||
|
||||
test 'find mapping by path' do
|
||||
assert_nil Devise::Mapping.find_by_path("/foo/bar")
|
||||
assert_equal Devise.mappings[:user], Devise::Mapping.find_by_path("/users/session")
|
||||
|
|
Loading…
Reference in New Issue