Compare commits

...

2 commits

Author SHA1 Message Date
Pranav Raj S
2cea65fba5 Merge branch 'develop' into fix/set-user 2022-06-17 14:04:33 +05:30
Pranav Raj S
7db2e683a3 fix: Disable auto-merge if contact info doesn't match 2022-06-16 11:18:55 +05:30
8 changed files with 123 additions and 7 deletions

View file

@ -1,6 +1,6 @@
class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
before_action :process_hmac, only: [:update] before_action :process_hmac, only: [:set_user]
before_action :validate_contact, only: [:set_user]
def show; end def show; end
def update def update
@ -18,8 +18,40 @@ class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
render json: @contact render json: @contact
end end
def set_user
contact = @is_a_different_contact ? build_contact : @contact
contact_identify_action = ContactIdentifyAction.new(
contact: contact,
params: permitted_params.to_h.deep_symbolize_keys
)
@contact = contact_identify_action.perform
end
private private
def build_contact
contact_inbox = @web_widget.create_contact_inbox
contact = contact_inbox.contact
payload = { source_id: contact_inbox.source_id, inbox_id: @web_widget.inbox.id }
@widget_auth_token = ::Widget::TokenService.new(payload: payload).generate_token
contact
end
def validate_contact
@is_a_different_contact = false
return unless @contact.resolved?
identifier_mismatch = @contact.identifier.present? && @contact.identifier != permitted_params[:identifier]
email_mismatch = @contact.email.present? && @contact.email != permitted_params[:email]
phone_mismatch = @contact.phone_number.present? && @contact.phone_number != permitted_params[:phone_number]
@is_a_different_contact = identifier_mismatch || email_mismatch || phone_mismatch
end
def process_hmac def process_hmac
return unless should_verify_hmac? return unless should_verify_hmac?

View file

@ -33,6 +33,12 @@ import {
import { isFlatWidgetStyle } from './settingsHelper'; import { isFlatWidgetStyle } from './settingsHelper';
import { popoutChatWindow } from '../widget/helpers/popoutHelper'; import { popoutChatWindow } from '../widget/helpers/popoutHelper';
const updateAuthCookie = cookieContent =>
Cookies.set('cw_conversation', cookieContent, {
expires: 365,
sameSite: 'Lax',
});
export const IFrameHelper = { export const IFrameHelper = {
getUrl({ baseUrl, websiteToken }) { getUrl({ baseUrl, websiteToken }) {
return `${baseUrl}/widget?website_token=${websiteToken}`; return `${baseUrl}/widget?website_token=${websiteToken}`;
@ -134,10 +140,7 @@ export const IFrameHelper = {
events: { events: {
loaded: message => { loaded: message => {
Cookies.set('cw_conversation', message.config.authToken, { updateAuthCookie(message.config.authToken);
expires: 365,
sameSite: 'Lax',
});
window.$chatwoot.hasLoaded = true; window.$chatwoot.hasLoaded = true;
IFrameHelper.sendMessage('config-set', { IFrameHelper.sendMessage('config-set', {
locale: window.$chatwoot.locale, locale: window.$chatwoot.locale,
@ -178,6 +181,10 @@ export const IFrameHelper = {
setBubbleText(window.$chatwoot.launcherTitle || message.label); setBubbleText(window.$chatwoot.launcherTitle || message.label);
}, },
setAuthCookie({ data: { authToken } }) {
updateAuthCookie(authToken);
},
toggleBubble: state => { toggleBubble: state => {
let bubbleState = {}; let bubbleState = {};
if (state === 'open') { if (state === 'open') {

View file

@ -253,7 +253,7 @@ export default {
} else if (message.event === 'remove-label') { } else if (message.event === 'remove-label') {
this.$store.dispatch('conversationLabels/destroy', message.label); this.$store.dispatch('conversationLabels/destroy', message.label);
} else if (message.event === 'set-user') { } else if (message.event === 'set-user') {
this.$store.dispatch('contacts/update', message); this.$store.dispatch('contacts/setUser', message);
} else if (message.event === 'set-custom-attributes') { } else if (message.event === 'set-custom-attributes') {
this.$store.dispatch( this.$store.dispatch(
'contacts/setCustomAttributes', 'contacts/setCustomAttributes',

View file

@ -12,6 +12,12 @@ export default {
...userObject, ...userObject,
}); });
}, },
setUser(identifier, userObject) {
return API.patch(buildUrl('widget/contact/set_user'), {
identifier,
...userObject,
});
},
setCustomAttributes(customAttributes = {}) { setCustomAttributes(customAttributes = {}) {
return API.patch(buildUrl('widget/contact'), { return API.patch(buildUrl('widget/contact'), {
custom_attributes: customAttributes, custom_attributes: customAttributes,

View file

@ -1,3 +1,4 @@
import { setHeader } from 'widget/helpers/axios';
import { IFrameHelper } from 'widget/helpers/utils'; import { IFrameHelper } from 'widget/helpers/utils';
import ContactsAPI from '../../api/contacts'; import ContactsAPI from '../../api/contacts';
import { SET_USER_ERROR } from '../../constants/errorTypes'; import { SET_USER_ERROR } from '../../constants/errorTypes';
@ -72,6 +73,63 @@ export const actions = {
}); });
} }
}, },
setUser: async ({ dispatch }, { identifier, user: userObject }) => {
try {
const {
email,
name,
avatar_url,
identifier_hash,
phone_number,
company_name,
city,
country_code,
description,
custom_attributes,
social_profiles,
} = userObject;
const user = {
email,
name,
avatar_url,
identifier_hash,
phone_number,
additional_attributes: {
company_name,
city,
description,
country_code,
social_profiles,
},
custom_attributes,
};
const response = await ContactsAPI.setUser(identifier, user);
const { data = {} } = response;
dispatch('get');
if (data.widget_auth_token) {
setHeader('X-Auth-Token', data.widget_auth_token);
IFrameHelper.sendMessage({
event: 'setAuthCookie',
data: { authToken: data.widget_auth_token },
});
}
if (identifier_hash || data.widget_auth_token) {
dispatch('conversation/clearConversations', {}, { root: true });
dispatch('conversation/fetchOldConversations', {}, { root: true });
dispatch('conversationAttributes/getAttributes', {}, { root: true });
}
} catch (error) {
const data =
error && error.response && error.response.data
? error.response.data
: error;
IFrameHelper.sendMessage({
event: 'error',
errorType: SET_USER_ERROR,
data,
});
}
},
setCustomAttributes: async (_, customAttributes = {}) => { setCustomAttributes: async (_, customAttributes = {}) => {
try { try {
await ContactsAPI.setCustomAttributes(customAttributes); await ContactsAPI.setCustomAttributes(customAttributes);

View file

@ -134,6 +134,10 @@ class Contact < ApplicationRecord
).or(Current.account.contacts.where.not(identifier: [nil, ''])) ).or(Current.account.contacts.where.not(identifier: [nil, '']))
end end
def resolved?
identifier.present? || email.present? || phone_number.present?
end
private private
def ip_lookup def ip_lookup

View file

@ -0,0 +1,8 @@
json.contact do
json.id @contact.id
json.name @contact.name
json.email @contact.email
json.phone_number @contact.phone_number
end if @contact
json.widget_auth_token @widget_auth_token if @widget_auth_token

View file

@ -199,6 +199,7 @@ Rails.application.routes.draw do
resource :contact, only: [:show, :update] do resource :contact, only: [:show, :update] do
collection do collection do
post :destroy_custom_attributes post :destroy_custom_attributes
patch :set_user
end end
end end
resources :inbox_members, only: [:index] resources :inbox_members, only: [:index]