devise 2.1.2 → 3.5.10

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.
Files changed (242) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +39 -10
  3. data/.yardopts +9 -0
  4. data/{CHANGELOG.rdoc → CHANGELOG.md} +445 -112
  5. data/CODE_OF_CONDUCT.md +22 -0
  6. data/CONTRIBUTING.md +16 -0
  7. data/Gemfile +10 -15
  8. data/Gemfile.lock +151 -129
  9. data/MIT-LICENSE +1 -1
  10. data/README.md +256 -96
  11. data/Rakefile +4 -2
  12. data/app/controllers/devise/confirmations_controller.rb +15 -7
  13. data/app/controllers/devise/omniauth_callbacks_controller.rb +6 -2
  14. data/app/controllers/devise/passwords_controller.rb +33 -9
  15. data/app/controllers/devise/registrations_controller.rb +66 -26
  16. data/app/controllers/devise/sessions_controller.rb +52 -21
  17. data/app/controllers/devise/unlocks_controller.rb +11 -6
  18. data/app/controllers/devise_controller.rb +65 -58
  19. data/app/helpers/devise_helper.rb +2 -2
  20. data/app/mailers/devise/mailer.rb +19 -10
  21. data/app/views/devise/confirmations/new.html.erb +8 -4
  22. data/app/views/devise/mailer/confirmation_instructions.html.erb +2 -2
  23. data/app/views/devise/mailer/password_change.html.erb +3 -0
  24. data/app/views/devise/mailer/reset_password_instructions.html.erb +2 -2
  25. data/app/views/devise/mailer/unlock_instructions.html.erb +2 -2
  26. data/app/views/devise/passwords/edit.html.erb +15 -6
  27. data/app/views/devise/passwords/new.html.erb +8 -4
  28. data/app/views/devise/registrations/edit.html.erb +29 -15
  29. data/app/views/devise/registrations/new.html.erb +19 -8
  30. data/app/views/devise/sessions/new.html.erb +17 -8
  31. data/app/views/devise/shared/{_links.erb → _links.html.erb} +4 -4
  32. data/app/views/devise/unlocks/new.html.erb +8 -4
  33. data/config/locales/en.yml +51 -47
  34. data/devise.gemspec +8 -6
  35. data/devise.png +0 -0
  36. data/gemfiles/Gemfile.rails-3.2-stable +29 -0
  37. data/gemfiles/Gemfile.rails-3.2-stable.lock +172 -0
  38. data/gemfiles/Gemfile.rails-4.0-stable +30 -0
  39. data/gemfiles/Gemfile.rails-4.0-stable.lock +166 -0
  40. data/gemfiles/Gemfile.rails-4.1-stable +30 -0
  41. data/gemfiles/Gemfile.rails-4.1-stable.lock +171 -0
  42. data/gemfiles/Gemfile.rails-4.2-stable +30 -0
  43. data/gemfiles/Gemfile.rails-4.2-stable.lock +193 -0
  44. data/lib/devise/controllers/helpers.rb +126 -108
  45. data/lib/devise/controllers/rememberable.rb +19 -17
  46. data/lib/devise/controllers/scoped_views.rb +1 -1
  47. data/lib/devise/controllers/sign_in_out.rb +96 -0
  48. data/lib/devise/controllers/store_location.rb +58 -0
  49. data/lib/devise/controllers/url_helpers.rb +7 -7
  50. data/lib/devise/encryptor.rb +22 -0
  51. data/lib/devise/failure_app.rb +85 -25
  52. data/lib/devise/hooks/activatable.rb +5 -6
  53. data/lib/devise/hooks/csrf_cleaner.rb +7 -0
  54. data/lib/devise/hooks/forgetable.rb +1 -1
  55. data/lib/devise/hooks/lockable.rb +2 -2
  56. data/lib/devise/hooks/proxy.rb +21 -0
  57. data/lib/devise/hooks/rememberable.rb +5 -4
  58. data/lib/devise/hooks/timeoutable.rb +16 -8
  59. data/lib/devise/hooks/trackable.rb +1 -1
  60. data/lib/devise/mailers/helpers.rb +27 -23
  61. data/lib/devise/mapping.rb +11 -7
  62. data/lib/devise/models/authenticatable.rb +82 -66
  63. data/lib/devise/models/confirmable.rb +142 -55
  64. data/lib/devise/models/database_authenticatable.rb +59 -15
  65. data/lib/devise/models/lockable.rb +41 -30
  66. data/lib/devise/models/omniauthable.rb +3 -3
  67. data/lib/devise/models/recoverable.rb +56 -41
  68. data/lib/devise/models/rememberable.rb +65 -27
  69. data/lib/devise/models/timeoutable.rb +2 -8
  70. data/lib/devise/models/trackable.rb +6 -4
  71. data/lib/devise/models/validatable.rb +9 -9
  72. data/lib/devise/models.rb +4 -13
  73. data/lib/devise/modules.rb +10 -11
  74. data/lib/devise/omniauth/url_helpers.rb +2 -2
  75. data/lib/devise/orm/active_record.rb +1 -1
  76. data/lib/devise/orm/mongoid.rb +1 -1
  77. data/lib/devise/{param_filter.rb → parameter_filter.rb} +10 -11
  78. data/lib/devise/parameter_sanitizer.rb +99 -0
  79. data/lib/devise/rails/routes.rb +173 -115
  80. data/lib/devise/rails/warden_compat.rb +10 -31
  81. data/lib/devise/rails.rb +14 -12
  82. data/lib/devise/strategies/authenticatable.rb +26 -26
  83. data/lib/devise/strategies/base.rb +1 -1
  84. data/lib/devise/strategies/database_authenticatable.rb +8 -4
  85. data/lib/devise/strategies/rememberable.rb +15 -5
  86. data/lib/devise/test_helpers.rb +7 -5
  87. data/lib/devise/time_inflector.rb +14 -0
  88. data/lib/devise/token_generator.rb +70 -0
  89. data/lib/devise/version.rb +1 -1
  90. data/lib/devise.rb +110 -52
  91. data/lib/generators/active_record/devise_generator.rb +34 -18
  92. data/lib/generators/active_record/templates/migration.rb +5 -6
  93. data/lib/generators/active_record/templates/migration_existing.rb +5 -6
  94. data/lib/generators/devise/controllers_generator.rb +44 -0
  95. data/lib/generators/devise/devise_generator.rb +5 -3
  96. data/lib/generators/devise/install_generator.rb +5 -0
  97. data/lib/generators/devise/orm_helpers.rb +25 -6
  98. data/lib/generators/devise/views_generator.rb +52 -22
  99. data/lib/generators/mongoid/devise_generator.rb +21 -26
  100. data/lib/generators/templates/README +9 -5
  101. data/lib/generators/templates/controllers/README +14 -0
  102. data/lib/generators/templates/controllers/confirmations_controller.rb +28 -0
  103. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +28 -0
  104. data/lib/generators/templates/controllers/passwords_controller.rb +32 -0
  105. data/lib/generators/templates/controllers/registrations_controller.rb +60 -0
  106. data/lib/generators/templates/controllers/sessions_controller.rb +25 -0
  107. data/lib/generators/templates/controllers/unlocks_controller.rb +28 -0
  108. data/lib/generators/templates/devise.rb +80 -43
  109. data/lib/generators/templates/markerb/confirmation_instructions.markerb +2 -2
  110. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  111. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  112. data/lib/generators/templates/markerb/unlock_instructions.markerb +2 -2
  113. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +3 -2
  114. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +4 -4
  115. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +2 -2
  116. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +11 -6
  117. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +4 -4
  118. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +6 -6
  119. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +3 -2
  120. data/script/cached-bundle +49 -0
  121. data/script/s3-put +71 -0
  122. data/test/controllers/custom_registrations_controller_test.rb +40 -0
  123. data/test/controllers/helper_methods_test.rb +21 -0
  124. data/test/controllers/helpers_test.rb +95 -32
  125. data/test/controllers/inherited_controller_i18n_messages_test.rb +51 -0
  126. data/test/controllers/internal_helpers_test.rb +39 -14
  127. data/test/controllers/load_hooks_controller_test.rb +19 -0
  128. data/test/controllers/passwords_controller_test.rb +31 -0
  129. data/test/controllers/sessions_controller_test.rb +66 -6
  130. data/test/controllers/url_helpers_test.rb +10 -4
  131. data/test/delegator_test.rb +1 -1
  132. data/test/devise_test.rb +45 -10
  133. data/test/failure_app_test.rb +121 -27
  134. data/test/generators/active_record_generator_test.rb +48 -8
  135. data/test/generators/controllers_generator_test.rb +48 -0
  136. data/test/generators/devise_generator_test.rb +2 -2
  137. data/test/generators/mongoid_generator_test.rb +3 -3
  138. data/test/generators/views_generator_test.rb +54 -3
  139. data/test/helpers/devise_helper_test.rb +18 -20
  140. data/test/integration/authenticatable_test.rb +161 -65
  141. data/test/integration/confirmable_test.rb +146 -77
  142. data/test/integration/database_authenticatable_test.rb +43 -30
  143. data/test/integration/http_authenticatable_test.rb +30 -22
  144. data/test/integration/lockable_test.rb +64 -49
  145. data/test/integration/omniauthable_test.rb +17 -15
  146. data/test/integration/recoverable_test.rb +111 -70
  147. data/test/integration/registerable_test.rb +114 -79
  148. data/test/integration/rememberable_test.rb +87 -31
  149. data/test/integration/timeoutable_test.rb +77 -33
  150. data/test/integration/trackable_test.rb +5 -5
  151. data/test/mailers/confirmation_instructions_test.rb +28 -8
  152. data/test/mailers/reset_password_instructions_test.rb +21 -8
  153. data/test/mailers/unlock_instructions_test.rb +20 -6
  154. data/test/mapping_test.rb +12 -5
  155. data/test/models/authenticatable_test.rb +17 -1
  156. data/test/models/confirmable_test.rb +216 -62
  157. data/test/models/database_authenticatable_test.rb +129 -49
  158. data/test/models/lockable_test.rb +132 -45
  159. data/test/models/recoverable_test.rb +100 -54
  160. data/test/models/rememberable_test.rb +89 -94
  161. data/test/models/serializable_test.rb +12 -11
  162. data/test/models/timeoutable_test.rb +6 -1
  163. data/test/models/trackable_test.rb +28 -0
  164. data/test/models/validatable_test.rb +31 -21
  165. data/test/models_test.rb +22 -48
  166. data/test/omniauth/config_test.rb +4 -4
  167. data/test/omniauth/url_helpers_test.rb +7 -4
  168. data/test/orm/active_record.rb +1 -0
  169. data/test/orm/mongoid.rb +2 -3
  170. data/test/parameter_sanitizer_test.rb +81 -0
  171. data/test/rails_app/Rakefile +0 -4
  172. data/test/rails_app/app/active_record/shim.rb +1 -1
  173. data/test/rails_app/app/active_record/user_on_engine.rb +7 -0
  174. data/test/rails_app/app/active_record/user_on_main_app.rb +7 -0
  175. data/test/rails_app/app/active_record/user_without_email.rb +8 -0
  176. data/test/rails_app/app/controllers/admins/sessions_controller.rb +1 -1
  177. data/test/rails_app/app/controllers/admins_controller.rb +0 -5
  178. data/test/rails_app/app/controllers/application_controller.rb +6 -2
  179. data/test/rails_app/app/controllers/application_with_fake_engine.rb +30 -0
  180. data/test/rails_app/app/controllers/custom/registrations_controller.rb +31 -0
  181. data/test/rails_app/app/controllers/home_controller.rb +1 -1
  182. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +1 -1
  183. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +1 -1
  184. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +4 -4
  185. data/test/rails_app/app/controllers/users_controller.rb +12 -4
  186. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +3 -0
  187. data/test/rails_app/app/mailers/users/mailer.rb +1 -1
  188. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +4 -0
  189. data/test/rails_app/app/mongoid/admin.rb +12 -10
  190. data/test/rails_app/app/mongoid/shim.rb +4 -5
  191. data/test/rails_app/app/mongoid/user.rb +19 -22
  192. data/test/rails_app/app/mongoid/user_on_engine.rb +39 -0
  193. data/test/rails_app/app/mongoid/user_on_main_app.rb +39 -0
  194. data/test/rails_app/app/mongoid/user_without_email.rb +33 -0
  195. data/test/rails_app/app/views/admins/sessions/new.html.erb +1 -1
  196. data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -1
  197. data/test/rails_app/app/views/home/index.html.erb +1 -1
  198. data/test/rails_app/app/views/home/join.html.erb +1 -1
  199. data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -1
  200. data/test/rails_app/app/views/layouts/application.html.erb +1 -1
  201. data/test/rails_app/app/views/users/edit_form.html.erb +1 -0
  202. data/test/rails_app/bin/bundle +3 -0
  203. data/test/rails_app/bin/rails +4 -0
  204. data/test/rails_app/bin/rake +4 -0
  205. data/test/rails_app/config/application.rb +4 -5
  206. data/test/rails_app/config/boot.rb +9 -3
  207. data/test/rails_app/config/environment.rb +2 -2
  208. data/test/rails_app/config/environments/development.rb +19 -7
  209. data/test/rails_app/config/environments/production.rb +68 -17
  210. data/test/rails_app/config/environments/test.rb +24 -16
  211. data/test/rails_app/config/initializers/devise.rb +22 -20
  212. data/test/rails_app/config/initializers/secret_token.rb +8 -2
  213. data/test/rails_app/config/initializers/session_store.rb +1 -0
  214. data/test/rails_app/config/routes.rb +71 -46
  215. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +9 -12
  216. data/test/rails_app/db/schema.rb +21 -18
  217. data/test/rails_app/lib/shared_admin.rb +7 -4
  218. data/test/rails_app/lib/shared_user.rb +6 -3
  219. data/test/rails_app/lib/shared_user_without_email.rb +26 -0
  220. data/test/rails_app/lib/shared_user_without_omniauth.rb +13 -0
  221. data/test/rails_test.rb +9 -0
  222. data/test/routes_test.rb +94 -78
  223. data/test/support/action_controller/record_identifier.rb +10 -0
  224. data/test/support/assertions.rb +2 -3
  225. data/test/support/helpers.rb +18 -32
  226. data/test/support/integration.rb +17 -16
  227. data/test/support/locale/en.yml +4 -0
  228. data/test/support/mongoid.yml +6 -0
  229. data/test/test_helper.rb +8 -1
  230. data/test/test_helpers_test.rb +64 -20
  231. data/test/test_models.rb +33 -0
  232. data/test/time_helpers.rb +137 -0
  233. metadata +172 -51
  234. data/app/views/devise/_links.erb +0 -3
  235. data/gemfiles/Gemfile.rails-3.1.x +0 -35
  236. data/gemfiles/Gemfile.rails-3.1.x.lock +0 -167
  237. data/lib/devise/models/token_authenticatable.rb +0 -77
  238. data/lib/devise/strategies/token_authenticatable.rb +0 -56
  239. data/test/indifferent_hash.rb +0 -33
  240. data/test/integration/token_authenticatable_test.rb +0 -161
  241. data/test/models/token_authenticatable_test.rb +0 -55
  242. data/test/rails_app/script/rails +0 -10
@@ -3,41 +3,20 @@ 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
+ # Deprecate: Remove this check once we move to Rails 4 only.
7
+ NULL_STORE =
8
+ defined?(ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash) ?
9
+ ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash : nil
10
+
7
11
  def reset_session!
8
- request.reset_session
12
+ # Calling reset_session on NULL_STORE causes it fail.
13
+ # This is a bug that needs to be fixed in Rails.
14
+ unless NULL_STORE && request.session.is_a?(NULL_STORE)
15
+ request.reset_session
16
+ end
9
17
  end
10
18
 
11
19
  def cookies
12
20
  request.cookie_jar
13
21
  end
14
22
  end
15
-
16
- class Warden::SessionSerializer
17
- def serialize(record)
18
- klass = record.class
19
- array = klass.serialize_into_session(record)
20
- array.unshift(klass.name)
21
- end
22
-
23
- def deserialize(keys)
24
- klass_name, *args = keys
25
-
26
- begin
27
- klass = ActiveSupport::Inflector.constantize(klass_name)
28
- if klass.respond_to? :serialize_from_session
29
- klass.serialize_from_session(*args)
30
- else
31
- Rails.logger.warn "[Devise] Stored serialized class #{klass_name} seems not to be Devise enabled anymore. Did you do that on purpose?"
32
- nil
33
- end
34
- rescue NameError => e
35
- if e.message =~ /uninitialized constant/
36
- Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass_name}"
37
- nil
38
- else
39
- raise
40
- end
41
- end
42
- end
43
- end
data/lib/devise/rails.rb CHANGED
@@ -17,7 +17,7 @@ module Devise
17
17
  Devise.include_helpers(Devise::Controllers)
18
18
  end
19
19
 
20
- initializer "devise.omniauth" do |app|
20
+ initializer "devise.omniauth", after: :load_config_initializers, before: :build_middleware_stack do |app|
21
21
  Devise.omniauth_configs.each do |provider, config|
22
22
  app.middleware.use config.strategy_class, *config.args do |strategy|
23
23
  config.strategy = strategy
@@ -29,21 +29,23 @@ module Devise
29
29
  end
30
30
  end
31
31
 
32
- initializer "devise.mongoid_version_warning" do
33
- if defined?(Mongoid)
34
- require 'mongoid/version'
35
- if Mongoid::VERSION.to_f < 2.1
36
- puts "\n[DEVISE] Please note that Mongoid versions prior to 2.1 handle dirty model " \
37
- "object attributes in such a way that the Devise `validatable` module will not apply " \
38
- "its usual uniqueness and format validations for the email field. It is recommended " \
39
- "that you upgrade to Mongoid 2.1+ for this and other fixes, but if for some reason you " \
40
- "are unable to do so, you should add these validations manually.\n"
41
- end
32
+ initializer "devise.secret_key" do |app|
33
+ if app.respond_to?(:secrets)
34
+ Devise.secret_key ||= app.secrets.secret_key_base
35
+ elsif app.config.respond_to?(:secret_key_base)
36
+ Devise.secret_key ||= app.config.secret_key_base
42
37
  end
38
+
39
+ Devise.token_generator ||=
40
+ if secret_key = Devise.secret_key
41
+ Devise::TokenGenerator.new(
42
+ Devise::CachingKeyGenerator.new(Devise::KeyGenerator.new(secret_key))
43
+ )
44
+ end
43
45
  end
44
46
 
45
47
  initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
46
- # We can get rid of this once we support only Rails > 3.2
48
+ # Deprecate: Remove once we move to Rails 4 only.
47
49
  ActionDispatch::Routing::RoutesProxy.class_eval do
48
50
  def respond_to?(method, include_private = false)
49
51
  super || routes.url_helpers.respond_to?(method)
@@ -16,32 +16,26 @@ module Devise
16
16
  valid_for_params_auth? || valid_for_http_auth?
17
17
  end
18
18
 
19
+ # Override and set to false for things like OmniAuth that technically
20
+ # run through Authentication (user_set) very often, which would normally
21
+ # reset CSRF data in the session
22
+ def clean_up_csrf?
23
+ true
24
+ end
25
+
19
26
  private
20
27
 
21
28
  # Receives a resource and check if it is valid by calling valid_for_authentication?
22
29
  # An optional block that will be triggered while validating can be optionally
23
- # given as parameter. Check Devise::Models::Authenticable.valid_for_authentication?
30
+ # given as parameter. Check Devise::Models::Authenticatable.valid_for_authentication?
24
31
  # for more information.
25
32
  #
26
33
  # In case the resource can't be validated, it will fail with the given
27
34
  # unauthenticated_message.
28
35
  def validate(resource, &block)
29
- unless resource
30
- ActiveSupport::Deprecation.warn "an empty resource was given to #{self.class.name}#validate. " \
31
- "Please ensure the resource is not nil", caller
32
- end
33
-
34
36
  result = resource && resource.valid_for_authentication?(&block)
35
37
 
36
- case result
37
- when Symbol, String
38
- ActiveSupport::Deprecation.warn "valid_for_authentication? should return a boolean value"
39
- fail!(result)
40
- return false
41
- end
42
-
43
38
  if result
44
- decorate(resource)
45
39
  true
46
40
  else
47
41
  if resource
@@ -52,7 +46,7 @@ module Devise
52
46
  end
53
47
 
54
48
  # Get values from params and set in the resource.
55
- def decorate(resource)
49
+ def remember_me(resource)
56
50
  resource.remember_me = remember_me? if resource.respond_to?(:remember_me=)
57
51
  end
58
52
 
@@ -61,9 +55,9 @@ module Devise
61
55
  valid_params? && Devise::TRUE_VALUES.include?(params_auth_hash[:remember_me])
62
56
  end
63
57
 
64
- # Check if this is strategy is valid for http authentication by:
58
+ # Check if this is a valid strategy for http authentication by:
65
59
  #
66
- # * Validating if the model allows params authentication;
60
+ # * Validating if the model allows http authentication;
67
61
  # * If any of the authorization headers were sent;
68
62
  # * If all authentication keys are present;
69
63
  #
@@ -71,7 +65,7 @@ module Devise
71
65
  http_authenticatable? && request.authorization && with_authentication_hash(:http_auth, http_auth_hash)
72
66
  end
73
67
 
74
- # Check if this is strategy is valid for params authentication by:
68
+ # Check if this is a valid strategy for params authentication by:
75
69
  #
76
70
  # * Validating if the model allows params authentication;
77
71
  # * If the request hits the sessions controller through POST;
@@ -100,7 +94,7 @@ module Devise
100
94
 
101
95
  # Extract a hash with attributes:values from the http params.
102
96
  def http_auth_hash
103
- keys = [authentication_keys.first, :password]
97
+ keys = [http_authentication_key, :password]
104
98
  Hash[*keys.zip(decode_credentials).flatten]
105
99
  end
106
100
 
@@ -114,14 +108,17 @@ module Devise
114
108
  params_auth_hash.is_a?(Hash)
115
109
  end
116
110
 
117
- # Check if password is present and is not equal to "X" (default value for token).
111
+ # Note: unlike `Model.valid_password?`, this method does not actually
112
+ # ensure that the password in the params matches the password stored in
113
+ # the database. It only checks if the password is *present*. Do not rely
114
+ # on this method for validating that a given password is correct.
118
115
  def valid_password?
119
- password.present? && password != "X"
116
+ password.present?
120
117
  end
121
118
 
122
119
  # Helper to decode credentials from HTTP.
123
120
  def decode_credentials
124
- return [] unless request.authorization && request.authorization =~ /^Basic (.*)/m
121
+ return [] unless request.authorization && request.authorization =~ /^Basic (.*)/mi
125
122
  Base64.decode64($1).split(/:/, 2)
126
123
  end
127
124
 
@@ -134,24 +131,27 @@ module Devise
134
131
  parse_authentication_key_values(request_values, request_keys)
135
132
  end
136
133
 
137
- # Holds the authentication keys.
138
134
  def authentication_keys
139
135
  @authentication_keys ||= mapping.to.authentication_keys
140
136
  end
141
137
 
142
- # Holds request keys.
138
+ def http_authentication_key
139
+ @http_authentication_key ||= mapping.to.http_authentication_key || case authentication_keys
140
+ when Array then authentication_keys.first
141
+ when Hash then authentication_keys.keys.first
142
+ end
143
+ end
144
+
143
145
  def request_keys
144
146
  @request_keys ||= mapping.to.request_keys
145
147
  end
146
148
 
147
- # Returns values from the request object.
148
149
  def request_values
149
150
  keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
150
151
  values = keys.map { |k| self.request.send(k) }
151
152
  Hash[keys.zip(values)]
152
153
  end
153
154
 
154
- # Parse authentication keys considering if they should be enforced or not.
155
155
  def parse_authentication_key_values(hash, keys)
156
156
  keys.each do |key, enforce|
157
157
  value = hash[key].presence
@@ -17,4 +17,4 @@ module Devise
17
17
  end
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -2,16 +2,20 @@ require 'devise/strategies/authenticatable'
2
2
 
3
3
  module Devise
4
4
  module Strategies
5
- # Default strategy for signing in a user, based on his email and password in the database.
5
+ # Default strategy for signing in a user, based on their email and password in the database.
6
6
  class DatabaseAuthenticatable < Authenticatable
7
7
  def authenticate!
8
- resource = valid_password? && mapping.to.find_for_database_authentication(authentication_hash)
9
- return fail(:invalid) unless resource
8
+ resource = password.present? && mapping.to.find_for_database_authentication(authentication_hash)
9
+ encrypted = false
10
10
 
11
- if validate(resource){ resource.valid_password?(password) }
11
+ if validate(resource){ encrypted = true; resource.valid_password?(password) }
12
+ remember_me(resource)
12
13
  resource.after_database_authentication
13
14
  success!(resource)
14
15
  end
16
+
17
+ mapping.to.new.password = password if !encrypted && Devise.paranoid
18
+ fail(:not_found_in_database) unless resource
15
19
  end
16
20
  end
17
21
  end
@@ -25,15 +25,25 @@ module Devise
25
25
  end
26
26
 
27
27
  if validate(resource)
28
+ remember_me(resource) if extend_remember_me?(resource)
29
+ resource.after_remembered
28
30
  success!(resource)
29
31
  end
30
32
  end
31
33
 
34
+ # No need to clean up the CSRF when using rememberable.
35
+ # In fact, cleaning it up here would be a bug because
36
+ # rememberable is triggered on GET requests which means
37
+ # we would render a page on first access with all csrf
38
+ # tokens expired.
39
+ def clean_up_csrf?
40
+ false
41
+ end
42
+
32
43
  private
33
44
 
34
- def decorate(resource)
35
- super
36
- resource.extend_remember_period = mapping.to.extend_remember_period if resource.respond_to?(:extend_remember_period=)
45
+ def extend_remember_me?(resource)
46
+ resource.respond_to?(:extend_remember_period) && resource.extend_remember_period
37
47
  end
38
48
 
39
49
  def remember_me?
@@ -41,7 +51,7 @@ module Devise
41
51
  end
42
52
 
43
53
  def remember_key
44
- "remember_#{scope}_token"
54
+ mapping.to.rememberable_options.fetch(:key, "remember_#{scope}_token")
45
55
  end
46
56
 
47
57
  def remember_cookie
@@ -52,4 +62,4 @@ module Devise
52
62
  end
53
63
  end
54
64
 
55
- Warden::Strategies.add(:rememberable, Devise::Strategies::Rememberable)
65
+ Warden::Strategies.add(:rememberable, Devise::Strategies::Rememberable)
@@ -26,11 +26,11 @@ module Devise
26
26
 
27
27
  # Quick access to Warden::Proxy.
28
28
  def warden #:nodoc:
29
- @warden ||= begin
29
+ @request.env['warden'] ||= begin
30
30
  manager = Warden::Manager.new(nil) do |config|
31
31
  config.merge! Devise.warden_config
32
32
  end
33
- @request.env['warden'] = Warden::Proxy.new(@request.env, manager)
33
+ Warden::Proxy.new(@request.env, manager)
34
34
  end
35
35
  end
36
36
 
@@ -45,6 +45,7 @@ module Devise
45
45
  def sign_in(resource_or_scope, resource=nil)
46
46
  scope ||= Devise::Mapping.find_scope!(resource_or_scope)
47
47
  resource ||= resource_or_scope
48
+ warden.instance_variable_get(:@users).delete(scope)
48
49
  warden.session_serializer.store(resource, scope)
49
50
  end
50
51
 
@@ -106,9 +107,10 @@ module Devise
106
107
  env["warden.options"] = options
107
108
  Warden::Manager._run_callbacks(:before_failure, env, options)
108
109
 
109
- status, headers, body = Devise.warden_config[:failure_app].call(env).to_a
110
- @controller.send :render, :status => status, :text => body,
111
- :content_type => headers["Content-Type"], :location => headers["Location"]
110
+ status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
111
+ @controller.response.headers.merge!(headers)
112
+ @controller.send :render, status: status, text: response.body,
113
+ content_type: headers["Content-Type"], location: headers["Location"]
112
114
  nil # causes process return @response
113
115
  end
114
116
 
@@ -0,0 +1,14 @@
1
+ require "active_support/core_ext/module/delegation"
2
+
3
+ module Devise
4
+ class TimeInflector
5
+ include ActionView::Helpers::DateHelper
6
+
7
+ class << self
8
+ attr_reader :instance
9
+ delegate :time_ago_in_words, to: :instance
10
+ end
11
+
12
+ @instance = new
13
+ end
14
+ end
@@ -0,0 +1,70 @@
1
+ # Deprecate: Copied verbatim from Rails source, remove once we move to Rails 4 only.
2
+ require 'thread_safe'
3
+ require 'openssl'
4
+ require 'securerandom'
5
+
6
+ module Devise
7
+ class TokenGenerator
8
+ def initialize(key_generator, digest="SHA256")
9
+ @key_generator = key_generator
10
+ @digest = digest
11
+ end
12
+
13
+ def digest(klass, column, value)
14
+ value.present? && OpenSSL::HMAC.hexdigest(@digest, key_for(column), value.to_s)
15
+ end
16
+
17
+ def generate(klass, column)
18
+ key = key_for(column)
19
+
20
+ loop do
21
+ raw = Devise.friendly_token
22
+ enc = OpenSSL::HMAC.hexdigest(@digest, key, raw)
23
+ break [raw, enc] unless klass.to_adapter.find_first({ column => enc })
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def key_for(column)
30
+ @key_generator.generate_key("Devise #{column}")
31
+ end
32
+ end
33
+
34
+ # KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2
35
+ # It can be used to derive a number of keys for various purposes from a given secret.
36
+ # This lets Rails applications have a single secure secret, but avoid reusing that
37
+ # key in multiple incompatible contexts.
38
+ class KeyGenerator
39
+ def initialize(secret, options = {})
40
+ @secret = secret
41
+ # The default iterations are higher than required for our key derivation uses
42
+ # on the off chance someone uses this for password storage
43
+ @iterations = options[:iterations] || 2**16
44
+ end
45
+
46
+ # Returns a derived key suitable for use. The default key_size is chosen
47
+ # to be compatible with the default settings of ActiveSupport::MessageVerifier.
48
+ # i.e. OpenSSL::Digest::SHA1#block_length
49
+ def generate_key(salt, key_size=64)
50
+ OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
51
+ end
52
+ end
53
+
54
+ # CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
55
+ # re-executing the key generation process when it's called using the same salt and
56
+ # key_size
57
+ class CachingKeyGenerator
58
+ def initialize(key_generator)
59
+ @key_generator = key_generator
60
+ @cache_keys = ThreadSafe::Cache.new
61
+ end
62
+
63
+ # Returns a derived key suitable for use. The default key_size is chosen
64
+ # to be compatible with the default settings of ActiveSupport::MessageVerifier.
65
+ # i.e. OpenSSL::Digest::SHA1#block_length
66
+ def generate_key(salt, key_size=64)
67
+ @cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
68
+ end
69
+ end
70
+ end
@@ -1,3 +1,3 @@
1
1
  module Devise
2
- VERSION = "2.1.2".freeze
2
+ VERSION = "3.5.10".freeze
3
3
  end
data/lib/devise.rb CHANGED
@@ -4,21 +4,33 @@ require 'active_support/dependencies'
4
4
  require 'orm_adapter'
5
5
  require 'set'
6
6
  require 'securerandom'
7
+ require 'responders'
7
8
 
8
9
  module Devise
9
- autoload :Delegator, 'devise/delegator'
10
- autoload :FailureApp, 'devise/failure_app'
11
- autoload :OmniAuth, 'devise/omniauth'
12
- autoload :ParamFilter, 'devise/param_filter'
13
- autoload :TestHelpers, 'devise/test_helpers'
10
+ autoload :Delegator, 'devise/delegator'
11
+ autoload :Encryptor, 'devise/encryptor'
12
+ autoload :FailureApp, 'devise/failure_app'
13
+ autoload :OmniAuth, 'devise/omniauth'
14
+ autoload :ParameterFilter, 'devise/parameter_filter'
15
+ autoload :BaseSanitizer, 'devise/parameter_sanitizer'
16
+ autoload :ParameterSanitizer, 'devise/parameter_sanitizer'
17
+ autoload :TestHelpers, 'devise/test_helpers'
18
+ autoload :TimeInflector, 'devise/time_inflector'
19
+ autoload :TokenGenerator, 'devise/token_generator'
14
20
 
15
21
  module Controllers
16
22
  autoload :Helpers, 'devise/controllers/helpers'
17
23
  autoload :Rememberable, 'devise/controllers/rememberable'
18
24
  autoload :ScopedViews, 'devise/controllers/scoped_views'
25
+ autoload :SignInOut, 'devise/controllers/sign_in_out'
26
+ autoload :StoreLocation, 'devise/controllers/store_location'
19
27
  autoload :UrlHelpers, 'devise/controllers/url_helpers'
20
28
  end
21
29
 
30
+ module Hooks
31
+ autoload :Proxy, 'devise/hooks/proxy'
32
+ end
33
+
22
34
  module Mailers
23
35
  autoload :Helpers, 'devise/mailers/helpers'
24
36
  end
@@ -42,7 +54,11 @@ module Devise
42
54
  # True values used to check params
43
55
  TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
44
56
 
45
- # Custom domain for cookies. Not set by default
57
+ # Secret key used by the key generator
58
+ mattr_accessor :secret_key
59
+ @@secret_key = nil
60
+
61
+ # Custom domain or key for cookies. Not set by default
46
62
  mattr_accessor :rememberable_options
47
63
  @@rememberable_options = {}
48
64
 
@@ -50,9 +66,13 @@ module Devise
50
66
  mattr_accessor :stretches
51
67
  @@stretches = 10
52
68
 
69
+ # The default key used when authenticating over http auth.
70
+ mattr_accessor :http_authentication_key
71
+ @@http_authentication_key = nil
72
+
53
73
  # Keys used when authenticating a user.
54
74
  mattr_accessor :authentication_keys
55
- @@authentication_keys = [ :email ]
75
+ @@authentication_keys = [:email]
56
76
 
57
77
  # Request keys used when authenticating a user.
58
78
  mattr_accessor :request_keys
@@ -60,7 +80,7 @@ module Devise
60
80
 
61
81
  # Keys that should be case-insensitive.
62
82
  mattr_accessor :case_insensitive_keys
63
- @@case_insensitive_keys = [ :email ]
83
+ @@case_insensitive_keys = [:email]
64
84
 
65
85
  # Keys that should have whitespace stripped.
66
86
  mattr_accessor :strip_whitespace_keys
@@ -86,7 +106,7 @@ module Devise
86
106
  # an one (and only one) @ exists in the given string. This is mainly
87
107
  # to give user feedback and not to assert the e-mail validity.
88
108
  mattr_accessor :email_regexp
89
- @@email_regexp = /\A[^@]+@([^@\.]+\.)+[^@\.]+\z/
109
+ @@email_regexp = /\A[^@\s]+@([^@\s]+\.)+[^@\W]+\z/
90
110
 
91
111
  # Range validation for password length
92
112
  mattr_accessor :password_length
@@ -100,13 +120,22 @@ module Devise
100
120
  mattr_accessor :extend_remember_period
101
121
  @@extend_remember_period = false
102
122
 
123
+ # If true, all the remember me tokens are going to be invalidated when the user signs out.
124
+ mattr_accessor :expire_all_remember_me_on_sign_out
125
+ @@expire_all_remember_me_on_sign_out = true
126
+
103
127
  # Time interval you can access your account before confirming your account.
128
+ # nil - allows unconfirmed access for unlimited time
104
129
  mattr_accessor :allow_unconfirmed_access_for
105
130
  @@allow_unconfirmed_access_for = 0.days
106
131
 
132
+ # Time interval the confirmation token is valid. nil = unlimited
133
+ mattr_accessor :confirm_within
134
+ @@confirm_within = nil
135
+
107
136
  # Defines which key will be used when confirming an account.
108
137
  mattr_accessor :confirmation_keys
109
- @@confirmation_keys = [ :email ]
138
+ @@confirmation_keys = [:email]
110
139
 
111
140
  # Defines if email should be reconfirmable.
112
141
  # False by default for backwards compatibility.
@@ -117,14 +146,14 @@ module Devise
117
146
  mattr_accessor :timeout_in
118
147
  @@timeout_in = 30.minutes
119
148
 
120
- # Authentication token expiration on timeout
121
- mattr_accessor :expire_auth_token_on_timeout
122
- @@expire_auth_token_on_timeout = false
123
-
124
149
  # Used to encrypt password. Please generate one with rake secret.
125
150
  mattr_accessor :pepper
126
151
  @@pepper = nil
127
152
 
153
+ # Used to enable sending notification to user when their password is changed
154
+ mattr_accessor :send_password_change_notification
155
+ @@send_password_change_notification = false
156
+
128
157
  # Scoped views. Since it relies on fallbacks to render default views, it's
129
158
  # turned off by default.
130
159
  mattr_accessor :scoped_views
@@ -137,7 +166,7 @@ module Devise
137
166
 
138
167
  # Defines which key will be used when locking and unlocking an account
139
168
  mattr_accessor :unlock_keys
140
- @@unlock_keys = [ :email ]
169
+ @@unlock_keys = [:email]
141
170
 
142
171
  # Defines which strategy can be used to unlock an account.
143
172
  # Values: :email, :time, :both
@@ -154,12 +183,16 @@ module Devise
154
183
 
155
184
  # Defines which key will be used when recovering the password for an account
156
185
  mattr_accessor :reset_password_keys
157
- @@reset_password_keys = [ :email ]
186
+ @@reset_password_keys = [:email]
158
187
 
159
188
  # Time interval you can reset your password with a reset password key
160
189
  mattr_accessor :reset_password_within
161
190
  @@reset_password_within = 6.hours
162
191
 
192
+ # When set to false, resetting a password does not automatically sign in a user
193
+ mattr_accessor :sign_in_after_reset_password
194
+ @@sign_in_after_reset_password = true
195
+
163
196
  # The default scope which is used by warden.
164
197
  mattr_accessor :default_scope
165
198
  @@default_scope = nil
@@ -168,10 +201,6 @@ module Devise
168
201
  mattr_accessor :mailer_sender
169
202
  @@mailer_sender = nil
170
203
 
171
- # Authentication token params key name of choice. E.g. /users/sign_in?some_key=...
172
- mattr_accessor :token_authentication_key
173
- @@token_authentication_key = :auth_token
174
-
175
204
  # Skip session storage for the following strategies
176
205
  mattr_accessor :skip_session_storage
177
206
  @@skip_session_storage = []
@@ -194,28 +223,26 @@ module Devise
194
223
  mattr_accessor :parent_controller
195
224
  @@parent_controller = "ApplicationController"
196
225
 
226
+ # The parent mailer all Devise mailers inherit from.
227
+ # Defaults to ActionMailer::Base. This should be set early
228
+ # in the initialization process and should be set to a string.
229
+ mattr_accessor :parent_mailer
230
+ @@parent_mailer = "ActionMailer::Base"
231
+
197
232
  # The router Devise should use to generate routes. Defaults
198
- # to :main_app. Should be overriden by engines in order
233
+ # to :main_app. Should be overridden by engines in order
199
234
  # to provide custom routes.
200
235
  mattr_accessor :router_name
201
236
  @@router_name = nil
202
-
203
- # Set the omniauth path prefix so it can be overriden when
237
+
238
+ # Set the OmniAuth path prefix so it can be overridden when
204
239
  # Devise is used in a mountable engine
205
240
  mattr_accessor :omniauth_path_prefix
206
241
  @@omniauth_path_prefix = nil
207
242
 
208
- def self.encryptor=(value)
209
- warn "\n[DEVISE] To select a encryption which isn't bcrypt, you should use devise-encryptable gem.\n"
210
- end
211
-
212
- def self.use_salt_as_remember_token=(value)
213
- warn "\n[DEVISE] Devise.use_salt_as_remember_token is deprecated and has no effect. Please remove it.\n"
214
- end
215
-
216
- def self.apply_schema=(value)
217
- warn "\n[DEVISE] Devise.apply_schema is deprecated and has no effect. Please remove it.\n"
218
- end
243
+ # Set if we should clean up the CSRF Token on authentication
244
+ mattr_accessor :clean_up_csrf_token_on_authentication
245
+ @@clean_up_csrf_token_on_authentication = true
219
246
 
220
247
  # PRIVATE CONFIGURATION
221
248
 
@@ -223,7 +250,7 @@ module Devise
223
250
  mattr_reader :mappings
224
251
  @@mappings = ActiveSupport::OrderedHash.new
225
252
 
226
- # Omniauth configurations.
253
+ # OmniAuth configurations.
227
254
  mattr_reader :omniauth_configs
228
255
  @@omniauth_configs = ActiveSupport::OrderedHash.new
229
256
 
@@ -235,12 +262,20 @@ module Devise
235
262
  # Private methods to interface with Warden.
236
263
  mattr_accessor :warden_config
237
264
  @@warden_config = nil
238
- @@warden_config_block = nil
265
+ @@warden_config_blocks = []
239
266
 
240
267
  # When true, enter in paranoid mode to avoid user enumeration.
241
268
  mattr_accessor :paranoid
242
269
  @@paranoid = false
243
270
 
271
+ # When true, warn user if they just used next-to-last attempt of authentication
272
+ mattr_accessor :last_attempt_warning
273
+ @@last_attempt_warning = true
274
+
275
+ # Stores the token generator
276
+ mattr_accessor :token_generator
277
+ @@token_generator = nil
278
+
244
279
  # Default way to setup Devise. Run rails generate devise_install to create
245
280
  # a fresh initializer with all configuration values.
246
281
  def self.setup
@@ -294,14 +329,20 @@ module Devise
294
329
  mapping
295
330
  end
296
331
 
297
- # Make Devise aware of an 3rd party Devise-module (like invitable). For convenience.
332
+ # Register available devise modules. For the standard modules that Devise provides, this method is
333
+ # called from lib/devise/modules.rb. Third-party modules need to be added explicitly using this method.
334
+ #
335
+ # Note that adding a module using this method does not cause it to be used in the authentication
336
+ # process. That requires that the module be listed in the arguments passed to the 'devise' method
337
+ # in the model class definition.
298
338
  #
299
339
  # == Options:
300
340
  #
301
341
  # +model+ - String representing the load path to a custom *model* for this module (to autoload.)
302
- # +controller+ - Symbol representing the name of an exisiting or custom *controller* for this module.
342
+ # +controller+ - Symbol representing the name of an existing or custom *controller* for this module.
303
343
  # +route+ - Symbol representing the named *route* helper for this module.
304
344
  # +strategy+ - Symbol representing if this module got a custom *strategy*.
345
+ # +insert_at+ - Integer representing the order in which this module's model will be included
305
346
  #
306
347
  # All values, except :model, accept also a boolean and will have the same name as the given module
307
348
  # name.
@@ -309,12 +350,14 @@ module Devise
309
350
  # == Examples:
310
351
  #
311
352
  # Devise.add_module(:party_module)
312
- # Devise.add_module(:party_module, :strategy => true, :controller => :sessions)
313
- # Devise.add_module(:party_module, :model => 'party_module/model')
353
+ # Devise.add_module(:party_module, strategy: true, controller: :sessions)
354
+ # Devise.add_module(:party_module, model: 'party_module/model')
355
+ # Devise.add_module(:party_module, insert_at: 0)
314
356
  #
315
357
  def self.add_module(module_name, options = {})
316
- ALL << module_name
317
- options.assert_valid_keys(:strategy, :model, :controller, :route, :no_input)
358
+ options.assert_valid_keys(:strategy, :model, :controller, :route, :no_input, :insert_at)
359
+
360
+ ALL.insert (options[:insert_at] || -1), module_name
318
361
 
319
362
  if strategy = options[:strategy]
320
363
  strategy = (strategy == true ? module_name : strategy)
@@ -359,7 +402,7 @@ module Devise
359
402
  # Sets warden configuration using a block that will be invoked on warden
360
403
  # initialization.
361
404
  #
362
- # Devise.initialize do |config|
405
+ # Devise.setup do |config|
363
406
  # config.allow_unconfirmed_access_for = 2.days
364
407
  #
365
408
  # config.warden do |manager|
@@ -368,10 +411,10 @@ module Devise
368
411
  # end
369
412
  # end
370
413
  def self.warden(&block)
371
- @@warden_config_block = block
414
+ @@warden_config_blocks << block
372
415
  end
373
416
 
374
- # Specify an omniauth provider.
417
+ # Specify an OmniAuth provider.
375
418
  #
376
419
  # config.omniauth :github, APP_ID, APP_SECRET
377
420
  #
@@ -399,8 +442,8 @@ module Devise
399
442
  Devise::Controllers::UrlHelpers.generate_helpers!
400
443
  end
401
444
 
402
- # A method used internally to setup warden manager from the Rails initialize
403
- # block.
445
+ # A method used internally to complete the setup of warden manager after routes are loaded.
446
+ # See lib/devise/rails/routes.rb - ActionDispatch::Routing::RouteSet#finalize_with_devise!
404
447
  def self.configure_warden! #:nodoc:
405
448
  @@warden_configured ||= begin
406
449
  warden_config.failure_app = Devise::Delegator.new
@@ -408,17 +451,32 @@ module Devise
408
451
  warden_config.intercept_401 = false
409
452
 
410
453
  Devise.mappings.each_value do |mapping|
411
- warden_config.scope_defaults mapping.name, :strategies => mapping.strategies
454
+ warden_config.scope_defaults mapping.name, strategies: mapping.strategies
455
+
456
+ warden_config.serialize_into_session(mapping.name) do |record|
457
+ mapping.to.serialize_into_session(record)
458
+ end
459
+
460
+ warden_config.serialize_from_session(mapping.name) do |key|
461
+ # Previous versions contained an additional entry at the beginning of
462
+ # key with the record's class name.
463
+ args = key[-2, 2]
464
+ mapping.to.serialize_from_session(*args)
465
+ end
412
466
  end
413
467
 
414
- @@warden_config_block.try :call, Devise.warden_config
468
+ @@warden_config_blocks.map { |block| block.call Devise.warden_config }
415
469
  true
416
470
  end
417
471
  end
418
472
 
419
- # Generate a friendly string randomically to be used as token.
420
- def self.friendly_token
421
- SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
473
+ # Generate a friendly string randomly to be used as token.
474
+ # By default, length is 20 characters.
475
+ def self.friendly_token(length = 20)
476
+ # To calculate real characters, we must perform this operation.
477
+ # See SecureRandom.urlsafe_base64
478
+ rlength = (length * 3) / 4
479
+ SecureRandom.urlsafe_base64(rlength).tr('lIO0', 'sxyz')
422
480
  end
423
481
 
424
482
  # constant-time comparison algorithm to prevent timing attacks