用Devise和Omniauth编辑用户 [英] Editing Users With Devise and Omniauth

查看:141
本文介绍了用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
除非用户
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,
电子邮件:auth.info.email,
密码:Devise.friendly_token [0,20]

结束
用户
结束

当用户编辑他的信息时,应用程序应该如果他通过O设置了他的账户,则不需要密码确认mniAuth。该教程建议方便的password_required?方法将有助于我实现这一成果。具体来说,将此方法添加到用户模型意味着如果用户没有通过OmniAuth注册,则该方法应该返回true(在这种情况下,provider属性将为零):



def $ _ $?
超级&& provider.blank?
end

因此,一段代码如:

 <%= form_for(resource,:as => resource_name,:url => registration_path(resource_name),:html => {:method = >:put})do | f | %GT; 
<%= devise_error_messages! %GT;
<%= render:partial => essential_user_info_inputs,:locals => {:f => f}%>
<%= render:partial => inessential_user_info_inputs,:locals => {:f => f}%>
<%if f.object.password_required? %GT;
<%= render:partial => password_inputs,:locals => {:f => f}%>
<%= f.label:current_password%> < i(我们需要您当前的密码来确认您的更改)< / i>< br />
<%= f.password_field:current_password%>
<%end%>
<%= f.submit更新%>
<%end%>理论上只需在需要时显示密码输入,

它还表明,Devise已经建立了逻辑,说OmniAuth用户不需要使用密码来编辑他们的帐户。我不知道如果这是真的,但教程的样子使它看起来像这样。但是当OmniAuth用户尝试编辑他的帐户时,我得到当前密码不能为空。与非OmniAuth用户同样的事情(这是有道理的,因为密码字段也不会显示在用户的编辑页面上)。



密码_需要?当用户通过OmniAuth注册并通过站点的常规用户注册时,方法返回false。即使我更改它只是运行超类方法,它返回false。



任何关于password_required方法发生什么的想法?我在任何地方找不到任何东西,但我觉得这是现在的事情。



更新:



这是现在正在工作,但不使用Railscast中概述的方法,它依赖于require_password?方法,一个我仍然不了解的话题。相反,我实现了 here ,如建议的这里。所以我现在只需要密码来更新非OmniAuth账号,代码如下:

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

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

如果successfully_updated
#登录用户绕过验证,以防其密码更改
sign_in @user,:bypass => true
redirect_to root_path
else
呈现编辑
结束
结束
结束


最简单的方法是覆盖您的 RegistrationsController 中的update_resource方法。这是由控制器自己实现的设计建议的:

 #默认情况下,我们需要对更新进行密码检查。 
#您可以在自己的RegistrationsController中覆盖此方法。
def update_resource(resource,params)
resource.update_with_password(params)
end

所以解决方案是在你自己的控制器中覆盖这个方法,如下所示:

  class Users :: RegistrationsController< ; Devise :: RegistrationsController 

#覆盖update_resource,让用户在不给出密码的情况下更新用户
def update_resource(resource,params)
如果current_user.provider ==facebook
params.delete(current_password)
resource.update_without_password(params)
else
resource.update_with_password(params)
end
end

end


I'm working through the Railscast on implementing Devise and OmniAuth (along with the Devise documentation) -- currently, I've got a site going where visitors can sign up using their facebook accounts or by filling out a form.

I'm running into trouble when users that sign up via OmniAuth try to edit their profiles, though. Devise looks for the user's current password when they submit changes to their profiles, but those that logged in with facebook don't know their passwords (they're set automatically in the user model):

  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

When a user edits his information, the app should not require password confirmation if he set up his account through OmniAuth. The tutorial suggests that the handy password_required? method will help me achieve this outcome. Specifically, adding this method to the user model means that it should only return true if the user didn't sign up through OmniAuth (the provider attribute would be nil in that case):

def password_required?
  super && provider.blank?
end

Thus, a piece of code like:

<%= 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 %>

would theoretically only display password inputs when needed. It also suggests that Devise has built in logic saying that OmniAuth users don't need to use passwords to edit their accounts. I have no idea if this is true, but the tutorial kind of makes it look like that. But when an OmniAuth user tries to edit his account, I get "Current password can't be blank." Same thing with non-OmniAuth users (this makes sense, since the password fields don't show up on those users' edit pages either).

Some poking around confirms that the password_required? method is returning false, both when the user signed up through OmniAuth and through the site's regular user signup. Even when I change it to simply run the superclass method, it returns false.

Any ideas of what's going on with the password_required method? I can't find anything about it anywhere, but I feel like that's what's tripping things up right now.

Update:

This is now working, but not using the method outlined in the Railscast, which relies on requires_password? method, a topic that I still know nothing about. Instead, I implemented the solution outlined here, as suggested here. So I am now only requiring passwords to update non-OmniAuth accounts with the code:

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

    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

解决方案

The easiest way is to overwrite the update_resource method in your RegistrationsController. This is advised by devise in their own implementation of the controller:

  # 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

So the solution is to overwrite this method in your own controller like this:

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

这篇关于用Devise和Omniauth编辑用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆