-
+
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.LABEL') }}
-
+
{{ $t('NEW_CONVERSATION.FORM.SUBJECT.ERROR') }}
@@ -93,7 +93,7 @@ import Thumbnail from 'dashboard/components/widgets/Thumbnail';
import alertMixin from 'shared/mixins/alertMixin';
import { INBOX_TYPES } from 'shared/mixins/inboxMixin';
import { ExceptionWithMessage } from 'shared/helpers/CustomErrors';
-import { required } from 'vuelidate/lib/validators';
+import { required, requiredIf } from 'vuelidate/lib/validators';
export default {
components: {
@@ -120,7 +120,7 @@ export default {
},
validations: {
subject: {
- required,
+ required: requiredIf('isAnEmailInbox'),
},
message: {
required,
diff --git a/app/javascript/widget/helpers/actionCable.js b/app/javascript/widget/helpers/actionCable.js
index a8c3f5d40..728e607b5 100644
--- a/app/javascript/widget/helpers/actionCable.js
+++ b/app/javascript/widget/helpers/actionCable.js
@@ -15,18 +15,6 @@ class ActionCableConnector extends BaseActionCableConnector {
};
}
- static refreshConnector = pubsubToken => {
- if (!pubsubToken || window.chatwootPubsubToken === pubsubToken) {
- return;
- }
- window.chatwootPubsubToken = pubsubToken;
- window.actionCable.disconnect();
- window.actionCable = new ActionCableConnector(
- window.WOOT_WIDGET,
- window.chatwootPubsubToken
- );
- };
-
onStatusChange = data => {
this.app.$store.dispatch('conversationAttributes/update', data);
};
@@ -57,7 +45,7 @@ class ActionCableConnector extends BaseActionCableConnector {
onTypingOn = data => {
if (data.is_private) {
- return
+ return;
}
this.clearTimer();
this.app.$store.dispatch('conversation/toggleAgentTyping', {
@@ -88,7 +76,4 @@ class ActionCableConnector extends BaseActionCableConnector {
};
}
-export const refreshActionCableConnector =
- ActionCableConnector.refreshConnector;
-
export default ActionCableConnector;
diff --git a/app/javascript/widget/helpers/campaignHelper.js b/app/javascript/widget/helpers/campaignHelper.js
index 4e527c853..e11a84f58 100644
--- a/app/javascript/widget/helpers/campaignHelper.js
+++ b/app/javascript/widget/helpers/campaignHelper.js
@@ -21,10 +21,16 @@ export const filterCampaigns = ({
currentURL,
isInBusinessHours,
}) => {
- return campaigns.filter(item =>
- item.triggerOnlyDuringBusinessHours
- ? isInBusinessHours
- : stripTrailingSlash({ URL: item.url }) ===
- stripTrailingSlash({ URL: currentURL })
- );
+ return campaigns.filter(campaign => {
+ const hasMatchingURL =
+ stripTrailingSlash({ URL: campaign.url }) ===
+ stripTrailingSlash({ URL: currentURL });
+ if (!hasMatchingURL) {
+ return false;
+ }
+ if (campaign.triggerOnlyDuringBusinessHours) {
+ return isInBusinessHours;
+ }
+ return true;
+ });
};
diff --git a/app/javascript/widget/helpers/specs/campaignHelper.spec.js b/app/javascript/widget/helpers/specs/campaignHelper.spec.js
index f0107465d..0037f4c8b 100644
--- a/app/javascript/widget/helpers/specs/campaignHelper.spec.js
+++ b/app/javascript/widget/helpers/specs/campaignHelper.spec.js
@@ -44,11 +44,13 @@ describe('#Campaigns Helper', () => {
id: 1,
timeOnPage: 3,
url: 'https://www.chatwoot.com/pricing',
+ triggerOnlyDuringBusinessHours: false,
},
{
id: 2,
timeOnPage: 6,
url: 'https://www.chatwoot.com/about',
+ triggerOnlyDuringBusinessHours: false,
},
],
currentURL: 'https://www.chatwoot.com/about/',
@@ -58,8 +60,60 @@ describe('#Campaigns Helper', () => {
id: 2,
timeOnPage: 6,
url: 'https://www.chatwoot.com/about',
+ triggerOnlyDuringBusinessHours: false,
},
]);
});
+ it('should return filtered campaigns if formatted campaigns are passed and business hours enabled', () => {
+ expect(
+ filterCampaigns({
+ campaigns: [
+ {
+ id: 1,
+ timeOnPage: 3,
+ url: 'https://www.chatwoot.com/pricing',
+ triggerOnlyDuringBusinessHours: false,
+ },
+ {
+ id: 2,
+ timeOnPage: 6,
+ url: 'https://www.chatwoot.com/about',
+ triggerOnlyDuringBusinessHours: true,
+ },
+ ],
+ currentURL: 'https://www.chatwoot.com/about/',
+ isInBusinessHours: true,
+ })
+ ).toStrictEqual([
+ {
+ id: 2,
+ timeOnPage: 6,
+ url: 'https://www.chatwoot.com/about',
+ triggerOnlyDuringBusinessHours: true,
+ },
+ ]);
+ });
+ it('should return empty campaigns if formatted campaigns are passed and business hours disabled', () => {
+ expect(
+ filterCampaigns({
+ campaigns: [
+ {
+ id: 1,
+ timeOnPage: 3,
+ url: 'https://www.chatwoot.com/pricing',
+ triggerOnlyDuringBusinessHours: true,
+ },
+ {
+ id: 2,
+ timeOnPage: 6,
+ url: 'https://www.chatwoot.com/about',
+ triggerOnlyDuringBusinessHours: true,
+ },
+ ],
+ currentURL: 'https://www.chatwoot.com/about/',
+ isInBusinessHours: false,
+ })
+ ).toStrictEqual([]);
+ });
});
});
diff --git a/app/javascript/widget/store/modules/contacts.js b/app/javascript/widget/store/modules/contacts.js
index f02083873..051061fc5 100644
--- a/app/javascript/widget/store/modules/contacts.js
+++ b/app/javascript/widget/store/modules/contacts.js
@@ -1,5 +1,4 @@
import ContactsAPI from '../../api/contacts';
-import { refreshActionCableConnector } from '../../helpers/actionCable';
const state = {
currentUser: {},
@@ -31,17 +30,13 @@ export const actions = {
identifier_hash: userObject.identifier_hash,
phone_number: userObject.phone_number,
};
- const {
- data: { pubsub_token: pubsubToken },
- } = await ContactsAPI.update(identifier, user);
+ await ContactsAPI.update(identifier, user);
dispatch('get');
if (userObject.identifier_hash) {
dispatch('conversation/clearConversations', {}, { root: true });
dispatch('conversation/fetchOldConversations', {}, { root: true });
}
-
- refreshActionCableConnector(pubsubToken);
} catch (error) {
// Ignore error
}
diff --git a/app/javascript/widget/store/modules/conversation/actions.js b/app/javascript/widget/store/modules/conversation/actions.js
index 42c915521..c163cc1a1 100644
--- a/app/javascript/widget/store/modules/conversation/actions.js
+++ b/app/javascript/widget/store/modules/conversation/actions.js
@@ -6,7 +6,6 @@ import {
toggleTyping,
setUserLastSeenAt,
} from 'widget/api/conversation';
-import { refreshActionCableConnector } from '../../../helpers/actionCable';
import { createTemporaryMessage, getNonDeletedMessages } from './helpers';
@@ -15,13 +14,9 @@ export const actions = {
commit('setConversationUIFlag', { isCreating: true });
try {
const { data } = await createConversationAPI(params);
- const {
- contact: { pubsub_token: pubsubToken },
- messages,
- } = data;
+ const { messages } = data;
const [message = {}] = messages;
commit('pushMessageToConversation', message);
- refreshActionCableConnector(pubsubToken);
dispatch('conversationAttributes/getAttributes', {}, { root: true });
} catch (error) {
// Ignore error
diff --git a/app/javascript/widget/store/modules/message.js b/app/javascript/widget/store/modules/message.js
index b11c5cdd4..99c284e1f 100644
--- a/app/javascript/widget/store/modules/message.js
+++ b/app/javascript/widget/store/modules/message.js
@@ -1,5 +1,4 @@
import MessageAPI from '../../api/message';
-import { refreshActionCableConnector } from '../../helpers/actionCable';
const state = {
uiFlags: {
@@ -18,9 +17,7 @@ export const actions = {
) => {
commit('toggleUpdateStatus', true);
try {
- const {
- data: { contact: { pubsub_token: pubsubToken } = {} },
- } = await MessageAPI.update({
+ await MessageAPI.update({
email,
messageId,
values: submittedValues,
@@ -37,7 +34,6 @@ export const actions = {
{ root: true }
);
dispatch('contacts/get', {}, { root: true });
- refreshActionCableConnector(pubsubToken);
} catch (error) {
// Ignore error
}
diff --git a/app/listeners/action_cable_listener.rb b/app/listeners/action_cable_listener.rb
index 04c930e7d..a81c74976 100644
--- a/app/listeners/action_cable_listener.rb
+++ b/app/listeners/action_cable_listener.rb
@@ -18,7 +18,7 @@ class ActionCableListener < BaseListener
def message_created(event)
message, account = extract_message_and_account(event)
conversation = message.conversation
- tokens = user_tokens(account, conversation.inbox.members) + contact_token(conversation.contact, message)
+ tokens = user_tokens(account, conversation.inbox.members) + contact_tokens(conversation.contact_inbox, message)
broadcast(account, tokens, MESSAGE_CREATED, message.push_event_data)
end
@@ -27,7 +27,7 @@ class ActionCableListener < BaseListener
message, account = extract_message_and_account(event)
conversation = message.conversation
contact = conversation.contact
- tokens = user_tokens(account, conversation.inbox.members) + contact_token(conversation.contact, message)
+ tokens = user_tokens(account, conversation.inbox.members) + contact_tokens(conversation.contact_inbox, message)
broadcast(account, tokens, MESSAGE_UPDATED, message.push_event_data)
end
@@ -132,12 +132,14 @@ class ActionCableListener < BaseListener
(agent_tokens + admin_tokens).uniq
end
- def contact_token(contact, message)
+ def contact_tokens(contact_inbox, message)
return [] if message.private?
return [] if message.activity?
- return [] if contact.nil?
+ return [] if contact_inbox.nil?
- [contact.pubsub_token]
+ contact = contact_inbox.contact
+
+ contact_inbox.hmac_verified? ? contact.contact_inboxes.where(hmac_verified: true).filter_map(&:pubsub_token) : [contact_inbox.pubsub_token]
end
def broadcast(account, tokens, event_name, data)
diff --git a/app/models/concerns/pubsubable.rb b/app/models/concerns/pubsubable.rb
index 2e8abb9da..21b42899c 100644
--- a/app/models/concerns/pubsubable.rb
+++ b/app/models/concerns/pubsubable.rb
@@ -7,4 +7,10 @@ module Pubsubable
# Used by the actionCable/PubSub Service we use for real time communications
has_secure_token :pubsub_token
end
+
+ def pubsub_token
+ # backfills tokens for existing records
+ regenerate_pubsub_token if self[:pubsub_token].blank?
+ self[:pubsub_token]
+ end
end
diff --git a/app/models/contact.rb b/app/models/contact.rb
index 9ba3a4178..7b257bab4 100644
--- a/app/models/contact.rb
+++ b/app/models/contact.rb
@@ -25,7 +25,7 @@
#
class Contact < ApplicationRecord
- include Pubsubable
+ # TODO: remove the pubsub_token attribute from this model in future.
include Avatarable
include AvailabilityStatusable
include Labelable
diff --git a/app/models/contact_inbox.rb b/app/models/contact_inbox.rb
index e87d30382..9a6564546 100644
--- a/app/models/contact_inbox.rb
+++ b/app/models/contact_inbox.rb
@@ -4,6 +4,7 @@
#
# id :bigint not null, primary key
# hmac_verified :boolean default(FALSE)
+# pubsub_token :string
# created_at :datetime not null
# updated_at :datetime not null
# contact_id :bigint
@@ -15,6 +16,7 @@
# index_contact_inboxes_on_contact_id (contact_id)
# index_contact_inboxes_on_inbox_id (inbox_id)
# index_contact_inboxes_on_inbox_id_and_source_id (inbox_id,source_id) UNIQUE
+# index_contact_inboxes_on_pubsub_token (pubsub_token) UNIQUE
# index_contact_inboxes_on_source_id (source_id)
#
# Foreign Keys
@@ -24,6 +26,7 @@
#
class ContactInbox < ApplicationRecord
+ include Pubsubable
validates :inbox_id, presence: true
validates :contact_id, presence: true
validates :source_id, presence: true
diff --git a/app/presenters/conversations/event_data_presenter.rb b/app/presenters/conversations/event_data_presenter.rb
index 306fda78c..b4a443f35 100644
--- a/app/presenters/conversations/event_data_presenter.rb
+++ b/app/presenters/conversations/event_data_presenter.rb
@@ -23,7 +23,11 @@ class Conversations::EventDataPresenter < SimpleDelegator
end
def push_meta
- { sender: contact.push_event_data, assignee: assignee&.push_event_data }
+ {
+ sender: contact.push_event_data,
+ assignee: assignee&.push_event_data,
+ hmac_verified: contact_inbox&.hmac_verified
+ }
end
def push_timestamps
diff --git a/app/views/api/v1/conversations/partials/_conversation.json.jbuilder b/app/views/api/v1/conversations/partials/_conversation.json.jbuilder
index d08672e77..3c645e093 100644
--- a/app/views/api/v1/conversations/partials/_conversation.json.jbuilder
+++ b/app/views/api/v1/conversations/partials/_conversation.json.jbuilder
@@ -13,6 +13,7 @@ json.meta do
json.partial! 'api/v1/models/team.json.jbuilder', resource: conversation.team
end
end
+ json.hmac_verified conversation.contact_inbox&.hmac_verified
end
json.id conversation.display_id
diff --git a/app/views/api/v1/widget/configs/create.json.jbuilder b/app/views/api/v1/widget/configs/create.json.jbuilder
index 8fbd5a502..2a7cf30b1 100644
--- a/app/views/api/v1/widget/configs/create.json.jbuilder
+++ b/app/views/api/v1/widget/configs/create.json.jbuilder
@@ -22,7 +22,7 @@ json.chatwoot_widget_defaults do
json.use_inbox_avatar_for_bot ActiveModel::Type::Boolean.new.cast(ENV.fetch('USE_INBOX_AVATAR_FOR_BOT', false))
end
json.contact do
- json.pubsub_token @contact.pubsub_token
+ json.pubsub_token @contact_inbox.pubsub_token
end
json.auth_token @token
json.global_config @global_config
diff --git a/app/views/public/api/v1/inboxes/contacts/create.json.jbuilder b/app/views/public/api/v1/inboxes/contacts/create.json.jbuilder
index 256b588a5..4a635bb5a 100644
--- a/app/views/public/api/v1/inboxes/contacts/create.json.jbuilder
+++ b/app/views/public/api/v1/inboxes/contacts/create.json.jbuilder
@@ -1,2 +1,3 @@
json.source_id @contact_inbox.source_id
+json.pubsub_token @contact_inbox.pubsub_token
json.partial! 'public/api/v1/models/contact.json.jbuilder', resource: @contact_inbox.contact
diff --git a/app/views/public/api/v1/inboxes/contacts/show.json.jbuilder b/app/views/public/api/v1/inboxes/contacts/show.json.jbuilder
index 256b588a5..4a635bb5a 100644
--- a/app/views/public/api/v1/inboxes/contacts/show.json.jbuilder
+++ b/app/views/public/api/v1/inboxes/contacts/show.json.jbuilder
@@ -1,2 +1,3 @@
json.source_id @contact_inbox.source_id
+json.pubsub_token @contact_inbox.pubsub_token
json.partial! 'public/api/v1/models/contact.json.jbuilder', resource: @contact_inbox.contact
diff --git a/app/views/public/api/v1/inboxes/contacts/update.json.jbuilder b/app/views/public/api/v1/inboxes/contacts/update.json.jbuilder
index 256b588a5..4a635bb5a 100644
--- a/app/views/public/api/v1/inboxes/contacts/update.json.jbuilder
+++ b/app/views/public/api/v1/inboxes/contacts/update.json.jbuilder
@@ -1,2 +1,3 @@
json.source_id @contact_inbox.source_id
+json.pubsub_token @contact_inbox.pubsub_token
json.partial! 'public/api/v1/models/contact.json.jbuilder', resource: @contact_inbox.contact
diff --git a/app/views/public/api/v1/models/_contact.json.jbuilder b/app/views/public/api/v1/models/_contact.json.jbuilder
index aa8abf2e2..c35705c6c 100644
--- a/app/views/public/api/v1/models/_contact.json.jbuilder
+++ b/app/views/public/api/v1/models/_contact.json.jbuilder
@@ -1,4 +1,3 @@
json.id resource.id
json.name resource.name
json.email resource.email
-json.pubsub_token resource.pubsub_token
diff --git a/app/views/widgets/show.html.erb b/app/views/widgets/show.html.erb
index 6c4d38f88..0cd60c453 100644
--- a/app/views/widgets/show.html.erb
+++ b/app/views/widgets/show.html.erb
@@ -28,7 +28,7 @@
window.chatwootWidgetDefaults = {
useInboxAvatarForBot: <%= ActiveModel::Type::Boolean.new.cast(ENV.fetch('USE_INBOX_AVATAR_FOR_BOT', false)) %>,
}
- window.chatwootPubsubToken = '<%= @contact.pubsub_token %>'
+ window.chatwootPubsubToken = '<%= @contact_inbox.pubsub_token %>'
window.authToken = '<%= @token %>'
window.globalConfig = <%= raw @global_config.to_json %>
diff --git a/config/app.yml b/config/app.yml
index 8aa5d22ad..b883f6deb 100644
--- a/config/app.yml
+++ b/config/app.yml
@@ -1,5 +1,5 @@
shared: &shared
- version: '1.22.0'
+ version: '1.22.1'
development:
<<: *shared
diff --git a/db/migrate/20211122061012_add_pub_sub_token_to_contact_inbox.rb b/db/migrate/20211122061012_add_pub_sub_token_to_contact_inbox.rb
new file mode 100644
index 000000000..7ba816efc
--- /dev/null
+++ b/db/migrate/20211122061012_add_pub_sub_token_to_contact_inbox.rb
@@ -0,0 +1,6 @@
+class AddPubSubTokenToContactInbox < ActiveRecord::Migration[6.1]
+ def change
+ add_column :contact_inboxes, :pubsub_token, :string
+ add_index :contact_inboxes, :pubsub_token, unique: true
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 66550552f..a05c3e7da 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.define(version: 2021_11_18_100301) do
+ActiveRecord::Schema.define(version: 2021_11_22_061012) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
@@ -288,9 +288,11 @@ ActiveRecord::Schema.define(version: 2021_11_18_100301) do
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.boolean "hmac_verified", default: false
+ t.string "pubsub_token"
t.index ["contact_id"], name: "index_contact_inboxes_on_contact_id"
t.index ["inbox_id", "source_id"], name: "index_contact_inboxes_on_inbox_id_and_source_id", unique: true
t.index ["inbox_id"], name: "index_contact_inboxes_on_inbox_id"
+ t.index ["pubsub_token"], name: "index_contact_inboxes_on_pubsub_token", unique: true
t.index ["source_id"], name: "index_contact_inboxes_on_source_id"
end
diff --git a/package.json b/package.json
index 96a40d8de..ea76748df 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@chatwoot/chatwoot",
- "version": "1.22.0",
+ "version": "1.22.1",
"license": "MIT",
"scripts": {
"eslint": "eslint app/javascript --fix",
diff --git a/spec/channels/room_channel_spec.rb b/spec/channels/room_channel_spec.rb
index 8cac85ce6..8db8c0a7c 100644
--- a/spec/channels/room_channel_spec.rb
+++ b/spec/channels/room_channel_spec.rb
@@ -1,15 +1,15 @@
require 'rails_helper'
RSpec.describe RoomChannel, type: :channel do
- let!(:contact) { create(:contact) }
+ let!(:contact_inbox) { create(:contact_inbox) }
before do
stub_connection
end
it 'subscribes to a stream when pubsub_token is provided' do
- subscribe(pubsub_token: contact.pubsub_token)
+ subscribe(pubsub_token: contact_inbox.pubsub_token)
expect(subscription).to be_confirmed
- expect(subscription).to have_stream_for(contact.pubsub_token)
+ expect(subscription).to have_stream_for(contact_inbox.pubsub_token)
end
end
diff --git a/spec/controllers/api/v1/widget/configs_controller_spec.rb b/spec/controllers/api/v1/widget/configs_controller_spec.rb
index b6bc0fba3..773e83102 100644
--- a/spec/controllers/api/v1/widget/configs_controller_spec.rb
+++ b/spec/controllers/api/v1/widget/configs_controller_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe '/api/v1/widget/config', type: :request do
expect(response).to have_http_status(:success)
response_data = JSON.parse(response.body)
expect(response_data.keys).to include(*response_keys)
- expect(response_data['contact']['pubsub_token']).to eq(contact.pubsub_token)
+ expect(response_data['contact']['pubsub_token']).to eq(contact_inbox.pubsub_token)
end
end
diff --git a/spec/controllers/public/api/v1/inbox/contacts_controller_spec.rb b/spec/controllers/public/api/v1/inbox/contacts_controller_spec.rb
index 284d21c83..151a2eec5 100644
--- a/spec/controllers/public/api/v1/inbox/contacts_controller_spec.rb
+++ b/spec/controllers/public/api/v1/inbox/contacts_controller_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe 'Public Inbox Contacts API', type: :request do
expect(response).to have_http_status(:success)
data = JSON.parse(response.body)
expect(data['source_id']).to eq contact_inbox.source_id
- expect(data['pubsub_token']).to eq contact.pubsub_token
+ expect(data['pubsub_token']).to eq contact_inbox.pubsub_token
end
end
diff --git a/spec/listeners/action_cable_listener_spec.rb b/spec/listeners/action_cable_listener_spec.rb
index ea7327e5b..16367848f 100644
--- a/spec/listeners/action_cable_listener_spec.rb
+++ b/spec/listeners/action_cable_listener_spec.rb
@@ -24,7 +24,23 @@ describe ActionCableListener do
expect(conversation.inbox.reload.inbox_members.count).to eq(1)
expect(ActionCableBroadcastJob).to receive(:perform_later).with(
- [agent.pubsub_token, admin.pubsub_token, conversation.contact.pubsub_token],
+ [agent.pubsub_token, admin.pubsub_token, conversation.contact_inbox.pubsub_token],
+ 'message.created',
+ message.push_event_data.merge(account_id: account.id)
+ )
+ listener.message_created(event)
+ end
+
+ it 'sends message to all hmac verified contact inboxes' do
+ # HACK: to reload conversation inbox members
+ expect(conversation.inbox.reload.inbox_members.count).to eq(1)
+ conversation.contact_inbox.update(hmac_verified: true)
+ # creating a non verified contact inbox to ensure the events are not sent to it
+ create(:contact_inbox, contact: conversation.contact, inbox: inbox)
+ verified_contact_inbox = create(:contact_inbox, contact: conversation.contact, inbox: inbox, hmac_verified: true)
+
+ expect(ActionCableBroadcastJob).to receive(:perform_later).with(
+ [agent.pubsub_token, admin.pubsub_token, conversation.contact_inbox.pubsub_token, verified_contact_inbox.pubsub_token],
'message.created',
message.push_event_data.merge(account_id: account.id)
)
diff --git a/spec/models/contact_inbox_spec.rb b/spec/models/contact_inbox_spec.rb
new file mode 100644
index 000000000..a162d6e7b
--- /dev/null
+++ b/spec/models/contact_inbox_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe ContactInbox do
+ describe 'pubsub_token' do
+ let(:contact_inbox) { create(:contact_inbox) }
+
+ it 'gets created on object create' do
+ obj = contact_inbox
+ expect(obj.pubsub_token).not_to eq(nil)
+ end
+
+ it 'does not get updated on object update' do
+ obj = contact_inbox
+ old_token = obj.pubsub_token
+ obj.update(source_id: '234234323')
+ expect(obj.pubsub_token).to eq(old_token)
+ end
+
+ it 'backfills pubsub_token on call for older objects' do
+ obj = create(:contact_inbox)
+ # to replicate an object with out pubsub_token
+ # rubocop:disable Rails/SkipsModelValidations
+ obj.update_column(:pubsub_token, nil)
+ # rubocop:enable Rails/SkipsModelValidations
+
+ obj.reload
+
+ # ensure the column is nil in database
+ results = ActiveRecord::Base.connection.execute('Select * from contact_inboxes;')
+ expect(results.first['pubsub_token']).to eq(nil)
+
+ new_token = obj.pubsub_token
+ obj.update(source_id: '234234323')
+ # the generated token shoul be persisted in db
+ expect(obj.pubsub_token).to eq(new_token)
+ end
+ end
+end
diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb
index 9833b392a..4306e9e44 100644
--- a/spec/models/contact_spec.rb
+++ b/spec/models/contact_spec.rb
@@ -11,20 +11,4 @@ RSpec.describe Contact do
it { is_expected.to belong_to(:account) }
it { is_expected.to have_many(:conversations).dependent(:destroy_async) }
end
-
- describe 'pubsub_token' do
- let(:user) { create(:user) }
-
- it 'gets created on object create' do
- obj = user
- expect(obj.pubsub_token).not_to eq(nil)
- end
-
- it 'does not get updated on object update' do
- obj = user
- old_token = obj.pubsub_token
- obj.update(name: 'test')
- expect(obj.pubsub_token).to eq(old_token)
- end
- end
end
diff --git a/spec/models/conversation_spec.rb b/spec/models/conversation_spec.rb
index 71adf6970..6fa916e54 100644
--- a/spec/models/conversation_spec.rb
+++ b/spec/models/conversation_spec.rb
@@ -399,7 +399,8 @@ RSpec.describe Conversation, type: :model do
additional_attributes: {},
meta: {
sender: conversation.contact.push_event_data,
- assignee: conversation.assignee
+ assignee: conversation.assignee,
+ hmac_verified: conversation.contact_inbox.hmac_verified
},
id: conversation.display_id,
messages: [],
diff --git a/spec/presenters/conversations/event_data_presenter_spec.rb b/spec/presenters/conversations/event_data_presenter_spec.rb
index f3ba9e140..88cd89f0a 100644
--- a/spec/presenters/conversations/event_data_presenter_spec.rb
+++ b/spec/presenters/conversations/event_data_presenter_spec.rb
@@ -12,7 +12,8 @@ RSpec.describe Conversations::EventDataPresenter do
additional_attributes: {},
meta: {
sender: conversation.contact.push_event_data,
- assignee: conversation.assignee
+ assignee: conversation.assignee,
+ hmac_verified: conversation.contact_inbox.hmac_verified
},
id: conversation.display_id,
messages: [],