trabajo-afectivo/app/models/transaction/clearbit_enrichment.rb

322 lines
8.8 KiB
Ruby
Raw Normal View History

# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class Transaction::ClearbitEnrichment
=begin
{
object: 'User',
type: 'create',
object_id: 123,
changes: {
'attribute1' => [before, now],
'attribute2' => [before, now],
}
},
=end
def initialize(item, params = {})
@item = item
@params = params
end
def perform
# return if we run import mode
return if Setting.get('import_mode')
return if @item[:object] != 'User'
return if @item[:type] != 'create'
return if !Setting.get('clearbit_integration')
config = Setting.get('clearbit_config')
return if !config
return if config['api_key'].empty?
user = User.lookup(id: @item[:object_id])
return if !user
Transaction::ClearbitEnrichment.sync_user(user)
end
def self.sync
users = User.of_role('Customer')
users.each {|user|
sync_user(user)
}
end
def self.sync_user(user)
return if !user.email
data = fetch(user.email)
#p 'OO: ' + data.inspect
config = Setting.get('clearbit_config')
return if !config
# get new user sync attributes
user_sync = config['user_sync']
user_sync_values = {}
if user_sync
user_sync.each {|callback, destination|
next if !user_sync_values[destination].empty?
value = _replace(callback, data)
next if !value
user_sync_values[destination] = value
}
end
# get new organization sync attributes
organization_sync = config['organization_sync']
organization_sync_values = {}
if organization_sync
organization_sync.each {|callback, destination|
next if !organization_sync_values[destination].empty?
value = _replace(callback, data)
next if !value
organization_sync_values[destination] = value
}
end
# get latest user synced attributes
external_syn_user = nil
user_sync_values_last_time = {}
if data && data['person'] && data['person']['id']
external_syn_user = ExternalSync.find_by(
source: 'clearbit',
source_id: data['person']['id'],
object: 'User',
o_id: user.id,
)
if external_syn_user && external_syn_user.last_payload
user_sync.each {|callback, destination|
next if !user_sync_values_last_time[destination].empty?
value = _replace(callback, external_syn_user.last_payload)
next if !value
user_sync_values_last_time[destination] = value
}
end
end
# if person record exists
user_has_changed = false
user_sync_values.each {|destination, value|
attribute = destination.sub(/^user\./, '')
next if user[attribute] == value
next if !user[attribute].empty? && user_sync_values_last_time[destination] != user[attribute]
begin
user[attribute] = value
rescue => e
Rails.logger.error "ERROR: Unable to assign user.#{attribute}: #{e.inspect}"
end
user_has_changed = true
}
if user_has_changed
user.updated_by_id = 1
if data['person'] && data['person']['id']
if external_syn_user
external_syn_user.last_payload = data
external_syn_user.save
else
external_syn_user = ExternalSync.create(
source: 'clearbit',
source_id: data['person']['id'],
object: 'User',
o_id: user.id,
last_payload: data,
)
end
end
end
# if no company record exists
if !data['company']
if user_has_changed
user.save
end
Observer::Transaction.commit
return
end
# if company record exists
external_syn_organization = ExternalSync.find_by(
source: 'clearbit',
source_id: data['company']['id'],
)
# create new organization
if !external_syn_organization
# can't create organization without name
if organization_sync_values['organization.name'].empty?
Observer::Transaction.commit
return
end
# find by name
organization = Organization.find_by(name: organization_sync_values['organization.name'])
# create new organization
if !organization
organization = Organization.new(
shared: config['organization_shared'],
updated_by_id: 1,
created_by_id: 1,
)
organization_sync_values.each {|destination, value|
attribute = destination.sub(/^organization\./, '')
next if !organization[attribute].empty?
begin
organization[attribute] = value
rescue => e
Rails.logger.error "ERROR: Unable to assign organization.#{attribute}: #{e.inspect}"
end
}
organization.save
end
ExternalSync.create(
source: 'clearbit',
source_id: data['company']['id'],
object: 'Organization',
o_id: organization.id,
last_payload: data,
)
# assign new organization to user
if !user.organization_id
user.organization_id = organization.id
user.save
end
Observer::Transaction.commit
return
end
# get latest organization synced attributes
organization_sync_values_last_time = {}
if external_syn_organization && external_syn_organization.last_payload
organization_sync.each {|callback, destination|
next if !organization_sync_values_last_time[destination].empty?
value = _replace(callback, external_syn_organization.last_payload)
next if !value
organization_sync_values_last_time[destination] = value
}
end
# update existing organization
organization = Organization.find(external_syn_organization[:o_id])
organization_has_changed = false
organization_sync_values.each {|destination, value|
attribute = destination.sub(/^organization\./, '')
next if organization[attribute] == value
next if !organization[attribute].empty? && organization_sync_values_last_time[destination] != organization[attribute]
begin
organization[attribute] = value
rescue => e
Rails.logger.error "ERROR: Unable to assign organization.#{attribute}: #{e.inspect}"
end
organization_has_changed = true
}
if organization_has_changed
organization.updated_by_id = 1
organization.save
external_syn_organization.last_payload = data
external_syn_organization.save
end
# assign new organization to user
if !user.organization_id
user_has_changed = true
user.organization_id = organization.id
end
if user_has_changed
user.save
end
Observer::Transaction.commit
true
end
def self._replace(callback, data)
object_name = nil
object_method = nil
placeholder = nil
if callback =~ /\A ( [\w]+ )\.( [\w\.]+ ) \z/x
object_name = $1
object_method = $2
end
return if !data
return if !data[object_name]
# do validaton, ignore some methodes
if callback =~ /(`|\.(|\s*)(save|destroy|delete|remove|drop|update\(|update_att|create\(|new|all|where|find))/i
placeholder = "#{callback} (not allowed)"
# get value based on object_name and object_method
elsif object_name && object_method
object_refs = data[object_name]
object_methods = object_method.split('.')
object_methods_s = ''
object_methods.each {|method|
if object_methods_s != ''
object_methods_s += '.'
end
object_methods_s += method
# if method exists
break if !object_refs.respond_to?(method.to_sym) && !object_refs[method]
object_refs = if object_refs.respond_to?(method.to_sym)
object_refs.send(method.to_sym)
else
object_refs[method]
end
}
if object_refs.class == String
placeholder = object_refs
end
end
placeholder
end
def self.fetch(email)
if !Rails.env.production?
filename = "#{Rails.root}/test/fixtures/clearbit/#{email}.json"
if File.exist?(filename)
data = IO.binread(filename)
return JSON.parse(data) if data
end
end
config = Setting.get('clearbit_config')
return if !config
return if config['api_key'].empty?
record = {
direction: 'out',
facility: 'clearbit',
url: "clearbit -> #{email}",
status: 200,
ip: nil,
request: { content: email },
response: {},
method: 'GET',
}
begin
Clearbit.key = config['api_key']
result = Clearbit::Enrichment.find(email: email, stream: true)
record[:response] = { code: 200, content: result.to_s }
rescue => e
record[:status] = 500
record[:response] = { code: 500, content: e.inspect }
end
HttpLog.create(record)
result
end
end