doctororange
doctororange

Reputation: 11810

changing password with authlogic - validation not catching blank inputs

I am trying to create a form to allow users to change their password:

View:

- form_tag change_password_users_path do

  = error_messages_for :user, :header_message => "Please Try Again", :message => "We had some problems updating your account" 
  %br

  = label_tag :password, "New password:"
  = password_field_tag "password"
  %br

  = label_tag :password_confirmation, "NConfirm new password:"
  = password_field_tag "password_confirmation"
  %br

  = submit_tag "Update Account"

Controller:

def change_password
  @user = current_user
  if request.post?
    @user.password = params[:password]
    @user.password_confirmation = params[:password_confirmation]
    if @user.save
      redirect_to user_path(current_user)
    else
      render :action => "change_password"
    end        
  end
end

Authlogic is catching validation errors when the password is 'too short' or the password doesn't match the confirmation, but doesn't do anything when the form is submitted with both fields blank. @user.save must be returning true, because I am redirected to 'user_path(current_user)'.

The password is not actually changed in the database.

Thanks for your help.

Upvotes: 4

Views: 4747

Answers (4)

temochka
temochka

Reputation: 436

Another way to do it is to exploit ActiveModel validation contexts. You will need to add a context-dependent validation to your User model:

validates :password, # :password_confirmation,
          :presence => {:message => 'Please enter your new password.'},
          :on => :reset_password

Then, in the controller it will be just:

def change_password
  @user = current_user
  if request.post?
    @user.password = params[:password]
    @user.password_confirmation = params[:password_confirmation]
    if @user.save(:context => :reset_password)
      redirect_to user_path(current_user)
    else
      render :action => "change_password"
    end        
  end
end

Hope it will suite ones who were not satisfied with other suggested solutions.

Upvotes: 0

Jimmy Huang
Jimmy Huang

Reputation: 4312

I think you should also provide the params[:user][:current_password], otherwise you can not save the @user. And when I tested, I found the current_user will be lost after changing password, so you need update usersession.

Add a 'current_password' accessor to your user model

class User < ActiveRecord::Base   
  act_as_authentic   
  attr_accessor :current_password 
end

In the user controller

def change_password
  @user = current_user
  if @user.valid_password? params[:user][:current_password]
    @user.password = params[:user][:password]
    @user.password_confirmation = params[:user][:password_confirmation]
    if @user.changed? && @user.save
      UserSession.create(:login => @user.login, :password => params[:user][:password])
      redirect_to user_path(current_user)
    else
      render :action => "change_password"
    end
  end
end

Upvotes: 3

caike
caike

Reputation: 9849

I suggest you call @user.changed? like the following example to check for blank passwords:

def change_password
  @user = current_user
  if request.post?
    @user.password = params[:user][:password]
    @user.password_confirmation = params[:user][:password_confirmation]
    if @user.changed? && @user.save
      redirect_to user_path(current_user)
    else
      render :action => "change_password"
    end
  end
end

Upvotes: 1

doctororange
doctororange

Reputation: 11810

Apparently this is the intended behavior.

http://www.ruby-forum.com/topic/198836

At least I know now...

Thanks.

Upvotes: 1

Related Questions