I'm working on multi vendor authentication on Ruby on Rails application using Devise and omniauth-*.
I, mostly followed this link except for omniauth_callbacks_controller.rb
where I added:
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
and app/models/user.rb
I modified self.find_for_oauth
to :
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
I succeeded to make a user able to sign in using different social media created with the same email address by creating identity
model in which user
has_many identities
.
However, Now, I can't sign up (with email and passwords) to an email that is already had by a user
object created using social media.
How can I solve this issue?
UPDATE
The approach I'm trying now is checking if the user has already signed in before with the same email. If so, the user account should be updated with sign up data and given on more identity
object with provider
set to blank.
UPDATE 2
I now can signup user with email and password by customizing create
method in registrations_controller.rb
to :
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
However, a message with "confirmation mail is sent to your email", while no confirmation mail is actually sent.
How can I make it send confirmation e-mail on when user enteres password for the first time (user signup with email and password)?
UPDATE3
My current question is :
Using Devise, how can I send confirmation email (identical to signup confirmation email) on first password update (or on a specific action)?