Change password

Is there an addition to the Rails Recipe or the method in AWDWR to allow
a user to change his/ her password? I have put something together that
does all the work again - mostly because I’m not sure how to leverage on
methods like ‘password=’ that are defined in the model. Has anyone got
a ready sample that I could learn from?

Right now, I’m basically examining the parameters from the form POST to
find the user, verify his current password is correct. Then, I manually
confirm that the new password and password_confirmation match - finally,
I create a hashed password and save it to the database using
update_attribute.

There MUST be a simpler way… help, anyone?

Thanks,
Mohit.

On 8/14/06, Mohit S. [email protected] wrote:

Is there an addition to the Rails Recipe or the method in AWDWR to allow
a user to change his/ her password? I have put something together that
does all the work again - mostly because I’m not sure how to leverage on
methods like ‘password=’ that are defined in the model. Has anyone got
a ready sample that I could learn from?

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:

<%= form_tag :action => controller.action_name, :id => @user%>

<label for="user_password" ><b>New Password</b>
<%= password_field :user, 'password' %></label><br />

<label for="user_password_confirmation" ><b>Password 

Confirmation
<%= password_field :user, ‘password_confirmation’ %>

<%= submit_tag "Change Password", :class => 'submit' %>

<%= end_form_tag %>

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,

Jim L. wrote:

end
create methods for. The password attribute has to be set up manually.

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.