mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
Add support for Rails 4 strong_parameters
This brings support for Rails 4 StrongParameters changes. - Parameter sanitizing is setup for Devise controllers via resource_params except Omniauth Callbacks which doesn't use resource_params. - Change #build_resource to not call resource_params for get requests. Parameter sanitizing is only needed when params are posted to the server so there's no need to try to construct resource params on get requests (new, edit).
This commit is contained in:
parent
af4a582300
commit
78f137368c
7 changed files with 153 additions and 14 deletions
|
@ -39,5 +39,4 @@ class Devise::ConfirmationsController < DeviseController
|
|||
def after_confirmation_path_for(resource_name, resource)
|
||||
after_sign_in_path_for(resource)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -83,7 +83,11 @@ class Devise::RegistrationsController < DeviseController
|
|||
# Build a devise resource passing in the session. Useful to move
|
||||
# temporary session data to the newly created user.
|
||||
def build_resource(hash=nil)
|
||||
hash ||= resource_params || {}
|
||||
if request.get?
|
||||
hash ||= {}
|
||||
else
|
||||
hash ||= resource_params || {}
|
||||
end
|
||||
self.resource = resource_class.new_with_session(hash, session)
|
||||
end
|
||||
|
||||
|
|
|
@ -40,5 +40,4 @@ class Devise::UnlocksController < DeviseController
|
|||
def after_unlock_path_for(resource)
|
||||
new_session_path(resource)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -28,10 +28,6 @@ class DeviseController < Devise.parent_controller.constantize
|
|||
devise_mapping.to
|
||||
end
|
||||
|
||||
def resource_params
|
||||
params[resource_name]
|
||||
end
|
||||
|
||||
# Returns a signed in resource from session (if one exists)
|
||||
def signed_in_resource
|
||||
warden.authenticate(:scope => resource_name)
|
||||
|
@ -96,7 +92,13 @@ MESSAGE
|
|||
# Build a devise resource.
|
||||
# Assignment bypasses attribute protection when :unsafe option is passed
|
||||
def build_resource(hash = nil, options = {})
|
||||
hash ||= resource_params || {}
|
||||
# When building a resource, invoke strong_parameters require/permit
|
||||
# steps if the params hash includes the resource name.
|
||||
if params[resource_name]
|
||||
hash ||= resource_params || {}
|
||||
else
|
||||
hash ||= {}
|
||||
end
|
||||
|
||||
if options[:unsafe]
|
||||
self.resource = resource_class.new.tap do |resource|
|
||||
|
@ -181,4 +183,21 @@ MESSAGE
|
|||
format.any(*navigational_formats, &block)
|
||||
end
|
||||
end
|
||||
|
||||
# Setup a param sanitizer to filter parameters using strong_parameters. See
|
||||
# lib/devise/controllers/parameter_sanitizer.rb for more info. Override this
|
||||
# method in your application controller to use your own parameter sanitizer.
|
||||
def parameters_sanitizer
|
||||
@parameters_sanitizer ||= Devise::ParameterSanitizer.new
|
||||
end
|
||||
|
||||
# Return the params to be used for mass assignment passed through the
|
||||
# strong_parameters require/permit step. To customize the parameters
|
||||
# permitted for a specific controller, simply prepend a before_filter and
|
||||
# call #permit_devise_param or #remove_permitted_devise_param on
|
||||
# parameters_sanitizer to update the default allowed lists of permitted
|
||||
# parameters.
|
||||
def resource_params
|
||||
params.require(resource_name).permit(parameters_sanitizer.permitted_params_for(controller_name))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,12 +6,13 @@ require 'set'
|
|||
require 'securerandom'
|
||||
|
||||
module Devise
|
||||
autoload :Delegator, 'devise/delegator'
|
||||
autoload :FailureApp, 'devise/failure_app'
|
||||
autoload :OmniAuth, 'devise/omniauth'
|
||||
autoload :ParamFilter, 'devise/param_filter'
|
||||
autoload :TestHelpers, 'devise/test_helpers'
|
||||
autoload :TimeInflector, 'devise/time_inflector'
|
||||
autoload :Delegator, 'devise/delegator'
|
||||
autoload :FailureApp, 'devise/failure_app'
|
||||
autoload :OmniAuth, 'devise/omniauth'
|
||||
autoload :ParamFilter, 'devise/param_filter'
|
||||
autoload :ParameterSanitizer, 'devise/parameter_sanitizer'
|
||||
autoload :TestHelpers, 'devise/test_helpers'
|
||||
autoload :TimeInflector, 'devise/time_inflector'
|
||||
|
||||
module Controllers
|
||||
autoload :Helpers, 'devise/controllers/helpers'
|
||||
|
|
65
lib/devise/parameter_sanitizer.rb
Normal file
65
lib/devise/parameter_sanitizer.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
module Devise
|
||||
class ParameterSanitizer
|
||||
attr_reader :allowed_params
|
||||
|
||||
# Return a list of parameter names permitted to be mass-assigned for the
|
||||
# passed controller.
|
||||
def permitted_params_for(controller_name)
|
||||
allowed_params.fetch(key_for_controller_name(controller_name), [])
|
||||
end
|
||||
|
||||
# Set up a new parameter sanitizer with a set of allowed parameters. This
|
||||
# gets initialized on each request so that parameters may be augmented or
|
||||
# changed as needed via before_filter.
|
||||
def initialize
|
||||
@allowed_params = {
|
||||
:confirmations_controller => [:email],
|
||||
:passwords_controller => authentication_keys + [:password, :password_confirmation, :reset_password_token],
|
||||
:registrations_controller => authentication_keys + [:password, :password_confirmation, :current_password],
|
||||
:sessions_controller => authentication_keys + [:password],
|
||||
:unlocks_controller => [:email]
|
||||
}
|
||||
end
|
||||
|
||||
# Allow additional parameters for a Devise controller. If the
|
||||
# controller_name doesn't exist in allowed_params, it will be added to it
|
||||
# as an empty array and param_name will be appended to that array. Note
|
||||
# that when adding a new controller, use the full controller name
|
||||
# (:confirmations_controller) and not the short names
|
||||
# (:confirmation/:confirmations).
|
||||
def permit_devise_param(controller_name, param_name)
|
||||
@allowed_params[key_for_controller_name(controller_name)] << param_name
|
||||
true
|
||||
end
|
||||
|
||||
# Remove specific allowed parameter for a Devise controller. If the
|
||||
# controller_name doesn't exist in allowed_params, it will be added to it
|
||||
# as an empty array.
|
||||
def remove_permitted_devise_param(controller_name, param_name)
|
||||
@allowed_params[key_for_controller_name(controller_name)].delete(param_name)
|
||||
true
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def authentication_keys
|
||||
Array(::Devise.authentication_keys)
|
||||
end
|
||||
|
||||
# Flexibly allow access to permitting/denying/checking parameters by
|
||||
# controller name in the following key formats: :confirmations_controller,
|
||||
# :confirmations, :confirmation
|
||||
def key_for_controller_name(name)
|
||||
if allowed_params.has_key?(name.to_sym)
|
||||
name.to_sym
|
||||
elsif allowed_params.has_key?(:"#{name}s_controller")
|
||||
:"#{name}s_controller"
|
||||
elsif allowed_params.has_key?(:"#{name}_controller")
|
||||
:"#{name}_controller"
|
||||
else
|
||||
@allowed_params[name.to_sym] = []
|
||||
name.to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
52
test/parameter_sanitizer_test.rb
Normal file
52
test/parameter_sanitizer_test.rb
Normal file
|
@ -0,0 +1,52 @@
|
|||
require 'test_helper'
|
||||
|
||||
class ParameterSanitizerTest < ActiveSupport::TestCase
|
||||
def sanitizer
|
||||
Devise::ParameterSanitizer.new
|
||||
end
|
||||
|
||||
test '#permitted_params_for allows querying of allowed parameters by controller' do
|
||||
assert_equal [:email], sanitizer.permitted_params_for(:confirmations_controller)
|
||||
assert_equal [:email, :password, :password_confirmation, :reset_password_token], sanitizer.permitted_params_for(:password)
|
||||
assert_equal [:email], sanitizer.permitted_params_for(:unlocks)
|
||||
end
|
||||
|
||||
test '#permitted_params_for returns an empty array for a bad key' do
|
||||
assert_equal [], sanitizer.permitted_params_for(:bad_key)
|
||||
end
|
||||
|
||||
test '#permit_devise_param allows adding an allowed param for a specific controller' do
|
||||
subject = sanitizer
|
||||
|
||||
subject.permit_devise_param(:confirmations_controller, :other)
|
||||
|
||||
assert_equal [:email, :other], subject.permitted_params_for(:confirmations_controller)
|
||||
end
|
||||
|
||||
test '#remove_permitted_devise_param allows disallowing a param for a specific controller' do
|
||||
subject = sanitizer
|
||||
|
||||
subject.remove_permitted_devise_param(:confirmations_controller, :email)
|
||||
|
||||
assert_equal [], subject.permitted_params_for(:confirmations_controller)
|
||||
end
|
||||
|
||||
test '#permit_devise_param allows adding additional devise controllers' do
|
||||
subject = sanitizer
|
||||
|
||||
subject.permit_devise_param(:invitations_controller, :email)
|
||||
|
||||
assert_equal [:email], subject.permitted_params_for(:invitations)
|
||||
end
|
||||
|
||||
test '#remove_permitted_devise_param fails gracefully when removing a missing param' do
|
||||
subject = sanitizer
|
||||
|
||||
# perform twice, just to be sure it handles it gracefully
|
||||
subject.remove_permitted_devise_param(:invitations_controller, :email)
|
||||
subject.remove_permitted_devise_param(:invitations_controller, :email)
|
||||
|
||||
assert_equal [], subject.permitted_params_for(:invitations)
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in a new issue