mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
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
10 changed files with 81 additions and 51 deletions
|
@ -27,7 +27,7 @@ module Devise
|
||||||
ALL = []
|
ALL = []
|
||||||
CONTROLLERS = {}
|
CONTROLLERS = {}
|
||||||
ROUTES = []
|
ROUTES = []
|
||||||
STRATEGIES = []
|
STRATEGIES = ActiveSupport::OrderedHash.new
|
||||||
FLASH_MESSAGES = [:unauthenticated]
|
FLASH_MESSAGES = [:unauthenticated]
|
||||||
|
|
||||||
# True values used to check params
|
# True values used to check params
|
||||||
|
@ -122,49 +122,73 @@ module Devise
|
||||||
mattr_accessor :token_authentication_key
|
mattr_accessor :token_authentication_key
|
||||||
@@token_authentication_key = :auth_token
|
@@token_authentication_key = :auth_token
|
||||||
|
|
||||||
# The realm used in Http Basic Authentication
|
# The realm used in Http Basic Authentication.
|
||||||
mattr_accessor :http_authentication_realm
|
mattr_accessor :http_authentication_realm
|
||||||
@@http_authentication_realm = "Application"
|
@@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
|
# Default way to setup Devise. Run rails generate devise_install to create
|
||||||
# a fresh initializer with all configuration values.
|
# a fresh initializer with all configuration values.
|
||||||
def self.setup
|
def self.setup
|
||||||
yield self
|
yield self
|
||||||
end
|
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.
|
# Make Devise aware of an 3rd party Devise-module. For convenience.
|
||||||
#
|
#
|
||||||
# == Options:
|
# == 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.)
|
# +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.
|
# +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 *route* helper for this module.
|
||||||
# +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.
|
# +flash+ - Symbol representing the *flash messages* used by this helper.
|
||||||
# Default is +nil+ (i.e. +false+).
|
# +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:
|
# == Examples:
|
||||||
#
|
#
|
||||||
# Devise.add_module(:party_module)
|
# Devise.add_module(:party_module)
|
||||||
# Devise.add_module(:party_module, :strategy => true, :controller => :sessions)
|
# 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 = {})
|
def self.add_module(module_name, options = {})
|
||||||
ALL << module_name
|
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]
|
next unless options[key]
|
||||||
name = (options[key] == true ? module_name : options[key])
|
name = (options[key] == true ? module_name : options[key])
|
||||||
value.unshift(name) unless value.include?(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
if options[:controller]
|
if value.is_a?(Hash)
|
||||||
Devise::CONTROLLERS[module_name] = options[:controller].to_sym
|
value[module_name] = name
|
||||||
|
else
|
||||||
|
value << name unless value.include?(name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if options[:model]
|
if options[:model]
|
||||||
|
@ -172,7 +196,7 @@ module Devise
|
||||||
Devise::Models.send(:autoload, module_name.to_s.camelize.to_sym, model_path)
|
Devise::Models.send(:autoload, module_name.to_s.camelize.to_sym, model_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
Devise::Mapping.register module_name
|
Devise::Mapping.add_module module_name
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sets warden configuration using a block that will be invoked on warden
|
# Sets warden configuration using a block that will be invoked on warden
|
||||||
|
@ -187,19 +211,17 @@ module Devise
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
def self.warden(&block)
|
def self.warden(&block)
|
||||||
@warden_config = block
|
@@warden_config_block = block
|
||||||
end
|
end
|
||||||
|
|
||||||
# A method used internally to setup warden manager from the Rails initialize
|
# A method used internally to setup warden manager from the Rails initialize
|
||||||
# block.
|
# block.
|
||||||
def self.configure_warden(config) #:nodoc:
|
def self.configure_warden(config) #:nodoc:
|
||||||
config.default_strategies *Devise::STRATEGIES
|
|
||||||
config.failure_app = Devise::FailureApp
|
config.failure_app = Devise::FailureApp
|
||||||
config.silence_missing_strategies!
|
|
||||||
config.default_scope = Devise.default_scope
|
config.default_scope = Devise.default_scope
|
||||||
|
|
||||||
# If the user provided a warden hook, call it now.
|
@@warden_config = config
|
||||||
@warden_config.try :call, config
|
@@warden_config_block.try :call, config
|
||||||
end
|
end
|
||||||
|
|
||||||
# Generate a friendly string randomically to be used as token.
|
# Generate a friendly string randomically to be used as token.
|
||||||
|
|
|
@ -77,6 +77,10 @@ module Devise
|
||||||
klass
|
klass
|
||||||
end
|
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
|
# 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
|
# that an Admin cannot access the registrations controller unless it has
|
||||||
# :registerable in the model.
|
# :registerable in the model.
|
||||||
|
@ -104,7 +108,7 @@ module Devise
|
||||||
# self.modules.include?(:confirmable)
|
# self.modules.include?(:confirmable)
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
def self.register(m)
|
def self.add_module(m)
|
||||||
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
||||||
def #{m}?
|
def #{m}?
|
||||||
self.modules.include?(:#{m})
|
self.modules.include?(:#{m})
|
||||||
|
|
|
@ -92,17 +92,14 @@ module ActionDispatch::Routing
|
||||||
resources.map!(&:to_sym)
|
resources.map!(&:to_sym)
|
||||||
|
|
||||||
resources.each do |resource|
|
resources.each do |resource|
|
||||||
mapping = Devise::Mapping.new(resource, options)
|
mapping = Devise.register(resource, options)
|
||||||
|
|
||||||
unless mapping.to.respond_to?(:devise)
|
unless mapping.to.respond_to?(:devise)
|
||||||
raise "#{mapping.to.name} does not respond to 'devise' method. This usually means you haven't " <<
|
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'"
|
"inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb'"
|
||||||
end
|
end
|
||||||
|
|
||||||
Devise.default_scope ||= mapping.name
|
|
||||||
Devise.mappings[mapping.name] = mapping
|
|
||||||
|
|
||||||
routes_modules = mapping.modules - Array(options.delete(:skip))
|
routes_modules = mapping.modules - Array(options.delete(:skip))
|
||||||
routes_modules.each do |mod|
|
routes_modules.each do |mod|
|
||||||
send(mod, mapping, mapping.controllers) if self.respond_to?(mod, true)
|
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
|
# Redirects to sign_in page if it's not authenticated
|
||||||
class Authenticatable < Base
|
class Authenticatable < Base
|
||||||
def valid?
|
def valid?
|
||||||
valid_controller? && valid_params? && mapping.to.respond_to?(:authenticate)
|
valid_controller? && valid_params?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Authenticate a user based on email and password params, returning to warden
|
# 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.
|
# Sign in an user using HTTP authentication.
|
||||||
class HttpAuthenticatable < Base
|
class HttpAuthenticatable < Base
|
||||||
def valid?
|
def valid?
|
||||||
request.authorization && mapping.to.respond_to?(:authenticate_with_http)
|
request.authorization
|
||||||
end
|
end
|
||||||
|
|
||||||
def authenticate!
|
def authenticate!
|
||||||
|
|
|
@ -10,7 +10,7 @@ module Devise
|
||||||
|
|
||||||
# A valid strategy for rememberable needs a remember token in the cookies.
|
# A valid strategy for rememberable needs a remember token in the cookies.
|
||||||
def valid?
|
def valid?
|
||||||
remember_me_cookie.present? && mapping.to.respond_to?(:serialize_from_cookie)
|
remember_me_cookie.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
# To authenticate a user we deserialize the cookie and attempt finding
|
# 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.
|
# Redirects to sign_in page if it's not authenticated.
|
||||||
class TokenAuthenticatable < Base
|
class TokenAuthenticatable < Base
|
||||||
def valid?
|
def valid?
|
||||||
mapping.to.respond_to?(:authenticate_with_token) && authentication_token(scope).present?
|
authentication_token(scope).present?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Authenticate a user based on authenticatable token params, returning to warden
|
# Authenticate a user based on authenticatable token params, returning to warden
|
||||||
|
|
|
@ -15,7 +15,7 @@ module Devise
|
||||||
def initialize(controller)
|
def initialize(controller)
|
||||||
@controller = controller
|
@controller = controller
|
||||||
manager = Warden::Manager.new(nil) do |config|
|
manager = Warden::Manager.new(nil) do |config|
|
||||||
Devise.configure_warden(config)
|
config.merge! Devise.warden_config
|
||||||
end
|
end
|
||||||
super(controller.request.env, manager)
|
super(controller.request.env, manager)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
module Devise
|
module Devise
|
||||||
def self.clean_warden_config!
|
def self.yield_and_restore
|
||||||
@warden_config = nil
|
c, b = @@warden_config, @@warden_config_block
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
@@warden_config, @@warden_config_block = c, b
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -21,17 +24,17 @@ class DeviseTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'warden manager configuration' do
|
test 'warden manager configuration' do
|
||||||
|
Devise.yield_and_restore do
|
||||||
config = Warden::Config.new
|
config = Warden::Config.new
|
||||||
Devise.configure_warden(config)
|
Devise.configure_warden(config)
|
||||||
|
|
||||||
assert_equal Devise::FailureApp, config.failure_app
|
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_equal :user, config.default_scope
|
||||||
assert config.silence_missing_strategies?
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'warden manager user configuration through a block' do
|
test 'warden manager user configuration through a block' do
|
||||||
begin
|
Devise.yield_and_restore do
|
||||||
@executed = false
|
@executed = false
|
||||||
Devise.warden do |config|
|
Devise.warden do |config|
|
||||||
@executed = true
|
@executed = true
|
||||||
|
@ -40,8 +43,6 @@ class DeviseTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
Devise.configure_warden(Warden::Config.new)
|
Devise.configure_warden(Warden::Config.new)
|
||||||
assert @executed
|
assert @executed
|
||||||
ensure
|
|
||||||
Devise.clean_warden_config!
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -52,8 +53,8 @@ class DeviseTest < ActiveSupport::TestCase
|
||||||
assert_not defined?(Devise::Models::Coconut)
|
assert_not defined?(Devise::Models::Coconut)
|
||||||
Devise::ALL.delete(:coconut)
|
Devise::ALL.delete(:coconut)
|
||||||
|
|
||||||
assert_nothing_raised(Exception) { Devise.add_module(:banana, :strategy => true) }
|
assert_nothing_raised(Exception) { Devise.add_module(:banana, :strategy => :fruits) }
|
||||||
assert_equal 1, Devise::STRATEGIES.select { |v| v == :banana }.size
|
assert_equal :fruits, Devise::STRATEGIES[:banana]
|
||||||
Devise::ALL.delete(:banana)
|
Devise::ALL.delete(:banana)
|
||||||
Devise::STRATEGIES.delete(:banana)
|
Devise::STRATEGIES.delete(:banana)
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ class MappingTest < ActiveSupport::TestCase
|
||||||
assert_equal :admin_area, Devise.mappings[:admin].as
|
assert_equal :admin_area, Devise.mappings[:admin].as
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'allow custom scope to be given' do
|
test 'allows custom scope to be given' do
|
||||||
assert_equal :accounts, Devise.mappings[:manager].as
|
assert_equal :accounts, Devise.mappings[:manager].as
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ class MappingTest < ActiveSupport::TestCase
|
||||||
assert_not allowed.include?("devise/unlocks")
|
assert_not allowed.include?("devise/unlocks")
|
||||||
end
|
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
|
test 'find mapping by path' do
|
||||||
assert_nil Devise::Mapping.find_by_path("/foo/bar")
|
assert_nil Devise::Mapping.find_by_path("/foo/bar")
|
||||||
assert_equal Devise.mappings[:user], Devise::Mapping.find_by_path("/users/session")
|
assert_equal Devise.mappings[:user], Devise::Mapping.find_by_path("/users/session")
|
||||||
|
|
Loading…
Reference in a new issue