From 038627574c66e53d1896910bcef92c81aeda0b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 3 Mar 2010 11:57:23 +0100 Subject: [PATCH] Keep modules definition in a different file. --- devise.gemspec | 3 +- lib/devise.rb | 191 +++++++++++++++++------------------------- lib/devise/mapping.rb | 15 ++-- lib/devise/models.rb | 11 --- lib/devise/modules.rb | 25 ++++++ test/devise_test.rb | 7 +- test/mapping_test.rb | 20 ++--- 7 files changed, 125 insertions(+), 147 deletions(-) create mode 100644 lib/devise/modules.rb diff --git a/devise.gemspec b/devise.gemspec index 1731034268..79ad2d818e 100644 --- a/devise.gemspec +++ b/devise.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= s.authors = ["Jos\303\251 Valim", "Carlos Ant\303\264nio"] - s.date = %q{2010-02-24} + s.date = %q{2010-03-03} s.description = %q{Flexible authentication solution for Rails with Warden} s.email = %q{contact@plataformatec.com.br} s.extra_rdoc_files = [ @@ -74,6 +74,7 @@ Gem::Specification.new do |s| "lib/devise/models/token_authenticatable.rb", "lib/devise/models/trackable.rb", "lib/devise/models/validatable.rb", + "lib/devise/modules.rb", "lib/devise/orm/active_record.rb", "lib/devise/orm/data_mapper.rb", "lib/devise/orm/mongo_mapper.rb", diff --git a/lib/devise.rb b/lib/devise.rb index b5d110794f..79e55a4631 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -1,6 +1,5 @@ module Devise autoload :FailureApp, 'devise/failure_app' - autoload :Models, 'devise/models' autoload :Schema, 'devise/schema' autoload :TestHelpers, 'devise/test_helpers' @@ -21,40 +20,17 @@ module Encryptors autoload :Sha1, 'devise/encryptors/sha1' end - ALL = [] - - # Authentication ones first - ALL.push :authenticatable, :http_authenticatable, :token_authenticatable, :rememberable - - # Misc after - ALL.push :recoverable, :registerable, :validatable - - # The ones which can sign out after - ALL.push :activatable, :confirmable, :lockable, :timeoutable - - # Stats for last, so we make sure the user is really signed in - ALL.push :trackable - - # Maps controller names to devise modules. - CONTROLLERS = { - :authenticatable => :sessions, - :token_authenticatable => :sessions, - :recoverable => :passwords, - :confirmable => :confirmations, - :registerable => :registrations, - :lockable => :unlocks - } - - # Routes for generating url helpers. - ROUTES = [:session, :password, :confirmation, :registration, :unlock] - - STRATEGIES = [:rememberable, :http_authenticatable, :token_authenticatable, :authenticatable] + # Constants which holds devise configuration for extensions. Those should + # not be modified by the "end user". + ALL = [] + CONTROLLERS = {} + ROUTES = [] + STRATEGIES = [] + FLASH_MESSAGES = [:unauthenticated] + # True values used to check params TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'] - # Maps the messages types that are used in flash message. - FLASH_MESSAGES = [:unauthenticated, :unconfirmed, :invalid, :invalid_token, :timeout, :inactive, :locked] - # Declare encryptors length which are used in migrations. ENCRYPTORS_LENGTH = { :sha1 => 40, @@ -143,99 +119,90 @@ module Encryptors mattr_accessor :http_authentication_realm @@http_authentication_realm = "Application" - class << self - # Default way to setup Devise. Run script/generate devise_install to create - # a fresh initializer with all configuration values. - def setup - yield self - end + # 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 - # TODO Remove me on 1.1.0 final - def orm=(value) - ActiveSupport::Deprecation.warn "Devise.orm= and config.orm= are deprecated. " << - "Just load \"devise/orm/\#{ORM_NAME}\" if Devise supports your ORM" + # 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+). + # + # == Examples: + # + # Devise.add_module(:party_module) + # Devise.add_module(:party_module, :strategy => true, :controller => :sessions) + # Devise.add_module(:party_module, :autoload => 'party_module/model') + # + def self.add_module(module_name, options = {}) + ALL << module_name + options.assert_valid_keys(:strategy, :model, :controller, :route, :flash) + + { :strategy => STRATEGIES, :flash => FLASH_MESSAGES, :route => ROUTES }.each do |key, value| + next unless options[key] + name = (options[key] == true ? module_name : options[key]) + value.unshift(name) unless value.include?(name) end - # TODO Remove me on 1.1.0 final - def default_url_options - ActiveSupport::Deprecation.warn "Devise.default_url_options and config.default_url_options are deprecated. " << - "Just modify ApplicationController.default_url_options and Devise will automatically pick it up" + if options[:controller] + Devise::CONTROLLERS[module_name] = options[:controller].to_sym end - # Sets warden configuration using a block that will be invoked on warden - # initialization. - # - # Devise.initialize do |config| - # config.confirm_within = 2.days - # - # config.warden do |manager| - # # Configure warden to use other strategies, like oauth. - # manager.oauth(:twitter) - # end - # end - def warden(&block) - @warden_config = block + if options[:model] + model_path = (options[:model] == true ? "devise/models/#{module_name}" : options[:model]) + Devise::Models.send(:autoload, module_name.to_s.camelize.to_sym, model_path) end - # A method used internally to setup warden manager from the Rails initialize - # block. - def configure_warden(config) #:nodoc: - config.default_strategies *Devise::STRATEGIES - config.failure_app = Devise::FailureApp - config.silence_missing_strategies! - config.default_scope = Devise.default_scope + Devise::Mapping.register module_name + end - # If the user provided a warden hook, call it now. - @warden_config.try :call, config - end + # Sets warden configuration using a block that will be invoked on warden + # initialization. + # + # Devise.initialize do |config| + # config.confirm_within = 2.days + # + # config.warden do |manager| + # # Configure warden to use other strategies, like oauth. + # manager.oauth(:twitter) + # end + # end + def self.warden(&block) + @warden_config = block + end - # Generate a friendly string randomically to be used as token. - def friendly_token - ActiveSupport::SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n") - 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.default_scope = Devise.default_scope - # 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 a load path to a custom *model* for this module (to autoload). - # Default is +nil+ (i.e. +false+). - # +controller+ - Symbol representing a name of an exisiting or custom *controller* for this module. - # Default is +nil+ (i.e. +false+). - # - # == Examples: - # - # Devise.add_module(:party_module) - # Devise.add_module(:party_module, :strategy => true, :controller => :sessions) - # Devise.add_module(:party_module, :model => 'party_module/model') - # - def add_module(module_name, options = {}) - Devise::ALL.unshift module_name unless Devise::ALL.include?(module_name) - Devise::STRATEGIES.unshift module_name if options[:strategy] && !Devise::STRATEGIES.include?(module_name) - - if options[:controller] - Devise::CONTROLLERS[module_name] = options[:controller].to_sym - end - - if options[:model] - Devise::Models.module_eval do - autoload :"#{module_name.to_s.classify}", options[:model] - end - end - - Devise::Mapping.register module_name - end + # If the user provided a warden hook, call it now. + @warden_config.try :call, config end -end -begin - require 'warden' -rescue - gem 'warden' - require 'warden' + # Generate a friendly string randomically to be used as token. + def self.friendly_token + ActiveSupport::SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n") + end end +require 'warden' require 'devise/mapping' +require 'devise/models' +require 'devise/modules' require 'devise/rails' diff --git a/lib/devise/mapping.rb b/lib/devise/mapping.rb index 17d19779cc..0de447353d 100644 --- a/lib/devise/mapping.rb +++ b/lib/devise/mapping.rb @@ -111,15 +111,12 @@ def path # self.modules.include?(:confirmable) # end # - def self.register(*modules) - modules.each do |m| - class_eval <<-METHOD, __FILE__, __LINE__ + 1 - def #{m}? - self.modules.include?(:#{m}) - end - METHOD - end + def self.register(m) + class_eval <<-METHOD, __FILE__, __LINE__ + 1 + def #{m}? + self.modules.include?(:#{m}) + end + METHOD end - Devise::Mapping.register *ALL end end diff --git a/lib/devise/models.rb b/lib/devise/models.rb index 6b145e4d6d..4a7d9af01c 100644 --- a/lib/devise/models.rb +++ b/lib/devise/models.rb @@ -1,16 +1,5 @@ module Devise module Models - autoload :Activatable, 'devise/models/activatable' - autoload :Authenticatable, 'devise/models/authenticatable' - autoload :Confirmable, 'devise/models/confirmable' - autoload :Lockable, 'devise/models/lockable' - autoload :Recoverable, 'devise/models/recoverable' - autoload :Rememberable, 'devise/models/rememberable' - autoload :Registerable, 'devise/models/registerable' - autoload :Timeoutable, 'devise/models/timeoutable' - autoload :Trackable, 'devise/models/trackable' - autoload :Validatable, 'devise/models/validatable' - # Creates configuration values for Devise and for the given module. # # Devise::Models.config(Devise::Authenticable, :stretches, 10) diff --git a/lib/devise/modules.rb b/lib/devise/modules.rb new file mode 100644 index 0000000000..57b22db56c --- /dev/null +++ b/lib/devise/modules.rb @@ -0,0 +1,25 @@ +require 'active_support/core_ext/object/with_options' + +Devise.with_options :model => true do |d| + # Strategies first + d.with_options :strategy => true do |s| + s.add_module :authenticatable, :controller => :sessions, :flash => :invalid, :route => :session + s.add_module :http_authenticatable + s.add_module :token_authenticatable, :controller => :sessions, :flash => :invalid_token, :route => :session + s.add_module :rememberable + end + + # Misc after + d.add_module :recoverable, :controller => :passwords, :route => :password + d.add_module :registerable, :controller => :registrations, :route => :registration + d.add_module :validatable + + # The ones which can sign out after + d.add_module :activatable, :flash => :inactive + d.add_module :confirmable, :controller => :confirmations, :flash => :unconfirmed, :route => :confirmation + d.add_module :lockable, :controller => :unlocks, :flash => :locked, :route => :unlock + d.add_module :timeoutable, :flash => :timeout + + # Stats for last, so we make sure the user is really signed in + d.add_module :trackable +end \ No newline at end of file diff --git a/test/devise_test.rb b/test/devise_test.rb index 6b2269fa3a..5607bab0e0 100644 --- a/test/devise_test.rb +++ b/test/devise_test.rb @@ -25,7 +25,7 @@ class DeviseTest < ActiveSupport::TestCase Devise.configure_warden(config) assert_equal Devise::FailureApp, config.failure_app - assert_equal [:rememberable, :http_authenticatable, :token_authenticatable, :authenticatable], config.default_strategies + assert_equal [:rememberable, :token_authenticatable, :http_authenticatable, :authenticatable], config.default_strategies assert_equal :user, config.default_scope assert config.silence_missing_strategies? end @@ -58,10 +58,9 @@ class DeviseTest < ActiveSupport::TestCase Devise::STRATEGIES.delete(:banana) assert_nothing_raised(Exception) { Devise.add_module(:kivi, :controller => :fruits) } - assert_not_nil Devise::CONTROLLERS[:fruits] - assert_equal 1, Devise::CONTROLLERS[:fruits].select { |v| v == :kivi }.size + assert_equal :fruits, Devise::CONTROLLERS[:kivi] Devise::ALL.delete(:kivi) - Devise::CONTROLLERS.delete(:fruits) + Devise::CONTROLLERS.delete(:kivi) assert_nothing_raised(Exception) { Devise.add_module(:authenticatable_again, :model => 'devise/model/authenticatable') } assert defined?(Devise::Models::AuthenticatableAgain) diff --git a/test/mapping_test.rb b/test/mapping_test.rb index c6e2fe8717..36ba93d17c 100644 --- a/test/mapping_test.rb +++ b/test/mapping_test.rb @@ -5,7 +5,7 @@ class MappingTest < ActiveSupport::TestCase test 'store options' do mapping = Devise.mappings[:user] assert_equal User, mapping.to - assert_equal User.devise_modules, mapping.for + assert_equal User.devise_modules, mapping.modules assert_equal :users, mapping.as end @@ -18,15 +18,15 @@ class MappingTest < ActiveSupport::TestCase end test 'allows a controller depending on the mapping' do - mapping = Devise.mappings[:user] - assert mapping.allows?(:sessions) - assert mapping.allows?(:confirmations) - assert mapping.allows?(:passwords) - - mapping = Devise.mappings[:admin] - assert mapping.allows?(:sessions) - assert_not mapping.allows?(:confirmations) - assert_not mapping.allows?(:passwords) + allowed = Devise.mappings[:user].allowed_controllers + assert allowed.include?("devise/sessions") + assert allowed.include?("devise/confirmations") + assert allowed.include?("devise/passwords") + + allowed = Devise.mappings[:admin].allowed_controllers + assert allowed.include?("sessions") + assert_not allowed.include?("devise/confirmations") + assert_not allowed.include?("devise/passwords") end test 'find mapping by path' do