Devise: update_with_password does NOT apply password presence/length validation

Created on 27 Mar 2013  Â·  8Comments  Â·  Source: heartcombo/devise

Devise validates password presence and minimum password length (8 chars) when creating a new user registration.

However, it does not apply these validations when using update_with_password() and the password is an empty string.

Ex: Devise will permit the following update:

user.update_with_password({
  current_password:      'some_old_password',
  password:              '',
  password_confirmation: ''
});
>> ok

but wont permit:

user.update_with_password({
  current_password:      'some_old_password',
  password:              'abc',
  password_confirmation: 'abc'
});
>> validation error "password is too short (minimum 8 characters)"

(user model has :validatable applied)

Most helpful comment

@mlilley I had the same problem and did the following to fix it:

def update_password
  @user = current_user
  # Enforce validation of the new password if it's blank and current password is correct
  params[:user][:password] = params[:user][:current_password] if params[:user][:password].blank? && @user.valid_password?(params[:user][:current_password])
  if @user.update_with_password(params[:user])
    # Sign in the user by passing validation in case his password changed
    sign_in @user, bypass: true
    redirect_to edit_user_path(@user), notice: t('.password_updated')
  else
    @user.errors[:password] << t('errors.messages.blank') if params[:user][:password].blank?
    render 'devise/registrations/edit'
  end
end

All 8 comments

I believe this is intended behavior. If you leave your password blank on
the update form it is intended to signal that you didn't want to change it,
not that you wanted to update it to blank.
On Mar 26, 2013 10:57 PM, "mlilley" [email protected] wrote:

Devise validates password presence and minimum password length (8 chars)
when creating a new user registration.

However, it does not apply these validations when using
update_with_password() and the password is an empty string.

Ex: Devise will permit the following update:

user.update_with_password({
current_password: 'some_old_password',
password: '',
password_confirmation: ''
});

ok

but wont permit:

user.update_with_password({
current_password: 'some_old_password',
password: 'abc',
password_confirmation: 'abc'
});

validation error "password is too short (minimum 8 characters)"

—
Reply to this email directly or view it on GitHubhttps://github.com/plataformatec/devise/issues/2349
.

Exactly.

Okay, so this behaviour is appropriate for situations in which you have a form for editting user details beyond just the password (so clicking update with blank password field doesn't change the password).

Solution 3 in the Allow Users to edit their password How To presents a method who's purpose is to ONLY edit a users password (by providing a form with only password and password confirmation fields). It does not mention this behaviour, or how to configure devise such that it will not permit a blank password. The end result being a rather confusing apparent bug.

So, can this behaviour be configured when calling update_with_password(), or what should one do to ensure the presence validation is applied?

Maybe a note about this in the linked documentation would be a good way to solve this issue.

There is no option to enforce the password to be presence validated on update_with_password.
The wiki is maintained by the community, so inconsistencies may appear over time. We'd love if you could update it so it becomes more consistent :)

@mlilley I had the same problem and did the following to fix it:

def update_password
  @user = current_user
  # Enforce validation of the new password if it's blank and current password is correct
  params[:user][:password] = params[:user][:current_password] if params[:user][:password].blank? && @user.valid_password?(params[:user][:current_password])
  if @user.update_with_password(params[:user])
    # Sign in the user by passing validation in case his password changed
    sign_in @user, bypass: true
    redirect_to edit_user_path(@user), notice: t('.password_updated')
  else
    @user.errors[:password] << t('errors.messages.blank') if params[:user][:password].blank?
    render 'devise/registrations/edit'
  end
end

@HatemMahmoud's solution worked for me. Thanks!

I have the same problem .. Could you tell me which file you added this code to? @HatemMahmoud

@HatemMahmoud is following instructions from https://github.com/heartcombo/devise/wiki/How-To:-Allow-users-to-edit-their-password

Was this page helpful?
0 / 5 - 0 ratings