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?
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.