I current use Rails 4 and I move the app from attr_accessible
to the StrongParams. So, I have customised Devise controller:
class UsersController < Devise::RegistrationsController
load_and_authorize_resource
#...
def update
unless @user.userable?
if params[:selected_person_type] == I18n::t('activerecord.attributes.user.individual')
redirect_to new_individual_path and return
elsif params[:selected_person_type] == I18n::t('activerecord.attributes.user.legal_entity')
redirect_to new_legal_entity_path and return
end
end
@avatar = params[:avatar_id].present? ? Avatar.find_by(id: params[:avatar_id]) : @user.avatar
if params[:user][:password].blank?
if @user.update_without_password(user_params)
notice = if @user.unconfirmed_email.present? && Date.today == @user.confirmation_sent_at.to_date
t('devise.confirmations.send_instructions')
else
t('views.messages.notices.personal_data_updated')
end
redirect_to edit_user_path(@user), notice: notice and return
end
else
if @user.valid_password?(params[:user][:current_password])
params[:user].delete("current_password")
if @user.update_attributes(user_params) && @user.save
sign_in(@user, bypass: true)
redirect_to edit_user_path(@user), notice: t('views.messages.notices.personal_data_updated') and return
end
else
@user.errors.add(:current_password, :invalid)
end
end
render action: "edit"
end
def create
if resource.save
SystemMailer.send_mail(to: resource.email, body: resource.temp_password, subject: I18n.t('mailers.password.new')).deliver if resource.generate_password == '1'
if request.xhr?
expire_data_after_sign_in!
respond_to do |format|
format.js
end
else
super
end
else
if request.xhr?
clean_up_passwords(resource)
respond_to do |format|
format.js
end
else
super
end
end
end
private
def user_params
if current_user.present?
params.require(:user).permit(:fullname, :about, :username, :email, :current_password, :password, :password_confirmation)
end
end
end
I got the error before:
Failure/Error: post :create, user: attributes_for(:unconfirmed_user)
ActiveModel::ForbiddenAttributesError:
ActiveModel::ForbiddenAttributesError
This is because CanCan isn't so compatible with StrongParams, so i tried this fix in ApplicationController:
class ApplicationController < ActionController::Base
include SimpleCaptcha::ControllerHelpers
include CaptchaHelper
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :cancan_workaround
rescue_from CanCan::AccessDenied do |e|
redirect_to '/', flash: { error: I18n.t('views.messages.notices.access_denied') }
end
private
def cancan_workaround
resource = controller_name.singularize.to_sym
method = "#{resource}_params"
params[resource] &&= send(method) if respond_to?(method, true)
end
end
After that fix i got that error:
UsersController should successfully create user
Failure/Error: post :create, user: attributes_for(:unconfirmed_user)
NoMethodError:
undefined method `permit' for nil:NilClass
# ./app/controllers/users_controller.rb:75:in 'create'
# ./spec/controllers/users_controller_spec.rb:10:in `block (3 levels) in <top (required)>'
# ./spec/controllers/users_controller_spec.rb:9:in `block (2 levels) in <top (required)>'
Here is ./app/controllers/users_controller.rb:75:in 'create'
is super
call in the action. Any idea how to fix that?
Devise
Devise doesn't work like other Rails input systems - it uses its own backend functionality to process the params. It seems devise automatically permits the email
& password
params, and its your job to add the other params its parameter_sanitizer
Bottom line is that, according to the Devise documentation , you'll have to use something like this:
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :username
end
end
Ok, i got it. Problem was not in Devise, it was with my permissions:
private
def user_params
if current_user.present?
params.require(:user).permit(:fullname, :about, :username, :email, :current_password, :password, :password_confirmation)
end
end
Test evaluated for non-signed user, so when cancan's hook tried to execute this method:
params[resource] &&= send(method) if respond_to?(method, true)
It received nil, because user wasn't signed-in, so hook transformed :user => { ... }
into the :user => nil
. So, i fixed it via removing current_user.present?
.
private
def user_params
params.require(:user).permit(:fullname, :about, :username, :email, :current_password, :password, :password_confirmation)
end
Not sure how well this solution is secure.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.