devise 3.5.10 → 4.8.0

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 (258) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +279 -1126
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +291 -97
  5. data/app/controllers/devise/confirmations_controller.rb +3 -1
  6. data/app/controllers/devise/omniauth_callbacks_controller.rb +8 -6
  7. data/app/controllers/devise/passwords_controller.rb +7 -4
  8. data/app/controllers/devise/registrations_controller.rb +39 -18
  9. data/app/controllers/devise/sessions_controller.rb +9 -7
  10. data/app/controllers/devise/unlocks_controller.rb +4 -2
  11. data/app/controllers/devise_controller.rb +25 -12
  12. data/app/helpers/devise_helper.rb +23 -18
  13. data/app/mailers/devise/mailer.rb +10 -4
  14. data/app/views/devise/confirmations/new.html.erb +2 -2
  15. data/app/views/devise/mailer/email_changed.html.erb +7 -0
  16. data/app/views/devise/passwords/edit.html.erb +3 -3
  17. data/app/views/devise/passwords/new.html.erb +2 -2
  18. data/app/views/devise/registrations/edit.html.erb +9 -5
  19. data/app/views/devise/registrations/new.html.erb +4 -4
  20. data/app/views/devise/sessions/new.html.erb +4 -4
  21. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  22. data/app/views/devise/shared/_links.html.erb +8 -8
  23. data/app/views/devise/unlocks/new.html.erb +2 -2
  24. data/config/locales/en.yml +5 -2
  25. data/lib/devise.rb +57 -40
  26. data/lib/devise/controllers/helpers.rb +30 -27
  27. data/lib/devise/controllers/rememberable.rb +3 -1
  28. data/lib/devise/controllers/scoped_views.rb +2 -0
  29. data/lib/devise/controllers/sign_in_out.rb +39 -14
  30. data/lib/devise/controllers/store_location.rb +25 -7
  31. data/lib/devise/controllers/url_helpers.rb +3 -1
  32. data/lib/devise/delegator.rb +2 -0
  33. data/lib/devise/encryptor.rb +6 -4
  34. data/lib/devise/failure_app.rb +75 -38
  35. data/lib/devise/hooks/activatable.rb +2 -0
  36. data/lib/devise/hooks/csrf_cleaner.rb +2 -0
  37. data/lib/devise/hooks/forgetable.rb +2 -0
  38. data/lib/devise/hooks/lockable.rb +4 -2
  39. data/lib/devise/hooks/proxy.rb +3 -1
  40. data/lib/devise/hooks/rememberable.rb +2 -0
  41. data/lib/devise/hooks/timeoutable.rb +4 -2
  42. data/lib/devise/hooks/trackable.rb +2 -0
  43. data/lib/devise/mailers/helpers.rb +7 -4
  44. data/lib/devise/mapping.rb +3 -1
  45. data/lib/devise/models.rb +3 -1
  46. data/lib/devise/models/authenticatable.rb +63 -33
  47. data/lib/devise/models/confirmable.rb +90 -29
  48. data/lib/devise/models/database_authenticatable.rb +93 -22
  49. data/lib/devise/models/lockable.rb +19 -5
  50. data/lib/devise/models/omniauthable.rb +2 -0
  51. data/lib/devise/models/recoverable.rb +33 -21
  52. data/lib/devise/models/registerable.rb +4 -0
  53. data/lib/devise/models/rememberable.rb +6 -11
  54. data/lib/devise/models/timeoutable.rb +2 -0
  55. data/lib/devise/models/trackable.rb +15 -1
  56. data/lib/devise/models/validatable.rb +10 -3
  57. data/lib/devise/modules.rb +2 -0
  58. data/lib/devise/omniauth.rb +4 -5
  59. data/lib/devise/omniauth/config.rb +2 -0
  60. data/lib/devise/omniauth/url_helpers.rb +14 -5
  61. data/lib/devise/orm/active_record.rb +5 -1
  62. data/lib/devise/orm/mongoid.rb +6 -2
  63. data/lib/devise/parameter_filter.rb +4 -0
  64. data/lib/devise/parameter_sanitizer.rb +139 -65
  65. data/lib/devise/rails.rb +7 -16
  66. data/lib/devise/rails/deprecated_constant_accessor.rb +39 -0
  67. data/lib/devise/rails/routes.rb +48 -37
  68. data/lib/devise/rails/warden_compat.rb +3 -10
  69. data/lib/devise/secret_key_finder.rb +27 -0
  70. data/lib/devise/strategies/authenticatable.rb +3 -1
  71. data/lib/devise/strategies/base.rb +2 -0
  72. data/lib/devise/strategies/database_authenticatable.rb +11 -4
  73. data/lib/devise/strategies/rememberable.rb +2 -0
  74. data/lib/devise/test/controller_helpers.rb +167 -0
  75. data/lib/devise/test/integration_helpers.rb +63 -0
  76. data/lib/devise/test_helpers.rb +7 -124
  77. data/lib/devise/time_inflector.rb +2 -0
  78. data/lib/devise/token_generator.rb +3 -41
  79. data/lib/devise/version.rb +3 -1
  80. data/lib/generators/active_record/devise_generator.rb +46 -12
  81. data/lib/generators/active_record/templates/migration.rb +4 -2
  82. data/lib/generators/active_record/templates/migration_existing.rb +4 -2
  83. data/lib/generators/devise/controllers_generator.rb +3 -1
  84. data/lib/generators/devise/devise_generator.rb +5 -3
  85. data/lib/generators/devise/install_generator.rb +18 -5
  86. data/lib/generators/devise/orm_helpers.rb +10 -21
  87. data/lib/generators/devise/views_generator.rb +8 -9
  88. data/lib/generators/mongoid/devise_generator.rb +7 -5
  89. data/lib/generators/templates/README +9 -8
  90. data/lib/generators/templates/controllers/confirmations_controller.rb +2 -0
  91. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +3 -1
  92. data/lib/generators/templates/controllers/passwords_controller.rb +2 -0
  93. data/lib/generators/templates/controllers/registrations_controller.rb +6 -4
  94. data/lib/generators/templates/controllers/sessions_controller.rb +4 -2
  95. data/lib/generators/templates/controllers/unlocks_controller.rb +2 -0
  96. data/lib/generators/templates/devise.rb +63 -21
  97. data/lib/generators/templates/markerb/email_changed.markerb +7 -0
  98. data/lib/generators/templates/markerb/password_change.markerb +2 -2
  99. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +5 -1
  100. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +10 -2
  101. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +4 -1
  102. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +11 -3
  103. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +11 -3
  104. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +7 -2
  105. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +4 -1
  106. metadata +19 -317
  107. data/.gitignore +0 -10
  108. data/.travis.yml +0 -44
  109. data/.yardopts +0 -9
  110. data/CODE_OF_CONDUCT.md +0 -22
  111. data/CONTRIBUTING.md +0 -16
  112. data/Gemfile +0 -30
  113. data/Gemfile.lock +0 -187
  114. data/Rakefile +0 -36
  115. data/devise.gemspec +0 -27
  116. data/devise.png +0 -0
  117. data/gemfiles/Gemfile.rails-3.2-stable +0 -29
  118. data/gemfiles/Gemfile.rails-3.2-stable.lock +0 -172
  119. data/gemfiles/Gemfile.rails-4.0-stable +0 -30
  120. data/gemfiles/Gemfile.rails-4.0-stable.lock +0 -166
  121. data/gemfiles/Gemfile.rails-4.1-stable +0 -30
  122. data/gemfiles/Gemfile.rails-4.1-stable.lock +0 -171
  123. data/gemfiles/Gemfile.rails-4.2-stable +0 -30
  124. data/gemfiles/Gemfile.rails-4.2-stable.lock +0 -193
  125. data/script/cached-bundle +0 -49
  126. data/script/s3-put +0 -71
  127. data/test/controllers/custom_registrations_controller_test.rb +0 -40
  128. data/test/controllers/custom_strategy_test.rb +0 -62
  129. data/test/controllers/helper_methods_test.rb +0 -21
  130. data/test/controllers/helpers_test.rb +0 -316
  131. data/test/controllers/inherited_controller_i18n_messages_test.rb +0 -51
  132. data/test/controllers/internal_helpers_test.rb +0 -129
  133. data/test/controllers/load_hooks_controller_test.rb +0 -19
  134. data/test/controllers/passwords_controller_test.rb +0 -31
  135. data/test/controllers/sessions_controller_test.rb +0 -103
  136. data/test/controllers/url_helpers_test.rb +0 -65
  137. data/test/delegator_test.rb +0 -19
  138. data/test/devise_test.rb +0 -107
  139. data/test/failure_app_test.rb +0 -315
  140. data/test/generators/active_record_generator_test.rb +0 -109
  141. data/test/generators/controllers_generator_test.rb +0 -48
  142. data/test/generators/devise_generator_test.rb +0 -39
  143. data/test/generators/install_generator_test.rb +0 -13
  144. data/test/generators/mongoid_generator_test.rb +0 -23
  145. data/test/generators/views_generator_test.rb +0 -103
  146. data/test/helpers/devise_helper_test.rb +0 -49
  147. data/test/integration/authenticatable_test.rb +0 -729
  148. data/test/integration/confirmable_test.rb +0 -324
  149. data/test/integration/database_authenticatable_test.rb +0 -95
  150. data/test/integration/http_authenticatable_test.rb +0 -105
  151. data/test/integration/lockable_test.rb +0 -239
  152. data/test/integration/omniauthable_test.rb +0 -135
  153. data/test/integration/recoverable_test.rb +0 -347
  154. data/test/integration/registerable_test.rb +0 -359
  155. data/test/integration/rememberable_test.rb +0 -214
  156. data/test/integration/timeoutable_test.rb +0 -184
  157. data/test/integration/trackable_test.rb +0 -92
  158. data/test/mailers/confirmation_instructions_test.rb +0 -115
  159. data/test/mailers/reset_password_instructions_test.rb +0 -96
  160. data/test/mailers/unlock_instructions_test.rb +0 -91
  161. data/test/mapping_test.rb +0 -134
  162. data/test/models/authenticatable_test.rb +0 -23
  163. data/test/models/confirmable_test.rb +0 -511
  164. data/test/models/database_authenticatable_test.rb +0 -269
  165. data/test/models/lockable_test.rb +0 -350
  166. data/test/models/omniauthable_test.rb +0 -7
  167. data/test/models/recoverable_test.rb +0 -251
  168. data/test/models/registerable_test.rb +0 -7
  169. data/test/models/rememberable_test.rb +0 -169
  170. data/test/models/serializable_test.rb +0 -49
  171. data/test/models/timeoutable_test.rb +0 -51
  172. data/test/models/trackable_test.rb +0 -41
  173. data/test/models/validatable_test.rb +0 -127
  174. data/test/models_test.rb +0 -153
  175. data/test/omniauth/config_test.rb +0 -57
  176. data/test/omniauth/url_helpers_test.rb +0 -54
  177. data/test/orm/active_record.rb +0 -10
  178. data/test/orm/mongoid.rb +0 -13
  179. data/test/parameter_sanitizer_test.rb +0 -81
  180. data/test/rails_app/Rakefile +0 -6
  181. data/test/rails_app/app/active_record/admin.rb +0 -6
  182. data/test/rails_app/app/active_record/shim.rb +0 -2
  183. data/test/rails_app/app/active_record/user.rb +0 -6
  184. data/test/rails_app/app/active_record/user_on_engine.rb +0 -7
  185. data/test/rails_app/app/active_record/user_on_main_app.rb +0 -7
  186. data/test/rails_app/app/active_record/user_without_email.rb +0 -8
  187. data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
  188. data/test/rails_app/app/controllers/admins_controller.rb +0 -6
  189. data/test/rails_app/app/controllers/application_controller.rb +0 -12
  190. data/test/rails_app/app/controllers/application_with_fake_engine.rb +0 -30
  191. data/test/rails_app/app/controllers/custom/registrations_controller.rb +0 -31
  192. data/test/rails_app/app/controllers/home_controller.rb +0 -25
  193. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -2
  194. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -2
  195. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -14
  196. data/test/rails_app/app/controllers/users_controller.rb +0 -31
  197. data/test/rails_app/app/helpers/application_helper.rb +0 -3
  198. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +0 -3
  199. data/test/rails_app/app/mailers/users/mailer.rb +0 -3
  200. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +0 -4
  201. data/test/rails_app/app/mongoid/admin.rb +0 -29
  202. data/test/rails_app/app/mongoid/shim.rb +0 -23
  203. data/test/rails_app/app/mongoid/user.rb +0 -39
  204. data/test/rails_app/app/mongoid/user_on_engine.rb +0 -39
  205. data/test/rails_app/app/mongoid/user_on_main_app.rb +0 -39
  206. data/test/rails_app/app/mongoid/user_without_email.rb +0 -33
  207. data/test/rails_app/app/views/admins/index.html.erb +0 -1
  208. data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
  209. data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
  210. data/test/rails_app/app/views/home/index.html.erb +0 -1
  211. data/test/rails_app/app/views/home/join.html.erb +0 -1
  212. data/test/rails_app/app/views/home/private.html.erb +0 -1
  213. data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
  214. data/test/rails_app/app/views/layouts/application.html.erb +0 -24
  215. data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
  216. data/test/rails_app/app/views/users/index.html.erb +0 -1
  217. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
  218. data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
  219. data/test/rails_app/bin/bundle +0 -3
  220. data/test/rails_app/bin/rails +0 -4
  221. data/test/rails_app/bin/rake +0 -4
  222. data/test/rails_app/config.ru +0 -4
  223. data/test/rails_app/config/application.rb +0 -40
  224. data/test/rails_app/config/boot.rb +0 -14
  225. data/test/rails_app/config/database.yml +0 -18
  226. data/test/rails_app/config/environment.rb +0 -5
  227. data/test/rails_app/config/environments/development.rb +0 -30
  228. data/test/rails_app/config/environments/production.rb +0 -84
  229. data/test/rails_app/config/environments/test.rb +0 -41
  230. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
  231. data/test/rails_app/config/initializers/devise.rb +0 -180
  232. data/test/rails_app/config/initializers/inflections.rb +0 -2
  233. data/test/rails_app/config/initializers/secret_token.rb +0 -8
  234. data/test/rails_app/config/initializers/session_store.rb +0 -1
  235. data/test/rails_app/config/routes.rb +0 -125
  236. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -71
  237. data/test/rails_app/db/schema.rb +0 -55
  238. data/test/rails_app/lib/shared_admin.rb +0 -17
  239. data/test/rails_app/lib/shared_user.rb +0 -29
  240. data/test/rails_app/lib/shared_user_without_email.rb +0 -26
  241. data/test/rails_app/lib/shared_user_without_omniauth.rb +0 -13
  242. data/test/rails_app/public/404.html +0 -26
  243. data/test/rails_app/public/422.html +0 -26
  244. data/test/rails_app/public/500.html +0 -26
  245. data/test/rails_app/public/favicon.ico +0 -0
  246. data/test/rails_test.rb +0 -9
  247. data/test/routes_test.rb +0 -264
  248. data/test/support/action_controller/record_identifier.rb +0 -10
  249. data/test/support/assertions.rb +0 -39
  250. data/test/support/helpers.rb +0 -77
  251. data/test/support/integration.rb +0 -92
  252. data/test/support/locale/en.yml +0 -8
  253. data/test/support/mongoid.yml +0 -6
  254. data/test/support/webrat/integrations/rails.rb +0 -24
  255. data/test/test_helper.rb +0 -34
  256. data/test/test_helpers_test.rb +0 -178
  257. data/test/test_models.rb +0 -33
  258. data/test/time_helpers.rb +0 -137
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Models
3
5
  # Validatable creates all needed validations for a user email and password.
@@ -10,7 +12,7 @@ module Devise
10
12
  # Validatable adds the following options to devise_for:
11
13
  #
12
14
  # * +email_regexp+: the regular expression used to validate e-mails;
13
- # * +password_length+: a range expressing password length. Defaults to 8..72.
15
+ # * +password_length+: a range expressing password length. Defaults to 6..128.
14
16
  #
15
17
  module Validatable
16
18
  # All validations used by this module.
@@ -27,8 +29,13 @@ module Devise
27
29
 
28
30
  base.class_eval do
29
31
  validates_presence_of :email, if: :email_required?
30
- validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
31
- validates_format_of :email, with: email_regexp, allow_blank: true, if: :email_changed?
32
+ if Devise.activerecord51?
33
+ validates_uniqueness_of :email, allow_blank: true, case_sensitive: true, if: :will_save_change_to_email?
34
+ validates_format_of :email, with: email_regexp, allow_blank: true, if: :will_save_change_to_email?
35
+ else
36
+ validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
37
+ validates_format_of :email, with: email_regexp, allow_blank: true, if: :email_changed?
38
+ end
32
39
 
33
40
  validates_presence_of :password, if: :password_required?
34
41
  validates_confirmation_of :password, if: :password_required?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/core_ext/object/with_options'
2
4
 
3
5
  Devise.with_options model: true do |d|
@@ -1,15 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
4
+ gem "omniauth", ">= 1.0.0"
5
+
2
6
  require "omniauth"
3
- require "omniauth/version"
4
7
  rescue LoadError
5
8
  warn "Could not load 'omniauth'. Please ensure you have the omniauth gem >= 1.0.0 installed and listed in your Gemfile."
6
9
  raise
7
10
  end
8
11
 
9
- unless OmniAuth::VERSION =~ /^1\./
10
- raise "You are using an old OmniAuth version, please ensure you have 1.0.0.pr2 version or later installed."
11
- end
12
-
13
12
  # Clean up the default path_prefix. It will be automatically set by Devise.
14
13
  OmniAuth.config.path_prefix = nil
15
14
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module OmniAuth
3
5
  class StrategyNotFound < NameError
@@ -1,17 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module OmniAuth
3
5
  module UrlHelpers
4
- def self.define_helpers(mapping)
6
+ def omniauth_authorize_path(resource_or_scope, provider, *args)
7
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
8
+ _devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_path", *args)
9
+ end
10
+
11
+ def omniauth_authorize_url(resource_or_scope, provider, *args)
12
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
13
+ _devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_url", *args)
5
14
  end
6
15
 
7
- def omniauth_authorize_path(resource_or_scope, *args)
16
+ def omniauth_callback_path(resource_or_scope, provider, *args)
8
17
  scope = Devise::Mapping.find_scope!(resource_or_scope)
9
- _devise_route_context.send("#{scope}_omniauth_authorize_path", *args)
18
+ _devise_route_context.send("#{scope}_#{provider}_omniauth_callback_path", *args)
10
19
  end
11
20
 
12
- def omniauth_callback_path(resource_or_scope, *args)
21
+ def omniauth_callback_url(resource_or_scope, provider, *args)
13
22
  scope = Devise::Mapping.find_scope!(resource_or_scope)
14
- _devise_route_context.send("#{scope}_omniauth_callback_path", *args)
23
+ _devise_route_context.send("#{scope}_#{provider}_omniauth_callback_url", *args)
15
24
  end
16
25
  end
17
26
  end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'orm_adapter/adapters/active_record'
2
4
 
3
- ActiveRecord::Base.extend Devise::Models
5
+ ActiveSupport.on_load(:active_record) do
6
+ extend Devise::Models
7
+ end
@@ -1,3 +1,7 @@
1
- require 'orm_adapter/adapters/mongoid'
1
+ # frozen_string_literal: true
2
2
 
3
- Mongoid::Document::ClassMethods.send :include, Devise::Models
3
+ ActiveSupport.on_load(:mongoid) do
4
+ require 'orm_adapter/adapters/mongoid'
5
+
6
+ Mongoid::Document::ClassMethods.send :include, Devise::Models
7
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  class ParameterFilter
3
5
  def initialize(case_insensitive_keys, strip_whitespace_keys)
@@ -16,6 +18,8 @@ module Devise
16
18
 
17
19
  def filtered_hash_by_method_for_given_keys(conditions, method, condition_keys)
18
20
  condition_keys.each do |k|
21
+ next unless conditions.key?(k)
22
+
19
23
  value = conditions[k]
20
24
  conditions[k] = value.send(method) if value.respond_to?(method)
21
25
  end
@@ -1,99 +1,173 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
- class BaseSanitizer
3
- attr_reader :params, :resource_name, :resource_class
4
+ # The +ParameterSanitizer+ deals with permitting specific parameters values
5
+ # for each +Devise+ scope in the application.
6
+ #
7
+ # The sanitizer knows about Devise default parameters (like +password+ and
8
+ # +password_confirmation+ for the `RegistrationsController`), and you can
9
+ # extend or change the permitted parameters list on your controllers.
10
+ #
11
+ # === Permitting new parameters
12
+ #
13
+ # You can add new parameters to the permitted list using the +permit+ method
14
+ # in a +before_action+ method, for instance.
15
+ #
16
+ # class ApplicationController < ActionController::Base
17
+ # before_action :configure_permitted_parameters, if: :devise_controller?
18
+ #
19
+ # protected
20
+ #
21
+ # def configure_permitted_parameters
22
+ # # Permit the `subscribe_newsletter` parameter along with the other
23
+ # # sign up parameters.
24
+ # devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
25
+ # end
26
+ # end
27
+ #
28
+ # Using a block yields an +ActionController::Parameters+ object so you can
29
+ # permit nested parameters and have more control over how the parameters are
30
+ # permitted in your controller.
31
+ #
32
+ # def configure_permitted_parameters
33
+ # devise_parameter_sanitizer.permit(:sign_up) do |user|
34
+ # user.permit(newsletter_preferences: [])
35
+ # end
36
+ # end
37
+ class ParameterSanitizer
38
+ DEFAULT_PERMITTED_ATTRIBUTES = {
39
+ sign_in: [:password, :remember_me],
40
+ sign_up: [:password, :password_confirmation],
41
+ account_update: [:password, :password_confirmation, :current_password]
42
+ }
4
43
 
5
44
  def initialize(resource_class, resource_name, params)
6
- @resource_class = resource_class
7
- @resource_name = resource_name
45
+ @auth_keys = extract_auth_keys(resource_class)
8
46
  @params = params
9
- @blocks = Hash.new
10
- end
47
+ @resource_name = resource_name
48
+ @permitted = {}
11
49
 
12
- def for(kind, &block)
13
- if block_given?
14
- @blocks[kind] = block
15
- else
16
- default_for(kind)
50
+ DEFAULT_PERMITTED_ATTRIBUTES.each_pair do |action, keys|
51
+ permit(action, keys: keys)
17
52
  end
18
53
  end
19
54
 
20
- def sanitize(kind)
21
- if block = @blocks[kind]
22
- block.call(default_params)
55
+ # Sanitize the parameters for a specific +action+.
56
+ #
57
+ # === Arguments
58
+ #
59
+ # * +action+ - A +Symbol+ with the action that the controller is
60
+ # performing, like +sign_up+, +sign_in+, etc.
61
+ #
62
+ # === Examples
63
+ #
64
+ # # Inside the `RegistrationsController#create` action.
65
+ # resource = build_resource(devise_parameter_sanitizer.sanitize(:sign_up))
66
+ # resource.save
67
+ #
68
+ # Returns an +ActiveSupport::HashWithIndifferentAccess+ with the permitted
69
+ # attributes.
70
+ def sanitize(action)
71
+ permissions = @permitted[action]
72
+
73
+ if permissions.respond_to?(:call)
74
+ cast_to_hash permissions.call(default_params)
75
+ elsif permissions.present?
76
+ cast_to_hash permit_keys(default_params, permissions)
23
77
  else
24
- default_sanitize(kind)
78
+ unknown_action!(action)
25
79
  end
26
80
  end
27
81
 
28
- private
82
+ # Add or remove new parameters to the permitted list of an +action+.
83
+ #
84
+ # === Arguments
85
+ #
86
+ # * +action+ - A +Symbol+ with the action that the controller is
87
+ # performing, like +sign_up+, +sign_in+, etc.
88
+ # * +keys:+ - An +Array+ of keys that also should be permitted.
89
+ # * +except:+ - An +Array+ of keys that shouldn't be permitted.
90
+ # * +block+ - A block that should be used to permit the action
91
+ # parameters instead of the +Array+ based approach. The block will be
92
+ # called with an +ActionController::Parameters+ instance.
93
+ #
94
+ # === Examples
95
+ #
96
+ # # Adding new parameters to be permitted in the `sign_up` action.
97
+ # devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
98
+ #
99
+ # # Removing the `password` parameter from the `account_update` action.
100
+ # devise_parameter_sanitizer.permit(:account_update, except: [:password])
101
+ #
102
+ # # Using the block form to completely override how we permit the
103
+ # # parameters for the `sign_up` action.
104
+ # devise_parameter_sanitizer.permit(:sign_up) do |user|
105
+ # user.permit(:email, :password, :password_confirmation)
106
+ # end
107
+ #
108
+ #
109
+ # Returns nothing.
110
+ def permit(action, keys: nil, except: nil, &block)
111
+ if block_given?
112
+ @permitted[action] = block
113
+ end
29
114
 
30
- def default_for(kind)
31
- raise ArgumentError, "a block is expected in Devise base sanitizer"
32
- end
115
+ if keys.present?
116
+ @permitted[action] ||= @auth_keys.dup
117
+ @permitted[action].concat(keys)
118
+ end
33
119
 
34
- def default_sanitize(kind)
35
- default_params
120
+ if except.present?
121
+ @permitted[action] ||= @auth_keys.dup
122
+ @permitted[action] = @permitted[action] - except
123
+ end
36
124
  end
37
125
 
38
- def default_params
39
- params.fetch(resource_name, {})
40
- end
41
- end
126
+ private
42
127
 
43
- class ParameterSanitizer < BaseSanitizer
44
- def initialize(*)
45
- super
46
- @permitted = Hash.new { |h,k| h[k] = attributes_for(k) }
128
+ # Cast a sanitized +ActionController::Parameters+ to a +HashWithIndifferentAccess+
129
+ # that can be used elsewhere.
130
+ #
131
+ # Returns an +ActiveSupport::HashWithIndifferentAccess+.
132
+ def cast_to_hash(params)
133
+ # TODO: Remove the `with_indifferent_access` method call when we only support Rails 5+.
134
+ params && params.to_h.with_indifferent_access
47
135
  end
48
136
 
49
- def sign_in
50
- permit self.for(:sign_in)
137
+ def default_params
138
+ if hashable_resource_params?
139
+ @params.fetch(@resource_name)
140
+ else
141
+ empty_params
142
+ end
51
143
  end
52
144
 
53
- def sign_up
54
- permit self.for(:sign_up)
145
+ def hashable_resource_params?
146
+ @params[@resource_name].respond_to?(:permit)
55
147
  end
56
148
 
57
- def account_update
58
- permit self.for(:account_update)
149
+ def empty_params
150
+ ActionController::Parameters.new({})
59
151
  end
60
152
 
61
- private
62
-
63
- # TODO: We do need to flatten so it works with strong_parameters
64
- # gem. We should drop it once we move to Rails 4 only support.
65
- def permit(keys)
66
- default_params.permit(*Array(keys))
153
+ def permit_keys(parameters, keys)
154
+ parameters.permit(*keys)
67
155
  end
68
156
 
69
- # Change for(kind) to return the values in the @permitted
70
- # hash, allowing the developer to customize at runtime.
71
- def default_for(kind)
72
- @permitted[kind] || raise("No sanitizer provided for #{kind}")
73
- end
157
+ def extract_auth_keys(klass)
158
+ auth_keys = klass.authentication_keys
74
159
 
75
- def default_sanitize(kind)
76
- if respond_to?(kind, true)
77
- send(kind)
78
- else
79
- raise NotImplementedError, "Devise doesn't know how to sanitize parameters for #{kind}"
80
- end
160
+ auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys
81
161
  end
82
162
 
83
- def attributes_for(kind)
84
- case kind
85
- when :sign_in
86
- auth_keys + [:password, :remember_me]
87
- when :sign_up
88
- auth_keys + [:password, :password_confirmation]
89
- when :account_update
90
- auth_keys + [:password, :password_confirmation, :current_password]
91
- end
92
- end
163
+ def unknown_action!(action)
164
+ raise NotImplementedError, <<-MESSAGE.strip_heredoc
165
+ "Devise doesn't know how to sanitize parameters for '#{action}'".
166
+ If you want to define a new set of parameters to be sanitized use the
167
+ `permit` method first:
93
168
 
94
- def auth_keys
95
- @auth_keys ||= @resource_class.authentication_keys.respond_to?(:keys) ?
96
- @resource_class.authentication_keys.keys : @resource_class.authentication_keys
169
+ devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
170
+ MESSAGE
97
171
  end
98
172
  end
99
173
  end
data/lib/devise/rails.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'devise/rails/routes'
2
4
  require 'devise/rails/warden_compat'
3
5
 
@@ -11,7 +13,9 @@ module Devise
11
13
  end
12
14
 
13
15
  # Force routes to be loaded if we are doing any eager load.
14
- config.before_eager_load { |app| app.reload_routes! }
16
+ config.before_eager_load do |app|
17
+ app.reload_routes! if Devise.reload_routes
18
+ end
15
19
 
16
20
  initializer "devise.url_helpers" do
17
21
  Devise.include_helpers(Devise::Controllers)
@@ -30,27 +34,14 @@ module Devise
30
34
  end
31
35
 
32
36
  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
37
- end
37
+ Devise.secret_key ||= Devise::SecretKeyFinder.new(app).find
38
38
 
39
39
  Devise.token_generator ||=
40
40
  if secret_key = Devise.secret_key
41
41
  Devise::TokenGenerator.new(
42
- Devise::CachingKeyGenerator.new(Devise::KeyGenerator.new(secret_key))
42
+ ActiveSupport::CachingKeyGenerator.new(ActiveSupport::KeyGenerator.new(secret_key))
43
43
  )
44
44
  end
45
45
  end
46
-
47
- initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
48
- # Deprecate: Remove once we move to Rails 4 only.
49
- ActionDispatch::Routing::RoutesProxy.class_eval do
50
- def respond_to?(method, include_private = false)
51
- super || routes.url_helpers.respond_to?(method)
52
- end
53
- end
54
- end
55
46
  end
56
47
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'active_support/deprecation/constant_accessor'
5
+
6
+ module Devise
7
+ DeprecatedConstantAccessor = ActiveSupport::Deprecation::DeprecatedConstantAccessor #:nodoc:
8
+ end
9
+ rescue LoadError
10
+
11
+ # Copy of constant deprecation module from Rails / Active Support version 6, so we can use it
12
+ # with Rails <= 5.0 versions. This can be removed once we support only Rails 5.1 or greater.
13
+ module Devise
14
+ module DeprecatedConstantAccessor #:nodoc:
15
+ def self.included(base)
16
+ require "active_support/inflector/methods"
17
+
18
+ extension = Module.new do
19
+ def const_missing(missing_const_name)
20
+ if class_variable_defined?(:@@_deprecated_constants)
21
+ if (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
22
+ replacement[:deprecator].warn(replacement[:message] || "#{name}::#{missing_const_name} is deprecated! Use #{replacement[:new]} instead.", Rails::VERSION::MAJOR == 4 ? caller : caller_locations)
23
+ return ActiveSupport::Inflector.constantize(replacement[:new].to_s)
24
+ end
25
+ end
26
+ super
27
+ end
28
+
29
+ def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
30
+ class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
31
+ class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
32
+ end
33
+ end
34
+ base.singleton_class.prepend extension
35
+ end
36
+ end
37
+ end
38
+
39
+ end