Hi, I''m doing something that seems so simple, but I can''t figure it out. I''m writing a change password function for the "my account" section of a site. I want the user to enter their old password and their new password (and a confirmation), and then check that the old password matches before updating the record. However, I don''t know how to keep the old password around in order to do the validation. Because the validations happen in the model, the attributes are wiped out when assigning the new password value to the object. I have to admit that I''m having trouble with validations generally. Database stuff is fine and relatively easy, but anything not backed by the database and I''m at a loss. Does this make sense? How do you handle this? Cheers, Jord --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Jordan Elver wrote:> Hi, > I''m doing something that seems so simple, but I can''t figure it out. > I''m writing a change password function for the "my account" section of > a site. I want the user to enter their old password and their new > password (and a confirmation), and then check that the old password > matches before updating the record. > > However, I don''t know how to keep the old password around in order to > do the validation. Because the validations happen in the model, the > attributes are wiped out when assigning the new password value to the > object. > > I have to admit that I''m having trouble with validations generally. > Database stuff is fine and relatively easy, but anything not backed by > the database and I''m at a loss. > > Does this make sense? How do you handle this?Validation is done in model, it provides means to check data consistency. Verifying if user is allowed to do something with model is a controller responsibility and should happen prior to updating model. This includes checking of old password to verify user. In my view I have: Old password: <% password_field_tag %> New password: <% password_field(:user, :password) %> New password (confirm): <% password_field(:user, :password_confirmation) %> and in my controller: if User.authenticate(current_user, params[:password]) == current_user current_user.update_attributes(params[:user]) else flash[:error] = ''Please provide valid current password'' redirect_to :action => ''change_password'' end Controller first checks if user is allowed to change password in if clause. Then model takes care of checking if password is confirmed - validations kick in during update_attributes. As you can see those are two distinct steps performed by two different entities. Model is good for checking data MODEL integrity. Controller is good for flow CONTROL and security :) Cheers, Bragi -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
No no no. I have to disagree. This 'change password' should be called in the model. However, I'd refactor it a bit. view: Old password: <% password_field_tag %> New password: <% password_field(:user, :password) %> New password (confirm): <% password_field(:user, :password_confirmation) %> controller def change_password end On 8/29/06, Łukasz Piestrzeniewicz <rails-mailing-list@andreas-s.net> wrote:> > > Jordan Elver wrote: > > Hi, > > I'm doing something that seems so simple, but I can't figure it out. > > I'm writing a change password function for the "my account" section of > > a site. I want the user to enter their old password and their new > > password (and a confirmation), and then check that the old password > > matches before updating the record. > > > > However, I don't know how to keep the old password around in order to > > do the validation. Because the validations happen in the model, the > > attributes are wiped out when assigning the new password value to the > > object. > > > > I have to admit that I'm having trouble with validations generally. > > Database stuff is fine and relatively easy, but anything not backed by > > the database and I'm at a loss. > > > > Does this make sense? How do you handle this? > > Validation is done in model, it provides means to check data > consistency. > > Verifying if user is allowed to do something with model is a controller > responsibility and should happen prior to updating model. This includes > checking of old password to verify user. > > In my view I have: > > Old password: <% password_field_tag %> > New password: <% password_field(:user, :password) %> > New password (confirm): <% password_field(:user, :password_confirmation) > %> > > and in my controller: > > if User.authenticate(current_user, params[:password]) == current_user > current_user.update_attributes(params[:user]) > else > flash[:error] = 'Please provide valid current password' > redirect_to :action => 'change_password' > end > > Controller first checks if user is allowed to change password in if > clause. Then model takes care of checking if password is confirmed - > validations kick in during update_attributes. > > As you can see those are two distinct steps performed by two different > entities. > > Model is good for checking data MODEL integrity. Controller is good for > flow CONTROL and security :) > > Cheers, > Bragi > > -- > Posted via http://www.ruby-forum.com/. > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk@googlegroups.com To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Sorry... gmail's being a pest. I tried to post an example but it got cut off. The solution provided by Lucasz is a great one. However, I still like to have that sort of stuff in the model instead of the controller because I may have various ways for a password to be changed. On 8/29/06, Brian Hogan <bphogan@gmail.com> wrote:> > No no no. > > I have to disagree. This 'change password' should be called in the model. > > However, I'd refactor it a bit. > > view: > > > Old password: <% password_field_tag %> > New password: <% password_field(:user, :password) %> > New password (confirm): <% password_field(:user, :password_confirmation) > %> > > controller > > def change_password > > end > > > > > > > > On 8/29/06, Łukasz Piestrzeniewicz <rails-mailing-list@andreas-s.net> > wrote: > > > > > > Jordan Elver wrote: > > > Hi, > > > I'm doing something that seems so simple, but I can't figure it out. > > > I'm writing a change password function for the "my account" section of > > > a site. I want the user to enter their old password and their new > > > password (and a confirmation), and then check that the old password > > > matches before updating the record. > > > > > > However, I don't know how to keep the old password around in order to > > > do the validation. Because the validations happen in the model, the > > > attributes are wiped out when assigning the new password value to the > > > object. > > > > > > I have to admit that I'm having trouble with validations generally. > > > Database stuff is fine and relatively easy, but anything not backed by > > > > > the database and I'm at a loss. > > > > > > Does this make sense? How do you handle this? > > > > Validation is done in model, it provides means to check data > > consistency. > > > > Verifying if user is allowed to do something with model is a controller > > responsibility and should happen prior to updating model. This includes > > checking of old password to verify user. > > > > In my view I have: > > > > Old password: <% password_field_tag %> > > New password: <% password_field(:user, :password) %> > > New password (confirm): <% password_field(:user, :password_confirmation) > > %> > > > > and in my controller: > > > > if User.authenticate(current_user, params[:password]) == current_user > > current_user.update_attributes(params[:user]) > > else > > flash[:error] = 'Please provide valid current password' > > redirect_to :action => 'change_password' > > end > > > > Controller first checks if user is allowed to change password in if > > clause. Then model takes care of checking if password is confirmed - > > validations kick in during update_attributes. > > > > As you can see those are two distinct steps performed by two different > > entities. > > > > Model is good for checking data MODEL integrity. Controller is good for > > flow CONTROL and security :) > > > > Cheers, > > Bragi > > > > -- > > Posted via http://www.ruby-forum.com/. > > > > > > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk@googlegroups.com To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Thanks both for your suggestions. I''ve managed to come up with something that works now. I''ve added a virtual attribute to take the current password from the user and this is only validated when a password is changed. So, now I have something like this: Model: class Customer < ActiveRecord::Base attr_accessor :current_password validates_presence_of :current_password, :on => :update, :if => :password_change? def change_password(attributes) @password_change = true self.attributes = attributes save end private def validate_on_update if password_change? errors.add(:current_password, "is incorrect") unless encrypt(current_password) == crypted_password end end def password_change? @password_change end end Controller: class AccountController < ApplicationController def change_password @customer = @current_customer if request.post? if @customer.change_password(params[:customer]) flash[:notice] = "Your password has been changed" end end end end Thanks for your advice. Cheers, Jord --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Very nice. On 9/6/06, Jordan Elver <jordan.elver-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > Thanks both for your suggestions. I''ve managed to come up with > something that works now. > > I''ve added a virtual attribute to take the current password from the > user and this is only validated when a password is changed. So, now I > have something like this: > > Model: > > class Customer < ActiveRecord::Base > attr_accessor :current_password > validates_presence_of :current_password, :on => :update, :if => > :password_change? > > def change_password(attributes) > @password_change = true > self.attributes = attributes > save > end > > private > > def validate_on_update > if password_change? > errors.add(:current_password, "is incorrect") unless > encrypt(current_password) == crypted_password > end > end > > def password_change? > @password_change > end > end > > Controller: > > class AccountController < ApplicationController > def change_password > @customer = @current_customer > if request.post? > if @customer.change_password(params[:customer]) > flash[:notice] = "Your password has been changed" > end > end > end > end > > Thanks for your advice. > > Cheers, > Jord > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---