Response.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <?php
  2. namespace Dotdigitalgroup\Email\Controller;
  3. /**
  4. * @SuppressWarnings(PHPMD.NumberOfChildren)
  5. */
  6. class Response extends \Magento\Framework\App\Action\Action
  7. {
  8. /**
  9. * @var \Dotdigitalgroup\Email\Helper\Data
  10. */
  11. public $helper;
  12. /**
  13. * @var \Magento\Framework\Escaper
  14. */
  15. public $escaper;
  16. /**
  17. * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface
  18. */
  19. private $timezone;
  20. /**
  21. * @var \Dotdigitalgroup\Email\Model\ResourceModel\FailedAuth
  22. */
  23. private $failedAuthResource;
  24. /**
  25. * @var \Dotdigitalgroup\Email\Model\FailedAuthFactory
  26. */
  27. private $failedAuthFactory;
  28. /**
  29. * @var \Magento\Store\Model\StoreManagerInterface
  30. */
  31. private $storeManager;
  32. /**
  33. * @var \Dotdigitalgroup\Email\Helper\Config
  34. */
  35. private $configHelper;
  36. /**
  37. * Response constructor.
  38. * @param \Dotdigitalgroup\Email\Helper\Data $data
  39. * @param \Magento\Framework\App\Action\Context $context
  40. * @param \Magento\Framework\Escaper $escaper
  41. * @param \Dotdigitalgroup\Email\Helper\Config $configHelper
  42. * @param \Magento\Store\Model\StoreManagerInterface $storeManager
  43. * @param \Dotdigitalgroup\Email\Model\FailedAuthFactory $failedAuthFactory
  44. * @param \Dotdigitalgroup\Email\Model\ResourceModel\FailedAuth $failedAuthResource
  45. * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone
  46. */
  47. public function __construct(
  48. \Dotdigitalgroup\Email\Helper\Data $data,
  49. \Magento\Framework\App\Action\Context $context,
  50. \Magento\Framework\Escaper $escaper,
  51. \Dotdigitalgroup\Email\Helper\Config $configHelper,
  52. \Magento\Store\Model\StoreManagerInterface $storeManager,
  53. \Dotdigitalgroup\Email\Model\FailedAuthFactory $failedAuthFactory,
  54. \Dotdigitalgroup\Email\Model\ResourceModel\FailedAuth $failedAuthResource,
  55. \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone
  56. ) {
  57. $this->helper = $data;
  58. $this->escaper = $escaper;
  59. $this->timezone = $timezone;
  60. $this->storeManager = $storeManager;
  61. $this->configHelper = $configHelper;
  62. $this->failedAuthFactory = $failedAuthFactory;
  63. $this->failedAuthResource = $failedAuthResource;
  64. parent::__construct($context);
  65. }
  66. /**
  67. * Auth.
  68. */
  69. public function authenticate()
  70. {
  71. //in locked state
  72. if ($this->isAuthLocked()) {
  73. $this->sendUnauthorizedResponse();
  74. return false;
  75. }
  76. //passcode not valid.
  77. if (!$this->helper->auth($this->getRequest()->getParam('code'))) {
  78. $this->processFailedRequest();
  79. $this->sendUnauthorizedResponse();
  80. return false;
  81. }
  82. //ip is not allowed
  83. if (!$this->helper->isIpAllowed()) {
  84. $this->sendNoContentResponse();
  85. return false;
  86. }
  87. return true;
  88. }
  89. /**
  90. *
  91. */
  92. public function execute()
  93. {
  94. }
  95. /**
  96. * @return \Zend\Http\PhpEnvironment\Response
  97. */
  98. public function sendUnauthorizedResponse()
  99. {
  100. $this->getResponse()
  101. ->setHttpResponseCode(401)
  102. ->setHeader('Pragma', 'public', true)
  103. ->setHeader(
  104. 'Cache-Control',
  105. 'must-revalidate, post-check=0, pre-check=0',
  106. true
  107. )
  108. ->setHeader('Content-type', 'text/html; charset=UTF-8', true)
  109. ->setBody('<h1>401 Unauthorized</h1>');
  110. return $this->getResponse()->sendHeaders();
  111. }
  112. /**
  113. * @return \Zend\Http\PhpEnvironment\Response
  114. */
  115. public function sendNoContentResponse()
  116. {
  117. try {
  118. $this->getResponse()
  119. ->setHttpResponseCode(204)
  120. ->setHeader('Pragma', 'public', true)
  121. ->setHeader(
  122. 'Cache-Control',
  123. 'must-revalidate, post-check=0, pre-check=0',
  124. true
  125. )
  126. ->setHeader('Content-type', 'text/html; charset=UTF-8', true);
  127. return $this->getResponse()->sendHeaders();
  128. } catch (\Exception $e) {
  129. $this->helper->log($e);
  130. }
  131. }
  132. /**
  133. * Register the failed attempt and set a lock with a 5min window if more then 5 request failed.
  134. */
  135. private function processFailedRequest()
  136. {
  137. $url = $this->_url->getCurrentUrl();
  138. $storeId = $this->storeManager->getStore()->getId();
  139. $failedAuth = $this->failedAuthFactory->create();
  140. $this->failedAuthResource->load($failedAuth, $storeId, 'store_id');
  141. $numOfFails = $failedAuth->getFailuresNum();
  142. $lastAttemptDate = $failedAuth->getLastAttemptDate();
  143. //set the first failed attempt
  144. if (!$failedAuth->getId()) {
  145. $failedAuth->setFirstAttemptDate(time());
  146. }
  147. //check the time for the last fail and update the records
  148. if ($numOfFails == \Dotdigitalgroup\Email\Model\FailedAuth::NUMBER_MAX_FAILS_LIMIT) {
  149. //ignore the resource is in a locked state
  150. if ($failedAuth->isLocked()) {
  151. $this->helper->log(sprintf('Resource locked time : %s ,store : %s', $lastAttemptDate, $storeId));
  152. return;
  153. } else {
  154. //reset with the first lock after the the lock expired
  155. $numOfFails = 0;
  156. $failedAuth->setFirstAttemptDate(time());
  157. }
  158. }
  159. try {
  160. $failedAuth->setFailuresNum(++$numOfFails)
  161. ->setStoreId($storeId)
  162. ->setUrl($url)
  163. ->setLastAttemptDate(time());
  164. $this->failedAuthResource->save($failedAuth);
  165. } catch (\Exception $e) {
  166. $this->helper->log($e);
  167. }
  168. }
  169. /**
  170. * @return bool
  171. */
  172. private function isAuthLocked()
  173. {
  174. $failedAuth = $this->failedAuthFactory->create();
  175. $storeId = $this->storeManager->getStore()->getId();
  176. $this->failedAuthResource->load($failedAuth, $storeId, 'store_id');
  177. return $failedAuth->isLocked();
  178. }
  179. }