feat: account onboarding with clearbit (#8857)
* feat: add clearbit lookup * chore: fix typo in .env.example * refactor: split lookup to reduce cognitive complexity * feat: add more fields to lookup * feat: extend accounts controller * feat: save extra data to custom_attributes * feat: allow v2 update with custom_attributes * feat: add update route * refactor: reduce complexity * feat: move update to v1 controller * test: add locale test * feat: remove update from routes * test: update API for custom attributes * test: all custom attributes * fix: v2 tests * test: enterprise accounts controller * fix: clearbit payload * fix: with modified env * feat: allow custom attributes updates to profile * refactor: reduce complexity * feat: allow clearbit api key in installation config * refactor: move clearbit to internal * feat: allow clearbit * chore: add display_title for June * feat: allow more internal options * refactor: use globalconfig to fetch clearbit token * test: move response body to a factory * refactor: update ops * chore: remove clearbit from .env.example * chore: apply suggestions from code review Co-authored-by: sojan-official <sojan@chatwoot.com> --------- Co-authored-by: sojan-official <sojan@chatwoot.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
module Enterprise::Api::V2::AccountsController
|
||||
private
|
||||
|
||||
def fetch_account_and_user_info
|
||||
data = fetch_from_clearbit
|
||||
|
||||
return if data.blank?
|
||||
|
||||
update_user_info(data)
|
||||
update_account_info(data)
|
||||
end
|
||||
|
||||
def fetch_from_clearbit
|
||||
Enterprise::ClearbitLookupService.lookup(@user.email)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error "Error fetching data from clearbit: #{e}"
|
||||
nil
|
||||
end
|
||||
|
||||
def update_user_info(data)
|
||||
@user.update!(name: data[:name])
|
||||
end
|
||||
|
||||
def update_account_info(data)
|
||||
@account.update!(
|
||||
name: data[:company_name],
|
||||
custom_attributes: @account.custom_attributes.merge(
|
||||
'industry' => data[:industry],
|
||||
'company_size' => data[:company_size],
|
||||
'timezone' => data[:timezone],
|
||||
'logo' => data[:logo]
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
@@ -6,20 +6,30 @@ module Enterprise::SuperAdmin::AppConfigsController
|
||||
|
||||
case @config
|
||||
when 'custom_branding'
|
||||
@allowed_configs = %w[
|
||||
LOGO_THUMBNAIL
|
||||
LOGO
|
||||
LOGO_DARK
|
||||
BRAND_NAME
|
||||
INSTALLATION_NAME
|
||||
BRAND_URL
|
||||
WIDGET_BRAND_URL
|
||||
TERMS_URL
|
||||
PRIVACY_URL
|
||||
DISPLAY_MANIFEST
|
||||
]
|
||||
@allowed_configs = custom_branding_options
|
||||
when 'internal'
|
||||
@allowed_configs = internal_config_options
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def custom_branding_options
|
||||
%w[
|
||||
LOGO_THUMBNAIL
|
||||
LOGO
|
||||
LOGO_DARK
|
||||
BRAND_NAME
|
||||
INSTALLATION_NAME
|
||||
BRAND_URL
|
||||
WIDGET_BRAND_URL
|
||||
TERMS_URL
|
||||
PRIVACY_URL
|
||||
DISPLAY_MANIFEST
|
||||
]
|
||||
end
|
||||
|
||||
def internal_config_options
|
||||
%w[CHATWOOT_INBOX_TOKEN CHATWOOT_INBOX_HMAC_KEY ANALYTICS_TOKEN CLEARBIT_API_KEY]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# The Enterprise::ClearbitLookupService class is responsible for interacting with the Clearbit API.
|
||||
# It provides methods to lookup a person's information using their email.
|
||||
# Clearbit API documentation: {https://dashboard.clearbit.com/docs?ruby#api-reference}
|
||||
# We use the combined API which returns both the person and comapnies together
|
||||
# Combined API: {https://dashboard.clearbit.com/docs?ruby=#enrichment-api-combined-api}
|
||||
# Persons API: {https://dashboard.clearbit.com/docs?ruby=#enrichment-api-person-api}
|
||||
# Companies API: {https://dashboard.clearbit.com/docs?ruby=#enrichment-api-company-api}
|
||||
#
|
||||
# Note: The Clearbit gem is not used in this service, since it is not longer maintained
|
||||
# GitHub: {https://github.com/clearbit/clearbit-ruby}
|
||||
#
|
||||
# @example
|
||||
# Enterprise::ClearbitLookupService.lookup('test@example.com')
|
||||
class Enterprise::ClearbitLookupService
|
||||
# Clearbit API endpoint for combined lookup
|
||||
CLEARBIT_ENDPOINT = 'https://person.clearbit.com/v2/combined/find'.freeze
|
||||
|
||||
# Performs a lookup on the Clearbit API using the provided email.
|
||||
#
|
||||
# @param email [String] The email address to lookup.
|
||||
# @return [Hash, nil] A hash containing the person's full name, company name, and company timezone, or nil if an error occurs.
|
||||
def self.lookup(email)
|
||||
return nil unless clearbit_enabled?
|
||||
|
||||
response = perform_request(email)
|
||||
process_response(response)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error "[ClearbitLookup] #{e.message}"
|
||||
nil
|
||||
end
|
||||
|
||||
# Performs a request to the Clearbit API using the provided email.
|
||||
#
|
||||
# @param email [String] The email address to lookup.
|
||||
# @return [HTTParty::Response] The response from the Clearbit API.
|
||||
def self.perform_request(email)
|
||||
options = {
|
||||
headers: { 'Authorization' => "Bearer #{clearbit_token}" },
|
||||
query: { email: email }
|
||||
}
|
||||
|
||||
HTTParty.get(CLEARBIT_ENDPOINT, options)
|
||||
end
|
||||
|
||||
# Handles an error response from the Clearbit API.
|
||||
#
|
||||
# @param response [HTTParty::Response] The response from the Clearbit API.
|
||||
# @return [nil] Always returns nil.
|
||||
def self.handle_error(response)
|
||||
Rails.logger.error "[ClearbitLookup] API Error: #{response.message} (Status: #{response.code})"
|
||||
nil
|
||||
end
|
||||
|
||||
# Checks if Clearbit is enabled by checking for the presence of the CLEARBIT_API_KEY environment variable.
|
||||
#
|
||||
# @return [Boolean] True if Clearbit is enabled, false otherwise.
|
||||
def self.clearbit_enabled?
|
||||
clearbit_token.present?
|
||||
end
|
||||
|
||||
def self.clearbit_token
|
||||
GlobalConfigService.load('CLEARBIT_API_KEY', '')
|
||||
end
|
||||
|
||||
# Processes the response from the Clearbit API.
|
||||
#
|
||||
# @param response [HTTParty::Response] The response from the Clearbit API.
|
||||
# @return [Hash, nil] A hash containing the person's full name, company name, and company timezone, or nil if an error occurs.
|
||||
def self.process_response(response)
|
||||
return handle_error(response) unless response.success?
|
||||
|
||||
format_response(response)
|
||||
end
|
||||
|
||||
# Formats the response data from the Clearbit API.
|
||||
#
|
||||
# @param data [Hash] The raw data from the Clearbit API.
|
||||
# @return [Hash] A hash containing the person's full name, company name, and company timezone.
|
||||
def self.format_response(response)
|
||||
data = response.parsed_response
|
||||
|
||||
{
|
||||
name: data.dig('person', 'name', 'fullName'),
|
||||
avatar: data.dig('person', 'avatar'),
|
||||
company_name: data.dig('company', 'name'),
|
||||
timezone: data.dig('company', 'timeZone'),
|
||||
logo: data.dig('company', 'logo'),
|
||||
industry: data.dig('company', 'category', 'industry'),
|
||||
company_size: data.dig('company', 'metrics', 'employees')
|
||||
}
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user