Rails dealing with blank params at controller level

Posted by stephenmurdoch on Stack Overflow See other posts from Stack Overflow or by stephenmurdoch
Published on 2012-10-25T04:58:41Z Indexed on 2012/10/25 5:00 UTC
Read the original article Hit count: 171

Filed under:

I have a User model:

class User < ActiveRecord::Base
  has_secure_password
  # validation lets users update accounts without entering password
  validates :password, presence: { on: :create }, allow_blank: { on: :update }
  validates :password_confirmation, presence: { if: :password_digest_changed? }
end

I also have a password_reset_controller:

def update
  # this is emailed to the user by the create action - not shown
  @user=User.find_by_password_reset_token!(params[:id])

  if @user.update_attributes(params[:user])
    # user is signed in if password and confirmation pass validations
    sign_in @user
    redirect_to root_url, :notice => "Password has been reset."
  else
    flash.now[:error] = "Something went wrong, please try again."
    render :edit
  end
end

Can you see the problem here? A user can submit a blank a password/confirmation and rails will sign them in, because the User model allows blank on update.

It's not a security concern, since an attacker would still need access to a user's email account before they could get anywhere near this action, but my problem is that a user submitting 6 blank chars would be signed in, and their password would not be changed for them, which could lead to confusion later on.

So, I've come up with the following solution, and I'd like to check if there's a better way of doing it, before I push to production:

def update
  @user=User.find_by_password_reset_token!(params[:id])

  # if user submits blank password, add an error, and render edit action     
  if params[:user][:password].blank?
    @user.errors.add(:password_digest, "can't be blank.")
    render :edit
  elsif @user.update_attributes(params[:user])
    sign_in @user
    redirect_to root_url, :notice => "Password has been reset."
  else
    flash.now[:error] = "Something went wrong, please try again."
    render :edit
  end
end

Should I be checking for nil as well as blank? Are there any rails patterns or idiomatic ruby techniques for solving this?

[Fwiw, I've got required: true on the html inputs, but want this handled server side too.]

© Stack Overflow or respective owner

Related posts about ruby-on-rails