2

There are numerous questions (ie: here and here) that address this issue (and were useful to others with the same problem), but none of them have worked yet for me.

Using Rails 5.0.0 and Devise 4.2, ultimately I am trying to allow admins to edit other users, and to allow regular users to edit their own accounts. This required a few modifications, since by default Devise doesn't let the logged-in user edit other users.

The form in the users/:id/edit view now populates with the correct user, BUT the update fails, with Unpermitted parameter: current_password in the logs. I believe that I need to whitelist :current_password, but none of the suggestions accomplish this for me.

routes.rb

devise_for :users, controllers: {registrations: 'registrations'}, path_prefix: 'my'
resources :users

(The path_prefix "my" was suggested as a way to avoid route conflicts between Devise and the :users resource.)

registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController
  before_action :configure_permitted_parameters, if: :devise_controller?


  ...

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) do |u|
      u.permit(:password, :password_confirmation)
    end

    devise_parameter_sanitizer.for(:account_update) do |u|
      u.permit(:password, :password_confirmation, :current_password)
    end
  end
end

users_controller.rb

class UsersController < ApplicationController
  before_action :set_user, only: [:edit, :show, :update, :destroy]

  ...

  def edit
  end


  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      redirect_to cohorts_path
    else
      render 'edit'
    end
  end

  private

  def set_user
    @user = User.find(params[:id])
  end

  def user_params
    params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :roles, :nickname, :location, :headshot, :goals)

  end
end

You might be wondering why I didn't add :current_password to the user_params. Doing so results in an unknown attribute 'current_password' for User. error. (Adding the suggested attr_accessor didn't help.)

This is the first time I've needed to customize Devise. Any help is appreciated!

  • What do you get when you type `User.column_names` in your console? – Md. Farhan Memon Jun 10 '17 at 03:27
  • => ["id", "email", "encrypted_password", "reset_password_token", "reset_password_sent_at", "remember_created_at", "sign_in_count", "current_sign_in_at", "last_sign_in_at", "current_sign_in_ip", "last_sign_in_ip", "created_at", "updated_at", "roles", "first_name", "last_name", "current_cohort", "nickname", "location", "goals", "headshot"] Does current_password need to be a member of that list? I guess I thought it was kind of a "pseudo" parameter. – Jonathan Dueck Jun 10 '17 at 03:55
  • @JonathanDueck - No you definitely don't need to include `current_password` in the list. Devise exposes this parameter exclusively for user's account update action. – 31piy Jun 10 '17 at 05:24
  • Are you sure adding `attr_accessor :current_password` to `user.rb` model didn't solve the problem while having it in the `user_params`? – Pavan Jun 10 '17 at 09:31
  • It fails silently. the server log shows the PATCH to 'users/1`, it shows the params including "current_password"=>"[FILTERED]", the SQL queries (IE: "SELECT "users".* FROM "users" WHERE...", a BEGIN, a ROLLBACK, and it concludes by re-rendering the edit form. – Jonathan Dueck Jun 10 '17 at 15:44
  • why don't you use the user_registration method provided by devise to change the password – Othmane El Kesri Jun 14 '17 at 01:23
  • @ Othmane Hi. Changing the password isn't a problem. (I was having a problem with the parameter "current_password"), but the problem is with editing the user. – Jonathan Dueck Jun 14 '17 at 15:01

2 Answers2

0

Add it in UsersController ->>> user_params function ->>> in the permit, I think you should add it in permit ...

def user_params
    params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :roles, :nickname, :location, :headshot, :goals, :current_password) <<<< THERE

  end
Ronan Louarn
  • 472
  • 1
  • 6
  • 27
  • I confirm that I have attr_accessor :current_password in User.rb, and that :current_password has been permitted in user_params in the UsersController. I get BEGIN and ROLLBACK, with no error message to indicate why the update doesn't occur. – Jonathan Dueck Jun 11 '17 at 16:19
  • Have you generate devise registration controller with this command? rails generate devise:controllers users – Ronan Louarn Jun 11 '17 at 18:14
  • I wrote the UsersController and RegistrationsController manually. (I hadn't been aware that you can generate Devise controller(s) in the manner you suggest.) – Jonathan Dueck Jun 11 '17 at 18:59
  • Yes you can and it is recommended with devise. Because devise's controllers are in a spacename 'users'. Maybe you should add a folder named 'users' in controllers folder, and put your registration controller in him. After that add 'Users::' in registration controller. Like that: 'class Users::RegistrationsController < Devise::RegistrationsController' – Ronan Louarn Jun 12 '17 at 11:21
  • I implemented this suggestion and the result is unchanged; BEGIN and ROLLBACK without an error message. I have noticed in "pry" that when I look at the params, "permitted:false". But when I look at the user_params, "permitted: true". Since the user_params are what get passed to the update action, and they are supposedly permitted, does that point out a direction for solving this? Maybe an issue with the devise parameter sanitizer? Not sure at this point. – Jonathan Dueck Jun 14 '17 at 15:43
  • Did you add the 'simple' users_controller just for redirect to cohorts_path? – Ronan Louarn Jun 15 '17 at 07:12
0

Finally solved this. I added the following to the update action of my UsersController:

if params[:user][:password].blank? && params[:user[:password_confirmation].blank?
    params[:user].delete(:password)
    params[:user].delete(:password_confirmation)
end

Since it was failing silently, the following was also helpful in diagnosing the update action:

    Rails.logger.info(@your_object.errors.inspect) 

Thanks all! Pleased to have this resolved.