Подтвердить что ты не робот

Редактирование пользователей с помощью Devise и Omniauth

Я работаю над Railscast при внедрении Devise и OmniAuth (вместе с Devise документация) - в настоящее время у меня есть сайт, где посетители могут зарегистрироваться с помощью своих учетных записей facebook или заполнив форму.

У меня возникают проблемы, когда пользователи, которые подписываются через OmniAuth, пытаются изменить свои профили. Devise ищет текущий пароль пользователя при отправке изменений в свои профили, но те, которые вошли в систему с facebook, не знают своих паролей (они автоматически устанавливаются в пользовательской модели):

  def self.find_for_facebook_oauth(auth, signed_in_resource=nil)
    user = User.where(:provider => auth.provider, :uid => auth.uid).first
    unless user
      user = User.create(first_name:auth.extra.raw_info.first_name,
                         last_name:auth.extra.raw_info.last_name,
                           provider:auth.provider,
                           uid:auth.uid,
                           email:auth.info.email,
                           password:Devise.friendly_token[0,20]
                           )
    end
    user
  end

Когда пользователь редактирует свою информацию, приложение не должно требовать подтверждения пароля, если он настроит свою учетную запись через OmniAuth. В учебном пособии предлагается удобный пароль для пароля? метод поможет мне достичь этого результата. В частности, добавление этого метода в пользовательскую модель означает, что он должен возвращать true только в том случае, если пользователь не зарегистрировался через OmniAuth (в этом случае атрибут провайдера будет равен нулю):

def password_required?
  super && provider.blank?
end

Таким образом, фрагмент кода, например:

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
  <%= devise_error_messages! %>
    <%= render :partial => "essential_user_info_inputs", :locals => { :f => f } %>
    <%= render :partial => "inessential_user_info_inputs", :locals => { :f => f } %>
    <% if f.object.password_required? %> 
        <%= render :partial => "password_inputs", :locals => { :f => f } %>
        <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
        <%= f.password_field :current_password %>
    <% end %>
  <%= f.submit "Update" %>
<% end %>

теоретически будет отображать только входные данные в случае необходимости. Это также говорит о том, что Devise построил логику, говоря, что пользователям OmniAuth не нужно использовать пароли для редактирования своих учетных записей. Я понятия не имею, верно ли это, но учебный вид делает это таким. Но когда пользователь OmniAuth пытается изменить свою учетную запись, я получаю: "Текущий пароль не может быть пустым". То же самое происходит с пользователями без OmniAuth (это имеет смысл, поскольку поля пароля также не отображаются на страницах редактирования этих пользователей).

Кто-то соскучился, подтверждая, что password_required? метод возвращает false, как при регистрации пользователем через OmniAuth, так и через обычную регистрацию сайта. Даже когда я меняю его, чтобы просто запустить метод суперкласса, он возвращает false.

Любые идеи о том, что происходит с методом password_required? Я ничего не могу найти об этом в любом месте, но я чувствую, что это то, что сейчас срабатывает.

Обновление:

Это работает, но не использует метод, описанный в Railscast, который полагается на require_password? метод, тема, о которой я до сих пор ничего не знаю. Вместо этого я внедрил решение здесь, как было предложено здесь. Поэтому теперь мне требуется только пароли для обновления учетных записей без OmniAuth с кодом:

class Users::RegistrationsController < Devise::RegistrationsController
def update
    @user = User.find(current_user.id)
    email_changed = @user.email != params[:user][:email]
    is_facebook_account = [email protected]?

    successfully_updated = if !is_facebook_account
      @user.update_with_password(params[:user])
    else
      @user.update_without_password(params[:user])
    end

    if successfully_updated
      # Sign in the user bypassing validation in case his password changed
      sign_in @user, :bypass => true
      redirect_to root_path
    else
      render "edit"
    end
  end
end
4b9b3361

Ответ 1

Самый простой способ - перезаписать метод update_resource в RegistrationsController. Это рекомендуется при разработке собственной реализации контроллера:

  # By default we want to require a password checks on update.
  # You can overwrite this method in your own RegistrationsController.
  def update_resource(resource, params)
    resource.update_with_password(params)
  end

Итак, решение состоит в том, чтобы перезаписать этот метод в вашем собственном контроллере следующим образом:

class Users::RegistrationsController < Devise::RegistrationsController

  # 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

end

Ответ 2

Я добавил обновление к приведенной ниже ссылке, включая мое решение проблемы с изменением профиля/пароля Devise/OmniAuth и собрал полезные ссылки:

fooobar.com/questions/436097/...

Ответ 3

Я видел, что это использовалось где-то.


def update
    params[:user].delete(:current_password)
    params[:user].delete(:password)
    params[:user].delete(:password_confirmation)
    if current_user.update_without_password(params[:user])
      redirect_to somewhere_wicked_path, notice => "You rock"
    else
      render 'edit', :alert => 'you roll'
    end
end

используйте что-то подобное в своем методе обновления в вашем контроллере. Довольно уверен, что этот метод также находится в разработке.