Design: request a password only for certain situations

I am developing an application that uses Rails and Devise to authenticate users. I wonder if there is a way to set a password for only some changes.

For example, I want a password to be requested when:

  • Delete account
  • change Password

And I want the user to be able to freely edit other fields without any password, for example:

  • Name
  • Username
  • Avatar

So, I would like to exchange these two methods. How can i solve this?

EDIT:

I found this in the Devise documentation and it works great, it allows me to change my password and email if I enter a password:

def update @user = User.find(current_user.id) successfully_updated = if needs_password?(@user, params) @user.update_with_password(params[:user]) else # remove the virtual current_password attribute update_without_password # doesn't know how to ignore it params[:user].delete(:current_password) @user.update_without_password(params[:user]) end if successfully_updated set_flash_message :notice, :updated # Sign in the user bypassing validation in case his password changed sign_in @user, :bypass => true redirect_to after_update_path_for(@user) else render "edit" end end private # check if we need password to update user data # ie if password or email was changed # extend this as needed def needs_password?(user, params) user.email != params[:user][:email] || !params[:user][:password].blank? #HERE end 

Now, what can I add to #HERE to also require a password when deleting an account?

+6
source share
3 answers

due to editing the question:

 def destroy if current_user.valid_password?(params[:user][:password]) current_user.destroy else render "destroy" # or what ever end end 
+3
source

You can create a form_tag redirect to an action in your controller.

 <%= form_tag url_for(:controller => :users, :action => :destroy), :method => :get do %> <%= label_tag(:password, "Enter password before deleting") %> <%= password_field_tag :password %> <%= submit_tag "Delete User With Confirmation" %> <% end %> 

The action in your UserController will look something like this:

 def destroy if current_user.authenticate(params[:password]) #do something else #do something end end 
0
source

Devise has a destroy_with_password method (at least since version 3.5.2). It is located in lib/devise/models/database_authenticatable.rb and is called

 destroy_with_password(current_password) 

It destroys the entry if current_password matches, and returns false otherwise.

0
source

All Articles