devise 1.1.9 → 1.2.rc

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of devise might be problematic. Click here for more details.

Files changed (121) hide show
  1. data/CHANGELOG.rdoc +34 -26
  2. data/README.rdoc +134 -100
  3. data/app/controllers/devise/confirmations_controller.rb +1 -1
  4. data/app/controllers/devise/omniauth_callbacks_controller.rb +26 -0
  5. data/app/controllers/devise/passwords_controller.rb +1 -1
  6. data/app/controllers/devise/registrations_controller.rb +59 -6
  7. data/app/controllers/devise/sessions_controller.rb +3 -2
  8. data/app/controllers/devise/unlocks_controller.rb +1 -1
  9. data/app/helpers/devise_helper.rb +4 -2
  10. data/app/mailers/devise/mailer.rb +27 -10
  11. data/app/views/devise/confirmations/new.html.erb +1 -1
  12. data/app/views/devise/passwords/edit.html.erb +2 -2
  13. data/app/views/devise/passwords/new.html.erb +1 -1
  14. data/app/views/devise/registrations/edit.html.erb +1 -1
  15. data/app/views/devise/registrations/new.html.erb +1 -1
  16. data/app/views/devise/sessions/new.html.erb +1 -1
  17. data/app/views/devise/shared/_links.erb +6 -0
  18. data/app/views/devise/unlocks/new.html.erb +1 -1
  19. data/config/locales/en.yml +9 -2
  20. data/lib/devise.rb +116 -58
  21. data/lib/devise/controllers/helpers.rb +103 -107
  22. data/lib/devise/controllers/internal_helpers.rb +23 -7
  23. data/lib/devise/controllers/scoped_views.rb +4 -6
  24. data/lib/devise/controllers/url_helpers.rb +3 -5
  25. data/lib/devise/encryptors/base.rb +1 -1
  26. data/lib/devise/encryptors/restful_authentication_sha1.rb +4 -4
  27. data/lib/devise/failure_app.rb +29 -21
  28. data/lib/devise/hooks/forgetable.rb +2 -1
  29. data/lib/devise/hooks/rememberable.rb +11 -9
  30. data/lib/devise/mapping.rb +12 -5
  31. data/lib/devise/models.rb +0 -14
  32. data/lib/devise/models/authenticatable.rb +40 -30
  33. data/lib/devise/models/confirmable.rb +11 -15
  34. data/lib/devise/models/database_authenticatable.rb +23 -35
  35. data/lib/devise/models/encryptable.rb +65 -0
  36. data/lib/devise/models/lockable.rb +8 -7
  37. data/lib/devise/models/omniauthable.rb +23 -0
  38. data/lib/devise/models/recoverable.rb +5 -3
  39. data/lib/devise/models/registerable.rb +13 -0
  40. data/lib/devise/models/rememberable.rb +38 -30
  41. data/lib/devise/models/timeoutable.rb +20 -3
  42. data/lib/devise/models/token_authenticatable.rb +19 -7
  43. data/lib/devise/models/validatable.rb +16 -4
  44. data/lib/devise/modules.rb +15 -8
  45. data/lib/devise/omniauth.rb +47 -0
  46. data/lib/devise/omniauth/config.rb +30 -0
  47. data/lib/devise/omniauth/test_helpers.rb +57 -0
  48. data/lib/devise/omniauth/url_helpers.rb +29 -0
  49. data/lib/devise/orm/active_record.rb +2 -0
  50. data/lib/devise/orm/mongoid.rb +4 -2
  51. data/lib/devise/rails.rb +26 -46
  52. data/lib/devise/rails/routes.rb +64 -20
  53. data/lib/devise/rails/warden_compat.rb +18 -20
  54. data/lib/devise/schema.rb +13 -14
  55. data/lib/devise/strategies/authenticatable.rb +33 -7
  56. data/lib/devise/strategies/database_authenticatable.rb +1 -1
  57. data/lib/devise/strategies/rememberable.rb +1 -1
  58. data/lib/devise/strategies/token_authenticatable.rb +6 -2
  59. data/lib/devise/test_helpers.rb +11 -1
  60. data/lib/devise/version.rb +1 -1
  61. data/lib/generators/active_record/templates/migration.rb +1 -0
  62. data/lib/generators/devise/orm_helpers.rb +3 -2
  63. data/lib/generators/templates/devise.rb +70 -39
  64. data/test/controllers/helpers_test.rb +43 -67
  65. data/test/controllers/internal_helpers_test.rb +29 -8
  66. data/test/controllers/url_helpers_test.rb +2 -1
  67. data/test/failure_app_test.rb +56 -21
  68. data/test/generators/generators_test_helper.rb +4 -0
  69. data/test/generators/install_generator_test.rb +14 -0
  70. data/test/generators/views_generator_test.rb +37 -0
  71. data/test/integration/authenticatable_test.rb +147 -62
  72. data/test/integration/database_authenticatable_test.rb +22 -0
  73. data/test/integration/http_authenticatable_test.rb +12 -2
  74. data/test/integration/omniauthable_test.rb +107 -0
  75. data/test/integration/recoverable_test.rb +39 -20
  76. data/test/integration/registerable_test.rb +30 -4
  77. data/test/integration/rememberable_test.rb +57 -34
  78. data/test/integration/timeoutable_test.rb +10 -1
  79. data/test/integration/token_authenticatable_test.rb +12 -17
  80. data/test/mailers/confirmation_instructions_test.rb +4 -0
  81. data/test/mailers/reset_password_instructions_test.rb +4 -0
  82. data/test/mailers/unlock_instructions_test.rb +4 -0
  83. data/test/mapping_test.rb +37 -3
  84. data/test/models/confirmable_test.rb +3 -3
  85. data/test/models/database_authenticatable_test.rb +14 -71
  86. data/test/models/encryptable_test.rb +65 -0
  87. data/test/models/lockable_test.rb +17 -1
  88. data/test/models/recoverable_test.rb +17 -0
  89. data/test/models/rememberable_test.rb +186 -125
  90. data/test/models/token_authenticatable_test.rb +1 -13
  91. data/test/models_test.rb +5 -5
  92. data/test/omniauth/url_helpers_test.rb +47 -0
  93. data/test/rails_app/app/active_record/admin.rb +4 -1
  94. data/test/rails_app/app/active_record/user.rb +5 -4
  95. data/test/rails_app/app/controllers/{sessions_controller.rb → admins/sessions_controller.rb} +1 -1
  96. data/test/rails_app/app/controllers/home_controller.rb +9 -0
  97. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +7 -0
  98. data/test/rails_app/app/mongoid/admin.rb +4 -1
  99. data/test/rails_app/app/mongoid/shim.rb +16 -3
  100. data/test/rails_app/app/mongoid/user.rb +5 -5
  101. data/test/rails_app/config/initializers/devise.rb +52 -28
  102. data/test/rails_app/config/routes.rb +14 -6
  103. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +21 -17
  104. data/test/rails_app/db/schema.rb +17 -51
  105. data/test/rails_app/lib/shared_admin.rb +9 -0
  106. data/test/rails_app/lib/shared_user.rb +23 -0
  107. data/test/routes_test.rb +42 -9
  108. data/test/support/integration.rb +3 -3
  109. data/test/support/webrat/integrations/rails.rb +7 -0
  110. data/test/test_helper.rb +2 -0
  111. data/test/test_helpers_test.rb +29 -0
  112. metadata +60 -30
  113. data/Gemfile +0 -27
  114. data/Gemfile.lock +0 -115
  115. data/Rakefile +0 -55
  116. data/TODO +0 -3
  117. data/lib/devise/encryptors/bcrypt.rb +0 -19
  118. data/lib/generators/devise_install_generator.rb +0 -4
  119. data/lib/generators/devise_views_generator.rb +0 -4
  120. data/test/indifferent_hash.rb +0 -33
  121. data/test/support/test_silencer.rb +0 -5
@@ -0,0 +1,29 @@
1
+ module Devise
2
+ module OmniAuth
3
+ module UrlHelpers
4
+ def self.define_helpers(mapping)
5
+ return unless mapping.omniauthable?
6
+
7
+ class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
8
+ def #{mapping.name}_omniauth_authorize_path(provider, params = {})
9
+ if Devise.omniauth_configs[provider.to_sym]
10
+ "/#{mapping.path}/auth/\#{provider}\#{'?'+params.to_param if params.present?}"
11
+ else
12
+ raise ArgumentError, "Could not find omniauth provider \#{provider.inspect}"
13
+ end
14
+ end
15
+ URL_HELPERS
16
+ end
17
+
18
+ def omniauth_authorize_path(resource_or_scope, *args)
19
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
20
+ send("#{scope}_omniauth_authorize_path", *args)
21
+ end
22
+
23
+ def omniauth_callback_path(resource_or_scope, *args)
24
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
25
+ send("#{scope}_omniauth_callback_path", *args)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,5 @@
1
+ require 'orm_adapter/adapters/active_record'
2
+
1
3
  module Devise
2
4
  module Orm
3
5
  # This module contains some helpers and handle schema (migrations):
@@ -1,3 +1,5 @@
1
+ require 'orm_adapter/adapters/mongoid'
2
+
1
3
  module Devise
2
4
  module Orm
3
5
  module Mongoid
@@ -16,7 +18,7 @@ module Devise
16
18
  # Tell how to apply schema methods
17
19
  def apply_devise_schema(name, type, options={})
18
20
  type = Time if type == DateTime
19
- field name, { :type => type }.merge(options)
21
+ field name, { :type => type }.merge!(options)
20
22
  end
21
23
  end
22
24
  end
@@ -26,4 +28,4 @@ end
26
28
  Mongoid::Document::ClassMethods.class_eval do
27
29
  include Devise::Models
28
30
  include Devise::Orm::Mongoid::Hook
29
- end
31
+ end
@@ -1,14 +1,11 @@
1
1
  require 'devise/rails/routes'
2
2
  require 'devise/rails/warden_compat'
3
3
 
4
- # Include UrlHelpers in ActionController and ActionView as soon as they are loaded.
5
- ActiveSupport.on_load(:action_controller) { include Devise::Controllers::UrlHelpers }
6
- ActiveSupport.on_load(:action_view) { include Devise::Controllers::UrlHelpers }
7
-
8
4
  module Devise
9
5
  class Engine < ::Rails::Engine
10
6
  config.devise = Devise
11
7
 
8
+ # Initialize Warden and copy its configurations.
12
9
  config.app_middleware.use Warden::Manager do |config|
13
10
  Devise.warden_config = config
14
11
  end
@@ -16,54 +13,37 @@ module Devise
16
13
  # Force routes to be loaded if we are doing any eager load.
17
14
  config.before_eager_load { |app| app.reload_routes! }
18
15
 
19
- config.after_initialize do
20
- Devise.encryptor ||= begin
21
- warn "[WARNING] config.encryptor is not set in your config/initializers/devise.rb. " \
22
- "Devise will then set it to :bcrypt. If you were using the previous default " \
23
- "encryptor, please add config.encryptor = :sha1 to your configuration file." if Devise.mailer_sender
24
- :bcrypt
25
- end
26
- end
27
-
28
- initializer "devise.add_filters" do |app|
29
- app.config.filter_parameters += [:password, :password_confirmation]
30
- app.config.filter_parameters.uniq
16
+ initializer "devise.url_helpers" do
17
+ Devise.include_helpers(Devise::Controllers)
31
18
  end
32
19
 
33
- unless Rails.env.production?
34
- config.after_initialize do
35
- actions = [:confirmation_instructions, :reset_password_instructions, :unlock_instructions]
36
-
37
- translations = begin
38
- I18n.t("devise.mailer", :raise => true).map { |k, v| k if v.is_a?(String) }.compact
39
- rescue Exception => e # Do not care if something fails
40
- []
41
- end
42
-
43
- keys = actions & translations
44
-
45
- keys.each do |key|
46
- ActiveSupport::Deprecation.warn "The I18n message 'devise.mailer.#{key}' is deprecated. " \
47
- "Please use 'devise.mailer.#{key}.subject' instead."
20
+ initializer "devise.omniauth" do |app|
21
+ Devise.omniauth_configs.each do |provider, config|
22
+ app.middleware.use config.strategy_class, *config.args do |strategy|
23
+ config.strategy = strategy
48
24
  end
49
25
  end
50
26
 
51
- config.after_initialize do
52
- flash = [:unauthenticated, :unconfirmed, :invalid, :invalid_token, :timeout, :inactive, :locked]
53
-
54
- translations = begin
55
- I18n.t("devise.sessions", :raise => true).keys
56
- rescue Exception => e # Do not care if something fails
57
- []
58
- end
59
-
60
- keys = flash & translations
27
+ if Devise.omniauth_configs.any?
28
+ Devise.include_helpers(Devise::OmniAuth)
29
+ end
30
+ end
61
31
 
62
- if keys.any?
63
- ActiveSupport::Deprecation.warn "The following I18n messages in 'devise.sessions' " \
64
- "are deprecated: #{keys.to_sentence}. Please move them to 'devise.failure' instead."
65
- end
32
+ initializer "devise.encryptor_check" do
33
+ case Devise.encryptor
34
+ when :bcrypt
35
+ puts "[DEVISE] From version 1.2, there is no need to set your encryptor to bcrypt " <<
36
+ "since encryptors are only enabled if you include :encryptable in your models. " <<
37
+ "With this change, we can integrate better with bcrypt and get rid of the " <<
38
+ "password_salt column (since bcrypt stores the salt with password). " <<
39
+ "Please comment config.encryptor in your initializer to get rid of this warning."
40
+ when nil
41
+ # Nothing to say
42
+ else
43
+ puts "[DEVISE] You are using #{Devise.encryptor} as encryptor. From version 1.2, " <<
44
+ "you need to explicitly add `devise :encryptable, :encryptor => #{Devise.encryptor.to_sym}` " <<
45
+ "to your models and comment the current value in the config/initializers/devise.rb"
66
46
  end
67
47
  end
68
48
  end
69
- end
49
+ end
@@ -5,7 +5,6 @@ module ActionDispatch::Routing
5
5
  def finalize_with_devise!
6
6
  finalize_without_devise!
7
7
  Devise.configure_warden!
8
- ActionController::Base.send :include, Devise::Controllers::Helpers
9
8
  end
10
9
  alias_method_chain :finalize!, :devise
11
10
  end
@@ -70,6 +69,13 @@ module ActionDispatch::Routing
70
69
  #
71
70
  # devise_for :users, :controllers => { :sessions => "users/sessions" }
72
71
  #
72
+ # * :sign_out_via => the HTTP method(s) accepted for the :sign_out action (default: :get),
73
+ # if you wish to restrict this to accept only :post or :delete requests you should do:
74
+ #
75
+ # devise_for :users, :sign_out_via => [ :post, :delete ]
76
+ #
77
+ # You need to make sure that your sign_out controls trigger a request with a matching HTTP method.
78
+ #
73
79
  # * :module => the namespace to find controlers. By default, devise will access devise/sessions,
74
80
  # devise/registrations and so on. If you want to namespace all at once, use module:
75
81
  #
@@ -85,6 +91,10 @@ module ActionDispatch::Routing
85
91
  # Will use publisher/sessions controller instead of devise/sessions controller. You can revert
86
92
  # this by providing the :module option to devise_for.
87
93
  #
94
+ # Also pay attention that when you use a namespace it will affect all the helpers and methods for controllers
95
+ # and views. For example, using the above setup you'll end with following methods:
96
+ # current_publisher_account, authenticate_publisher_account!, pusblisher_account_signed_in, etc.
97
+ #
88
98
  # * :skip => tell which controller you want to skip routes from being created:
89
99
  #
90
100
  # devise_for :users, :skip => :sessions
@@ -113,19 +123,33 @@ module ActionDispatch::Routing
113
123
  # end
114
124
  # end
115
125
  #
126
+ # ==== Adding custom actions to override controllers
127
+ #
128
+ # You can pass a block to devise_for that will add any routes defined in the block to Devise's
129
+ # list of known actions. This is important if you add a custom action to a controller that
130
+ # overrides an out of the box Devise controller.
131
+ # For example:
132
+ #
133
+ # class RegistrationsController < Devise::RegistrationsController
134
+ # def update
135
+ # # do something different here
136
+ # end
137
+ #
138
+ # def deactivate
139
+ # # not a standard action
140
+ # # deactivate code here
141
+ # end
142
+ # end
143
+ #
144
+ # In order to get Devise to recognize the deactivate action, your devise_for entry should look like this,
145
+ #
146
+ # devise_for :owners, :controllers => { :registrations => "registrations" } do
147
+ # post "deactivate", :to => "registrations#deactivate", :as => "deactivate_registration"
148
+ # end
149
+ #
116
150
  def devise_for(*resources)
117
151
  options = resources.extract_options!
118
152
 
119
- if as = options.delete(:as)
120
- ActiveSupport::Deprecation.warn ":as is deprecated, please use :path instead."
121
- options[:path] ||= as
122
- end
123
-
124
- if scope = options.delete(:scope)
125
- ActiveSupport::Deprecation.warn ":scope is deprecated, please use :singular instead."
126
- options[:singular] ||= scope
127
- end
128
-
129
153
  options[:as] ||= @scope[:as] if @scope[:as].present?
130
154
  options[:module] ||= @scope[:module] if @scope[:module].present?
131
155
  options[:path_prefix] ||= @scope[:path] if @scope[:path].present?
@@ -154,7 +178,7 @@ module ActionDispatch::Routing
154
178
  devise_scope mapping.name do
155
179
  yield if block_given?
156
180
  with_devise_exclusive_scope mapping.fullpath, mapping.name do
157
- routes.each { |mod| send(:"devise_#{mod}", mapping, mapping.controllers) }
181
+ routes.each { |mod| send("devise_#{mod}", mapping, mapping.controllers) }
158
182
  end
159
183
  end
160
184
  end
@@ -203,22 +227,22 @@ module ActionDispatch::Routing
203
227
 
204
228
  def devise_session(mapping, controllers) #:nodoc:
205
229
  resource :session, :only => [], :controller => controllers[:sessions], :path => "" do
206
- get :new, :path => mapping.path_names[:sign_in], :as => "new"
207
- post :create, :path => mapping.path_names[:sign_in]
208
- get :destroy, :path => mapping.path_names[:sign_out], :as => "destroy"
230
+ get :new, :path => mapping.path_names[:sign_in], :as => "new"
231
+ post :create, :path => mapping.path_names[:sign_in]
232
+ match :destroy, :path => mapping.path_names[:sign_out], :as => "destroy", :via => mapping.sign_out_via
209
233
  end
210
234
  end
211
-
235
+
212
236
  def devise_password(mapping, controllers) #:nodoc:
213
237
  resource :password, :only => [:new, :create, :edit, :update],
214
238
  :path => mapping.path_names[:password], :controller => controllers[:passwords]
215
239
  end
216
-
240
+
217
241
  def devise_confirmation(mapping, controllers) #:nodoc:
218
242
  resource :confirmation, :only => [:new, :create, :show],
219
243
  :path => mapping.path_names[:confirmation], :controller => controllers[:confirmations]
220
244
  end
221
-
245
+
222
246
  def devise_unlock(mapping, controllers) #:nodoc:
223
247
  if mapping.to.unlock_strategy_enabled?(:email)
224
248
  resource :unlock, :only => [:new, :create, :show],
@@ -227,8 +251,28 @@ module ActionDispatch::Routing
227
251
  end
228
252
 
229
253
  def devise_registration(mapping, controllers) #:nodoc:
230
- resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
231
- :path_names => { :new => mapping.path_names[:sign_up] }, :controller => controllers[:registrations]
254
+ path_names = {
255
+ :new => mapping.path_names[:sign_up],
256
+ :cancel => mapping.path_names[:cancel]
257
+ }
258
+
259
+ resource :registration, :except => :show, :path => mapping.path_names[:registration],
260
+ :path_names => path_names, :controller => controllers[:registrations] do
261
+ get :cancel
262
+ end
263
+ end
264
+
265
+ def devise_omniauth_callback(mapping, controllers) #:nodoc:
266
+ path_prefix = "/#{mapping.path}/auth"
267
+
268
+ if ::OmniAuth.config.path_prefix && ::OmniAuth.config.path_prefix != path_prefix
269
+ warn "[DEVISE] You can only add :omniauthable behavior to one model."
270
+ else
271
+ ::OmniAuth.config.path_prefix = path_prefix
272
+ end
273
+
274
+ match "/auth/:action/callback", :action => Regexp.union(mapping.to.omniauth_providers.map(&:to_s)),
275
+ :to => controllers[:omniauth_callbacks], :as => :omniauth_callback
232
276
  end
233
277
 
234
278
  def with_devise_exclusive_scope(new_path, new_as) #:nodoc:
@@ -3,9 +3,9 @@ module Warden::Mixins::Common
3
3
  @request ||= ActionDispatch::Request.new(env)
4
4
  end
5
5
 
6
+ # This is called internally by Warden on logout
6
7
  def reset_session!
7
- raw_session.inspect # why do I have to inspect it to get it to clear?
8
- raw_session.clear
8
+ request.reset_session
9
9
  end
10
10
 
11
11
  def cookies
@@ -15,25 +15,28 @@ end
15
15
 
16
16
  class Warden::SessionSerializer
17
17
  def serialize(record)
18
- [record.class.name, record.id]
18
+ [record.class.name, record.to_key, record.authenticatable_salt]
19
19
  end
20
20
 
21
21
  def deserialize(keys)
22
- klass, id = keys
23
-
24
- if klass.is_a?(Class)
22
+ if keys.size == 2
25
23
  raise "Devise changed how it stores objects in session. If you are seeing this message, " <<
26
- "you can fix it by changing one character in your cookie secret, forcing all previous " <<
27
- "cookies to expire, or cleaning up your database sessions if you are using a db store."
24
+ "you can fix it by changing one character in your cookie secret or cleaning up your " <<
25
+ "database sessions if you are using a db store."
28
26
  end
29
27
 
30
- klass.constantize.find(:first, :conditions => { :id => id })
31
- rescue NameError => e
32
- if e.message =~ /uninitialized constant/
33
- Rails.logger.debug "Trying to deserialize invalid class #{klass}"
34
- nil
35
- else
36
- raise
28
+ klass, id, salt = keys
29
+
30
+ begin
31
+ record = klass.constantize.to_adapter.get(id)
32
+ record if record && record.authenticatable_salt == salt
33
+ rescue NameError => e
34
+ if e.message =~ /uninitialized constant/
35
+ Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass}"
36
+ nil
37
+ else
38
+ raise
39
+ end
37
40
  end
38
41
  end
39
42
  end
@@ -44,10 +47,6 @@ unless Devise.rack_session?
44
47
  alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
45
48
  alias_method :regular_update, :update unless method_defined?(:regular_update)
46
49
 
47
- def [](key)
48
- super(convert_key(key))
49
- end
50
-
51
50
  def []=(key, value)
52
51
  regular_writer(convert_key(key), value)
53
52
  end
@@ -92,7 +91,6 @@ unless Devise.rack_session?
92
91
  def symbolize_keys; to_hash.symbolize_keys end
93
92
 
94
93
  def to_options!; self end
95
- def to_hash; Hash.new.update(self) end
96
94
 
97
95
  protected
98
96
 
@@ -3,11 +3,6 @@ module Devise
3
3
  # and overwrite the apply_schema method.
4
4
  module Schema
5
5
 
6
- def authenticatable(*args)
7
- ActiveSupport::Deprecation.warn "t.authenticatable in migrations is deprecated. Please use t.database_authenticatable instead.", caller
8
- database_authenticatable(*args)
9
- end
10
-
11
6
  # Creates email, encrypted_password and password_salt.
12
7
  #
13
8
  # == Options
@@ -21,17 +16,17 @@ module Devise
21
16
  null = options[:null] || false
22
17
  default = options.key?(:default) ? options[:default] : ("" if null == false)
23
18
 
24
- if options.delete(:encryptor)
25
- ActiveSupport::Deprecation.warn ":encryptor as option is deprecated, simply remove it."
26
- end
27
-
28
19
  apply_devise_schema :email, String, :null => null, :default => default
29
20
  apply_devise_schema :encrypted_password, String, :null => null, :default => default, :limit => 128
30
- apply_devise_schema :password_salt, String, :null => null, :default => default
31
- end
21
+ end
22
+
23
+ # Creates password salt for encryption support.
24
+ def encryptable
25
+ apply_devise_schema :password_salt, String
26
+ end
32
27
 
33
28
  # Creates authentication_token.
34
- def token_authenticatable(options={})
29
+ def token_authenticatable
35
30
  apply_devise_schema :authentication_token, String
36
31
  end
37
32
 
@@ -48,8 +43,12 @@ module Devise
48
43
  end
49
44
 
50
45
  # Creates remember_token and remember_created_at.
51
- def rememberable
52
- apply_devise_schema :remember_token, String
46
+ #
47
+ # == Options
48
+ # * :use_salt - When true, does not create a remember_token and use password_salt instead.
49
+ def rememberable(options={})
50
+ use_salt = options.fetch(:use_salt, Devise.use_salt_as_remember_token)
51
+ apply_devise_schema :remember_token, String unless use_salt
53
52
  apply_devise_schema :remember_created_at, DateTime
54
53
  end
55
54
 
@@ -9,7 +9,7 @@ module Devise
9
9
  attr_accessor :authentication_hash, :password
10
10
 
11
11
  def valid?
12
- valid_for_http_auth? || valid_for_params_auth?
12
+ valid_for_params_auth? || valid_for_http_auth?
13
13
  end
14
14
 
15
15
  private
@@ -21,7 +21,6 @@ module Devise
21
21
  case result
22
22
  when Symbol, String
23
23
  fail!(result)
24
- false
25
24
  else
26
25
  result
27
26
  end
@@ -97,15 +96,17 @@ module Devise
97
96
 
98
97
  # Helper to decode credentials from HTTP.
99
98
  def decode_credentials
100
- return [] unless request.authorization && request.authorization =~ /^Basic (.*)/
99
+ return [] unless request.authorization && request.authorization =~ /^Basic (.*)/m
101
100
  ActiveSupport::Base64.decode64($1).split(/:/, 2)
102
101
  end
103
102
 
104
103
  # Sets the authentication hash and the password from params_auth_hash or http_auth_hash.
105
- def with_authentication_hash(hash)
106
- self.authentication_hash = hash.slice(*authentication_keys)
107
- self.password = hash[:password]
108
- authentication_keys.all?{ |k| authentication_hash[k].present? }
104
+ def with_authentication_hash(auth_values)
105
+ self.authentication_hash = {}
106
+ self.password = auth_values[:password]
107
+
108
+ parse_authentication_key_values(auth_values, authentication_keys) &&
109
+ parse_authentication_key_values(request_values, request_keys)
109
110
  end
110
111
 
111
112
  # Holds the authentication keys.
@@ -113,6 +114,31 @@ module Devise
113
114
  @authentication_keys ||= mapping.to.authentication_keys
114
115
  end
115
116
 
117
+ # Holds request keys.
118
+ def request_keys
119
+ @request_keys ||= mapping.to.request_keys
120
+ end
121
+
122
+ # Returns values from the request object.
123
+ def request_values
124
+ keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
125
+ values = keys.map { |k| self.request.send(k) }
126
+ Hash[keys.zip(values)]
127
+ end
128
+
129
+ # Parse authentication keys considering if they should be enforced or not.
130
+ def parse_authentication_key_values(hash, keys)
131
+ keys.each do |key, enforce|
132
+ value = hash[key].presence
133
+ if value
134
+ self.authentication_hash[key] = value
135
+ else
136
+ return false unless enforce == false
137
+ end
138
+ end
139
+ true
140
+ end
141
+
116
142
  # Holds the authenticatable name for this class. Devise::Strategies::DatabaseAuthenticatable
117
143
  # becomes simply :database.
118
144
  def authenticatable_name