Last active
December 11, 2015 07:08
-
-
Save b-murphy/4564124 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require './lib/enthuse/social_network_mappings' | |
require 'virtus' | |
class Authenticator | |
# Required for Errors & Messages | |
########################################## | |
include Virtus | |
extend ActiveModel::Naming | |
include ActiveModel::Conversion | |
include ActiveModel::Validations | |
def persisted? | |
false | |
end | |
attr_reader :url | |
def self.authenticator_for_provider(provider) | |
provider_name = Enthuse::SocialNetworkMappings.downcased_provider_to_camelcased(provider) | |
"#{provider_name}Authenticator".constantize.new | |
end | |
##### Authentication Finder Methods | |
###################################################### | |
def add_authentication_to_user(user, auth) | |
authentication = create_authentication_for_user(user, auth) | |
if authentication.persisted? | |
@url = Rails.application.routes.url_helpers.profile_path(slug: user.slug) | |
else | |
Enthuse.log_persistence_error(authentication) | |
end | |
rescue StandardError => e | |
errors.add(:base, "Sorry, something went wrong and your details were not saved. We're looking into it.") | |
Enthuse.log_error(e) | |
end | |
# this method can and is overidden by subclasses. | |
def create_authentication_for_user(user, auth) | |
auth_info = HashWithIndifferentAccess.new(auth) | |
provider_name = Enthuse::SocialNetworkMappings.downcased_provider_to_camelcased(auth_info['provider']) | |
if network = user.find_social_network(provider_name) | |
ActiveRecord::Base.transaction { network.destroy } | |
end | |
network_user = "#{provider_name}DataParser".constantize.new(auth_info) | |
attributes = { | |
network_name: provider_name, | |
handle: network_user.handle, | |
meta_data: network_user.stats | |
} | |
ActiveRecord::Base.transaction do | |
uid = auth_info['uid'].to_s | |
credentials = auth_info['credentials'] | |
social_network = SocialNetworkServices.create(user, attributes) | |
authentication = user.find_or_create_by_user_provider_uid_and_credentials(provider_name, uid, credentials['token'], credentials['secret']) | |
end | |
user | |
end | |
def find_user_with_auth(auth) | |
auth_info = HashWithIndifferentAccess.new(auth) | |
provider_name = self.class.to_s.gsub('Authenticator', '') | |
uid = auth_info[:uid].to_s | |
if user = User.find_by_provider_and_uid(provider_name, uid) | |
user.update_provider_token_and_secret(provider_name, auth_info[:credentials][:token], auth_info[:credentials][:secret]) | |
user | |
end | |
end | |
###################################################### | |
## Authentication setting method: Included in all subclasses. | |
##################################################### | |
def apply_omniauth_info_to_invite(token, auth) | |
invite = Invite.find_incomplete_by_token!(token) | |
if invite | |
auth_info = HashWithIndifferentAccess.new(auth) | |
provider_name = Enthuse::SocialNetworkMappings.downcased_provider_to_camelcased(auth_info['provider']) | |
data = "#{provider_name}DataParser".constantize.new(auth_info) | |
invite.set_authentication_provider_info data.as_json | |
invite | |
end | |
rescue ActiveRecord::RecordNotFound | |
binding.pry | |
Stats.increment("signup.#{@provider}.fail") | |
errors.add(:base, "Sorry, we couldn't find your invite. Please follow the link from your invite email.") | |
# When calling valid? after this it is returning true... even with errors. | |
return | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require './lib/enthuse/error_logger' | |
require './app/authenticators/authenticator' | |
require './app/authenticators/facebook_authenticator' | |
require './app/authenticators/tumblr_authenticator' | |
require './app/authenticators/twitter_authenticator' | |
require './app/authenticators/you_tube_authenticator' | |
require './app/authenticators/linked_in_authenticator' | |
require './app/authenticators/klout_authenticator' | |
require './app/authenticators/sound_cloud_authenticator' | |
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController | |
def authenticate | |
@auth = request.env['omniauth.auth'] | |
@provider = @auth.fetch('provider').downcase | |
@authenticator = Authenticator.authenticator_for_provider(@provider) | |
if user_signed_in? | |
@authenticator.add_authentication_to_user(current_user, @auth) | |
@authenticator.valid? ? authentication_added : authentication_failed_to_save | |
else | |
@user = @authenticator.find_user_with_auth(@auth) | |
if @user | |
sign_in_user_and_redirect | |
else | |
@invite = @authenticator.apply_omniauth_info_to_invite(session[:token], @auth) | |
@invite.valid? ? edit_signup_details : back_to_homepage | |
# called at this point. | |
end | |
end | |
end | |
# TODO: find a way to get omniauth callbacks working with a single action | |
alias_method :facebook, :authenticate | |
alias_method :linkedin, :authenticate | |
alias_method :twitter, :authenticate | |
alias_method :youtube, :authenticate | |
alias_method :klout, :authenticate | |
alias_method :tumblr, :authenticate | |
alias_method :soundcloud, :authenticate | |
########## Devise related path helpers | |
def after_omniauth_failure_path_for(scope) | |
new_user_session_path | |
end | |
def after_sign_in_path_for(scope) | |
profile_path(slug: scope.slug) | |
end | |
###################################### | |
private | |
def edit_signup_details | |
redirect_to edit_signup_path(@invite.token) | |
end | |
def back_to_homepage | |
redirect_to root_url | |
end | |
def sign_in_user_and_redirect | |
Stats.increment("login.#{@provider}") | |
url = session[:referer] || profile_path(@user.slug) | |
sign_in @user | |
redirect_to url, :event => :authentication | |
end | |
def authentication_added | |
flash[:alert] = "Your #{@provider} details have been updated" | |
redirect_to(@authenticator.url) | |
end | |
def authentication_failed_to_save | |
@authenticator.errors.each { |error| flash[:error] = error } | |
if current_user | |
redirect_to profile_path(slug: current_user.slug) | |
else | |
redirect_to root_url | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment