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 @@
+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,60 @@ public function getCurrentCustomerDetails()
}
$customerSession = $this->modelSessionFactory->getCustomer();
+
+ $hash = null;
+ try {
+ $hash = $this->getVisitorHash($customerSession->getEmail());
+ } catch (LocalizedException $e) {
+ error_log($e->getMessage());
+ }
+
return [
'name' => $customerSession->getName(),
- 'email' => $customerSession->getEmail()
+ 'email' => $customerSession->getEmail(),
+ 'hash' => $hash
];
}
+ /**
+ * Get visitor hash
+ *
+ * @param string $email Visitor email
+ * @return string
+ */
+ 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)) {
+ $currentSession = $this->modelSessionFactory->getData(self::TAWKTO_VISITOR_SESSION);
+
+ if (isset($currentSession['hash']) &&
+ $currentSession['email'] === $email &&
+ $currentSession['config_version'] === $configVersion) {
+ return $currentSession['hash'];
+ }
+ }
+
+ $jsApiKey = $this->encryptor->decrypt($encryptedJsApiKey);
+
+ $hash = hash_hmac('sha256', $email, $jsApiKey);
+
+ $this->modelSessionFactory->setData(self::TAWKTO_VISITOR_SESSION, [
+ 'hash' => $hash,
+ 'email' => $email,
+ 'config_version' => $configVersion,
+ ]);
+
+ return $hash;
+ }
+
/**
* To or to not display the selected widget.
*/
diff --git a/Controller/Adminhtml/SaveWidget/Index.php b/Controller/Adminhtml/SaveWidget/Index.php
index b41324c..5f80da1 100755
--- a/Controller/Adminhtml/SaveWidget/Index.php
+++ b/Controller/Adminhtml/SaveWidget/Index.php
@@ -20,9 +20,14 @@
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Backend\App\Action\Context;
+use Magento\Framework\Encryption\EncryptorInterface;
+use Magento\Framework\Exception\LocalizedException;
+
use Psr\Log\LoggerInterface;
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
{
@@ -61,6 +66,13 @@ class Index extends \Magento\Backend\App\Action
*/
protected $helper;
+ /**
+ * Encryptor instance
+ *
+ * @var EncryptorInterface $encryptor
+ */
+ protected $encryptor;
+
/**
* Constructor
*
@@ -69,13 +81,15 @@ class Index extends \Magento\Backend\App\Action
* @param JsonFactory $resultJsonFactory Json Factory instance
* @param LoggerInterface $logger PSR Logger
* @param StringUtil $helper String util helper
+ * @param EncryptorInterface $encryptor Encryptor instance
*/
public function __construct(
WidgetFactory $modelFactory,
Context $context,
JsonFactory $resultJsonFactory,
LoggerInterface $logger,
- StringUtil $helper
+ StringUtil $helper,
+ EncryptorInterface $encryptor
) {
parent::__construct($context);
$this->resultJsonFactory = $resultJsonFactory;
@@ -83,6 +97,7 @@ public function __construct(
$this->modelWidgetFactory = $modelFactory->create();
$this->request = $this->getRequest();
$this->helper = $helper;
+ $this->encryptor = $encryptor;
}
/**
@@ -106,13 +121,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 +150,46 @@ public function execute()
$model->setEnableVisitorRecognition($enableVisitorRecognition);
+ try {
+ $this->setJsApiKey($model, $jsApiKey);
+ } 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);
+
$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);
+ }
+
+ $jsApiKey = trim($jsApiKey);
+
+ if (strlen($jsApiKey) !== 40) {
+ throw new SaveWidgetException(__('Invalid API key'));
+ }
+
+ 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/Exception/SaveWidgetException.php b/Exception/SaveWidgetException.php
new file mode 100644
index 0000000..d5651d7
--- /dev/null
+++ b/Exception/SaveWidgetException.php
@@ -0,0 +1,25 @@
+
+ Note: If Secure Mode is enabled on your property, please enter + your Javascript API Key to ensure visitor recognition works correctly. +
+ + +