From 4bbe230922222cf0616bf754bec655c13f233b35 Mon Sep 17 00:00:00 2001 From: eug-L Date: Wed, 26 Feb 2025 10:01:50 +0800 Subject: [PATCH 01/10] add proper alert on save settings --- view/adminhtml/templates/selectwidget.phtml | 11 +++++++ view/adminhtml/web/css/tawk-widget-select.css | 9 ++++++ view/adminhtml/web/js/tawk-widget-select.js | 32 ++++++++++--------- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/view/adminhtml/templates/selectwidget.phtml b/view/adminhtml/templates/selectwidget.phtml index c86dc0a..025a17f 100755 --- a/view/adminhtml/templates/selectwidget.phtml +++ b/view/adminhtml/templates/selectwidget.phtml @@ -149,5 +149,16 @@
Save Settings +
+ Settings saved successfully +
+
+
diff --git a/view/adminhtml/web/css/tawk-widget-select.css b/view/adminhtml/web/css/tawk-widget-select.css index 9d2ea48..53d773a 100644 --- a/view/adminhtml/web/css/tawk-widget-select.css +++ b/view/adminhtml/web/css/tawk-widget-select.css @@ -158,3 +158,12 @@ input:checked + .slider:before { .tawk-tooltip:hover .tawk-tooltiptext { visibility: visible; } + +.options-alert { + width: 50%; + font-weight: bold; + display: none; + padding: 10px; + border-radius: 5px; + margin: 5px 0; +} diff --git a/view/adminhtml/web/js/tawk-widget-select.js b/view/adminhtml/web/js/tawk-widget-select.js index 157d4e0..6b008e7 100644 --- a/view/adminhtml/web/js/tawk-widget-select.js +++ b/view/adminhtml/web/js/tawk-widget-select.js @@ -5,11 +5,11 @@ define(['jquery', 'jquery/ui'], function ($) { return function (config) { var domain = config.domain, - baseUrl = config.baseUrl, - removeWidgetUrl = config.removeWidgetUrl, - storedWidgetUrl = config.storedWidgetUrl, - formAction = config.form.action, - formKey = config.form.key; + baseUrl = config.baseUrl, + removeWidgetUrl = config.removeWidgetUrl, + storedWidgetUrl = config.storedWidgetUrl, + formAction = config.form.action, + formKey = config.form.key; function displayWidget(websiteId) { jQuery.get(storedWidgetUrl + '?id=' + websiteId, function (response) { @@ -48,10 +48,10 @@ define(['jquery', 'jquery/ui'], function ($) { function setWidget(e) { var alwaysdisplay = jQuery('#alwaysdisplay').is(':checked'), - alwaysdisplayvalue = alwaysdisplay ? 1 : 0, + alwaysdisplayvalue = alwaysdisplay ? 1 : 0, - donotdisplay = jQuery('#donotdisplay').is(':checked'), - donotdisplayvalue = donotdisplay ? 1 : 0; + donotdisplay = jQuery('#donotdisplay').is(':checked'), + donotdisplayvalue = donotdisplay ? 1 : 0; jQuery.post(formAction, { pageId : e.data.pageId, @@ -76,9 +76,9 @@ define(['jquery', 'jquery/ui'], function ($) { function saveVisibilityOptions(e) { var alwaysdisplay = jQuery('#alwaysdisplay').is(':checked'), - alwaysdisplayvalue = alwaysdisplay ? 1 : 0, - donotdisplay = jQuery('#donotdisplay').is(':checked'), - donotdisplayvalue = donotdisplay ? 1 : 0; + alwaysdisplayvalue = alwaysdisplay ? 1 : 0, + donotdisplay = jQuery('#donotdisplay').is(':checked'), + donotdisplayvalue = donotdisplay ? 1 : 0; e.preventDefault(); @@ -92,10 +92,12 @@ define(['jquery', 'jquery/ui'], function ($) { donotdisplay: donotdisplayvalue, enableVisitorRecognition : jQuery('#enable_visitor_recognition').is(':checked') ? 1 : 0, form_key : formKey - }, function () { - /* TODO: convert this to a different type of alert that doesn't use the browser alert func */ - /* eslint-disable-next-line no-alert */ - alert('Visibility options Saved'); + }, function (response) { + if (response.success) { + jQuery('#optionsSuccessMessage').toggle().delay(3000).fadeOut(); + } else { + jQuery('#optionsFailureMessage').text(response.message).toggle().delay(3000).fadeOut(); + } }); } From 228a32dfc97536602d4fd120ef7dd9b4d0c0a10d Mon Sep 17 00:00:00 2001 From: eug-L Date: Wed, 26 Feb 2025 10:42:18 +0800 Subject: [PATCH 02/10] add js api key for widget settings --- Api/ConfigInterface.php | 24 +++++++++ Controller/Adminhtml/SaveWidget/Index.php | 51 +++++++++++++++++-- Controller/Adminhtml/StoreWidget/Index.php | 13 ++++- etc/db_schema.xml | 1 + view/adminhtml/templates/selectwidget.phtml | 12 +++++ view/adminhtml/web/css/tawk-widget-select.css | 28 ++++++---- view/adminhtml/web/js/tawk-widget-select.js | 9 +++- 7 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 Api/ConfigInterface.php diff --git a/Api/ConfigInterface.php b/Api/ConfigInterface.php new file mode 100644 index 0000000..8882b2d --- /dev/null +++ b/Api/ConfigInterface.php @@ -0,0 +1,24 @@ +resultJsonFactory = $resultJsonFactory; @@ -83,6 +96,7 @@ public function __construct( $this->modelWidgetFactory = $modelFactory->create(); $this->request = $this->getRequest(); $this->helper = $helper; + $this->encryptor = $encryptor; } /** @@ -106,13 +120,14 @@ public function execute() } $alwaysdisplay = filter_var($this->request->getParam('alwaysdisplay'), FILTER_SANITIZE_NUMBER_INT); - $excludeurl = $this->request->getParam('excludeurl'); + $excludeurl = $this->helper->stripTagsandQuotes($this->request->getParam('excludeurl')); $donotdisplay = filter_var($this->request->getParam('donotdisplay'), FILTER_SANITIZE_NUMBER_INT); - $includeurl = $this->request->getParam('includeurl'); + $includeurl = $this->helper->stripTagsAndQuotes($this->request->getParam('includeurl')); $enableVisitorRecognition = filter_var( $this->request->getParam('enableVisitorRecognition'), FILTER_SANITIZE_NUMBER_INT ); + $jsApiKey = $this->helper->stripTagsandQuotes($this->request->getParam('jsApiKey')); $model = $this->modelWidgetFactory->loadByForStoreId($storeId); @@ -134,8 +149,38 @@ public function execute() $model->setEnableVisitorRecognition($enableVisitorRecognition); + try { + $this->setJsApiKey($model, $jsApiKey); + } catch (\Exception $e) { + return $response->setData(['success' => false, 'message' => $e->getMessage()]); + } + $model->save(); return $response->setData(['success' => true]); } + + /** + * Sets the JS API key for the widget. + * + * @param \Tawk\Widget\Model\Widget $model The widget model + * @param string $jsApiKey The JS API key + * @return void + */ + private function setJsApiKey($model, $jsApiKey) + { + if ($jsApiKey === ConfigInterface::JS_API_KEY_NO_CHANGE) { + return; + } + + if ($jsApiKey === '') { + return $model->setJsApiKey(null); + } + + if (strlen(trim($jsApiKey)) !== 40) { + throw new LocalizedException(__('Invalid API key. Please provide value with 40 characters')); + } + + return $model->setJsApiKey($this->encryptor->encrypt($jsApiKey)); + } } diff --git a/Controller/Adminhtml/StoreWidget/Index.php b/Controller/Adminhtml/StoreWidget/Index.php index 27758c4..8eeeb8f 100755 --- a/Controller/Adminhtml/StoreWidget/Index.php +++ b/Controller/Adminhtml/StoreWidget/Index.php @@ -20,9 +20,11 @@ use Magento\Backend\App\Action\Context; use Magento\Framework\Controller\Result\JsonFactory; + use Psr\Log\LoggerInterface; use Tawk\Widget\Model\WidgetFactory; use Tawk\Widget\Helper\StringUtil; +use Tawk\Widget\Api\ConfigInterface; class Index extends \Magento\Backend\App\Action { @@ -96,7 +98,8 @@ public function __construct( * excludeurl: string, * donotdisplay: int, * includeurl: string, - * enableVisitorRecognition: int + * enableVisitorRecognition: int, + * jsApiKey: string * } */ public function execute() @@ -126,6 +129,11 @@ public function execute() $enableVisitorRecognition = $model->getEnableVisitorRecognition(); + $jsApiKey = $model->getJsApiKey(); + if (!empty($jsApiKey)) { + $jsApiKey = ConfigInterface::JS_API_KEY_NO_CHANGE; + } + return $response->setData([ 'success' => true, 'pageid' => $pageId, @@ -134,7 +142,8 @@ public function execute() 'excludeurl' => $excludeurl, 'donotdisplay' => $donotdisplay, 'includeurl' => $includeurl, - 'enableVisitorRecognition' => $enableVisitorRecognition + 'enableVisitorRecognition' => $enableVisitorRecognition, + 'jsApiKey' => $jsApiKey ]); } } diff --git a/etc/db_schema.xml b/etc/db_schema.xml index 3611983..e594218 100644 --- a/etc/db_schema.xml +++ b/etc/db_schema.xml @@ -18,5 +18,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/et comment="Comma-separated list of url patterns where widget should be displayed"/> + diff --git a/view/adminhtml/templates/selectwidget.phtml b/view/adminhtml/templates/selectwidget.phtml index 025a17f..46a3110 100755 --- a/view/adminhtml/templates/selectwidget.phtml +++ b/view/adminhtml/templates/selectwidget.phtml @@ -147,6 +147,18 @@ +
+

Security Options

+
+

+ Note: If Secure Mode is enabled on your property, please enter + your Javascript API Key to ensure visitor recognition works correctly. +

+ + +
+
+
Save Settings
Date: Mon, 3 Mar 2025 17:26:29 +0800 Subject: [PATCH 03/10] hash email for visitor recognition --- Block/Embed.php | 52 +++++++++++++++++++++++++++-- view/frontend/templates/embed.phtml | 3 +- view/frontend/web/js/tawk-embed.js | 10 ++++-- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/Block/Embed.php b/Block/Embed.php index 4c763ca..6deb4cc 100755 --- a/Block/Embed.php +++ b/Block/Embed.php @@ -21,12 +21,16 @@ use Magento\Framework\View\Element\Template; use Magento\Framework\Escaper; use Magento\Customer\Model\SessionFactory; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Framework\Exception\LocalizedException; use Tawk\Modules\UrlPatternMatcher; use Tawk\Widget\Model\WidgetFactory; class Embed extends Template { + public const TAWKTO_JS_API_KEY = 'TAWKTO_JS_API_KEY'; + /** * Tawk.to Widget Model instance * @@ -76,6 +80,13 @@ class Embed extends Template */ protected $escaper; + /** + * Encryptor instance + * + * @var EncryptorInterface $encryptor + */ + protected $encryptor; + /** * Constructor * @@ -83,6 +94,7 @@ class Embed extends Template * @param WidgetFactory $modelFactory Tawk.to Widget Model instance * @param Template\Context $context Template Context * @param Escaper $escaper Escaper instance + * @param EncryptorInterface $encryptor Encryptor instance * @param array $data Template data */ public function __construct( @@ -90,6 +102,7 @@ public function __construct( WidgetFactory $modelFactory, Template\Context $context, Escaper $escaper, + EncryptorInterface $encryptor, array $data = [] ) { parent::__construct($context, $data); @@ -100,6 +113,7 @@ public function __construct( $this->request = $context->getRequest(); $this->modelSessionFactory = $sessionFactory->create(); $this->escaper = $escaper; + $this->encryptor = $encryptor; } /** @@ -146,7 +160,8 @@ private function getWidgetModel() * * @return array { * name: string, - * email: string + * email: string, + * hash: string * } */ public function getCurrentCustomerDetails() @@ -160,12 +175,45 @@ public function getCurrentCustomerDetails() } $customerSession = $this->modelSessionFactory->getCustomer(); + + try { + $jsApiKey = $this->decryptJsApiKey($this->model->getJsApiKey()); + $hash = hash_hmac('sha256', $customerSession->getEmail(), $jsApiKey); + } catch (\Exception $e) { + $hash = ''; + } + return [ 'name' => $customerSession->getName(), - 'email' => $customerSession->getEmail() + 'email' => $customerSession->getEmail(), + 'hash' => $hash ]; } + /** + * Retrieve JS API key + * + * @param string $js_api_key Encrypted JS API key + * @return string + * @throws \Exception error retrieving JS API key + */ + private function decryptJsApiKey(string $js_api_key) + { + if (empty($js_api_key)) { + throw new LocalizedException(__('JS API key is empty')); + } + + if ($this->modelSessionFactory->hasData(self::TAWKTO_JS_API_KEY)) { + return $this->modelSessionFactory->getData(self::TAWKTO_JS_API_KEY); + } + + $key = $this->encryptor->decrypt($js_api_key); + + $this->modelSessionFactory->setData(self::TAWKTO_JS_API_KEY, $key); + + return $key; + } + /** * To or to not display the selected widget. */ diff --git a/view/frontend/templates/embed.phtml b/view/frontend/templates/embed.phtml index e25c3f4..8b015f0 100755 --- a/view/frontend/templates/embed.phtml +++ b/view/frontend/templates/embed.phtml @@ -34,7 +34,8 @@ "embedUrl" : "escapeUrl($block->getEmbedUrl()); ?>", "visitor" : { "name" : "escapeJs($customer_details['name']); ?>", - "email" : "escapeJs($customer_details['email']); ?>" + "email" : "escapeJs($customer_details['email']); ?>", + "hash" : "escapeJs($customer_details['hash']); ?>" } } } diff --git a/view/frontend/web/js/tawk-embed.js b/view/frontend/web/js/tawk-embed.js index 8951ae0..7ba1f19 100644 --- a/view/frontend/web/js/tawk-embed.js +++ b/view/frontend/web/js/tawk-embed.js @@ -3,9 +3,9 @@ define([], function () { return function (config) { var visitor = config.visitor, - embedUrl = config.embedUrl, - /* eslint-disable-next-line no-unused-vars */ - Tawk_LoadStart = new Date(); + embedUrl = config.embedUrl, + /* eslint-disable-next-line no-unused-vars */ + Tawk_LoadStart = new Date(); window.Tawk_API = window.Tawk_API || {}; @@ -16,6 +16,10 @@ define([], function () { }; } + if (visitor.hash) { + window.Tawk_API.visitor.hash = visitor.hash; + } + (function () { var s1 = document.createElement('script'),s0 = document.getElementsByTagName('script')[0]; From 8d3db1e11679fe5b0dbda0a18ef88d7613951b0d Mon Sep 17 00:00:00 2001 From: eug-L Date: Mon, 3 Mar 2025 17:31:14 +0800 Subject: [PATCH 04/10] add builld script --- build/build-package.sh | 18 ++++++++++++++++++ composer.json | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100755 build/build-package.sh diff --git a/build/build-package.sh b/build/build-package.sh new file mode 100755 index 0000000..0d044b8 --- /dev/null +++ b/build/build-package.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +composer run clean + +mkdir -p ./tmp/tawkmagento2 +cp -r ./view ./tmp/tawkmagento2 +cp -r ./etc ./tmp/tawkmagento2 +cp -r ./Setup ./tmp/tawkmagento2 +cp -r ./Model ./tmp/tawkmagento2 +cp -r ./Controller ./tmp/tawkmagento2 +cp -r ./Block ./tmp/tawkmagento2 +cp -r ./Helper ./tmp/tawkmagento2 +cp -r ./Api ./tmp/tawkmagento2 +cp ./registration.php ./tmp/tawkmagento2 +cp ./composer.json ./tmp/tawkmagento2 +cp README.md ./tmp/tawkmagento2 + +(cd ./tmp && zip -9 -rq ./tawkmagento2.zip ./tawkmagento2) diff --git a/composer.json b/composer.json index f0e2942..d11bbf5 100755 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "build:prod": "composer install --no-dev", "lint": "phpcs -p -s -v --runtime-set ignore_warnings_on_exit true .", "lint:fix": "phpcbf -p -s -v .; err=$?; if [ $err -eq 1 ]; then exit 0; else exit $err; fi;", - "package": "composer run clean && mkdir -p ./tmp/tawkmagento2 && cp -r ./view ./tmp/tawkmagento2 && cp -r ./etc ./tmp/tawkmagento2 && cp -r ./Setup ./tmp/tawkmagento2 && cp -r ./Model ./tmp/tawkmagento2 && cp -r ./Controller ./tmp/tawkmagento2 && cp -r ./Block ./tmp/tawkmagento2 && cp -r ./Helper ./tmp/tawkmagento2 && cp ./registration.php ./tmp/tawkmagento2 && cp ./composer.json ./tmp/tawkmagento2 && cp README.md ./tmp/tawkmagento2 && (cd ./tmp && zip -9 -rq ./tawkmagento2.zip ./tawkmagento2)", + "package": "./build/build-package.sh", "clean": "rm -rf ./tmp" }, "repositories": { From 7520f2266e56521fca75534a3aac7835336e0ba4 Mon Sep 17 00:00:00 2001 From: eug-L Date: Wed, 12 Mar 2025 16:19:56 +0800 Subject: [PATCH 05/10] add config version --- Controller/Adminhtml/SaveWidget/Index.php | 2 ++ etc/db_schema.xml | 1 + 2 files changed, 3 insertions(+) diff --git a/Controller/Adminhtml/SaveWidget/Index.php b/Controller/Adminhtml/SaveWidget/Index.php index dc55e24..d54ef45 100755 --- a/Controller/Adminhtml/SaveWidget/Index.php +++ b/Controller/Adminhtml/SaveWidget/Index.php @@ -155,6 +155,8 @@ public function execute() return $response->setData(['success' => false, 'message' => $e->getMessage()]); } + $model->setConfigVersion($model->getConfigVersion() + 1); + $model->save(); return $response->setData(['success' => true]); diff --git a/etc/db_schema.xml b/etc/db_schema.xml index e594218..e55689a 100644 --- a/etc/db_schema.xml +++ b/etc/db_schema.xml @@ -5,6 +5,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/et + From 8c1f1f921b7e2ef64688b0df3cdc18f5378a10c4 Mon Sep 17 00:00:00 2001 From: eug-L Date: Wed, 12 Mar 2025 16:45:41 +0800 Subject: [PATCH 06/10] fix render visitor hash --- view/frontend/web/js/tawk-embed.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/view/frontend/web/js/tawk-embed.js b/view/frontend/web/js/tawk-embed.js index 7ba1f19..c9f470e 100644 --- a/view/frontend/web/js/tawk-embed.js +++ b/view/frontend/web/js/tawk-embed.js @@ -14,10 +14,10 @@ define([], function () { name : visitor.name, email : visitor.email }; - } - if (visitor.hash) { - window.Tawk_API.visitor.hash = visitor.hash; + if (visitor.hash) { + window.Tawk_API.visitor.hash = visitor.hash; + } } (function () { From 63dd82eb29bb481a45b85ea9163e985827ba3b5b Mon Sep 17 00:00:00 2001 From: eug-L Date: Wed, 12 Mar 2025 16:46:45 +0800 Subject: [PATCH 07/10] store visitor hash in session instead of api key --- Block/Embed.php | 52 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/Block/Embed.php b/Block/Embed.php index 6deb4cc..bb4ac77 100755 --- a/Block/Embed.php +++ b/Block/Embed.php @@ -29,7 +29,7 @@ class Embed extends Template { - public const TAWKTO_JS_API_KEY = 'TAWKTO_JS_API_KEY'; + public const TAWKTO_VISITOR_SESSION = 'TAWKTO_VISITOR_SESSION'; /** * Tawk.to Widget Model instance @@ -176,12 +176,7 @@ public function getCurrentCustomerDetails() $customerSession = $this->modelSessionFactory->getCustomer(); - try { - $jsApiKey = $this->decryptJsApiKey($this->model->getJsApiKey()); - $hash = hash_hmac('sha256', $customerSession->getEmail(), $jsApiKey); - } catch (\Exception $e) { - $hash = ''; - } + $hash = $this->getVisitorHash($customerSession->getEmail()); return [ 'name' => $customerSession->getName(), @@ -190,6 +185,43 @@ public function getCurrentCustomerDetails() ]; } + /** + * Get visitor hash + * + * @param string $email Visitor email + * @return string + */ + private function getVisitorHash(string $email) + { + $configVersion = $this->model->getConfigVersion(); + + if ($this->modelSessionFactory->hasData(self::TAWKTO_VISITOR_SESSION)) { + $currentSession = $this->modelSessionFactory->getData(self::TAWKTO_VISITOR_SESSION); + + if (isset($currentSession['hash']) && + $currentSession['email'] === $email && + $currentSession['config_version'] === $configVersion) { + return $currentSession['hash']; + } + } + + try { + $jsApiKey = $this->decryptJsApiKey($this->model->getJsApiKey()); + } catch (LocalizedException $e) { + return ''; + } + + $hash = hash_hmac('sha256', $email, $jsApiKey); + + $this->modelSessionFactory->setData(self::TAWKTO_VISITOR_SESSION, [ + 'hash' => $hash, + 'email' => $email, + 'config_version' => $configVersion, + ]); + + return $hash; + } + /** * Retrieve JS API key * @@ -203,14 +235,8 @@ private function decryptJsApiKey(string $js_api_key) throw new LocalizedException(__('JS API key is empty')); } - if ($this->modelSessionFactory->hasData(self::TAWKTO_JS_API_KEY)) { - return $this->modelSessionFactory->getData(self::TAWKTO_JS_API_KEY); - } - $key = $this->encryptor->decrypt($js_api_key); - $this->modelSessionFactory->setData(self::TAWKTO_JS_API_KEY, $key); - return $key; } From 6fd126ddfc5aff74def091a016a5a99e412459b3 Mon Sep 17 00:00:00 2001 From: eug-L Date: Fri, 21 Mar 2025 10:27:52 +0200 Subject: [PATCH 08/10] improve hash null handling --- Block/Embed.php | 35 ++++++++++------------------- view/frontend/templates/embed.phtml | 6 +++-- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/Block/Embed.php b/Block/Embed.php index bb4ac77..a1268a5 100755 --- a/Block/Embed.php +++ b/Block/Embed.php @@ -176,7 +176,12 @@ public function getCurrentCustomerDetails() $customerSession = $this->modelSessionFactory->getCustomer(); - $hash = $this->getVisitorHash($customerSession->getEmail()); + $hash = null; + try { + $hash = $this->getVisitorHash($customerSession->getEmail()); + } catch (LocalizedException $e) { + error_log($e->getMessage()); + } return [ 'name' => $customerSession->getName(), @@ -205,12 +210,14 @@ private function getVisitorHash(string $email) } } - try { - $jsApiKey = $this->decryptJsApiKey($this->model->getJsApiKey()); - } catch (LocalizedException $e) { - return ''; + $encryptedJsApiKey = $this->model->getJsApiKey(); + + if (empty($encryptedJsApiKey)) { + return null; } + $jsApiKey = $this->encryptor->decrypt($encryptedJsApiKey); + $hash = hash_hmac('sha256', $email, $jsApiKey); $this->modelSessionFactory->setData(self::TAWKTO_VISITOR_SESSION, [ @@ -222,24 +229,6 @@ private function getVisitorHash(string $email) return $hash; } - /** - * Retrieve JS API key - * - * @param string $js_api_key Encrypted JS API key - * @return string - * @throws \Exception error retrieving JS API key - */ - private function decryptJsApiKey(string $js_api_key) - { - if (empty($js_api_key)) { - throw new LocalizedException(__('JS API key is empty')); - } - - $key = $this->encryptor->decrypt($js_api_key); - - return $key; - } - /** * To or to not display the selected widget. */ diff --git a/view/frontend/templates/embed.phtml b/view/frontend/templates/embed.phtml index 8b015f0..e1f56e8 100755 --- a/view/frontend/templates/embed.phtml +++ b/view/frontend/templates/embed.phtml @@ -34,8 +34,10 @@ "embedUrl" : "escapeUrl($block->getEmbedUrl()); ?>", "visitor" : { "name" : "escapeJs($customer_details['name']); ?>", - "email" : "escapeJs($customer_details['email']); ?>", - "hash" : "escapeJs($customer_details['hash']); ?>" + "email" : "escapeJs($customer_details['email']); ?>" + + , "hash" : "escapeJs($customer_details['hash']); ?>" + } } } From e6e3ea222194abfcef3dc9c854fb075f2f1d7963 Mon Sep 17 00:00:00 2001 From: eug-L Date: Fri, 21 Mar 2025 10:35:45 +0200 Subject: [PATCH 09/10] improve error handling for settings page --- Controller/Adminhtml/SaveWidget/Index.php | 15 +++++++++---- Exception/SaveWidgetException.php | 25 +++++++++++++++++++++ build/build-package.sh | 1 + view/adminhtml/web/js/tawk-widget-select.js | 2 ++ 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 Exception/SaveWidgetException.php diff --git a/Controller/Adminhtml/SaveWidget/Index.php b/Controller/Adminhtml/SaveWidget/Index.php index d54ef45..5f80da1 100755 --- a/Controller/Adminhtml/SaveWidget/Index.php +++ b/Controller/Adminhtml/SaveWidget/Index.php @@ -27,6 +27,7 @@ use Tawk\Widget\Model\WidgetFactory; use Tawk\Widget\Helper\StringUtil; use Tawk\Widget\Api\ConfigInterface; +use Tawk\Widget\Exception\SaveWidgetException; class Index extends \Magento\Backend\App\Action { @@ -151,8 +152,12 @@ public function execute() try { $this->setJsApiKey($model, $jsApiKey); - } catch (\Exception $e) { - return $response->setData(['success' => false, 'message' => $e->getMessage()]); + } catch (LocalizedException $e) { + if ($e instanceof SaveWidgetException) { + return $response->setData(['success' => false, 'message' => $e->getMessage()]); + } + + return $response->setData(['success' => false, 'message' => 'An error occurred while saving the widget']); } $model->setConfigVersion($model->getConfigVersion() + 1); @@ -179,8 +184,10 @@ private function setJsApiKey($model, $jsApiKey) return $model->setJsApiKey(null); } - if (strlen(trim($jsApiKey)) !== 40) { - throw new LocalizedException(__('Invalid API key. Please provide value with 40 characters')); + $jsApiKey = trim($jsApiKey); + + if (strlen($jsApiKey) !== 40) { + throw new SaveWidgetException(__('Invalid API key')); } return $model->setJsApiKey($this->encryptor->encrypt($jsApiKey)); diff --git a/Exception/SaveWidgetException.php b/Exception/SaveWidgetException.php new file mode 100644 index 0000000..d5651d7 --- /dev/null +++ b/Exception/SaveWidgetException.php @@ -0,0 +1,25 @@ + Date: Fri, 21 Mar 2025 12:07:24 +0200 Subject: [PATCH 10/10] move check api key before session check --- Block/Embed.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Block/Embed.php b/Block/Embed.php index a1268a5..1a230e3 100755 --- a/Block/Embed.php +++ b/Block/Embed.php @@ -198,6 +198,12 @@ public function getCurrentCustomerDetails() */ private function getVisitorHash(string $email) { + $encryptedJsApiKey = $this->model->getJsApiKey(); + + if (empty($encryptedJsApiKey)) { + return null; + } + $configVersion = $this->model->getConfigVersion(); if ($this->modelSessionFactory->hasData(self::TAWKTO_VISITOR_SESSION)) { @@ -210,12 +216,6 @@ private function getVisitorHash(string $email) } } - $encryptedJsApiKey = $this->model->getJsApiKey(); - - if (empty($encryptedJsApiKey)) { - return null; - } - $jsApiKey = $this->encryptor->decrypt($encryptedJsApiKey); $hash = hash_hmac('sha256', $email, $jsApiKey);