Ruby on Rails, Devise gem. How to remove current password when password is blank?

后端 未结 2 1940
情深已故
情深已故 2021-02-09 19:24

Now I realise this topic has been covered many times before. However there did not appear to be a solution that wanted to make the current password field exempt only when the pa

相关标签:
2条回答
  • 2021-02-09 19:28

    Okay so I have finally figured this out!

    Add the following to your class RegistrationsController < Devise::RegistrationsController

    def update
      if resource.update_with_password(params[resource_name])
        set_flash_message :notice, :updated
        sign_in resource_name, resource, :bypass => true
        redirect_to after_update_path_for(resource)
      else
        clean_up_passwords(resource)
        render_with_scope :edit
      end
    end
    

    Then the following to your User model:

    def update_with_password(params={})
      current_password = params.delete(:current_password) if !params[:current_password].blank?
    
      if params[:password].blank?
        params.delete(:password)
        params.delete(:password_confirmation) if params[:password_confirmation].blank?
      end
    
      result = if has_no_password?  || valid_password?(current_password)
        update_attributes(params) 
      else
        self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
        self.attributes = params
        false
      end
    
      clean_up_passwords
      result
    end
    
    def has_no_password?
      self.encrypted_password.blank?
    end
    

    The only thing I was slightly confused about is that in the edit view:

    <% if !current_user.has_no_password? %>
    

    I wrapped it in that if, I would have thought it would have been:

    <% if current_user.has_no_password? %>
    

    If anyone can see anything to improve my code or a different, more efficient way let me know!

    0 讨论(0)
  • 2021-02-09 19:47

    Another very minor change on requiring the current password field or not: my goal is never require a current password unless they are updating their password. for oauth'ed accounts, I check for the facebook id in the view, and don't display the password fields at all.

    In the registrations controller:

    Users::RegistrationsController < Devise::RegistrationsController
    
    def update
    
    self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
    
       if resource.update_with_password(params[resource_name])
         set_flash_message :notice, :updated if is_navigational_format?
         sign_in resource_name, resource, :bypass => true
         respond_with resource, :location => after_update_path_for(resource)
       else
         clean_up_passwords(resource)
         respond_with_navigational(resource){ render_with_scope :edit }
       end
    
    
    end
    

    In User.rb, I use update_with_password, and then call verify_password_and_update only if the user has entered something in the password field from the view. Otherwise, I clear the current password param and call update_without_password (this method is built in to devise now as well):

    #to remove the current password check if updating a profile originally gotten via oauth (fb, twitter)
    
    
      def update_with_password(params={})
        if params[:password].blank?
          params.delete(:current_password)
          self.update_without_password(params)
        else
          self.verify_password_and_update(params)
        end
      end
    
      def update_without_password(params={})
    
        params.delete(:password)
        params.delete(:password_confirmation)
        result = update_attributes(params)
        clean_up_passwords
        result
      end
      def verify_password_and_update(params)
        #devises' update_with_password 
        # https://github.com/plataformatec/devise/blob/master/lib/devise/models/database_authenticatable.rb
        current_password = params.delete(:current_password)
    
        if params[:password].blank?
          params.delete(:password)
          params.delete(:password_confirmation) if params[:password_confirmation].blank?
        end
    
        result = if valid_password?(current_password)
          update_attributes(params)
        else
          self.attributes = params
          self.valid?
          self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
          false
        end
    
        clean_up_passwords
        result
      end
    
    0 讨论(0)
提交回复
热议问题