繁体   English   中英

Devise-Omniauth-如果以前使用提供商登录,则无法注册(电子邮件已经存在)

[英]Devise - Omniauth - Can't sign up (Email already exists) if previously logged in with provider

我正在使用Devise和omniauth- *在Ruby on Rails应用程序上进行多供应商身份验证。

除了添加的omniauth_callbacks_controller.rb ,我大都关注此链接

class OmniauthCallbacksController < Devise::OmniauthCallbacksController
    def after_sign_in_path_for(resource)
        if resource.email_verified?
            super resource
        else
            finish_signup_path(resource)
        end
    end

    def all
        puts request.env["omniauth.auth"]
        user = User.find_for_oauth(request.env["omniauth.auth"], current_user)
        if user.persisted?
            sign_in_and_redirect user, notice: "Signed in!"
        else
            session["devise.all"] = request.env["omniauth.auth"]
            redirect_to new_user_registration_url
        end
    end
    alias_method :twitter, :all
    alias_method :google_oauth2, :all
    alias_method :facebook, :all
    alias_method :instagram, :all
end

app/models/user.rb我将self.find_for_oauth修改为:

def self.find_for_oauth(auth, signed_in_resource = nil)
    identity = Identity.find_for_oauth(auth)

    user = signed_in_resource ? signed_in_resource :identity.user
    if user.nil?
        email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
        email = auth.info.email || if auth.info.nickname then auth.info.nickname + "@twitter.org" end
        user = User.where("email = ?", email).first if email

        if user.nil?
            user = User.new(
                first_name: auth.extra.raw_info.name,
                email: if auth.info.email != nil and auth.info.email != "" then auth.info.email else if auth.info.nickname then auth.info.nickname + "@twitter.org" end end ,
                password: Devise.friendly_token[0, 20]
            )
            user.skip_confirmation!
            user.save!
        end
    end

    if identity.user != user
        identity.user = user

        identity.save!
    end
    user
end

通过创建user has_many identities identity模型,我成功使用户能够使用使用相同电子邮件地址创建的不同社交媒体登录。

但是,现在,我无法(使用电子邮件和密码)注册到使用社交媒体创建的user对象已经拥有的电子邮件。

我该如何解决这个问题?

更新

我现在尝试的方法是检查用户之前是否已经使用相同的电子邮件登录。 如果是这样,应使用注册数据更新用户帐户,并在provider设置为空白的更多identity对象上provider该帐户。

更新2

现在,我可以通过将registrations_controller.rb create方法自定义为来使用电子邮件和密码注册用户:

def create
    build_resource(sign_up_params)

    resource[:provider] = "<default provider>"
    if !User.find_by_email(resource.email) then
        resource.save
        yield resource if block_given?
        if resource.persisted?
            if resource.active_for_authentication?
                set_flash_message! :notice, :signed_up
                sign_up(resource_name, resource)
                respond_with resource, location: after_sign_up_path_for(resource)
            else
                set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
                expire_data_after_sign_in!
                respond_with resource, location: after_inactive_sign_up_path_for(resource)
            end
        else
            set_flash_message! :error, :"Something went wrong"
            clean_up_passwords resource
            set_minimum_password_length
            respond_with resource
        end
    else
        user = User.find_by_email(resource.email)
        if user.identities.count > 0 and user.provider != "<default provider>" then
        @identity = Identity.new
        @identity.provider = "made up provider"
        @identity.save
        user.password = resource.password
        if resource.country != nil and resource.country != "" then
             user.country = resource.country
        end
        if resource.title != nil and resource.title != "" then
            if resource.title != nil and resource.title != "" then
                user.title = resource.title
            end
            if resource.first_name != nil and resource.first_name != "" then
                user.first_name = resource.first_name
            end
            if resource.last_name != nil and resource.last_name != "" then
                user.last_name = resource.last_name
            end
            if resource.phone_number != nil and resource.phone_number != "" then
                user.phone_number = resource.phone_number
            end
            if resource.country_code != nil and resource.country_code != "" then
                user.country_code = resource.country_code
            end
            user.provider = "<default provider>"

            user.save
            yield user if block_given?
            if user.persisted?
                if resource.active_for_authentication?
                    set_flash_message! :notice, :signed_up
                    respond_with resource, location: after_sign_up_path_for(resource)
                else
                    set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
                    expire_data_after_sign_in!
                    respond_with resource, location: after_inactive_sign_up_path_for(user)
                end
            else
            set_flash_message! :error, :"Something went wrong"
            clean_up_passwords resource
            set_minimum_password_length
            respond_with resource
        end
    else
        set_flash_message! :error, "This Account already exists"
        redirect_to new_user_session_path
    end
end

但是,带有“确认邮件已发送到您的电子邮件”的消息,而实际上没有发送确认邮件。

当用户首次输入密码(用户使用电子邮件和密码注册)时,如何使它发送确认电子邮件?

更新3

我当前的问题是:

使用Devise,如何在首次密码更新(或特定操作)时发送确认电子邮件(与注册确认电子邮件相同)?

我通过修改制定固定的登记和确认问题registrations_controller.rbconfirmations_controller.rbsessions_controller.rb

registrations_controller.rb我将create方法修改为:

def create
    build_resource(sign_up_params)

    resource[:provider] = "<default provider>"
    if !User.find_by_email(resource.email) then
      resource.save
      yield resource if block_given?
      if resource.persisted?
        if resource.active_for_authentication?
          set_flash_message! :notice, :signed_up
          sign_up(resource_name, resource)
          respond_with resource, location: after_sign_up_path_for(resource)
        else
          set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
          expire_data_after_sign_in!
          respond_with resource, location: after_inactive_sign_up_path_for(resource)
        end
      else
        set_flash_message! :error, :"Something went wrong"
        clean_up_passwords resource
        set_minimum_password_length
        respond_with resource
      end
    else
      user = User.find_by_email(resource.email)
      if user.identities.count > 0 and (user.provider != "<default provider>" or user.provider != "<default provider>-confirmed") then
        @identity = Identity.new
        @identity.provider = "<default provider>"
        @identity.save
        user.password = resource.password
        if resource.username != nil and resource.username != "" then
            user.username = resource.username
        end
        if resource.phone_number != nil and resource.phone_number != "" then
            user.phone_number = resource.phone_number
        end
        ...
        user.provider = "<default provider>"
        user.save
        user.send_confirmation_instructions
        yield user if block_given?
        if user.persisted?
          if resource.active_for_authentication?
            set_flash_message! :notice, :signed_up
            respond_with resource, location: after_sign_up_path_for(resource)
          else
            set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
            expire_data_after_sign_in!
            respond_with resource, location: after_inactive_sign_up_path_for(user)
          end
        else
          set_flash_message! :error, :"Something went wrong"
          clean_up_passwords resource
          set_minimum_password_length
          respond_with resource
        end
      else
        set_flash_message! :error, "This Account already exists"
        redirect_to new_user_session_path
      end
    end
end

confirmations_controller.rb我修改了createshow方法:

# POST /resource/confirmation
def create
  self.resource = resource_class.send_confirmation_instructions(resource_params)
  yield resource if block_given?

  if successfully_sent?(resource)
    respond_with({}, location: after_resending_confirmation_instructions_path_for(resource_name))
  else
    if User.find_by_email(resource.email).provider != "<default provider>-confirmed" then
     User.find_by_email(resource.email).send_confirmation_instructions
     respond_with({}, location: after_resending_confirmation_instructions_path_for(resource_name))
    else
      respond_with(resource)
    end
  end
end

# GET /resource/confirmation?confirmation_token=abcdef
def show
  self.resource = resource_class.confirm_by_token(params[:confirmation_token])
  yield resource if block_given?

  if resource.errors.empty?
    resource.provider = "<default provider>-confirmed"
    resource.save
    set_flash_message!(:notice, :confirmed)
    respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
  else
    if User.find_by_email(resource.email).provider != "<default provider>-confirmed" then
      a = User.find_by_email(resource.email)
      a.provider = "<defualt provider>-confirmed"
      a.save
      set_flash_message!(:notice, :confirmed)
      respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
    else
      respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
    end
  end
end

sessions_controller.rb我还修改了create方法:

def create
    self.resource = warden.authenticate!(auth_options)
    if User.find_by_email(resource.email) and User.find_by_email(resource.email).provider == "<default provier>-confirmed" then
      self.resource = warden.authenticate!(auth_options)
      set_flash_message!(:notice, :signed_in)
      sign_in(resource_name, resource)
      yield resource if block_given?
      respond_with resource, location: after_sign_in_path_for(resource)
    else
      signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
      set_flash_message!(:error, "You have not yet confirmed your email");
      redirect_to root_path
    end
end

暂无
暂无

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

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