mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-03 04:27:53 +00:00
feat: Add support for API key authentication in Twilio (#7523)
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
This commit is contained in:
@@ -18,7 +18,11 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts:
|
|||||||
end
|
end
|
||||||
|
|
||||||
def authenticate_twilio
|
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)
|
client.messages.list(limit: 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -40,6 +44,7 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts:
|
|||||||
@twilio_channel = Current.account.twilio_sms.create!(
|
@twilio_channel = Current.account.twilio_sms.create!(
|
||||||
account_sid: permitted_params[:account_sid],
|
account_sid: permitted_params[:account_sid],
|
||||||
auth_token: permitted_params[:auth_token],
|
auth_token: permitted_params[:auth_token],
|
||||||
|
api_key_sid: permitted_params[:api_key_sid],
|
||||||
messaging_service_sid: permitted_params[:messaging_service_sid].presence,
|
messaging_service_sid: permitted_params[:messaging_service_sid].presence,
|
||||||
phone_number: phone_number,
|
phone_number: phone_number,
|
||||||
medium: medium
|
medium: medium
|
||||||
@@ -52,7 +57,7 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::V1::Accounts:
|
|||||||
|
|
||||||
def permitted_params
|
def permitted_params
|
||||||
params.require(:twilio_channel).permit(
|
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
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -111,6 +111,17 @@
|
|||||||
"PLACEHOLDER": "Please enter your Twilio Account SID",
|
"PLACEHOLDER": "Please enter your Twilio Account SID",
|
||||||
"ERROR": "This field is required"
|
"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": {
|
"MESSAGING_SERVICE_SID": {
|
||||||
"LABEL": "Messaging Service SID",
|
"LABEL": "Messaging Service SID",
|
||||||
"PLACEHOLDER": "Please enter your Twilio Messaging Service SID",
|
"PLACEHOLDER": "Please enter your Twilio Messaging Service SID",
|
||||||
|
|||||||
@@ -81,18 +81,45 @@
|
|||||||
}}</span>
|
}}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="medium-8 columns messagingServiceHelptext">
|
||||||
|
<label for="useAPIKey">
|
||||||
|
<input
|
||||||
|
id="useAPIKey"
|
||||||
|
v-model="useAPIKey"
|
||||||
|
type="checkbox"
|
||||||
|
class="checkbox"
|
||||||
|
/>
|
||||||
|
{{ $t('INBOX_MGMT.ADD.TWILIO.API_KEY.USE_API_KEY') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div v-if="useAPIKey" class="medium-8 columns">
|
||||||
|
<label :class="{ error: $v.apiKeySID.$error }">
|
||||||
|
{{ $t('INBOX_MGMT.ADD.TWILIO.API_KEY.LABEL') }}
|
||||||
|
<input
|
||||||
|
v-model.trim="apiKeySID"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.API_KEY.PLACEHOLDER')"
|
||||||
|
@blur="$v.apiKeySID.$touch"
|
||||||
|
/>
|
||||||
|
<span v-if="$v.apiKeySID.$error" class="message">{{
|
||||||
|
$t('INBOX_MGMT.ADD.TWILIO.API_KEY.ERROR')
|
||||||
|
}}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div class="medium-8 columns">
|
<div class="medium-8 columns">
|
||||||
<label :class="{ error: $v.authToken.$error }">
|
<label :class="{ error: $v.authToken.$error }">
|
||||||
{{ $t('INBOX_MGMT.ADD.TWILIO.AUTH_TOKEN.LABEL') }}
|
{{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.LABEL`) }}
|
||||||
<input
|
<input
|
||||||
v-model.trim="authToken"
|
v-model.trim="authToken"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.AUTH_TOKEN.PLACEHOLDER')"
|
:placeholder="
|
||||||
|
$t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.PLACEHOLDER`)
|
||||||
|
"
|
||||||
@blur="$v.authToken.$touch"
|
@blur="$v.authToken.$touch"
|
||||||
/>
|
/>
|
||||||
<span v-if="$v.authToken.$error" class="message">{{
|
<span v-if="$v.authToken.$error" class="message">
|
||||||
$t('INBOX_MGMT.ADD.TWILIO.AUTH_TOKEN.ERROR')
|
{{ $t(`INBOX_MGMT.ADD.TWILIO.${authTokeni18nKey}.ERROR`) }}
|
||||||
}}</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -123,11 +150,13 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
accountSID: '',
|
accountSID: '',
|
||||||
|
apiKeySID: '',
|
||||||
authToken: '',
|
authToken: '',
|
||||||
medium: this.type,
|
medium: this.type,
|
||||||
channelName: '',
|
channelName: '',
|
||||||
messagingServiceSID: '',
|
messagingServiceSID: '',
|
||||||
useMessagingService: false,
|
useMessagingService: false,
|
||||||
|
useAPIKey: false,
|
||||||
phoneNumber: '',
|
phoneNumber: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -135,26 +164,39 @@ export default {
|
|||||||
...mapGetters({
|
...mapGetters({
|
||||||
uiFlags: 'inboxes/getUIFlags',
|
uiFlags: 'inboxes/getUIFlags',
|
||||||
}),
|
}),
|
||||||
|
authTokeni18nKey() {
|
||||||
|
return this.useAPIKey ? 'API_KEY_SECRET' : 'AUTH_TOKEN';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
validations() {
|
validations() {
|
||||||
if (this.phoneNumber) {
|
let validations = {
|
||||||
return {
|
|
||||||
channelName: { required },
|
|
||||||
messagingServiceSID: {},
|
|
||||||
phoneNumber: { required, isPhoneE164OrEmpty },
|
|
||||||
authToken: { required },
|
|
||||||
accountSID: { required },
|
|
||||||
medium: { required },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
channelName: { required },
|
channelName: { required },
|
||||||
messagingServiceSID: { required },
|
|
||||||
phoneNumber: {},
|
|
||||||
authToken: { required },
|
authToken: { required },
|
||||||
accountSID: { required },
|
accountSID: { required },
|
||||||
medium: { 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: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
@@ -171,6 +213,7 @@ export default {
|
|||||||
name: this.channelName,
|
name: this.channelName,
|
||||||
medium: this.medium,
|
medium: this.medium,
|
||||||
account_sid: this.accountSID,
|
account_sid: this.accountSID,
|
||||||
|
api_key_sid: this.apiKeySID,
|
||||||
auth_token: this.authToken,
|
auth_token: this.authToken,
|
||||||
messaging_service_sid: this.messagingServiceSID,
|
messaging_service_sid: this.messagingServiceSID,
|
||||||
phone_number: this.messagingServiceSID
|
phone_number: this.messagingServiceSID
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#
|
#
|
||||||
# id :bigint not null, primary key
|
# id :bigint not null, primary key
|
||||||
# account_sid :string not null
|
# account_sid :string not null
|
||||||
|
# api_key_sid :string
|
||||||
# auth_token :string not null
|
# auth_token :string not null
|
||||||
# medium :integer default("sms")
|
# medium :integer default("sms")
|
||||||
# messaging_service_sid :string
|
# messaging_service_sid :string
|
||||||
@@ -25,6 +26,7 @@ class Channel::TwilioSms < ApplicationRecord
|
|||||||
self.table_name = 'channel_twilio_sms'
|
self.table_name = 'channel_twilio_sms'
|
||||||
|
|
||||||
validates :account_sid, presence: true
|
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
|
validates :auth_token, presence: true
|
||||||
|
|
||||||
# Must have _one_ of messaging_service_sid _or_ phone_number, and messaging_service_sid is preferred
|
# 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
|
private
|
||||||
|
|
||||||
def client
|
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
|
end
|
||||||
|
|
||||||
def send_message_from
|
def send_message_from
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class AddApiKeySidToTwilioSms < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
add_column :channel_twilio_sms, :api_key_sid, :string
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# 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
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "pg_stat_statements"
|
enable_extension "pg_stat_statements"
|
||||||
enable_extension "pg_trgm"
|
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.datetime "updated_at", null: false
|
||||||
t.integer "medium", default: 0
|
t.integer "medium", default: 0
|
||||||
t.string "messaging_service_sid"
|
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 ["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 ["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
|
t.index ["phone_number"], name: "index_channel_twilio_sms_on_phone_number", unique: true
|
||||||
|
|||||||
Reference in New Issue
Block a user