devise 3.5.10 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -9
  3. data/CHANGELOG.md +33 -1188
  4. data/Gemfile +0 -1
  5. data/Gemfile.lock +15 -18
  6. data/MIT-LICENSE +1 -1
  7. data/README.md +20 -10
  8. data/app/controllers/devise/omniauth_callbacks_controller.rb +4 -4
  9. data/app/controllers/devise/passwords_controller.rb +2 -2
  10. data/app/controllers/devise/registrations_controller.rb +2 -2
  11. data/app/controllers/devise/sessions_controller.rb +4 -4
  12. data/app/controllers/devise/unlocks_controller.rb +1 -1
  13. data/app/controllers/devise_controller.rb +11 -7
  14. data/devise.gemspec +2 -3
  15. data/gemfiles/Gemfile.rails-4.1-stable +0 -1
  16. data/gemfiles/Gemfile.rails-4.1-stable.lock +38 -41
  17. data/gemfiles/Gemfile.rails-4.2-stable +0 -1
  18. data/gemfiles/Gemfile.rails-4.2-stable.lock +47 -50
  19. data/gemfiles/Gemfile.rails-5.0-beta +37 -0
  20. data/gemfiles/Gemfile.rails-5.0-beta.lock +242 -0
  21. data/lib/devise.rb +8 -8
  22. data/lib/devise/controllers/helpers.rb +7 -11
  23. data/lib/devise/failure_app.rb +17 -9
  24. data/lib/devise/models/authenticatable.rb +5 -1
  25. data/lib/devise/models/confirmable.rb +3 -4
  26. data/lib/devise/models/database_authenticatable.rb +1 -0
  27. data/lib/devise/models/lockable.rb +1 -5
  28. data/lib/devise/models/rememberable.rb +5 -11
  29. data/lib/devise/parameter_sanitizer.rb +176 -61
  30. data/lib/devise/rails.rb +1 -10
  31. data/lib/devise/rails/routes.rb +25 -14
  32. data/lib/devise/rails/warden_compat.rb +1 -10
  33. data/lib/devise/strategies/rememberable.rb +6 -3
  34. data/lib/devise/test_helpers.rb +9 -4
  35. data/lib/devise/token_generator.rb +1 -41
  36. data/lib/devise/version.rb +1 -1
  37. data/lib/generators/active_record/devise_generator.rb +3 -3
  38. data/lib/generators/active_record/templates/migration.rb +1 -1
  39. data/lib/generators/active_record/templates/migration_existing.rb +1 -1
  40. data/lib/generators/devise/orm_helpers.rb +0 -17
  41. data/lib/generators/templates/controllers/registrations_controller.rb +4 -4
  42. data/lib/generators/templates/controllers/sessions_controller.rb +2 -2
  43. data/lib/generators/templates/devise.rb +4 -5
  44. data/test/controllers/custom_registrations_controller_test.rb +5 -5
  45. data/test/controllers/custom_strategy_test.rb +7 -5
  46. data/test/controllers/helper_methods_test.rb +3 -2
  47. data/test/controllers/helpers_test.rb +1 -1
  48. data/test/controllers/inherited_controller_i18n_messages_test.rb +2 -2
  49. data/test/controllers/internal_helpers_test.rb +8 -10
  50. data/test/controllers/load_hooks_controller_test.rb +1 -1
  51. data/test/controllers/passwords_controller_test.rb +4 -3
  52. data/test/controllers/sessions_controller_test.rb +21 -18
  53. data/test/controllers/url_helpers_test.rb +1 -1
  54. data/test/failure_app_test.rb +19 -14
  55. data/test/generators/active_record_generator_test.rb +0 -26
  56. data/test/helpers/devise_helper_test.rb +1 -1
  57. data/test/integration/authenticatable_test.rb +18 -18
  58. data/test/integration/confirmable_test.rb +5 -5
  59. data/test/integration/database_authenticatable_test.rb +1 -1
  60. data/test/integration/http_authenticatable_test.rb +4 -5
  61. data/test/integration/lockable_test.rb +4 -3
  62. data/test/integration/omniauthable_test.rb +1 -1
  63. data/test/integration/recoverable_test.rb +10 -10
  64. data/test/integration/registerable_test.rb +9 -11
  65. data/test/integration/rememberable_test.rb +7 -43
  66. data/test/integration/timeoutable_test.rb +4 -4
  67. data/test/integration/trackable_test.rb +1 -1
  68. data/test/models/confirmable_test.rb +5 -13
  69. data/test/models/lockable_test.rb +0 -22
  70. data/test/models/rememberable_test.rb +0 -12
  71. data/test/models/validatable_test.rb +2 -10
  72. data/test/omniauth/url_helpers_test.rb +1 -2
  73. data/test/orm/active_record.rb +6 -1
  74. data/test/parameter_sanitizer_test.rb +103 -53
  75. data/test/rails_app/app/active_record/user.rb +3 -0
  76. data/test/rails_app/app/controllers/admins_controller.rb +1 -1
  77. data/test/rails_app/app/controllers/application_controller.rb +2 -2
  78. data/test/rails_app/app/controllers/home_controller.rb +5 -1
  79. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +2 -2
  80. data/test/rails_app/app/controllers/users_controller.rb +5 -5
  81. data/test/rails_app/config/application.rb +1 -1
  82. data/test/rails_app/config/boot.rb +3 -3
  83. data/test/rails_app/config/environments/test.rb +6 -1
  84. data/test/rails_app/config/initializers/secret_token.rb +1 -6
  85. data/test/routes_test.rb +26 -11
  86. data/test/support/http_method_compatibility.rb +51 -0
  87. data/test/support/webrat/integrations/rails.rb +9 -0
  88. data/test/test_helpers_test.rb +3 -3
  89. metadata +13 -31
  90. data/gemfiles/Gemfile.rails-3.2-stable +0 -29
  91. data/gemfiles/Gemfile.rails-3.2-stable.lock +0 -172
  92. data/gemfiles/Gemfile.rails-4.0-stable +0 -30
  93. data/gemfiles/Gemfile.rails-4.0-stable.lock +0 -166
  94. data/script/cached-bundle +0 -49
  95. data/script/s3-put +0 -71
  96. data/test/time_helpers.rb +0 -137
@@ -12,19 +12,18 @@ module Devise
12
12
  autoload :FailureApp, 'devise/failure_app'
13
13
  autoload :OmniAuth, 'devise/omniauth'
14
14
  autoload :ParameterFilter, 'devise/parameter_filter'
15
- autoload :BaseSanitizer, 'devise/parameter_sanitizer'
16
15
  autoload :ParameterSanitizer, 'devise/parameter_sanitizer'
17
16
  autoload :TestHelpers, 'devise/test_helpers'
18
17
  autoload :TimeInflector, 'devise/time_inflector'
19
18
  autoload :TokenGenerator, 'devise/token_generator'
20
19
 
21
20
  module Controllers
22
- autoload :Helpers, 'devise/controllers/helpers'
23
- autoload :Rememberable, 'devise/controllers/rememberable'
24
- autoload :ScopedViews, 'devise/controllers/scoped_views'
25
- autoload :SignInOut, 'devise/controllers/sign_in_out'
26
- autoload :StoreLocation, 'devise/controllers/store_location'
27
- autoload :UrlHelpers, 'devise/controllers/url_helpers'
21
+ autoload :Helpers, 'devise/controllers/helpers'
22
+ autoload :Rememberable, 'devise/controllers/rememberable'
23
+ autoload :ScopedViews, 'devise/controllers/scoped_views'
24
+ autoload :SignInOut, 'devise/controllers/sign_in_out'
25
+ autoload :StoreLocation, 'devise/controllers/store_location'
26
+ autoload :UrlHelpers, 'devise/controllers/url_helpers'
28
27
  end
29
28
 
30
29
  module Hooks
@@ -36,7 +35,7 @@ module Devise
36
35
  end
37
36
 
38
37
  module Strategies
39
- autoload :Base, 'devise/strategies/base'
38
+ autoload :Base, 'devise/strategies/base'
40
39
  autoload :Authenticatable, 'devise/strategies/authenticatable'
41
40
  end
42
41
 
@@ -116,6 +115,7 @@ module Devise
116
115
  mattr_accessor :remember_for
117
116
  @@remember_for = 2.weeks
118
117
 
118
+ # TODO: extend_remember_period is no longer used
119
119
  # If true, extends the user's remember period when remembered via cookie.
120
120
  mattr_accessor :extend_remember_period
121
121
  @@extend_remember_period = false
@@ -30,8 +30,8 @@ module Devise
30
30
  # current_bloggers # Currently signed in user and admin
31
31
  #
32
32
  # Use:
33
- # before_filter :authenticate_blogger! # Redirects unless either a user or an admin are authenticated
34
- # before_filter ->{ authenticate_blogger! :admin } # Redirects to the admin login page
33
+ # before_action :authenticate_blogger! # Redirects unless either a user or an admin are authenticated
34
+ # before_action ->{ authenticate_blogger! :admin } # Redirects to the admin login page
35
35
  # current_blogger :user # Preferably returns a User if one is signed in
36
36
  #
37
37
  def devise_group(group_name, opts={})
@@ -84,7 +84,7 @@ module Devise
84
84
  end
85
85
 
86
86
  # Define authentication filters and accessor helpers based on mappings.
87
- # These filters should be used inside the controllers as before_filters,
87
+ # These filters should be used inside the controllers as before_actions,
88
88
  # so you can control the scope of the user who should be signed in to
89
89
  # access that specific controller/action.
90
90
  # Example:
@@ -104,8 +104,8 @@ module Devise
104
104
  # admin_session # Session data available only to the admin scope
105
105
  #
106
106
  # Use:
107
- # before_filter :authenticate_user! # Tell devise to use :user map
108
- # before_filter :authenticate_admin! # Tell devise to use :admin map
107
+ # before_action :authenticate_user! # Tell devise to use :user map
108
+ # before_action :authenticate_admin! # Tell devise to use :admin map
109
109
  #
110
110
  def self.define_helpers(mapping) #:nodoc:
111
111
  mapping = mapping.name
@@ -145,7 +145,7 @@ module Devise
145
145
  # the controllers defined inside devise. Useful if you want to apply a before
146
146
  # filter to all controllers, except the ones in devise:
147
147
  #
148
- # before_filter :my_filter, unless: :devise_controller?
148
+ # before_action :my_filter, unless: :devise_controller?
149
149
  def devise_controller?
150
150
  is_a?(::DeviseController)
151
151
  end
@@ -154,11 +154,7 @@ module Devise
154
154
  # lib/devise/parameter_sanitizer.rb for more info. Override this
155
155
  # method in your application controller to use your own parameter sanitizer.
156
156
  def devise_parameter_sanitizer
157
- @devise_parameter_sanitizer ||= if defined?(ActionController::StrongParameters)
158
- Devise::ParameterSanitizer.new(resource_class, resource_name, params)
159
- else
160
- Devise::BaseSanitizer.new(resource_class, resource_name, params)
161
- end
157
+ @devise_parameter_sanitizer ||= Devise::ParameterSanitizer.new(resource_class, resource_name, params)
162
158
  end
163
159
 
164
160
  # Tell warden that params authentication is allowed for that specific page.
@@ -6,7 +6,6 @@ module Devise
6
6
  # page based on current scope and mapping. If no scope is given, redirect
7
7
  # to the default_url.
8
8
  class FailureApp < ActionController::Metal
9
- include ActionController::RackDelegation
10
9
  include ActionController::UrlFor
11
10
  include ActionController::Redirecting
12
11
 
@@ -22,7 +21,7 @@ module Devise
22
21
  @respond.call(env)
23
22
  end
24
23
 
25
- # Try retrieving the URL options from the parent controller (usually
24
+ # Try retrieving the URL options from the parent controller (usually
26
25
  # ApplicationController). Instance methods are not supported at the moment,
27
26
  # so only the class-level attribute is used.
28
27
  def self.default_url_options(*args)
@@ -53,18 +52,27 @@ module Devise
53
52
  def recall
54
53
  config = Rails.application.config
55
54
 
56
- if config.try(:relative_url_root)
55
+ header_info = if config.try(:relative_url_root)
57
56
  base_path = Pathname.new(config.relative_url_root)
58
57
  full_path = Pathname.new(attempted_path)
59
58
 
60
- env["SCRIPT_NAME"] = config.relative_url_root
61
- env["PATH_INFO"] = '/' + full_path.relative_path_from(base_path).to_s
59
+ { "SCRIPT_NAME" => config.relative_url_root,
60
+ "PATH_INFO" => '/' + full_path.relative_path_from(base_path).to_s }
62
61
  else
63
- env["PATH_INFO"] = attempted_path
62
+ { "PATH_INFO" => attempted_path }
63
+ end
64
+
65
+ header_info.each do | var, value|
66
+ if request.respond_to?(:set_header)
67
+ request.set_header(var, value)
68
+ else
69
+ env[var] = value
70
+ end
64
71
  end
65
72
 
66
73
  flash.now[:alert] = i18n_message(:invalid) if is_flashing_format?
67
- self.response = recall_app(warden_options[:recall]).call(env)
74
+ # self.response = recall_app(warden_options[:recall]).call(env)
75
+ self.response = recall_app(warden_options[:recall]).call(request.env)
68
76
  end
69
77
 
70
78
  def redirect
@@ -199,11 +207,11 @@ module Devise
199
207
  end
200
208
 
201
209
  def warden
202
- env['warden']
210
+ request.respond_to?(:get_header) ? request.get_header("warden") : env["warden"]
203
211
  end
204
212
 
205
213
  def warden_options
206
- env['warden.options']
214
+ request.respond_to?(:get_header) ? request.get_header("warden.options") : env["warden.options"]
207
215
  end
208
216
 
209
217
  def warden_message
@@ -253,7 +253,11 @@ module Devise
253
253
 
254
254
  # Find or initialize a record with group of attributes based on a list of required attributes.
255
255
  def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc:
256
- attributes = attributes.slice(*required_attributes).with_indifferent_access
256
+ attributes = if attributes.respond_to? :permit
257
+ attributes.slice(*required_attributes).permit!.to_h.with_indifferent_access
258
+ else
259
+ attributes.with_indifferent_access.slice(*required_attributes)
260
+ end
257
261
  attributes.delete_if { |key, value| value.blank? }
258
262
 
259
263
  if attributes.size == required_attributes.size
@@ -40,7 +40,6 @@ module Devise
40
40
  #
41
41
  module Confirmable
42
42
  extend ActiveSupport::Concern
43
- include ActionView::Helpers::DateHelper
44
43
 
45
44
  included do
46
45
  before_create :generate_confirmation_token, if: :confirmation_required?
@@ -170,7 +169,6 @@ module Devise
170
169
  # in models to map to a nice sign up e-mail.
171
170
  def send_on_create_confirmation_instructions
172
171
  send_confirmation_instructions
173
- skip_reconfirmation!
174
172
  end
175
173
 
176
174
  # Callback to overwrite if confirmation is required or not.
@@ -255,13 +253,13 @@ module Devise
255
253
  end
256
254
 
257
255
  def postpone_email_change?
258
- postpone = self.class.reconfirmable && email_changed? && !@bypass_confirmation_postpone && self.email.present?
256
+ postpone = self.class.reconfirmable && email_changed? && email_was.present? && !@bypass_confirmation_postpone && self.email.present?
259
257
  @bypass_confirmation_postpone = false
260
258
  postpone
261
259
  end
262
260
 
263
261
  def reconfirmation_required?
264
- self.class.reconfirmable && @reconfirmation_required && (self.email.present? || self.unconfirmed_email.present?)
262
+ self.class.reconfirmable && @reconfirmation_required && self.email.present?
265
263
  end
266
264
 
267
265
  def send_confirmation_notification?
@@ -316,6 +314,7 @@ module Devise
316
314
 
317
315
  # Find a record for confirmation by unconfirmed email field
318
316
  def find_by_unconfirmed_email_with_errors(attributes = {})
317
+ attributes = attributes.slice(*confirmation_keys).permit!.to_h if attributes.respond_to? :permit
319
318
  unconfirmed_required_attributes = confirmation_keys.map { |k| k == :email ? :unconfirmed_email : k }
320
319
  unconfirmed_attributes = attributes.symbolize_keys
321
320
  unconfirmed_attributes[:unconfirmed_email] = unconfirmed_attributes.delete(:email)
@@ -39,6 +39,7 @@ module Devise
39
39
 
40
40
  # Generates password encryption based on the given value.
41
41
  def password=(new_password)
42
+ attribute_will_change! 'password'
42
43
  @password = new_password
43
44
  self.encrypted_password = password_digest(@password) if @password.present?
44
45
  end
@@ -155,9 +155,6 @@ module Devise
155
155
  end
156
156
 
157
157
  module ClassMethods
158
- # List of strategies that are enabled/supported if :both is used.
159
- BOTH_STRATEGIES = [:time, :email]
160
-
161
158
  # Attempt to find a user by its unlock keys. If a record is found, send new
162
159
  # unlock instructions to it. If not user is found, returns a new user
163
160
  # with an email not found error.
@@ -184,8 +181,7 @@ module Devise
184
181
 
185
182
  # Is the unlock enabled for the given unlock strategy?
186
183
  def unlock_strategy_enabled?(strategy)
187
- self.unlock_strategy == strategy ||
188
- (self.unlock_strategy == :both && BOTH_STRATEGIES.include?(strategy))
184
+ [:both, strategy].include?(self.unlock_strategy)
189
185
  end
190
186
 
191
187
  # Is the lock enabled for the given lock strategy?
@@ -39,7 +39,7 @@ module Devise
39
39
  module Rememberable
40
40
  extend ActiveSupport::Concern
41
41
 
42
- attr_accessor :remember_me
42
+ attr_accessor :remember_me, :extend_remember_period
43
43
 
44
44
  def self.required_fields(klass)
45
45
  [:remember_created_at]
@@ -48,7 +48,7 @@ module Devise
48
48
  # TODO: We were used to receive a extend period argument but we no longer do.
49
49
  # Remove this for Devise 4.0.
50
50
  def remember_me!(*)
51
- self.remember_token ||= self.class.remember_token if respond_to?(:remember_token)
51
+ self.remember_token = self.class.remember_token if respond_to?(:remember_token)
52
52
  self.remember_created_at ||= Time.now.utc
53
53
  save(validate: false) if self.changed?
54
54
  end
@@ -62,19 +62,10 @@ module Devise
62
62
  save(validate: false)
63
63
  end
64
64
 
65
- # Remember token should be expired if expiration time not overpass now.
66
- def remember_expired?
67
- remember_created_at.nil?
68
- end
69
-
70
65
  def remember_expires_at
71
66
  self.class.remember_for.from_now
72
67
  end
73
68
 
74
- def extend_remember_period
75
- self.class.extend_remember_period
76
- end
77
-
78
69
  def rememberable_value
79
70
  if respond_to?(:remember_token)
80
71
  remember_token
@@ -156,6 +147,9 @@ module Devise
156
147
  end
157
148
  end
158
149
 
150
+ private
151
+
152
+ # TODO: extend_remember_period is no longer used
159
153
  Devise::Models.config(self, :remember_for, :extend_remember_period, :rememberable_options, :expire_all_remember_me_on_sign_out)
160
154
  end
161
155
  end
@@ -1,99 +1,214 @@
1
1
  module Devise
2
- class BaseSanitizer
3
- attr_reader :params, :resource_name, :resource_class
2
+ # The +ParameterSanitizer+ deals with permitting specific parameters values
3
+ # for each +Devise+ scope in the application.
4
+ #
5
+ # The sanitizer knows about Devise default parameters (like +password+ and
6
+ # +password_confirmation+ for the `RegistrationsController`), and you can
7
+ # extend or change the permitted parameters list on your controllers.
8
+ #
9
+ # === Permitting new parameters
10
+ #
11
+ # You can add new parameters to the permitted list using the +permit+ method
12
+ # in a +before_action+ method, for instance.
13
+ #
14
+ # class ApplicationController < ActionController::Base
15
+ # before_action :configure_permitted_parameters, if: :devise_controller?
16
+ #
17
+ # protected
18
+ #
19
+ # def configure_permitted_parameters
20
+ # # Permit the `subscribe_newsletter` parameter along with the other
21
+ # # sign up parameters.
22
+ # devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
23
+ # end
24
+ # end
25
+ #
26
+ # Using a block yields an +ActionController::Parameters+ object so you can
27
+ # permit nested parameters and have more control over how the parameters are
28
+ # permitted in your controller.
29
+ #
30
+ # def configure_permitted_parameters
31
+ # devise_parameter_sanitizer.permit(:sign_up) do |user|
32
+ # user.permit(newsletter_preferences: [])
33
+ # end
34
+ # end
35
+ class ParameterSanitizer
36
+ DEFAULT_PERMITTED_ATTRIBUTES = {
37
+ sign_in: [:password, :remember_me],
38
+ sign_up: [:password, :password_confirmation],
39
+ account_update: [:password, :password_confirmation, :current_password]
40
+ }
4
41
 
5
42
  def initialize(resource_class, resource_name, params)
6
- @resource_class = resource_class
7
- @resource_name = resource_name
43
+ @auth_keys = extract_auth_keys(resource_class)
8
44
  @params = params
9
- @blocks = Hash.new
45
+ @resource_name = resource_name
46
+ @permitted = {}
47
+
48
+ DEFAULT_PERMITTED_ATTRIBUTES.each_pair do |action, keys|
49
+ permit(action, keys: keys)
50
+ end
10
51
  end
11
52
 
12
- def for(kind, &block)
13
- if block_given?
14
- @blocks[kind] = block
53
+ # Sanitize the parameters for a specific +action+.
54
+ #
55
+ # === Arguments
56
+ #
57
+ # * +action+ - A +Symbol+ with the action that the controller is
58
+ # performing, like +sign_up+, +sign_in+, etc.
59
+ #
60
+ # === Examples
61
+ #
62
+ # # Inside the `RegistrationsController#create` action.
63
+ # resource = build_resource(devise_parameter_sanitizer.sanitize(:sign_up))
64
+ # resource.save
65
+ #
66
+ # Returns an +ActiveSupport::HashWithIndifferentAccess+ with the permitted
67
+ # attributes.
68
+ def sanitize(action)
69
+ permissions = @permitted[action]
70
+
71
+ # DEPRECATED: Remove this branch on Devise 4.1.
72
+ if respond_to?(action, true)
73
+ deprecate_instance_method_sanitization(action)
74
+ return cast_to_hash send(action)
75
+ end
76
+
77
+ if permissions.respond_to?(:call)
78
+ cast_to_hash permissions.call(default_params)
79
+ elsif permissions.present?
80
+ cast_to_hash permit_keys(default_params, permissions)
15
81
  else
16
- default_for(kind)
82
+ unknown_action!(action)
17
83
  end
18
84
  end
19
85
 
20
- def sanitize(kind)
21
- if block = @blocks[kind]
22
- block.call(default_params)
86
+ # Add or remove new parameters to the permitted list of an +action+.
87
+ #
88
+ # === Arguments
89
+ #
90
+ # * +action+ - A +Symbol+ with the action that the controller is
91
+ # performing, like +sign_up+, +sign_in+, etc.
92
+ # * +keys:+ - An +Array+ of keys that also should be permitted.
93
+ # * +except:+ - An +Array+ of keys that shouldn't be permitted.
94
+ # * +block+ - A block that should be used to permit the action
95
+ # parameters instead of the +Array+ based approach. The block will be
96
+ # called with an +ActionController::Parameters+ instance.
97
+ #
98
+ # === Examples
99
+ #
100
+ # # Adding new parameters to be permitted in the `sign_up` action.
101
+ # devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
102
+ #
103
+ # # Removing the `password` parameter from the `account_update` action.
104
+ # devise_parameter_sanitizer.permit(:account_update, except: [:password])
105
+ #
106
+ # # Using the block form to completely override how we permit the
107
+ # # parameters for the `sign_up` action.
108
+ # devise_parameter_sanitizer.permit(:sign_up) do |user|
109
+ # user.permit(:email, :password, :password_confirmation)
110
+ # end
111
+ #
112
+ #
113
+ # Returns nothing.
114
+ def permit(action, keys: nil, except: nil, &block)
115
+ if block_given?
116
+ @permitted[action] = block
117
+ end
118
+
119
+ if keys.present?
120
+ @permitted[action] ||= @auth_keys.dup
121
+ @permitted[action].concat(keys)
122
+ end
123
+
124
+ if except.present?
125
+ @permitted[action] ||= @auth_keys.dup
126
+ @permitted[action] = @permitted[action] - except
127
+ end
128
+ end
129
+
130
+ # DEPRECATED: Remove this method on Devise 4.1.
131
+ def for(action, &block) # :nodoc:
132
+ if block_given?
133
+ deprecate_for_with_block(action)
134
+ permit(action, &block)
23
135
  else
24
- default_sanitize(kind)
136
+ deprecate_for_without_block(action)
137
+ @permitted[action] or unknown_action!(action)
25
138
  end
26
139
  end
27
140
 
28
141
  private
29
142
 
30
- def default_for(kind)
31
- raise ArgumentError, "a block is expected in Devise base sanitizer"
32
- end
33
-
34
- def default_sanitize(kind)
35
- default_params
143
+ # Cast a sanitized +ActionController::Parameters+ to a +HashWithIndifferentAccess+
144
+ # that can be used elsewhere.
145
+ #
146
+ # Returns an +ActiveSupport::HashWithIndifferentAccess+.
147
+ def cast_to_hash(params)
148
+ # TODO: Remove the `with_indifferent_access` method call when we only support Rails 5+.
149
+ params && params.to_h.with_indifferent_access
36
150
  end
37
151
 
38
152
  def default_params
39
- params.fetch(resource_name, {})
153
+ @params.fetch(@resource_name, {})
40
154
  end
41
- end
42
155
 
43
- class ParameterSanitizer < BaseSanitizer
44
- def initialize(*)
45
- super
46
- @permitted = Hash.new { |h,k| h[k] = attributes_for(k) }
156
+ def permit_keys(parameters, keys)
157
+ parameters.permit(*keys)
47
158
  end
48
159
 
49
- def sign_in
50
- permit self.for(:sign_in)
51
- end
160
+ def extract_auth_keys(klass)
161
+ auth_keys = klass.authentication_keys
52
162
 
53
- def sign_up
54
- permit self.for(:sign_up)
163
+ auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys
55
164
  end
56
165
 
57
- def account_update
58
- permit self.for(:account_update)
166
+ def unknown_action!(action)
167
+ raise NotImplementedError, <<-MESSAGE.strip_heredoc
168
+ "Devise doesn't know how to sanitize parameters for '#{action}'".
169
+ If you want to define a new set of parameters to be sanitized use the
170
+ `permit` method first:
171
+
172
+ devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, param2, param3])
173
+ MESSAGE
59
174
  end
60
175
 
61
- private
176
+ def deprecate_for_with_block(action)
177
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
178
+ [Devise] Changing the sanitized parameters through "#{self.class.name}#for(#{action}) is deprecated and it will be removed from Devise 4.1.
179
+ Please use the `permit` method:
62
180
 
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))
181
+ devise_parameter_sanitizer.permit(:#{action}) do |user|
182
+ # Your block here.
183
+ end
184
+ MESSAGE
67
185
  end
68
186
 
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
187
+ def deprecate_for_without_block(action)
188
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
189
+ [Devise] Changing the sanitized parameters through "#{self.class.name}#for(#{action}) is deprecated and it will be removed from Devise 4.1.
190
+ Please use the `permit` method to add or remove any key:
74
191
 
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
81
- end
192
+ To add any new key, use the `keys` keyword argument:
193
+ devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
82
194
 
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
195
+ To remove any existing key, use the `except` keyword argument:
196
+ devise_parameter_sanitizer.permit(:#{action}, except: [:email])
197
+ MESSAGE
92
198
  end
93
199
 
94
- def auth_keys
95
- @auth_keys ||= @resource_class.authentication_keys.respond_to?(:keys) ?
96
- @resource_class.authentication_keys.keys : @resource_class.authentication_keys
200
+ def deprecate_instance_method_sanitization(action)
201
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
202
+ [Devise] Parameter sanitization through a "#{self.class.name}##{action}" method is deprecated and it will be removed from Devise 4.1.
203
+ Please use the `permit` method on your sanitizer `initialize` method.
204
+
205
+ class #{self.class.name} < Devise::ParameterSanitizer
206
+ def initialize(*)
207
+ super
208
+ permit(:#{action}, keys: [:param1, :param2, :param3])
209
+ end
210
+ end
211
+ MESSAGE
97
212
  end
98
213
  end
99
214
  end