Skip to content

Commit

Permalink
Remove global env variables from organizations (#2016)
Browse files Browse the repository at this point in the history
Closes #1947 

@soey there is still the `three_sixty_dialog_partner_token` attribute
that lives at the organization level, which it probably shouldn't. This
is also a value that is global and is not unique to the organization.
The token is only good for 24 hours, which makes it difficult to get the
value from env variables. Previously, with `rails-settings-cached`, we
would save the value to the db in the `settings` table and then check to
see if there was a value and that it had been updated within 24 hours
before asking for a new token, or using the valid one.

Currently, this is used for creating the api key for a newly onboarded
client. It then is used to create the templates needed to send out
messages for that client.

I think a better way to handle this would be to assume the token is not
valid, if it even exists, since we are unlikely to be onboarding
multiple clients in the same 24-hour period and always ask for a new
token when we run the create api key job. The create template job is
currently called from a rake task that collects the templates from our
`de.yml` before scheduling the job. We would need to rethink this flow
if we wanted to be able to use the same token to create the templates.
  • Loading branch information
mattwr18 authored Sep 17, 2024
1 parent c6c60b6 commit 347a810
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 74 deletions.
20 changes: 10 additions & 10 deletions app/jobs/whats_app_adapter/create_api_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@ module WhatsAppAdapter
class CreateApiKey < ApplicationJob
def perform(organization_id:, channel_id:)
@organization = Organization.find_by(id: organization_id)
return unless organization && organization.three_sixty_dialog_partner_id.present?
return unless organization && ENV.fetch('THREE_SIXTY_DIALOG_PARTNER_ID', nil).present?

@base_uri = ENV.fetch('THREE_SIXTY_DIALOG_PARTNER_REST_API_ENDPOINT', 'https://stoplight.io/mocks/360dialog/360dialog-partner-api/24588693')

token = organization.three_sixty_dialog_partner_token
fetch_token unless token.present? && organization.updated_at > 24.hours.ago
partner_id = organization.three_sixty_dialog_partner_id
@token = fetch_token
partner_id = ENV.fetch('THREE_SIXTY_DIALOG_PARTNER_ID', nil)

url = URI.parse(
"#{base_uri}/partners/#{partner_id}/channels/#{channel_id}/api_keys"
)
headers = {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: "Bearer #{organization.three_sixty_dialog_partner_token}"
Authorization: "Bearer #{token}"
}
request = Net::HTTP::Post.new(url.to_s, headers)
response = Net::HTTP.start(url.host, url.port, use_ssl: true) do |http|
Expand All @@ -31,7 +30,7 @@ def perform(organization_id:, channel_id:)

private

attr_reader :base_uri, :organization
attr_reader :base_uri, :organization, :token

def fetch_token
url = URI.parse("#{base_uri}/token")
Expand All @@ -40,14 +39,13 @@ def fetch_token
}
request = Net::HTTP::Post.new(url.to_s, headers)
request.body = {
username: organization.three_sixty_dialog_partner_username,
password: organization.three_sixty_dialog_partner_password
username: ENV.fetch('THREE_SIXTY_DIALOG_PARTNER_USERNAME', nil),
password: ENV.fetch('THREE_SIXTY_DIALOG_PARTNER_PASSWORD', nil)
}.to_json
response = Net::HTTP.start(url.host, url.port, use_ssl: true) do |http|
http.request(request)
end
token = JSON.parse(response.body)['access_token']
organization.update!(three_sixty_dialog_partner_token: token)
JSON.parse(response.body)['access_token']
end

def handle_response(response)
Expand All @@ -57,6 +55,8 @@ def handle_response(response)
Rails.logger.debug api_key
organization.update!(three_sixty_dialog_client_api_key: api_key)
WhatsAppAdapter::SetWebhookUrl.perform_later(organization_id: organization.id)
WhatsAppAdapter::CreateTemplates.perform_later(organization_id: organization.id, token: token)

when 400..599
exception = WhatsAppAdapter::ThreeSixtyDialogError.new(error_code: response.code, message: response.body)
ErrorNotifier.report(exception)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,46 @@

require 'net/http'

# rubocop:disable Metrics/ClassLength
module WhatsAppAdapter
class CreateTemplate < ApplicationJob
def perform(organization_id:, template_name:, template_text:)
class CreateTemplates < ApplicationJob
def perform(organization_id:, token:)
@organization = Organization.find_by(id: organization_id)
return unless organization

@base_uri = ENV.fetch('THREE_SIXTY_DIALOG_PARTNER_REST_API_ENDPOINT', 'https://stoplight.io/mocks/360dialog/360dialog-partner-api/24588693')
@partner_id = ENV.fetch('THREE_SIXTY_DIALOG_PARTNER_ID', nil)
@template_name = template_name
@template_text = template_text

@token = organization.three_sixty_dialog_partner_token
@token = fetch_token unless token.present? && organization.updated_at > 24.hours.ago

@token = token
@waba_account_id = organization.three_sixty_dialog_client_waba_account_id
waba_accont_namespace = organization.three_sixty_dialog_whats_app_template_namespace
@waba_account_id = fetch_client_info if waba_account_id.blank? || waba_accont_namespace.blank?
@waba_account_id = fetch_client_info if waba_account_id.blank? || organization.three_sixty_dialog_whats_app_template_namespace.blank?

templates_to_create_array = whats_app_templates.keys.difference(existing_templates)
templates_to_create = whats_app_templates.select { |key, _value| key.in?(templates_to_create_array) }
templates_to_create.each do |key, value|
@template_name = key
@template_text = value

conditionally_create_template
create_template
end
end

attr_reader :organization, :base_uri, :partner_id, :template_name, :template_text, :token, :waba_account_id

private

def conditionally_create_template
# rubocop:disable Style/FormatStringToken
def whats_app_templates
default_welcome_message = ["*#{File.read(File.join('config', 'locales', 'onboarding', 'success_heading.txt'))}*",
File.read(File.join('config', 'locales', 'onboarding',
'success_text.txt'))].join("\n\n").gsub('100eyes', '{{1}}')
default_welcome_message_hash = { default_welcome_message: default_welcome_message }
requests_hash = I18n.t('.')[:adapter][:whats_app][:request_template].transform_values do |value|
value.gsub('%{first_name}', '{{1}}').gsub('%{request_title}', '{{2}}')
end
default_welcome_message_hash.merge(requests_hash)
end
# rubocop:enable Style/FormatStringToken

def existing_templates
url = URI.parse(
"#{base_uri}/partners/#{partner_id}/waba_accounts/#{waba_account_id}/waba_templates"
)
Expand All @@ -38,10 +51,7 @@ def conditionally_create_template
http.request(request)
end
waba_templates = JSON.parse(response.body)['waba_templates']
template_names_array = waba_templates.pluck('name')
return if template_name.in?(template_names_array)

create_template
waba_templates.pluck('name').map(&:to_sym)
end

def create_template
Expand All @@ -61,33 +71,15 @@ def create_template

def set_headers
{
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: "Bearer #{organization.three_sixty_dialog_partner_token}"
Authorization: "Bearer #{token}"
}
end

def fetch_token
url = URI.parse("#{base_uri}/token")
headers = { 'Content-Type': 'application/json' }
request = Net::HTTP::Post.new(url.to_s, headers)
request.body = {
username: organization.three_sixty_dialog_partner_username,
password: organization.three_sixty_dialog_partner_password
}.to_json
response = Net::HTTP.start(url.host, url.port, use_ssl: true) do |http|
http.request(request)
end
token = JSON.parse(response.body)['access_token']
organization.update!(three_sixty_dialog_partner_token: token)
end

def fetch_client_info
url = URI.parse("#{base_uri}/partners/#{partner_id}/channels")
headers = {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: "Bearer #{organization.three_sixty_dialog_partner_token}"
}
headers = set_headers
request = Net::HTTP::Get.new(url.to_s, headers)
response = Net::HTTP.start(url.host, url.port, use_ssl: true) do |http|
http.request(request)
Expand Down Expand Up @@ -170,4 +162,3 @@ def handle_response(response)
end
end
end
# rubocop:enable Metrics/ClassLength
2 changes: 1 addition & 1 deletion app/models/organization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Organization < ApplicationRecord
attr_encrypted_options.merge!(key: Base64.decode64(ENV.fetch('ATTR_ENCRYPTED_KEY', nil)))
attr_encrypted :threemarb_api_secret, :threemarb_private
attr_encrypted :twilio_api_key_secret
attr_encrypted :three_sixty_dialog_partner_password, :three_sixty_dialog_partner_token, :three_sixty_dialog_client_api_key
attr_encrypted :three_sixty_dialog_client_api_key
attr_encrypted :telegram_bot_api_key

belongs_to :business_plan
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

class RemoveGlobalEnvVariablesFromOrganizations < ActiveRecord::Migration[6.1]
def change
change_table :organizations, bulk: true do |t|
t.remove :three_sixty_dialog_partner_id, type: :string
t.remove :three_sixty_dialog_partner_username, type: :string
t.remove :encrypted_three_sixty_dialog_partner_password, type: :string
t.remove :encrypted_three_sixty_dialog_partner_password_iv, type: :string
t.remove :encrypted_three_sixty_dialog_partner_token, type: :string
t.remove :encrypted_three_sixty_dialog_partner_token_iv, type: :string
end
end
end
6 changes: 0 additions & 6 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,6 @@
t.string "twilio_account_sid"
t.string "whats_app_server_phone_number"
t.string "three_sixty_dialog_whats_app_template_namespace"
t.string "three_sixty_dialog_partner_id"
t.string "three_sixty_dialog_partner_username"
t.string "encrypted_three_sixty_dialog_partner_password"
t.string "encrypted_three_sixty_dialog_partner_password_iv"
t.string "encrypted_three_sixty_dialog_partner_token"
t.string "encrypted_three_sixty_dialog_partner_token_iv"
t.string "encrypted_three_sixty_dialog_client_api_key"
t.string "encrypted_three_sixty_dialog_client_api_key_iv"
t.string "three_sixty_dialog_client_id"
Expand Down
18 changes: 0 additions & 18 deletions lib/tasks/whats_app/create_templates.rake

This file was deleted.

0 comments on commit 347a810

Please sign in to comment.