![](/img/trans.png)
[英]Linking existing Devise user (email sign up) with Omniauth-Twitter
[英]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.rb
, confirmations_controller.rb
和sessions_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
我修改了create
和show
方法:
# 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.