Fran Barros
Fran Barros

Reputation: 307

Devise: ask password only for certain situations

I'm developing an app using Rails and Devise for user's authentication. I wonder if there is a way to ask the password only for some changes.

For instance, I want the password to be asked when:

And I want the user to be free to edit other fields without any password, such as:

So, I'd like a way to swap between this two methods. How can I solve this?

EDIT:

In Devise's documentation I found this and it works fine, it only allows changing password and email if I enter the 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 could i put in #HERE to also require the password when I'm deleting the account?

Upvotes: 6

Views: 2062

Answers (3)

littleforest
littleforest

Reputation: 2245

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

destroy_with_password(current_password)

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

Upvotes: 0

ted
ted

Reputation: 5329

due to question edit:

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

Upvotes: 3

Zippie
Zippie

Reputation: 6088

You could create a form_tag redirecting to a 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 UsersController would be something like:

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

Upvotes: 0

Related Questions