[Rails] Change password

Mohit Sindhwani
Tue, 15 Aug 2006 02:11:14 -0000

Hi Jim,

Jim Lindley wrote:
> In the controller:
>
> def change_password
>     @user = User.find(session[:user])
>     if request.post? && @user.update_attributes(params[:user])
>       flash[:notice] = "Successfully updated your password."
>       redirect_to home_url && return
>     else
>       flash[:notice] = "There was a problem, please check for errors
> and try again."
>    end
> end
>
> In the view:
> ** snip **
> You''ll need to tweak validations a bit to get everything to work.
If
> you are validating the presence of other attributes on save,
you''ll
> need to add them in before saving.
>
> The reasoning for having a password= method is that there is no
> underlying field in the database for ActiveRecord to automatically
> create methods for. The password attribute has to be set up manually.
>
> You use the writer just as you''d assign a value to a
model''s other fields.
>
> def password
>   @password
> end
>
> def password=(pass)
>   @password = pass
> end
>
> User.password = ''secret'' # this line will invoke
password> pass = User.password    # this line will invoke password
>
> What problems are you running into that you have to recreate different
> methods to update? You didn''t give any specifics on the problems
that
> you are having, you just gave them for your work-arounds.
>
>
Hi Jim,

Thanks a lot for the detailed reply!  It was not that I was having any
errors, it''s just that I did not know that I got use this directly:
    if request.post? && @user.update_attributes(params[:user])

That was one problem.  Also, I think I may have made the problem more
complex by:
1. Requiring the user to enter his username & current password before
changing the password.  Then, I had to check if some other iser was
logged in.
2. Allowing the change password page to be accessed directly even if a
user was not logged in - I could use ''before_filter'' to find
this and
get the user to sign in and then direct him to the change pwd page.
But, that would take him to a page where he would need to enter his
username/ password again - that seemed a bit silly.

As a result, what I had was a large number of is statements to take care
of the conditions.  Anyway, this is what I had got to, but I think I can
fix the view to take inputs for :user and then use the update_attributes
as you have shown.  My (not so elegant) code was as follows:

  def ch_pwd
    if request.post?
      if session[:user_id]
         u2 = User.find(session[:user_id])
      end
      user = User.authenticate(params[:username], params[:pwd])
      #so, we have the user, now to update the password
      if (u2 && (u2.id == user.id)) || u2.nil?
          if user
            if params[:password] == params[:password_confirmation]
              hash_password = Digest::SHA256.hexdigest(params[:password]
+ user.password_salt)
              user.update_attribute(:password_hash,hash_password)
              flash[:notice] = "Password changed successfully"
            else
              flash[:notice] = "Password & Confirmation do not
match"
            end
          else
            flash[:notice] = "Invalid user/password combination"
          end
      else
          flash[:notice] = "You cannot change another user''s
password"
      end
    end
  end


Cheers
Mohit.