简体   繁体   English

Omniauth Twitter-重定向至表格以获取更多信息

[英]Omniauth Twitter - Redirect to form for extra Information

I'm following this tutorial but fail on how to redirect the User to a page to fill out more information when he connects with omniauth. 我正在按照本教程进行操作,但是当用户使用omniauth连接时,如何将用户重定向到页面以填写更多信息失败。

In my User Model I have: 在我的用户模型中,我有:

user = User.new(
  name: auth.extra.raw_info.name,
  user_name: auth.info.nickname,
  about_me: auth.info.description,
  email: email ? email : "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
  password: Devise.friendly_token[0,20]
)
user.skip_confirmation!
user.save!

In my Omniauth callbacks controller I have: 在我的Omniauth回调控制器中,我有:

def after_sign_in_path_for(resource)
  if resource.profile_valid?
    super resource
  else
    finish_signup_path(resource        
  end
end

profile_valid checks for: profile_valid检查以下内容:

def profile_valid?
  self.email && self.email !~ TEMP_EMAIL_REGEX
end

Twitter auth doesn't give you an email, which I require for a Registration, so i'm passing a dummy email with a regex (TEMP_EMAIL_REGEX). Twitter身份验证没有给您发送电子邮件,我需要注册才能通过电子邮件发送,因此我要传递带有正则表达式(TEMP_EMAIL_REGEX)的虚拟电子邮件。

So when a valid email isn't present it should redirect to the finish_signup_page which contains: 因此,当没有有效的电子邮件时,应将其重定向到包含以下内容的finish_signup_page:

<div id="add-email" class="container">
  <h1>Add Email</h1>
  <%= form_for(current_user, :as => 'user', :url => finish_signup_path(current_user), :html => { role: 'form'}) do |f| %>


    <% if @show_errors && current_user.errors.any? %>
      <div id="error_explanation">
        <% current_user.errors.full_messages.each do |msg| %>
          <%= msg %><br>
        <% end %>
      </div>
    <% end %>

    <!-- User Name -->
    <div class="form-group">
      <%= f.label :user_name %>
      <div class="controls">
        <%= f.text_field :user_name, :autofocus => true, :value => '', class: 'form-control', placeholder: 'Username' %>
        <p class="help-block">Please enter your username</p>
      </div>
    </div>

    <div class="form-group">
      <%= f.label :email %>
      <div class="controls">
        <%= f.text_field :email, :autofocus => true, :value => '', class: 'form-control', placeholder: 'Example: email@me.com' %>
        <p class="help-block">Please confirm your email address. No spam.</p>
      </div>
    </div>
    <div class="actions">
      <%= f.submit 'Continue', :class => 'btn btn-primary' %>
    </div>
  <% end %>
</div>

Here is my problem, when I enter something it doesn't save the User and it would be better if in the actual fields the current values would be present? 这是我的问题,当我输入某些内容时不会保存用户,如果在实际字段中显示当前值会更好?

But I'm lost on how to do that, or maybe I'm trying this now for too long and have a tunnel-vision. 但是我对如何做到这一点迷失了,或者也许我已经尝试了太久了,并且已经有了一个通道视觉。

What am I Missing? 我想念什么?

First go through the following classes. 首先经历以下课程。 You need to store the correct data for the user, a generated email is not a good solution. 您需要为用户存储正确的数据,生成的电子邮件不是一个好的解决方案。 So we basically store the provider's data in a separate model Social Provider . 因此,我们基本上将提供者的数据存储在单独的模型Social Provider

Registration Flow: 注册流程:

  • sp = Social Provider is created sp =社会提供者已创建
  • The user is initialized by the data received from the provider (not saved). 通过从提供者接收的数据(未保存)初始化用户。
  • We store the sp id in the session, to isolate it from the user reach. 我们将sp id存储在会话中,以将其与用户隔离。
  • we render device registration/new view (adding all fields we need). 我们呈现设备注册/新视图(添加我们需要的所有字段)。
  • On successful registeration, we link the sp to the created user. 成功注册后,我们将sp链接到创建的用户。

1.The User Class, has update_from_oauth method, which updates the main attributes in the user without saving it. update_from_oauth类具有update_from_oauth方法,该方法将更新用户中的主要属性而不保存它。

##########################
# User Class
##########################

class User < ActiveRecord::Base
  has_many :social_providers, dependent: :destroy

  # update from OAuth
  def update_from_oauth(auth, provider_type)
    self.email = auth[:info][:email] if self.email.blank?
    case provider_type
    when :twitter
      name = auth[:info][:name].split(' ')
      self.first_name ||= name[0]
      self.last_name ||= name[1]
      self.remote_avatar_url = auth[:extra][:raw_info][:profile_image_url]
    when :facebook
      ...
    when :google
      ...
    end
  end
end

2. SocialProvider class or (Identity) 2. SocialProvider类别或(身份)

class SocialProvider < ActiveRecord::Base

  #Relations
  belongs_to :user

  def self.find_for_oauth(auth, provider_type)
    unless social_provider = self.find_by(pid: auth[:uid].to_s, provider_type: provider_type)
      user = User.find_by_email(auth[:info][:email])
      social_provider = user.social_providers.where(provider_type: provider_type).first if user.present?
      social_provider ||= SocialProvider.new
    end
    social_provider.update_from_oauth(auth, provider_type)
    social_provider
  end

  def update_from_oauth(auth, provider_type)
    self.email= auth[:info][:email]
    self.pid= auth[:uid]
    self.provider_type= provider_type
    credentials = auth[:credentials]
    case provider_type
    when :twitter
      self.token = credentials[:token]
      self.secret = credentials[:secret]
      self.url = auth[:info][:urls][:Twitter]
    when :facebook
      ...
    when :google
      ...
    end
  end
end

##########################
# SocialProvider Migration
##########################

class CreateSocialProviders < ActiveRecord::Migration
  def change
    create_table "social_providers" do |t|
      t.string   "pid" # user provider id
      t.string   "token"
      t.string   "refresh_token"
      t.string   "secret"
      t.datetime "expires_at"
      t.string   "provider_type"
      t.integer  "user_id"
      t.string   "url"
      t.string   "email"
      t.timestamps
    end
  end
end

3. Omniauth Callbacks Controller 3. Omniauth回调控制器

###############################
# OmniAuth Callbacks Controller
###############################

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  before_filter :prepare_auth

  def facebook
    connect(:facebook)
  end

  def twitter
    connect(:twitter)
  end

  def google_oauth2
    connect(:google)
  end

  private

    def prepare_auth
      @auth = request.env["omniauth.auth"]
    end

    def connect(provider_type)
      social_provider = SocialProvider.find_for_oauth(@auth, provider_type)
      if user_signed_in?
        if social_provider and social_provider.user_id == current_user.id
          flash[:notice] = "Your #{provider_type} account is already attached"
          redirect_to current_user and return
        elsif social_provider.user_id.nil?
          current_user.update_from_oauth(@auth, provider_type)
          current_user.social_providers << social_provider if current_user.save
          flash[:notice] = "Successfully attached #{provider_type} account"
          redirect_to current_user and return
        else
          flash[:notice] = "#{provider_type} is already connected to another account"
          redirect_to current_user and return
        end
      else
        @user = social_provider.user || User.find_by_email(@auth[:info][:email]) || User.new
        @user.update_from_oauth(@auth, provider_type)
        social_provider.save
        if @user.persisted? # If user already has account and not logged in
          @user.social_providers << social_provider if @user.save
          flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => provider_type.capitalize
          sign_in_and_redirect @user, :event => :authentication
        else # If user has no account
          session[:sp_id] = social_provider.id 
          render 'registrations/new'
        end
      end
    end
end

4. Overriding Devise registration controller 4.覆盖Devise注册控制器

#################################
# Devise::RegistrationsController
#################################

class RegistrationsController < Devise::RegistrationsController

  def create
    super
    if user_signed_in? and session[:sp_id].present?
      SocialProvider.find_by(id: session[:sp_id],user_id: nil).update(user_id: current_user.id)
    end
  end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM