2016-10-19 03:11:36 +00:00
|
|
|
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
2016-04-25 23:04:59 +00:00
|
|
|
|
|
|
|
class Transaction::ClearbitEnrichment
|
|
|
|
|
|
|
|
=begin
|
|
|
|
{
|
|
|
|
object: 'User',
|
|
|
|
type: 'create',
|
|
|
|
object_id: 123,
|
|
|
|
changes: {
|
|
|
|
'attribute1' => [before, now],
|
|
|
|
'attribute2' => [before, now],
|
2016-07-16 21:43:08 +00:00
|
|
|
},
|
|
|
|
created_at: Time.zone.now,
|
2016-04-27 07:31:11 +00:00
|
|
|
user_id: 123,
|
2016-04-25 23:04:59 +00:00
|
|
|
},
|
|
|
|
=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
|
|
|
|
|
2016-05-16 15:02:15 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
sync all users against clearbit
|
|
|
|
|
|
|
|
Transaction::ClearbitEnrichment.sync
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
2016-04-25 23:04:59 +00:00
|
|
|
def self.sync
|
2016-08-12 16:39:09 +00:00
|
|
|
users = User.of_role(Role.signup_roles)
|
2016-06-30 20:04:48 +00:00
|
|
|
users.each { |user|
|
2016-04-25 23:04:59 +00:00
|
|
|
sync_user(user)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2016-05-16 15:02:15 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
sync one users against clearbit
|
|
|
|
|
|
|
|
Transaction::ClearbitEnrichment.sync_user(user)
|
|
|
|
|
|
|
|
users = [...]
|
|
|
|
|
|
|
|
users.each {|user|
|
|
|
|
Transaction::ClearbitEnrichment.sync_user(user)
|
|
|
|
}
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
2016-04-25 23:04:59 +00:00
|
|
|
def self.sync_user(user)
|
2016-04-26 09:30:46 +00:00
|
|
|
UserInfo.current_user_id = 1
|
2016-04-25 23:04:59 +00:00
|
|
|
|
2016-04-25 23:38:37 +00:00
|
|
|
return if user.email.empty?
|
2016-04-25 23:04:59 +00:00
|
|
|
data = fetch(user.email)
|
|
|
|
#p 'OO: ' + data.inspect
|
2016-04-25 23:25:53 +00:00
|
|
|
return if !data
|
2016-04-25 23:04:59 +00:00
|
|
|
|
|
|
|
config = Setting.get('clearbit_config')
|
|
|
|
return if !config
|
|
|
|
|
|
|
|
# get new user sync attributes
|
|
|
|
user_sync = config['user_sync']
|
|
|
|
user_sync_values = {}
|
|
|
|
if user_sync
|
2016-06-30 20:04:48 +00:00
|
|
|
user_sync.each { |callback, destination|
|
2016-04-25 23:04:59 +00:00
|
|
|
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
|
2016-06-30 20:04:48 +00:00
|
|
|
organization_sync.each { |callback, destination|
|
2016-04-25 23:04:59 +00:00
|
|
|
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
|
2016-06-30 20:04:48 +00:00
|
|
|
user_sync.each { |callback, destination|
|
2016-04-25 23:04:59 +00:00
|
|
|
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
|
2016-06-30 20:04:48 +00:00
|
|
|
user_sync_values.each { |destination, value|
|
2016-04-25 23:04:59 +00:00
|
|
|
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
|
|
|
|
|
2016-04-25 23:38:37 +00:00
|
|
|
# if no company record exists or no organization should be created
|
|
|
|
if !data['company'] || config['organization_autocreate'] != true
|
2016-04-25 23:04:59 +00:00
|
|
|
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
|
|
|
|
|
2016-04-26 06:48:44 +00:00
|
|
|
# if organization is already assigned, do not create a new one
|
|
|
|
if user.organization_id
|
|
|
|
if user_has_changed
|
|
|
|
user.save
|
|
|
|
Observer::Transaction.commit
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2016-04-25 23:04:59 +00:00
|
|
|
# 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'],
|
|
|
|
)
|
2016-06-30 20:04:48 +00:00
|
|
|
organization_sync_values.each { |destination, value|
|
2016-04-25 23:04:59 +00:00
|
|
|
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
|
2016-06-30 20:04:48 +00:00
|
|
|
organization_sync.each { |callback, destination|
|
2016-04-25 23:04:59 +00:00
|
|
|
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
|
2016-06-30 20:04:48 +00:00
|
|
|
organization_sync_values.each { |destination, value|
|
2016-04-25 23:04:59 +00:00
|
|
|
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 = ''
|
2016-06-30 20:04:48 +00:00
|
|
|
object_methods.each { |method|
|
2016-04-25 23:04:59 +00:00
|
|
|
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
|