parent
2be71e73dc
commit
2f63ebb8a6
11 changed files with 124 additions and 110 deletions
|
@ -1,5 +1,5 @@
|
|||
class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
|
||||
before_action :process_hmac
|
||||
before_action :process_hmac, only: [:update]
|
||||
|
||||
def show; end
|
||||
|
||||
|
@ -8,7 +8,7 @@ class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
|
|||
contact: @contact,
|
||||
params: permitted_params.to_h.deep_symbolize_keys
|
||||
)
|
||||
render json: contact_identify_action.perform
|
||||
@contact = contact_identify_action.perform
|
||||
end
|
||||
|
||||
# TODO : clean up this with proper routes delete contacts/custom_attributes
|
||||
|
@ -21,13 +21,22 @@ class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
|
|||
private
|
||||
|
||||
def process_hmac
|
||||
return if params[:identifier_hash].blank? && !@web_widget.hmac_mandatory
|
||||
return unless should_verify_hmac?
|
||||
|
||||
render json: { error: 'HMAC failed: Invalid Identifier Hash Provided' }, status: :unauthorized unless valid_hmac?
|
||||
|
||||
@contact_inbox.update(hmac_verified: true)
|
||||
end
|
||||
|
||||
def should_verify_hmac?
|
||||
return false if params[:identifier_hash].blank? && !@web_widget.hmac_mandatory
|
||||
|
||||
# Taking an extra caution that the hmac is triggered whenever identifier is present
|
||||
return false if params[:custom_attributes].present? && params[:identifier].blank?
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def valid_hmac?
|
||||
params[:identifier_hash] == OpenSSL::HMAC.hexdigest(
|
||||
'sha256',
|
||||
|
|
|
@ -13,7 +13,7 @@ class ConversationDrop < BaseDrop
|
|||
@obj.try(:recent_messages).map do |message|
|
||||
{
|
||||
'sender' => message_sender_name(message.sender),
|
||||
'content' => transform_user_mention_content(message.content),
|
||||
'content' => render_message_content(transform_user_mention_content(message.content)),
|
||||
'attachments' => message.attachments.map(&:file_url)
|
||||
}
|
||||
end
|
||||
|
|
|
@ -6,7 +6,7 @@ class MessageDrop < BaseDrop
|
|||
end
|
||||
|
||||
def text_content
|
||||
content = @obj.try(:content)
|
||||
transform_user_mention_content content
|
||||
content = @obj.try(:content) || ''
|
||||
render_message_content(transform_user_mention_content(content))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
module MessageFormatHelper
|
||||
include RegexHelper
|
||||
|
||||
def transform_user_mention_content(message_content)
|
||||
message_content.gsub(MENTION_REGEX, '\1')
|
||||
end
|
||||
|
||||
def render_message_content(message_content)
|
||||
# rubocop:disable Rails/OutputSafety
|
||||
CommonMarker.render_html(message_content).html_safe
|
||||
# rubocop:enable Rails/OutputSafety
|
||||
end
|
||||
end
|
||||
|
|
|
@ -85,7 +85,6 @@ export default {
|
|||
},
|
||||
toggleEmailActionsModal() {
|
||||
this.showEmailActionsModal = !this.showEmailActionsModal;
|
||||
this.hideConversationActions();
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -199,6 +199,10 @@ export const IFrameHelper = {
|
|||
},
|
||||
|
||||
handleNotificationDot: event => {
|
||||
if (window.$chatwoot.hideMessageBubble) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bubbleElement = document.querySelector('.woot-widget-bubble');
|
||||
if (
|
||||
event.unreadMessageCount > 0 &&
|
||||
|
|
3
app/views/api/v1/widget/contacts/update.json.jbuilder
Normal file
3
app/views/api/v1/widget/contacts/update.json.jbuilder
Normal file
|
@ -0,0 +1,3 @@
|
|||
json.id @contact.id
|
||||
json.name @contact.name
|
||||
json.email @contact.email
|
|
@ -1,112 +1,94 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
||||
|
||||
<head>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title></title>
|
||||
|
||||
<style type="text/css">
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-text-size-adjust: none;
|
||||
height: 100%;
|
||||
line-height: 1.6em;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #F8FAFC;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 640px) {
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-text-size-adjust: none;
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
line-height: 1.6em;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #f6f6f6;
|
||||
h1 {
|
||||
font-size: 22px !important;
|
||||
font-weight: 800 !important;
|
||||
margin: 20px 0 5px !important;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 640px) {
|
||||
body {
|
||||
padding: 0 !important;
|
||||
}
|
||||
h1 {
|
||||
font-weight: 800 !important;
|
||||
margin: 20px 0 5px !important;
|
||||
}
|
||||
h2 {
|
||||
font-weight: 800 !important;
|
||||
margin: 20px 0 5px !important;
|
||||
}
|
||||
h3 {
|
||||
font-weight: 800 !important;
|
||||
margin: 20px 0 5px !important;
|
||||
}
|
||||
h4 {
|
||||
font-weight: 800 !important;
|
||||
margin: 20px 0 5px !important;
|
||||
}
|
||||
h1 {
|
||||
font-size: 22px !important;
|
||||
}
|
||||
h2 {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
h3 {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
.container {
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
.content-wrap {
|
||||
padding: 10px !important;
|
||||
}
|
||||
.invoice {
|
||||
width: 100% !important;
|
||||
}
|
||||
h2 {
|
||||
font-size: 18px !important;
|
||||
font-weight: 800 !important;
|
||||
margin: 20px 0 5px !important;
|
||||
}
|
||||
h3 {
|
||||
font-size: 16px !important;
|
||||
font-weight: 800 !important;
|
||||
margin: 20px 0 5px !important;
|
||||
}
|
||||
h4 {
|
||||
font-weight: 800 !important;
|
||||
margin: 20px 0 5px !important;
|
||||
}
|
||||
.container {
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
.content-wrap {
|
||||
padding: 10px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
</head>
|
||||
|
||||
<body itemscope itemtype="http://schema.org/EmailMessage" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em; background-color: #f6f6f6; margin: 0;" bgcolor="#f6f6f6">
|
||||
|
||||
<table class="body-wrap" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; background-color: #f6f6f6; margin: 0;" bgcolor="#f6f6f6">
|
||||
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
||||
<td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top"></td>
|
||||
<td class="container" width="600" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; display: block !important; max-width: 600px !important; clear: both !important; margin: 0 auto;" valign="top">
|
||||
<div class="content" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; max-width: 600px; display: block; margin: 0 auto; padding: 20px; text-align:center;">
|
||||
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; border-radius: 4px; background-color: #fff; text-align:left; margin: 0; border: 1px solid #e9e9e9; box-shadow:0 2px 11px 0 rgba(0,0,0,0.15)" bgcolor="#fff">
|
||||
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
||||
<td class="content-wrap" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 20px;" valign="top">
|
||||
<meta itemprop="name" content="Confirm Email" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;" />
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
||||
{{ content_for_layout }}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="footer" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; clear: both; color: #999; margin: 0; padding: 20px;">
|
||||
<table width="100%" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
||||
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
||||
{% if global_config['BRAND_NAME'] != '' %}
|
||||
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
||||
Powered by
|
||||
<a href="{{ global_config['BRAND_URL'] }}" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; color: #999; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">
|
||||
{{ global_config['BRAND_NAME'] }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0;" valign="top"></td>
|
||||
</tr>
|
||||
<body itemscope itemtype="http://schema.org/EmailMessage" style="font-size: 14px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em; background-color: #F8FAFC; margin: 0;" bgcolor="#F8FAFC">
|
||||
<table class="body-wrap" style="width: 100%; background-color: #F8FAFC; margin: 0;" bgcolor="#F8FAFC">
|
||||
<tr style="margin: 0;">
|
||||
<td class="container" width="600" style="display: block !important; max-width: 600px !important; clear: both !important; margin: 0 auto;" valign="top">
|
||||
<div class="content" style="display: block; margin: 0 auto; padding: 20px; text-align:center;">
|
||||
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction" style="border-radius: 6px; background-color: #fff; text-align:left; margin: 0; border: 1px solid #e9e9e9; border-top:3px solid #0080f8;" bgcolor="#fff">
|
||||
<tr style="margin: 0;">
|
||||
<td class="content-wrap" style="vertical-align: top; margin: 0; padding: 20px; font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;" valign="top">
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 0;">
|
||||
{{ content_for_layout }}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="footer" style="color: #93AFC8; margin: 0; padding: 0 20px 40px; text-align: center">
|
||||
<table width="100%" style="margin: 0;">
|
||||
<tr style="margin: 0;">
|
||||
{% if global_config['BRAND_NAME'] != '' %}
|
||||
<td class="content-block" style="font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
|
||||
Powered by
|
||||
<a href="{{ global_config['BRAND_URL'] }}" style="vertical-align: top; color: #93AFC8; text-align: center; margin: 0; padding: 0 0 20px;" align="center" valign="top">
|
||||
{{ global_config['BRAND_NAME'] }}
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
{{message.text_content}}
|
||||
</blockquote>
|
||||
|
||||
<p><b>Previous messages:</b></p>
|
||||
{% for chat_message in conversation.recent_messages %}
|
||||
<div>
|
||||
{% if chat_message.sender == user.available_name %}
|
||||
|
@ -15,7 +16,7 @@
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<p style="padding: 10px 20px; margin: 5px 0 20px 0; background: #F2F3F7; border-radius: 10px; display: inline-block; font-family: "Helvetica Neue",Tahoma,Arial,sans-serif; text-align: start; unicode-bidi: plaintext;">
|
||||
<p style="padding: 10px 20px; margin: 5px 0 20px 0; background: #F2F3F7; border-radius: 10px; display: inline-block; text-align: start; unicode-bidi: plaintext;">
|
||||
{% if chat_message.content %}
|
||||
{{chat_message.content}}
|
||||
{% endif %}
|
||||
|
@ -28,5 +29,6 @@
|
|||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<p><a href="{{ action_url }}">View Message</a></p>
|
||||
<p>
|
||||
<a href="{{ action_url }}">View Message</a>
|
||||
</p>
|
||||
|
|
|
@ -23,7 +23,7 @@ RSpec.describe '/api/v1/widget/contacts', type: :request do
|
|||
|
||||
before do
|
||||
allow(ContactIdentifyAction).to receive(:new).and_return(identify_action)
|
||||
allow(identify_action).to receive(:perform)
|
||||
allow(identify_action).to receive(:perform).and_return(contact)
|
||||
end
|
||||
|
||||
it 'calls contact identify' do
|
||||
|
@ -47,7 +47,7 @@ RSpec.describe '/api/v1/widget/contacts', type: :request do
|
|||
|
||||
before do
|
||||
allow(ContactIdentifyAction).to receive(:new).and_return(identify_action)
|
||||
allow(identify_action).to receive(:perform)
|
||||
allow(identify_action).to receive(:perform).and_return(contact)
|
||||
end
|
||||
|
||||
it 'returns success when correct identifier hash is provided' do
|
||||
|
|
|
@ -8,4 +8,12 @@ describe MessageFormatHelper, type: :helper do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#render_message_content' do
|
||||
context 'when render_message_content called' do
|
||||
it 'render text correctly' do
|
||||
expect(helper.render_message_content('Hi *there*, I am mostly text!')).to eq "<p>Hi <em>there</em>, I am mostly text!</p>\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue