123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- # 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
- return if !data
- 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
|