Devise - Omniauth - Hide password fields if user signed up via Facebook

Using Devise with Omniauth, I was able to allow users to log in with their Facebook accounts. Using the Omniauth wiki, I was also able to disable the ability to enter a password when editing my account.

The current issue I am facing is hiding the password fields in my view registrations#edit

if they follow through Facebook. As a newbie to both gems, I am still trying to adjust. So when it comes to setting up the required helper method (s), I understand the loss.

As stated in the wiki, this is what my registration manager looks like:

class RegistrationsController < Devise::RegistrationsController
  before_filter :configure_permitted_parameters, if: :devise_controller?

  def update
    @user = User.find(current_user.id)

    successfully_updated = if needs_password?(@user, params)
      @user.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
    else
      # remove the virtual current_password attribute
      # update_without_password doesn't know how to ignore it
      params[:user].delete(:current_password)
      @user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
    end

    if successfully_updated
      set_flash_message :notice, :updated
      # Sign in the user bypassing validation in case their password changed
      sign_in @user, :bypass => true
      redirect_to after_update_path_for(@user)
    else
      render "edit"
    end
  end

  private

  # check if we need password to update user data
  # ie if password or email was changed
  # extend this as needed
  def needs_password?(user, params)
    user.email != params[:user][:email] ||
      params[:user][:password].present? ||
      params[:user][:password_confirmation].present?
  end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) do |u|
      u.permit(:first_name, :last_name, :email, :password, :password_confirmation)
    end
    devise_parameter_sanitizer.for(:account_update) do |u|
      u.permit(:first_name, :last_name, :email, :password, :password_confirmation)
    end
  end
end

      

And here is my registrations#edit

view:

<% provide :title, 'Edit Profile' %>

<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= devise_error_messages! %>

  <div><%= f.label :first_name %><br />
  <%= f.text_field :first_name %></div>

  <div><%= f.label :last_name %><br />
  <%= f.text_field :last_name %></div>

  <div><%= f.label :email %><br />
  <%= f.email_field :email %></div>

  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
  <% end %>

  <div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
    <%= f.password_field :password, autocomplete: "off" %></div>

  <div><%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %></div>

  <div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password, autocomplete: "off" %></div>

  <div><%= f.submit "Update" %></div>
<% end %>

      

UPDATE

After some extensive research, I was able to find a question that answered unequivocally what I was looking for in terms of hiding input fields (from the second to the last comment in the question). The only problem is that for some reason it throws a password validation error, even though it doesn't exist ...

   <div>
    <%= f.label :first_name %><br />
    <%= f.text_field :first_name %>
  </div>

  <div>
    <%= f.label :last_name %><br />
    <%= f.text_field :last_name %>
  </div>

  <% if user_signed_in? && !current_user.provider == 'facebook' %>
    <div>
      <%= f.label :email %><br />
      <%= f.email_field :email %>
    </div>

    <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
      <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
    <% end %>

    <div>
      <%= f.label :password %><br />
      <%= f.password_field :password %>
    </div>

    <div>
      <%= f.label :password_confirmation %><br />
      <%= f.password_field :password_confirmation %>
    </div>

    <div>
      <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
      <%= f.password_field :current_password %>
    </div>

      

+3


source to share


1 answer


After searching the site, I FINALLY figured out how to get this to work.

My first order was to use the first sample code for the registration controller from this devile wiki

  def update
    # For Rails 4
    account_update_params = devise_parameter_sanitizer.sanitize(:account_update)
    # For Rails 3
    # account_update_params = params[:user]

    # required for settings form to submit when password is left blank
    if account_update_params[:password].blank?
      account_update_params.delete("password")
      account_update_params.delete("password_confirmation")
    end

    @user = User.find(current_user.id)
    if @user.update_attributes(account_update_params)
      set_flash_message :notice, :updated
      # Sign in the user bypassing validation in case their password changed
      sign_in @user, :bypass => true
      redirect_to after_update_path_for(@user)
    else
      render "edit"
    end
  end

      

Next added a method to override the validation of the user's current password from the above code. Special thanks to Lauri Lane for her answer in this post: Editing Users with Devise and Omniauth



  # Overwrite update_resource to let users to update their user without giving their password
  def update_resource(resource, params)
    if current_user.provider == "facebook"
      params.delete("current_password")
      resource.update_without_password(params)
    else
      resource.update_with_password(params)
    end
  end

      

Finally, I had to add :current_password

as a virtual attribute to my user model and it worked!

attr_accessor :current_password

      

Hope this helps anyone who comes across this issue. I know this puzzled me a little, but I'm glad I was able to figure it all out. Coming soon to be tested in conjunction with the omniauth twitter gem.

+7


source







All Articles