如何通过电子邮件找到用户,如果没有,将他重定向到注册页面

How to find user by email and if not, redirect him to register page

我使用 Omniauth 和 Omniauth-facebook gems 我想点击按钮,如果找到用户,然后登录。如果没有,将他重定向到注册页面。

到目前为止我只使用经典 login/register:

user.rb:

def self.from_omniauth(auth, role)
  user = User.where(:provider => auth.provider, :uid => auth.uid).first

  if user
    return user
  else
    registered_user = User.where(:email => auth.info.email).first

    if registered_user
      registered_user.provider = auth.provider
      return registered_user
    else
      where(provider: auth.provider, uid: auth.uid).first_or_create do |user|

        if (role == "1")
          user.add_role :sportsman
        elsif (role == "2")
          user.add_role :donor
        end

        user.provider = auth.provider
        user.uid = auth.uid
        user.email = auth.info.email
        user.password = Devise.friendly_token[0,20]
      end
    end
  end
end

omniauth_callbacks_controller.rb:

def facebook
  role = cookies[:role]
  # signin = cookies[:signin]
  user = User.from_omniauth(request.env["omniauth.auth"], role)

  if user.persisted?
    flash.notice = "Signed by Facebooku"
    sign_in_and_redirect user
  else
    flash.notice = "Error, try again."
    session["devise.user_attributes"] = user.attributes
    redirect_to new_user_registration_url
  end
end

此代码有效,但如果用户未注册,它将注册他。但是我在用户自己注册时签署角色。

感谢您的帮助。

因为您已经将用户属性保存到会话中 session["devise.user_attributes"] = user.attributes

那么下面应该已经起作用了:

def self.from_omniauth(auth, role)
  user = User.where(:provider => auth.provider, :uid => auth.uid).first

  if user
    return user
  else
    # NOTE: because you're searching "email" and not both "email" + "provider", then I assume
    # that you want users to have only one shared account between all providers (i.e. if they also sign-in in Google with the exact email as his email in Facebook)
    registered_user = User.where(:email => auth.info.email).first
    if registered_user
      # NOTE: this line doesn't do anything because registered_user is not being "saved"
      registered_user.provider = auth.provider
      return registered_user
    else
      # build a new User object (don't save yet!)
      return User.new.tap do |u|
        u.provider = auth.provider
        u.email = auth.info.email
        u.uid = uid: auth.uid
        u.password = Devise.friendly_token[0,20]

        # because I assume you're using "rolify" gem, don't add the roles yet here, because I don't think you can store the "roles" into the session
        # add the roles logic in whatever controller you have for user registration
      end
    end
  end
end

然后在您的 user 模型中覆盖 new_with_sessionnew_with_session 由 Devise 在 registrations#new 中自动调用。我们需要设置 我们之前存储在session里面的用户属性omniauth_callbacks#facebook

class User < ApplicationRecord
  def self.new_with_session(params, session)
    super.tap do |user|
      if user_attributes = session['devise.user_attributes']
        user.assign(user_attributes)
      end
    end
  end
end

所以我使用简单的参数来获取用户来自哪里:

<script type="text/javascript">
    document.cookie = "login=0"
</script>

此代码在 views/devise/registrations/new.html.erb(和 views/devise/sessions/new.html.erb)中,并且是 JavaScript。它告诉我用户是从登录页面(会话文件夹-登录=1)还是从注册页面(注册文件夹-登录=0)进入的。然后我使用此代码来确定用户是否来自登录页面以及他是否尚未注册。如果两个条件都为真,那么他将被重定向到注册页面。简单到我都尴尬了...

def facebook
    hash  = request.env["omniauth.auth"]
    info  = hash.info
    email = info["email"]

    user = User.find_by_email(email)

    login = cookies[:login]

    if (user == nil && login == "1")
      redirect_to new_user_registration_path
    else
      role = cookies[:role]
      user = User.from_omniauth(request.env["omniauth.auth"], role)
      if user.persisted?
        flash.notice = "Logged in by Facebook"
        sign_in_and_redirect user
      else
        flash.notice = "Error, try again."
        session["devise.user_attributes"] = user.attributes
        redirect_to new_user_registration_url
      end
    end
  end