require 'trusty/omniauth/mapping_helpers'
require 'trusty/omniauth/model_mapper'
module Trusty
module Omniauth
class ProviderMapper
include MappingHelpers
attr_reader :provider_name, :provider_attributes, :options
attr_reader :provider_identity, :provider_user
def initialize(provider_attributes, options = {})
@provider_attributes = provider_attributes.with_indifferent_access
@provider_name = provider_attributes['provider']
@options = {
:user_attributes => {},
:identity_attributes => {},
:skip_raw_info => false,
:skip_nils => true
}.merge(options)
@provider_identity = ModelMapper.new(self,
:model => @options[:identity_model] || ::Identity,
:attributes => @options[:identity_attributes],
:attribute_names => @options[:identity_attribute_names],
:unique_identifiers => @options[:identity_identifiers] || [:provider, :uid],
:required_criteria => @options[:identity_required_criteria]
)
@provider_user = ModelMapper.new(self,
:model => @options[:user_model] || ::User,
:attributes => @options[:user_attributes],
:attribute_names => @options[:user_attribute_names],
:unique_identifiers => @options[:user_identifiers] || [:email],
:required_criteria => @options[:user_required_criteria]
)
end
def find_identities_for_user(user)
@provider_identity.find_records(user_id: user.id)
end
def matched_identities
@matched_identities ||= @provider_identity.find_records
end
def identities_exist?
matched_identities.any?
end
def single_identity?
matched_identities.size == 1
end
def multiple_identities?
matched_identities.size > 1
end
def matched_users
@matched_users ||= @provider_user.find_records
end
def users_exist?
matched_users.any?
end
def single_user?
matched_users.size == 1
end
def multiple_users?
matched_users.size > 1
end
def single_user
@single_user ||= matched_users.first if single_user?
end
def single_identity
@single_identity ||= matched_identities.first if single_identity?
end
def build_user(attributes = {})
@provider_user.build_record(attributes)
end
def build_identity(attributes = {})
@provider_identity.build_record(attributes)
end
def build_identity_for_user(user)
build_identity(user: user)
end
def update_identity!(identity)
@provider_identity.update_record!(identity)
end
def attributes(*filter_attribute_names)
unless @attributes
info = provider_attributes.fetch('info', {})
credentials = provider_attributes['credentials']
name = clean(info['name']) { [info['first_name'], info['last_name']].join(" ").strip }
first_name = clean(info['first_name']) { name.split(/\s+/, 2).first }
last_name = clean(info['last_name']) { name.split(/\s+/, 2).last }
@attributes = {
:provider => provider_name,
:uid => clean(provider_attributes['uid']),
:name => name,
:email => clean(info['email'], :downcase, :strip),
:verified => provider_attributes['extra']['raw_info']['verified_email'] == true,
:username => clean(info['nickname']),
:first_name => first_name,
:middle_name => clean(info['middle_name']),
:last_name => last_name,
:phone => clean(info['phone']),
:image_url => info['image'],
:profile_url => info.fetch('urls', {})['public_profile'],
:token_type => clean(credentials['token_type']),
:token => clean(credentials['token']),
:secret => clean(credentials['secret']),
:refresh_token => clean(credentials['refresh_token']),
:expires => credentials['expires'] == true,
:expires_at => (Time.at(credentials['expires_at']) rescue nil),
:raw_info => provider_attributes['extra'].except('access_token').as_json,
:location => info['location'],
:time_zone => info['time_zone'] || Time.zone.name,
:locale => info['locale'] || I18n.locale
}.with_indifferent_access
@attributes.reject!{|_,value| value.nil?} if options[:skip_nils]
@attributes.delete(:raw_info) if options[:skip_raw_info]
end
if filter_attribute_names.any?
@attributes.slice(*filter_attribute_names)
else
@attributes.dup
end
end
end
end
end