diff --git a/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb b/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb index e6e5b63c3..d2d51baef 100644 --- a/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb +++ b/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb @@ -18,7 +18,11 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts: end def authenticate_twilio - client = Twilio::REST::Client.new(permitted_params[:account_sid], permitted_params[:auth_token]) + client = if permitted_params[:api_key_sid].present? + Twilio::REST::Client.new(permitted_params[:api_key_sid], permitted_params[:auth_token], permitted_params[:account_sid]) + else + Twilio::REST::Client.new(permitted_params[:account_sid], permitted_params[:auth_token]) + end client.messages.list(limit: 1) end @@ -40,6 +44,7 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts: @twilio_channel = Current.account.twilio_sms.create!( account_sid: permitted_params[:account_sid], auth_token: permitted_params[:auth_token], + api_key_sid: permitted_params[:api_key_sid], messaging_service_sid: permitted_params[:messaging_service_sid].presence, phone_number: phone_number, medium: medium @@ -52,7 +57,7 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts: def permitted_params params.require(:twilio_channel).permit( - :account_id, :messaging_service_sid, :phone_number, :account_sid, :auth_token, :name, :medium + :account_id, :messaging_service_sid, :phone_number, :account_sid, :auth_token, :name, :medium, :api_key_sid ) end end diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json index f77124121..99ac944a8 100644 --- a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json +++ b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json @@ -111,6 +111,17 @@ "PLACEHOLDER": "Please enter your Twilio Account SID", "ERROR": "This field is required" }, + "API_KEY": { + "USE_API_KEY": "Use API Key Authentication", + "LABEL": "API Key SID", + "PLACEHOLDER": "Please enter your API Key SID", + "ERROR": "This field is required" + }, + "API_KEY_SECRET": { + "LABEL": "API Key Secret", + "PLACEHOLDER": "Please enter your API Key Secret", + "ERROR": "This field is required" + }, "MESSAGING_SERVICE_SID": { "LABEL": "Messaging Service SID", "PLACEHOLDER": "Please enter your Twilio Messaging Service SID", diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Twilio.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Twilio.vue index 17596f8bc..1dfd6dfe0 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Twilio.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Twilio.vue @@ -81,18 +81,45 @@ }} +
+ +
+
+ +
@@ -123,11 +150,13 @@ export default { data() { return { accountSID: '', + apiKeySID: '', authToken: '', medium: this.type, channelName: '', messagingServiceSID: '', useMessagingService: false, + useAPIKey: false, phoneNumber: '', }; }, @@ -135,26 +164,39 @@ export default { ...mapGetters({ uiFlags: 'inboxes/getUIFlags', }), + authTokeni18nKey() { + return this.useAPIKey ? 'API_KEY_SECRET' : 'AUTH_TOKEN'; + }, }, validations() { - if (this.phoneNumber) { - return { - channelName: { required }, - messagingServiceSID: {}, - phoneNumber: { required, isPhoneE164OrEmpty }, - authToken: { required }, - accountSID: { required }, - medium: { required }, - }; - } - return { + let validations = { channelName: { required }, - messagingServiceSID: { required }, - phoneNumber: {}, + authToken: { required }, accountSID: { required }, medium: { required }, }; + if (this.phoneNumber) { + validations = { + ...validations, + phoneNumber: { required, isPhoneE164OrEmpty }, + messagingServiceSID: {}, + }; + } else { + validations = { + ...validations, + messagingServiceSID: { required }, + phoneNumber: {}, + }; + } + + if (this.useAPIKey) { + validations = { + ...validations, + apiKeySID: { required }, + }; + } + return validations; }, methods: { async createChannel() { @@ -171,6 +213,7 @@ export default { name: this.channelName, medium: this.medium, account_sid: this.accountSID, + api_key_sid: this.apiKeySID, auth_token: this.authToken, messaging_service_sid: this.messagingServiceSID, phone_number: this.messagingServiceSID diff --git a/app/models/channel/twilio_sms.rb b/app/models/channel/twilio_sms.rb index d6c9177fb..05ca9a567 100644 --- a/app/models/channel/twilio_sms.rb +++ b/app/models/channel/twilio_sms.rb @@ -4,6 +4,7 @@ # # id :bigint not null, primary key # account_sid :string not null +# api_key_sid :string # auth_token :string not null # medium :integer default("sms") # messaging_service_sid :string @@ -25,6 +26,7 @@ class Channel::TwilioSms < ApplicationRecord self.table_name = 'channel_twilio_sms' validates :account_sid, presence: true + # The same parameter is used to store api_key_secret if api_key authentication is opted validates :auth_token, presence: true # Must have _one_ of messaging_service_sid _or_ phone_number, and messaging_service_sid is preferred @@ -51,7 +53,11 @@ class Channel::TwilioSms < ApplicationRecord private def client - ::Twilio::REST::Client.new(account_sid, auth_token) + if api_key_sid.present? + Twilio::REST::Client.new(api_key_sid, auth_token, account_sid) + else + Twilio::REST::Client.new(account_sid, auth_token) + end end def send_message_from diff --git a/db/migrate/20230714054138_add_api_key_sid_to_twilio_sms.rb b/db/migrate/20230714054138_add_api_key_sid_to_twilio_sms.rb new file mode 100644 index 000000000..532d036e0 --- /dev/null +++ b/db/migrate/20230714054138_add_api_key_sid_to_twilio_sms.rb @@ -0,0 +1,5 @@ +class AddApiKeySidToTwilioSms < ActiveRecord::Migration[7.0] + def change + add_column :channel_twilio_sms, :api_key_sid, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index baa433702..ab3986e15 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_07_06_090122) do +ActiveRecord::Schema[7.0].define(version: 2023_07_14_054138) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" enable_extension "pg_trgm" @@ -330,6 +330,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_07_06_090122) do t.datetime "updated_at", null: false t.integer "medium", default: 0 t.string "messaging_service_sid" + t.string "api_key_sid" t.index ["account_sid", "phone_number"], name: "index_channel_twilio_sms_on_account_sid_and_phone_number", unique: true t.index ["messaging_service_sid"], name: "index_channel_twilio_sms_on_messaging_service_sid", unique: true t.index ["phone_number"], name: "index_channel_twilio_sms_on_phone_number", unique: true