chore: Generate webhook-verify-token automatically (#5593)
- Autogenerate webhook verification token in the WhatsAppCloud channel. Co-authored-by: Sojan <sojan@pepalo.com>
This commit is contained in:
@@ -239,7 +239,9 @@
|
|||||||
},
|
},
|
||||||
"API_CALLBACK": {
|
"API_CALLBACK": {
|
||||||
"TITLE": "Callback URL",
|
"TITLE": "Callback URL",
|
||||||
"SUBTITLE": "You have to configure the webhook URL in facebook developer portal with the URL mentioned here."
|
"SUBTITLE": "You have to configure the webhook URL and the verification token in the Facebook Developer portal with the values shown below.",
|
||||||
|
"WEBHOOK_URL": "Webhook URL",
|
||||||
|
"WEBHOOK_VERIFICATION_TOKEN": "Webhook Verification Token"
|
||||||
},
|
},
|
||||||
"SUBMIT_BUTTON": "Create WhatsApp Channel",
|
"SUBMIT_BUTTON": "Create WhatsApp Channel",
|
||||||
"API": {
|
"API": {
|
||||||
@@ -357,7 +359,7 @@
|
|||||||
},
|
},
|
||||||
"FINISH": {
|
"FINISH": {
|
||||||
"TITLE": "Your Inbox is ready!",
|
"TITLE": "Your Inbox is ready!",
|
||||||
"MESSAGE": "You can now engage with your customers through your new Channel. Happy supporting ",
|
"MESSAGE": "You can now engage with your customers through your new Channel. Happy supporting",
|
||||||
"BUTTON_TEXT": "Take me there",
|
"BUTTON_TEXT": "Take me there",
|
||||||
"MORE_SETTINGS": "More settings",
|
"MORE_SETTINGS": "More settings",
|
||||||
"WEBSITE_SUCCESS": "You have successfully finished creating a website channel. Copy the code shown below and paste it on your website. Next time a customer use the live chat, the conversation will automatically appear on your inbox."
|
"WEBSITE_SUCCESS": "You have successfully finished creating a website channel. Copy the code shown below and paste it on your website. Next time a customer use the live chat, the conversation will automatically appear on your inbox."
|
||||||
|
|||||||
@@ -20,11 +20,26 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="medium-6 small-offset-3">
|
<div class="medium-6 small-offset-3">
|
||||||
|
<p class="config--label">
|
||||||
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.API_CALLBACK.WEBHOOK_URL') }}
|
||||||
|
</p>
|
||||||
<woot-code
|
<woot-code
|
||||||
v-if="isAWhatsappWhatsappCloudInbox"
|
v-if="isWhatsAppCloudInbox"
|
||||||
lang="html"
|
lang="html"
|
||||||
:script="currentInbox.callback_webhook_url"
|
:script="currentInbox.callback_webhook_url"
|
||||||
/>
|
/>
|
||||||
|
<p class="config--label">
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
'INBOX_MGMT.ADD.WHATSAPP.API_CALLBACK.WEBHOOK_VERIFICATION_TOKEN'
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<woot-code
|
||||||
|
v-if="isWhatsAppCloudInbox"
|
||||||
|
lang="html"
|
||||||
|
:script="currentInbox.provider_config.webhook_verify_token"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="medium-6 small-offset-3">
|
<div class="medium-6 small-offset-3">
|
||||||
<woot-code
|
<woot-code
|
||||||
@@ -99,7 +114,7 @@ export default {
|
|||||||
isASmsInbox() {
|
isASmsInbox() {
|
||||||
return this.currentInbox.channel_type === 'Channel::Sms';
|
return this.currentInbox.channel_type === 'Channel::Sms';
|
||||||
},
|
},
|
||||||
isAWhatsappWhatsappCloudInbox() {
|
isWhatsAppCloudInbox() {
|
||||||
return (
|
return (
|
||||||
this.currentInbox.channel_type === 'Channel::Whatsapp' &&
|
this.currentInbox.channel_type === 'Channel::Whatsapp' &&
|
||||||
this.currentInbox.provider === 'whatsapp_cloud'
|
this.currentInbox.provider === 'whatsapp_cloud'
|
||||||
@@ -124,7 +139,7 @@ export default {
|
|||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isAWhatsappWhatsappCloudInbox) {
|
if (this.isWhatsAppCloudInbox) {
|
||||||
return `${this.$t('INBOX_MGMT.FINISH.MESSAGE')}. ${this.$t(
|
return `${this.$t('INBOX_MGMT.FINISH.MESSAGE')}. ${this.$t(
|
||||||
'INBOX_MGMT.ADD.WHATSAPP.API_CALLBACK.SUBTITLE'
|
'INBOX_MGMT.ADD.WHATSAPP.API_CALLBACK.SUBTITLE'
|
||||||
)}`;
|
)}`;
|
||||||
@@ -159,4 +174,10 @@ export default {
|
|||||||
.settings-button {
|
.settings-button {
|
||||||
margin-right: var(--space-small);
|
margin-right: var(--space-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.config--label {
|
||||||
|
color: var(--b-600);
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
margin-top: var(--space-large);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -85,25 +85,6 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="medium-8 columns">
|
|
||||||
<label :class="{ error: $v.webhookVerifyToken.$error }">
|
|
||||||
<span>
|
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.WEBHOOK_VERIFY_TOKEN.LABEL') }}
|
|
||||||
</span>
|
|
||||||
<input
|
|
||||||
v-model.trim="webhookVerifyToken"
|
|
||||||
type="text"
|
|
||||||
:placeholder="
|
|
||||||
$t('INBOX_MGMT.ADD.WHATSAPP.WEBHOOK_VERIFY_TOKEN.PLACEHOLDER')
|
|
||||||
"
|
|
||||||
@blur="$v.webhookVerifyToken.$touch"
|
|
||||||
/>
|
|
||||||
<span v-if="$v.webhookVerifyToken.$error" class="message">
|
|
||||||
{{ $t('INBOX_MGMT.ADD.WHATSAPP.WEBHOOK_VERIFY_TOKEN.ERROR') }}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="medium-12 columns">
|
<div class="medium-12 columns">
|
||||||
<woot-submit-button
|
<woot-submit-button
|
||||||
:loading="uiFlags.isCreating"
|
:loading="uiFlags.isCreating"
|
||||||
@@ -130,7 +111,6 @@ export default {
|
|||||||
apiKey: '',
|
apiKey: '',
|
||||||
phoneNumberId: '',
|
phoneNumberId: '',
|
||||||
businessAccountId: '',
|
businessAccountId: '',
|
||||||
webhookVerifyToken: '',
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -142,7 +122,6 @@ export default {
|
|||||||
apiKey: { required },
|
apiKey: { required },
|
||||||
phoneNumberId: { required },
|
phoneNumberId: { required },
|
||||||
businessAccountId: { required },
|
businessAccountId: { required },
|
||||||
webhookVerifyToken: { required },
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async createChannel() {
|
async createChannel() {
|
||||||
@@ -164,7 +143,6 @@ export default {
|
|||||||
api_key: this.apiKey,
|
api_key: this.apiKey,
|
||||||
phone_number_id: this.phoneNumberId,
|
phone_number_id: this.phoneNumberId,
|
||||||
business_account_id: this.businessAccountId,
|
business_account_id: this.businessAccountId,
|
||||||
webhook_verify_token: this.webhookVerifyToken,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,12 @@ class Channel::Whatsapp < ApplicationRecord
|
|||||||
|
|
||||||
# default at the moment is 360dialog lets change later.
|
# default at the moment is 360dialog lets change later.
|
||||||
PROVIDERS = %w[default whatsapp_cloud].freeze
|
PROVIDERS = %w[default whatsapp_cloud].freeze
|
||||||
|
before_validation :ensure_webhook_verify_token
|
||||||
|
|
||||||
validates :provider, inclusion: { in: PROVIDERS }
|
validates :provider, inclusion: { in: PROVIDERS }
|
||||||
|
|
||||||
validates :phone_number, presence: true, uniqueness: true
|
validates :phone_number, presence: true, uniqueness: true
|
||||||
validate :validate_provider_config
|
validate :validate_provider_config
|
||||||
|
|
||||||
after_create :sync_templates
|
after_create :sync_templates
|
||||||
|
|
||||||
def name
|
def name
|
||||||
@@ -56,6 +57,10 @@ class Channel::Whatsapp < ApplicationRecord
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def ensure_webhook_verify_token
|
||||||
|
provider_config['webhook_verify_token'] ||= SecureRandom.hex(16) if provider == 'whatsapp_cloud'
|
||||||
|
end
|
||||||
|
|
||||||
def validate_provider_config
|
def validate_provider_config
|
||||||
errors.add(:provider_config, 'Invalid Credentials') unless provider_service.validate_provider_config?
|
errors.add(:provider_config, 'Invalid Credentials') unless provider_service.validate_provider_config?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ module RegexHelper
|
|||||||
UNICODE_CHARACTER_NUMBER_HYPHEN_UNDERSCORE = Regexp.new('\A[\p{L}\p{N}]+[\p{L}\p{N}_-]+\Z')
|
UNICODE_CHARACTER_NUMBER_HYPHEN_UNDERSCORE = Regexp.new('\A[\p{L}\p{N}]+[\p{L}\p{N}_-]+\Z')
|
||||||
MENTION_REGEX = Regexp.new('\[(@[\w_. ]+)\]\(mention://(?:user|team)/\d+/(.*?)+\)')
|
MENTION_REGEX = Regexp.new('\[(@[\w_. ]+)\]\(mention://(?:user|team)/\d+/(.*?)+\)')
|
||||||
|
|
||||||
TWILIO_CHANNEL_SMS_REGEX = Regexp.new('^\+\d{1,14}\z')
|
TWILIO_CHANNEL_SMS_REGEX = Regexp.new('^\+\d{1,15}\z')
|
||||||
TWILIO_CHANNEL_WHATSAPP_REGEX = Regexp.new('^whatsapp:\+\d{1,14}\z')
|
TWILIO_CHANNEL_WHATSAPP_REGEX = Regexp.new('^whatsapp:\+\d{1,15}\z')
|
||||||
WHATSAPP_CHANNEL_REGEX = Regexp.new('^\d{1,14}\z')
|
WHATSAPP_CHANNEL_REGEX = Regexp.new('^\d{1,14}\z')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ FactoryBot.define do
|
|||||||
channel_whatsapp.define_singleton_method(:sync_templates) { return } unless options.sync_templates
|
channel_whatsapp.define_singleton_method(:sync_templates) { return } unless options.sync_templates
|
||||||
channel_whatsapp.define_singleton_method(:validate_provider_config) { return } unless options.validate_provider_config
|
channel_whatsapp.define_singleton_method(:validate_provider_config) { return } unless options.validate_provider_config
|
||||||
if channel_whatsapp.provider == 'whatsapp_cloud'
|
if channel_whatsapp.provider == 'whatsapp_cloud'
|
||||||
channel_whatsapp.provider_config = { 'api_key' => 'test_key', 'phone_number_id' => '123456789', 'business_account_id' => '123456789',
|
channel_whatsapp.provider_config = channel_whatsapp.provider_config.merge({ 'api_key' => 'test_key', 'phone_number_id' => '123456789',
|
||||||
'webhook_verify_token': 'test_token' }
|
'business_account_id' => '123456789' })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -20,4 +20,20 @@ RSpec.describe Channel::Whatsapp do
|
|||||||
expect(channel.save).to be(true)
|
expect(channel.save).to be(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'webhook_verify_token' do
|
||||||
|
it 'generates webhook_verify_token if not present' do
|
||||||
|
channel = create(:channel_whatsapp, provider_config: { webhook_verify_token: nil }, provider: 'whatsapp_cloud', account: create(:account),
|
||||||
|
validate_provider_config: false, sync_templates: false)
|
||||||
|
|
||||||
|
expect(channel.provider_config['webhook_verify_token']).not_to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not generate webhook_verify_token if present' do
|
||||||
|
channel = create(:channel_whatsapp, provider: 'whatsapp_cloud', provider_config: { webhook_verify_token: '123' }, account: create(:account),
|
||||||
|
validate_provider_config: false, sync_templates: false)
|
||||||
|
|
||||||
|
expect(channel.provider_config['webhook_verify_token']).to eq '123'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -66,11 +66,11 @@ RSpec.describe ContactInbox do
|
|||||||
expect(valid_source_id.valid?).to be(true)
|
expect(valid_source_id.valid?).to be(true)
|
||||||
expect(ci_character_in_source_id.valid?).to be(false)
|
expect(ci_character_in_source_id.valid?).to be(false)
|
||||||
expect(ci_character_in_source_id.errors.full_messages).to eq(
|
expect(ci_character_in_source_id.errors.full_messages).to eq(
|
||||||
['Source invalid source id for twilio sms inbox. valid Regex (?-mix:^\\+\\d{1,14}\\z)']
|
['Source invalid source id for twilio sms inbox. valid Regex (?-mix:^\\+\\d{1,15}\\z)']
|
||||||
)
|
)
|
||||||
expect(ci_without_plus_in_source_id.valid?).to be(false)
|
expect(ci_without_plus_in_source_id.valid?).to be(false)
|
||||||
expect(ci_without_plus_in_source_id.errors.full_messages).to eq(
|
expect(ci_without_plus_in_source_id.errors.full_messages).to eq(
|
||||||
['Source invalid source id for twilio sms inbox. valid Regex (?-mix:^\\+\\d{1,14}\\z)']
|
['Source invalid source id for twilio sms inbox. valid Regex (?-mix:^\\+\\d{1,15}\\z)']
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -83,11 +83,11 @@ RSpec.describe ContactInbox do
|
|||||||
expect(valid_source_id.valid?).to be(true)
|
expect(valid_source_id.valid?).to be(true)
|
||||||
expect(ci_character_in_source_id.valid?).to be(false)
|
expect(ci_character_in_source_id.valid?).to be(false)
|
||||||
expect(ci_character_in_source_id.errors.full_messages).to eq(
|
expect(ci_character_in_source_id.errors.full_messages).to eq(
|
||||||
['Source invalid source id for twilio whatsapp inbox. valid Regex (?-mix:^whatsapp:\\+\\d{1,14}\\z)']
|
['Source invalid source id for twilio whatsapp inbox. valid Regex (?-mix:^whatsapp:\\+\\d{1,15}\\z)']
|
||||||
)
|
)
|
||||||
expect(ci_without_plus_in_source_id.valid?).to be(false)
|
expect(ci_without_plus_in_source_id.valid?).to be(false)
|
||||||
expect(ci_without_plus_in_source_id.errors.full_messages).to eq(
|
expect(ci_without_plus_in_source_id.errors.full_messages).to eq(
|
||||||
['Source invalid source id for twilio whatsapp inbox. valid Regex (?-mix:^whatsapp:\\+\\d{1,14}\\z)']
|
['Source invalid source id for twilio whatsapp inbox. valid Regex (?-mix:^whatsapp:\\+\\d{1,15}\\z)']
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user