FrequencyTest.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Security\Test\Unit\Model\SecurityChecker;
  7. use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress;
  8. use Magento\Framework\Stdlib\DateTime\DateTime;
  9. use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
  10. use Magento\Security\Model\ConfigInterface;
  11. /**
  12. * Test class for \Magento\Security\Model\SecurityChecker\Frequency testing
  13. */
  14. class FrequencyTest extends \PHPUnit\Framework\TestCase
  15. {
  16. /**
  17. * @var \Magento\Security\Model\SecurityChecker\Frequency
  18. */
  19. protected $model;
  20. /**
  21. * @var ConfigInterface
  22. */
  23. protected $securityConfigMock;
  24. /**
  25. * @var \Magento\Security\Model\ResourceModel\PasswordResetRequestEvent\CollectionFactory
  26. */
  27. protected $collectionFactoryMock;
  28. /**
  29. * @var \Magento\Security\Model\ResourceModel\PasswordResetRequestEvent\Collection
  30. */
  31. protected $collectionMock;
  32. /**
  33. * @var DateTime
  34. */
  35. protected $dateTimeMock;
  36. /**
  37. * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
  38. */
  39. protected $objectManager;
  40. /*
  41. * @var RemoteAddress
  42. */
  43. protected $remoteAddressMock;
  44. /**
  45. * Init mocks for tests
  46. * @return void
  47. */
  48. public function setUp()
  49. {
  50. $this->objectManager = new ObjectManager($this);
  51. $this->securityConfigMock = $this->getMockBuilder(\Magento\Security\Model\ConfigInterface::class)
  52. ->setMethods(['getScopeByEventType'])
  53. ->disableOriginalConstructor()
  54. ->getMockForAbstractClass();
  55. $this->securityConfigMock->expects($this->any())
  56. ->method('getScopeByEventType')
  57. ->willReturnMap(
  58. [
  59. [0, 1],
  60. [1, 0]
  61. ]
  62. );
  63. $this->collectionFactoryMock = $this->createPartialMock(
  64. \Magento\Security\Model\ResourceModel\PasswordResetRequestEvent\CollectionFactory::class,
  65. ['create']
  66. );
  67. $this->collectionMock = $this->createPartialMock(
  68. \Magento\Security\Model\ResourceModel\PasswordResetRequestEvent\Collection::class,
  69. ['addFieldToFilter', 'filterLastItem', 'getFirstItem']
  70. );
  71. $this->dateTimeMock = $this->getMockBuilder(DateTime::class)
  72. ->disableOriginalConstructor()
  73. ->getMock();
  74. $this->remoteAddressMock = $this->getMockBuilder(RemoteAddress::class)
  75. ->disableOriginalConstructor()
  76. ->getMock();
  77. $this->model = $this->objectManager->getObject(
  78. \Magento\Security\Model\SecurityChecker\Frequency::class,
  79. [
  80. 'securityConfig' => $this->securityConfigMock,
  81. 'collectionFactory' => $this->collectionFactoryMock,
  82. 'dateTime' => $this->dateTimeMock,
  83. 'remoteAddress' => $this->remoteAddressMock
  84. ]
  85. );
  86. }
  87. /**
  88. * @param int $securityEventType
  89. * @param int $requestsMethod
  90. * @dataProvider dataProviderSecurityEventTypeWithRequestsMethod
  91. */
  92. public function testCheck($securityEventType, $requestsMethod)
  93. {
  94. $limitTimeBetweenPasswordResetRequests = 600;
  95. $timestamp = time();
  96. $this->prepareTestCheck($requestsMethod, $limitTimeBetweenPasswordResetRequests);
  97. $this->dateTimeMock->expects($this->once())
  98. ->method('gmtTimestamp')
  99. ->willReturn($timestamp);
  100. /** @var \Magento\Security\Model\PasswordResetRequestEvent $record */
  101. $record = $this->objectManager->getObject(\Magento\Security\Model\PasswordResetRequestEvent::class);
  102. $record->setCreatedAt(
  103. date("Y-m-d H:i:s", $timestamp - $limitTimeBetweenPasswordResetRequests)
  104. );
  105. $this->collectionMock->expects($this->once())
  106. ->method('getFirstItem')
  107. ->willReturn($record);
  108. $this->model->check($securityEventType);
  109. }
  110. /**
  111. * @param int $securityEventType
  112. * @param int $requestsMethod
  113. * @dataProvider dataProviderSecurityEventTypeWithRequestsMethod
  114. * @expectedException \Magento\Framework\Exception\SecurityViolationException
  115. */
  116. public function testCheckException($securityEventType, $requestsMethod)
  117. {
  118. $limitTimeBetweenPasswordResetRequests = 600;
  119. $timestamp = time();
  120. $this->prepareTestCheck($requestsMethod, $limitTimeBetweenPasswordResetRequests);
  121. $this->dateTimeMock->expects($this->once())
  122. ->method('gmtTimestamp')
  123. ->willReturn($timestamp);
  124. /** @var \Magento\Security\Model\PasswordResetRequestEvent $record */
  125. $record = $this->objectManager->getObject(\Magento\Security\Model\PasswordResetRequestEvent::class);
  126. $record->setCreatedAt(
  127. date("Y-m-d H:i:s", $timestamp - $limitTimeBetweenPasswordResetRequests + 1)
  128. );
  129. $this->collectionMock->expects($this->once())
  130. ->method('getFirstItem')
  131. ->willReturn($record);
  132. $this->model->check($securityEventType);
  133. $this->expectExceptionMessage(
  134. 'We received too many requests for password resets. '
  135. . 'Please wait and try again later or contact test@host.com.'
  136. );
  137. }
  138. /**
  139. * @return array
  140. */
  141. public function dataProviderSecurityEventTypeWithRequestsMethod()
  142. {
  143. return [
  144. [
  145. \Magento\Security\Model\PasswordResetRequestEvent::CUSTOMER_PASSWORD_RESET_REQUEST,
  146. \Magento\Security\Model\Config\Source\ResetMethod::OPTION_BY_IP_AND_EMAIL
  147. ],
  148. [
  149. \Magento\Security\Model\PasswordResetRequestEvent::CUSTOMER_PASSWORD_RESET_REQUEST,
  150. \Magento\Security\Model\Config\Source\ResetMethod::OPTION_BY_IP
  151. ],
  152. [
  153. \Magento\Security\Model\PasswordResetRequestEvent::CUSTOMER_PASSWORD_RESET_REQUEST,
  154. \Magento\Security\Model\Config\Source\ResetMethod::OPTION_BY_EMAIL
  155. ],
  156. [
  157. \Magento\Security\Model\PasswordResetRequestEvent::ADMIN_PASSWORD_RESET_REQUEST,
  158. \Magento\Security\Model\Config\Source\ResetMethod::OPTION_BY_IP_AND_EMAIL
  159. ],
  160. [
  161. \Magento\Security\Model\PasswordResetRequestEvent::ADMIN_PASSWORD_RESET_REQUEST,
  162. \Magento\Security\Model\Config\Source\ResetMethod::OPTION_BY_IP
  163. ],
  164. [
  165. \Magento\Security\Model\PasswordResetRequestEvent::ADMIN_PASSWORD_RESET_REQUEST,
  166. \Magento\Security\Model\Config\Source\ResetMethod::OPTION_BY_EMAIL
  167. ],
  168. ];
  169. }
  170. /**
  171. * @param int $requestsMethod
  172. * @param int $limitTimeBetweenPasswordResetRequests
  173. */
  174. protected function prepareTestCheck($requestsMethod, $limitTimeBetweenPasswordResetRequests)
  175. {
  176. $this->remoteAddressMock->expects($this->once())
  177. ->method('getRemoteAddress')
  178. ->will($this->returnValue(12345));
  179. $this->securityConfigMock->expects($this->any())
  180. ->method('getPasswordResetProtectionType')
  181. ->will($this->returnValue($requestsMethod));
  182. $this->securityConfigMock->expects($this->once())
  183. ->method('getMinTimeBetweenPasswordResetRequests')
  184. ->will($this->returnValue($limitTimeBetweenPasswordResetRequests));
  185. $this->securityConfigMock->expects($this->any())
  186. ->method('getCustomerServiceEmail')
  187. ->will($this->returnValue('test@host.com'));
  188. $this->collectionFactoryMock->expects($this->once())
  189. ->method('create')
  190. ->willReturn($this->collectionMock);
  191. $this->collectionMock->expects($this->any())
  192. ->method('addFieldToFilter')
  193. ->willReturnSelf();
  194. $this->collectionMock->expects($this->once())
  195. ->method('filterLastItem')
  196. ->willReturnSelf();
  197. }
  198. }