user.rb 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. module Enrichment
  3. module Clearbit
  4. class User
  5. def initialize(user)
  6. @local_user = user
  7. @source = 'clearbit'
  8. @config = Setting.get('clearbit_config')
  9. end
  10. def synced?
  11. return false if !@config
  12. return false if @local_user.email.blank?
  13. UserInfo.current_user_id = 1
  14. return false if !mapping?
  15. payload = fetch
  16. return false if !payload
  17. attributes_changed = attributes_changed?(payload)
  18. organization_synced = false
  19. if payload['company'] && @config['organization_autocreate']
  20. organization = Enrichment::Clearbit::Organization.new(
  21. user: @local_user,
  22. payload: payload
  23. )
  24. organization_synced = organization.synced?
  25. end
  26. return false if !attributes_changed && !organization_synced
  27. @local_user.save if attributes_changed || organization_synced
  28. true
  29. end
  30. private
  31. def mapping?
  32. @mapping = @config['user_sync'].dup
  33. return false if @mapping.blank?
  34. # TODO: Refactoring:
  35. # Currently all target keys are prefixed with
  36. # user.
  37. # which is not necessary since the target object
  38. # is always a user
  39. @mapping.transform_values! { |value| value.sub('user.', '') }
  40. true
  41. end
  42. def load_remote(data)
  43. return if !remote_id?(data)
  44. return if !external_found?
  45. load_previous_changes
  46. end
  47. def remote_id?(data)
  48. return if !data
  49. return if !data['person']
  50. @remote_id = data['person']['id']
  51. end
  52. def external_found?
  53. return true if @external_user
  54. @external_user = ExternalSync.find_by(
  55. source: @source,
  56. source_id: @remote_id,
  57. object: @local_user.class.name,
  58. o_id: @local_user.id,
  59. )
  60. @external_user.present?
  61. end
  62. def load_previous_changes
  63. last_payload = @external_user.last_payload
  64. return if !last_payload
  65. @previous_changes = ExternalSync.map(
  66. mapping: @mapping,
  67. source: last_payload
  68. )
  69. end
  70. def attributes_changed?(payload)
  71. current_changes = ExternalSync.map(
  72. mapping: @mapping,
  73. source: payload
  74. )
  75. return false if !current_changes
  76. previous_changes = load_remote(payload)
  77. return false if !ExternalSync.changed?(
  78. object: @local_user,
  79. previous_changes: previous_changes,
  80. current_changes: current_changes,
  81. )
  82. @local_user.updated_by_id = 1
  83. return true if !@remote_id
  84. store_current(payload)
  85. true
  86. end
  87. def store_current(payload)
  88. if !external_found?
  89. @external_user = ExternalSync.new(
  90. source: @source,
  91. source_id: @remote_id,
  92. object: @local_user.class.name,
  93. o_id: @local_user.id,
  94. )
  95. end
  96. @external_user.last_payload = payload
  97. @external_user.save
  98. end
  99. def fetch
  100. if !Rails.env.production?
  101. filename = Rails.root.join('test', 'data', 'clearbit', "#{@local_user.email}.json")
  102. if File.exist?(filename)
  103. data = File.binread(filename)
  104. return JSON.parse(data) if data
  105. end
  106. end
  107. return if @config['api_key'].blank?
  108. record = {
  109. direction: 'out',
  110. facility: 'clearbit',
  111. url: "clearbit -> #{@local_user.email}",
  112. status: 200,
  113. ip: nil,
  114. request: { content: @local_user.email },
  115. response: {},
  116. method: 'GET',
  117. }
  118. begin
  119. require 'clearbit' # Only load this gem when it is really used.
  120. ::Clearbit.key = @config['api_key']
  121. result = ::Clearbit::Enrichment.find(email: @local_user.email, stream: true)
  122. record[:response] = { code: 200, content: result.to_s }
  123. rescue => e
  124. record[:status] = 500
  125. record[:response] = { code: 500, content: e.inspect }
  126. end
  127. HttpLog.create(record)
  128. result
  129. end
  130. class << self
  131. def all
  132. users = User.of_role(Role.signup_roles)
  133. users.each do |user|
  134. new(user).synced?
  135. end
  136. end
  137. end
  138. end
  139. end
  140. end