ruby on rails - Password validation triggers when it should not be triggering? -
working on password reset mechanism users. password length validation triggering , i'm trying understand why.
user.rb
class user < activerecord::base has_secure_password validates :password, length: { minimum: 6 } ... def create_password_reset_token self.update_attributes!(password_reset_token: securerandom.urlsafe_base64, password_reset_sent_at: time.zone.now) end def reset_password(params) self.update_attributes!(params) self.update_attributes!(password_reset_token: nil, password_reset_sent_at: nil) end end
password_resets_controller.rb
def create user = user.find_by_email(params[:email]) if user user.create_password_reset_token usermailer.password_reset_email(user).deliver redirect_to root_url, :notice => "email sent password reset instructions!" else flash[:error] = "a user email address not found." render 'new' end end def edit @user = user.find_by_password_reset_token(params[:id]) if @user render 'edit' else flash[:error] = "invalid password reset code." redirect_to root_url end end def update @user = user.find_by_password_reset_token(params[:id]) if @user.password_reset_sent_at < 2.hours.ago flash[:error] = "password reset has expired." redirect_to new_password_reset_path elsif @user.reset_password(user_params) flash[:success] = "password has been reset." redirect_to root_url else render 'edit' end end
password_resets/new.html.erb:
<%= form_tag password_resets_path, :method => :post %> <%= label_tag :email %> <%= text_field_tag :email, params[:email] %> <%= submit_tag "reset password" %> <% end %>
password_resets/edit.html.erb:
<%= form_for @user, :url => password_reset_path(params[:id]) |f| %> <h1 class="centertext">reset password</h1> <%= render 'shared/error_messages', object: f.object %> <%= f.label :password %> <%= f.password_field :password %> <%= f.label :password_confirmation, "confirm password" %> <%= f.password_field :password_confirmation %> <%= f.submit "update password" %> <% end %>
the error is:
validation failed: password short (minimum 6 characters)
the line throws inside create_password_reset_token
method:
self.update_attributes!(password_reset_token: securerandom.urlsafe_base64, password_reset_sent_at: time.zone.now)
why validation trigger here? i'm not doing password itself. i'm creating token , time inside user record.
changing validation on: :create
makes not trigger. problem users able reset password fewer 6 characters.
clarification
to clear, order of operations is:
- user clicks link saying "i forgot password."
- they taken password_reset_controller/new.html.erb. form has 1 field: email address. enter email , submit it.
- controller checks see if user exists. if does, tells model generate password_reset_token.
- controller orders email sent user url contains token.
- the user clicks url. if token valid, taken edit.html.erb , enter new email , confirmation.
- the controller calls reset_password method, resets user's password.
currently, validation triggers on step 2, after enter email , click submit.
your create_password_reset_token calling update_attributes trigger validations on every field in user model , hence trigger password validation doesn't have current 1 set
you need either
1) use update_attribute specific fields , wouldn't trigger validation
2) add password_reset field or enum model , set true when password reset button clicked , in user model
has_secure_password :validations => false validates :password, length: {minimum: 6}, unless: -> { user_password_reset? }
3) use devise gem take care of you
update:
try this
def create_password_reset_token self.update_attribute(:password_reset_token, securerandom.urlsafe_base64) self.update_attribute(:password_reset_sent_at, time.zone.now) end
Comments
Post a Comment