From 791d90c6b71d94124a93fc85aaa8c5094f9b7613 Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Mon, 22 Nov 2021 23:32:17 +0530 Subject: [PATCH] chore: Migrate PubSub Token to contact inbox (#3434) At present, the websocket pubsub tokens are present at the contact objects in chatwoot. A better approach would be to have these tokens at the contact_inbox object instead. This helps chatwoot to deliver the websocket events targetted to the specific widget connection, stop contact events from leaking into other chat sessions from the same contact. Fixes #1682 Fixes #1664 Co-authored-by: Pranav Raj S Co-authored-by: Muhsin Keloth --- app/actions/contact_merge_action.rb | 5 +- app/channels/room_channel.rb | 2 +- app/controllers/widgets_controller.rb | 10 ++-- app/finders/conversation_finder.rb | 2 +- .../assets/scss/_utility-helpers.scss | 8 +++ .../conversation/ConversationHeader.vue | 15 ++++-- .../i18n/locale/en/conversation.json | 1 + .../conversation/contact/ConversationForm.vue | 12 ++--- app/javascript/widget/helpers/actionCable.js | 17 +----- .../widget/helpers/campaignHelper.js | 18 ++++--- .../helpers/specs/campaignHelper.spec.js | 54 +++++++++++++++++++ .../widget/store/modules/contacts.js | 7 +-- .../store/modules/conversation/actions.js | 7 +-- .../widget/store/modules/message.js | 6 +-- app/listeners/action_cable_listener.rb | 12 +++-- app/models/concerns/pubsubable.rb | 6 +++ app/models/contact.rb | 2 +- app/models/contact_inbox.rb | 3 ++ .../conversations/event_data_presenter.rb | 6 ++- .../partials/_conversation.json.jbuilder | 1 + .../v1/widget/configs/create.json.jbuilder | 2 +- .../v1/inboxes/contacts/create.json.jbuilder | 1 + .../v1/inboxes/contacts/show.json.jbuilder | 1 + .../v1/inboxes/contacts/update.json.jbuilder | 1 + .../api/v1/models/_contact.json.jbuilder | 1 - app/views/widgets/show.html.erb | 2 +- config/app.yml | 2 +- ...1012_add_pub_sub_token_to_contact_inbox.rb | 6 +++ db/schema.rb | 4 +- package.json | 2 +- spec/channels/room_channel_spec.rb | 6 +-- .../api/v1/widget/configs_controller_spec.rb | 2 +- .../api/v1/inbox/contacts_controller_spec.rb | 2 +- spec/listeners/action_cable_listener_spec.rb | 18 ++++++- spec/models/contact_inbox_spec.rb | 40 ++++++++++++++ spec/models/contact_spec.rb | 16 ------ spec/models/conversation_spec.rb | 3 +- .../event_data_presenter_spec.rb | 3 +- 38 files changed, 211 insertions(+), 95 deletions(-) create mode 100644 db/migrate/20211122061012_add_pub_sub_token_to_contact_inbox.rb create mode 100644 spec/models/contact_inbox_spec.rb diff --git a/app/actions/contact_merge_action.rb b/app/actions/contact_merge_action.rb index d31b6a3673e4..9d58ef2072a4 100644 --- a/app/actions/contact_merge_action.rb +++ b/app/actions/contact_merge_action.rb @@ -48,11 +48,10 @@ def merge_and_remove_mergee_contact # attributes in base contact are given preference merged_attributes = mergee_contact_attributes.deep_merge(base_contact_attributes) - # retaining old pubsub token to notify the contacts that are listening - mergee_pubsub_token = mergee_contact.pubsub_token @mergee_contact.destroy! - Rails.configuration.dispatcher.dispatch(CONTACT_MERGED, Time.zone.now, contact: @base_contact, tokens: [mergee_pubsub_token]) + Rails.configuration.dispatcher.dispatch(CONTACT_MERGED, Time.zone.now, contact: @base_contact, + tokens: [@base_contact.contact_inboxes.filter_map(&:pubsub_token)]) @base_contact.update!(merged_attributes) end end diff --git a/app/channels/room_channel.rb b/app/channels/room_channel.rb index ab3af0c92880..b3c5977709cc 100644 --- a/app/channels/room_channel.rb +++ b/app/channels/room_channel.rb @@ -31,7 +31,7 @@ def update_subscription def current_user @current_user ||= if params[:user_id].blank? - Contact.find_by!(pubsub_token: @pubsub_token) + ContactInbox.find_by!(pubsub_token: @pubsub_token).contact else User.find_by!(pubsub_token: @pubsub_token, id: params[:user_id]) end diff --git a/app/controllers/widgets_controller.rb b/app/controllers/widgets_controller.rb index f19a2488830b..29c1f97f9764 100644 --- a/app/controllers/widgets_controller.rb +++ b/app/controllers/widgets_controller.rb @@ -29,21 +29,21 @@ def set_token def set_contact return if @auth_token_params[:source_id].nil? - contact_inbox = ::ContactInbox.find_by( + @contact_inbox = ::ContactInbox.find_by( inbox_id: @web_widget.inbox.id, source_id: @auth_token_params[:source_id] ) - @contact = contact_inbox ? contact_inbox.contact : nil + @contact = @contact_inbox ? @contact_inbox.contact : nil end def build_contact return if @contact.present? - contact_inbox = @web_widget.create_contact_inbox(additional_attributes) - @contact = contact_inbox.contact + @contact_inbox = @web_widget.create_contact_inbox(additional_attributes) + @contact = @contact_inbox.contact - payload = { source_id: contact_inbox.source_id, inbox_id: @web_widget.inbox.id } + payload = { source_id: @contact_inbox.source_id, inbox_id: @web_widget.inbox.id } @token = ::Widget::TokenService.new(payload: payload).generate_token end diff --git a/app/finders/conversation_finder.rb b/app/finders/conversation_finder.rb index a0dda66eab65..f2641dde0caa 100644 --- a/app/finders/conversation_finder.rb +++ b/app/finders/conversation_finder.rb @@ -121,7 +121,7 @@ def current_page def conversations @conversations = @conversations.includes( - :taggings, :inbox, { assignee: { avatar_attachment: [:blob] } }, { contact: { avatar_attachment: [:blob] } }, :team + :taggings, :inbox, { assignee: { avatar_attachment: [:blob] } }, { contact: { avatar_attachment: [:blob] } }, :team, :contact_inbox ) @conversations.latest.page(current_page) end diff --git a/app/javascript/dashboard/assets/scss/_utility-helpers.scss b/app/javascript/dashboard/assets/scss/_utility-helpers.scss index 8785f1313951..1072a0878f9b 100644 --- a/app/javascript/dashboard/assets/scss/_utility-helpers.scss +++ b/app/javascript/dashboard/assets/scss/_utility-helpers.scss @@ -2,6 +2,10 @@ margin-right: var(--space-small); } +.margin-right-smaller { + margin-right: var(--space-smaller); +} + .fs-small { font-size: var(--font-size-small); } @@ -42,3 +46,7 @@ .bg-white { background-color: var(--white); } + +.text-y-800 { + color: var(--y-800); +} diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue index bdb917695efc..22989f36f552 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue @@ -10,7 +10,12 @@ />

- {{ currentContact.name }} + {{ currentContact.name }} +

@@ -73,11 +78,15 @@ export default { uiFlags: 'inboxAssignableAgents/getUIFlags', currentChat: 'getSelectedChat', }), - chatMetadata() { return this.chat.meta; }, - + isHMACVerified() { + if (!this.isAWebWidgetInbox) { + return true; + } + return this.chatMetadata.hmac_verified; + }, currentContact() { return this.$store.getters['contacts/getContact']( this.chat.meta.sender.id diff --git a/app/javascript/dashboard/i18n/locale/en/conversation.json b/app/javascript/dashboard/i18n/locale/en/conversation.json index a50e8cb16cf3..9e2e3ea08353 100644 --- a/app/javascript/dashboard/i18n/locale/en/conversation.json +++ b/app/javascript/dashboard/i18n/locale/en/conversation.json @@ -1,6 +1,7 @@ { "CONVERSATION": { "404": "Please select a conversation from left pane", + "UNVERIFIED_SESSION": "The identity of this user is not verified", "NO_MESSAGE_1": "Uh oh! Looks like there are no messages from customers in your inbox.", "NO_MESSAGE_2": " to send a message to your page!", "NO_INBOX_1": "Hola! Looks like you haven't added any inboxes yet.", diff --git a/app/javascript/dashboard/routes/dashboard/conversation/contact/ConversationForm.vue b/app/javascript/dashboard/routes/dashboard/conversation/contact/ConversationForm.vue index 22acd84e5362..b0251df18652 100644 --- a/app/javascript/dashboard/routes/dashboard/conversation/contact/ConversationForm.vue +++ b/app/javascript/dashboard/routes/dashboard/conversation/contact/ConversationForm.vue @@ -41,17 +41,17 @@
-
+
-