TokenTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Integration\Model\ResourceModel\Oauth;
  7. use Magento\Authorization\Model\UserContextInterface;
  8. use Magento\Integration\Model\Oauth\Token;
  9. /**
  10. * Integration test for @see \Magento\Integration\Model\ResourceModel\Oauth\Token
  11. *
  12. * Also tests @see \Magento\Integration\Cron\CleanExpiredTokens
  13. */
  14. class TokenTest extends \PHPUnit\Framework\TestCase
  15. {
  16. const TOKEN_LIFETIME = 1; // in hours
  17. const BASE_CREATED_AT_TIMESTAMP = 100000;
  18. /**
  19. * @var array
  20. */
  21. private $generatedTokens;
  22. /**
  23. * @var \Magento\Framework\Stdlib\DateTime\DateTime | \PHPUnit_Framework_MockObject_MockObject
  24. */
  25. private $dateTimeMock;
  26. /**
  27. * @var \Magento\Integration\Model\ResourceModel\Oauth\Token
  28. */
  29. private $tokenResourceModel;
  30. /**
  31. * @var \Magento\Framework\ObjectManagerInterface
  32. */
  33. private $objectManager;
  34. /**
  35. * @var \Magento\Integration\Model\Oauth\TokenFactory
  36. */
  37. private $tokenFactory;
  38. protected function setUp()
  39. {
  40. $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
  41. $this->tokenFactory = $this->objectManager->create(\Magento\Integration\Model\Oauth\TokenFactory::class);
  42. /** Mock date model to be able to specify "current timestamp" and avoid dependency on real timestamp */
  43. $this->dateTimeMock = $this->getMockBuilder(\Magento\Framework\Stdlib\DateTime\DateTime::class)
  44. ->disableOriginalConstructor()
  45. ->getMock();
  46. /** @var \Magento\Integration\Model\ResourceModel\Oauth\Token $tokenResourceModel */
  47. $this->tokenResourceModel = $this->objectManager->create(
  48. \Magento\Integration\Model\ResourceModel\Oauth\Token::class,
  49. ['date' => $this->dateTimeMock]
  50. );
  51. $this->generatedTokens = $this->generateTokens();
  52. parent::setUp();
  53. }
  54. /**
  55. * @return array
  56. */
  57. private function generateTokens()
  58. {
  59. /** Generate several tokens with different user types and created at combinations */
  60. $tokensToBeGenerated = [
  61. '#1' => [
  62. 'userType' => UserContextInterface::USER_TYPE_ADMIN,
  63. 'createdAt' => self::BASE_CREATED_AT_TIMESTAMP
  64. ],
  65. '#2' => [
  66. 'userType' => UserContextInterface::USER_TYPE_ADMIN,
  67. 'createdAt' => self::BASE_CREATED_AT_TIMESTAMP + 5
  68. ],
  69. '#3' => [
  70. 'userType' => UserContextInterface::USER_TYPE_CUSTOMER,
  71. 'createdAt' => self::BASE_CREATED_AT_TIMESTAMP
  72. ],
  73. '#4' => [
  74. 'userType' => UserContextInterface::USER_TYPE_CUSTOMER,
  75. 'createdAt' => self::BASE_CREATED_AT_TIMESTAMP - 5
  76. ],
  77. '#5' => [
  78. 'userType' => UserContextInterface::USER_TYPE_INTEGRATION,
  79. 'createdAt' => self::BASE_CREATED_AT_TIMESTAMP
  80. ],
  81. '#6' => [
  82. 'userType' => UserContextInterface::USER_TYPE_INTEGRATION,
  83. 'createdAt' => self::BASE_CREATED_AT_TIMESTAMP + 5
  84. ],
  85. ];
  86. /** @var \Magento\Framework\Stdlib\DateTime $dateTimeUtils */
  87. $dateTimeUtils = $this->objectManager->get(\Magento\Framework\Stdlib\DateTime::class);
  88. foreach ($tokensToBeGenerated as &$tokenData) {
  89. $token = $this->tokenFactory->create();
  90. $token->setType(Token::TYPE_ACCESS)
  91. ->setUserType($tokenData['userType'])
  92. ->setToken(rand(1, PHP_INT_MAX))
  93. ->setCreatedAt($dateTimeUtils->formatDate($tokenData['createdAt']));
  94. $this->tokenResourceModel->save($token);
  95. $tokenData['tokenId'] = $token->getId();
  96. }
  97. return $tokensToBeGenerated;
  98. }
  99. /**
  100. * Make sure that @see \Magento\Integration\Cron\CleanExpiredTokens cleans tokens correctly per configuration
  101. *
  102. * 1. Generate several tokens with different user type and creation time
  103. * 2. Emulate current time stamp to be equal to (expiration period + some adjustment)
  104. * 3. Run clean up
  105. * 4. Make sure that clean up removed tokens that were expected to be removed,
  106. * and those tokens which were not expected to be removed are still there
  107. *
  108. * @param int $secondsAfterBaseCreatedTimestamp
  109. * @param array $expectedRemovedTokenNumbers
  110. * @param array $expectedPreservedTokenNumbers
  111. *
  112. * @dataProvider deleteExpiredTokenUsingObserverDataProvider
  113. * @covers \Magento\Integration\Cron\CleanExpiredTokens::execute
  114. */
  115. public function testDeleteExpiredTokenUsingObserver(
  116. $secondsAfterBaseCreatedTimestamp,
  117. $expectedRemovedTokenNumbers,
  118. $expectedPreservedTokenNumbers
  119. ) {
  120. /** @var \Magento\Integration\Cron\CleanExpiredTokens $cleanExpiredTokensModel */
  121. $cleanExpiredTokensModel = $this->objectManager->create(
  122. \Magento\Integration\Cron\CleanExpiredTokens::class,
  123. ['tokenResourceModel' => $this->tokenResourceModel]
  124. );
  125. $emulatedCurrentTimestamp = self::BASE_CREATED_AT_TIMESTAMP + $secondsAfterBaseCreatedTimestamp;
  126. $this->dateTimeMock->method('gmtTimestamp')->willReturn($emulatedCurrentTimestamp);
  127. $cleanExpiredTokensModel->execute();
  128. $this->assertTokenCleanUp(
  129. $expectedRemovedTokenNumbers,
  130. $expectedPreservedTokenNumbers,
  131. $this->generatedTokens
  132. );
  133. }
  134. public function deleteExpiredTokenUsingObserverDataProvider()
  135. {
  136. return [
  137. "Clean up long before default admin and default customer token life time" => [
  138. 3600 - 6, // time passed after base creation time
  139. [], // expected to be removed
  140. ['#1', '#2', '#3', '#4', '#5', '#6'], // expected to exist
  141. ],
  142. "Clean up just before default admin and default customer token life time" => [
  143. 3600 - 1, // time passed after base creation time
  144. ['#4'], // expected to be removed
  145. ['#1', '#2', '#3', '#5', '#6'], // expected to exist
  146. ],
  147. "Clean up after default admin token life time, but before default customer token life time" => [
  148. 3600 + 1, // time passed after base creation time
  149. ['#3', '#4'], // expected to be removed
  150. ['#1', '#2', '#5', '#6'], // expected to exist
  151. ],
  152. "Clean up after default customer and default admin token life time" => [
  153. 14400 + 1, // time passed after base creation time
  154. ['#1', '#3', '#4'], // expected to be removed
  155. ['#2', '#5', '#6'], // expected to exist
  156. ],
  157. ];
  158. }
  159. /**
  160. * Verify that expired tokens removal works as expected, @see \Magento\Integration\Model\ResourceModel\Oauth\Token
  161. *
  162. * 1. Generate several tokens with different user type and creation time
  163. * 2. Emulate current time stamp to be equal to (expiration period + some adjustment)
  164. * 3. Run clean up for some token types
  165. * 4. Make sure that clean up removed tokens that were expected to be removed,
  166. * and those tokens which were not expected to be removed are still there
  167. *
  168. * @param $secondsAfterBaseCreatedTimestamp
  169. * @param $tokenTypesToClean
  170. * @param $expectedRemovedTokenNumbers
  171. * @param $expectedPreservedTokenNumbers
  172. *
  173. * @magentoDbIsolation enabled
  174. * @dataProvider deleteExpiredTokensDataProvider
  175. * @covers \Magento\Integration\Model\ResourceModel\Oauth\Token::deleteExpiredTokens
  176. */
  177. public function testDeleteExpiredTokens(
  178. $secondsAfterBaseCreatedTimestamp,
  179. $tokenTypesToClean,
  180. $expectedRemovedTokenNumbers,
  181. $expectedPreservedTokenNumbers
  182. ) {
  183. /** Run clean up for tokens of {$tokenTypesToClean} type, created {$secondsAfterBaseCreatedTimestamp} ago */
  184. $emulatedCurrentTimestamp = self::BASE_CREATED_AT_TIMESTAMP + $secondsAfterBaseCreatedTimestamp;
  185. $this->dateTimeMock->method('gmtTimestamp')->willReturn($emulatedCurrentTimestamp);
  186. $this->tokenResourceModel->deleteExpiredTokens(self::TOKEN_LIFETIME, $tokenTypesToClean);
  187. $this->assertTokenCleanUp(
  188. $expectedRemovedTokenNumbers,
  189. $expectedPreservedTokenNumbers,
  190. $this->generatedTokens
  191. );
  192. }
  193. public function deleteExpiredTokensDataProvider()
  194. {
  195. return [
  196. "Clean up for admin tokens which were created ('token_lifetime' + 1 second) ago" => [
  197. self::TOKEN_LIFETIME * 60 * 60 + 1, // time passed after base creation time
  198. [UserContextInterface::USER_TYPE_ADMIN], // token types to clean up
  199. ['#1'], // expected to be removed
  200. ['#2', '#3', '#4', '#5', '#6'], // expected to exist
  201. ],
  202. "Clean up for admin, integration, guest tokens which were created ('token_lifetime' + 6 second) ago" => [
  203. self::TOKEN_LIFETIME * 60 * 60 + 6, // time passed after base creation time
  204. [ // token types to clean up
  205. UserContextInterface::USER_TYPE_ADMIN,
  206. UserContextInterface::USER_TYPE_INTEGRATION,
  207. UserContextInterface::USER_TYPE_GUEST
  208. ],
  209. ['#1', '#2', '#5', '#6'], // expected to be removed
  210. ['#3', '#4'], // expected to exist
  211. ],
  212. "Clean up for admin, integration, customer tokens which were created ('token_lifetime' + 6 second) ago" => [
  213. self::TOKEN_LIFETIME * 60 * 60 + 6, // time passed after base creation time
  214. [ // token types to clean up
  215. UserContextInterface::USER_TYPE_ADMIN,
  216. UserContextInterface::USER_TYPE_INTEGRATION,
  217. UserContextInterface::USER_TYPE_CUSTOMER
  218. ],
  219. ['#1', '#2', '#3', '#4', '#5', '#6'], // expected to be removed
  220. [], // expected to exist
  221. ],
  222. "Clean up for admin, integration, customer tokens which were created ('token_lifetime' + 1 second) ago" => [
  223. self::TOKEN_LIFETIME * 60 * 60 + 1, // time passed after base creation time
  224. [ // token types to clean up
  225. UserContextInterface::USER_TYPE_ADMIN,
  226. UserContextInterface::USER_TYPE_INTEGRATION,
  227. UserContextInterface::USER_TYPE_CUSTOMER
  228. ],
  229. ['#1', '#3', '#4', '#5'], // expected to be removed
  230. ['#2', '#6'], // expected to exist
  231. ],
  232. ];
  233. }
  234. /**
  235. * Make that only expired tokens were cleaned up
  236. *
  237. * @param array $expectedRemovedTokenNumbers
  238. * @param array $expectedPreservedTokenNumbers
  239. * @param array $generatedTokens
  240. */
  241. private function assertTokenCleanUp(
  242. $expectedRemovedTokenNumbers,
  243. $expectedPreservedTokenNumbers,
  244. $generatedTokens
  245. ) {
  246. foreach ($expectedRemovedTokenNumbers as $tokenNumber) {
  247. $token = $this->tokenFactory->create();
  248. $this->tokenResourceModel->load($token, $generatedTokens[$tokenNumber]['tokenId']);
  249. $this->assertEmpty(
  250. $token->getId(),
  251. "Token {$tokenNumber} was expected to be deleted after clean up"
  252. );
  253. }
  254. foreach ($expectedPreservedTokenNumbers as $tokenNumber) {
  255. $token = $this->tokenFactory->create();
  256. $this->tokenResourceModel->load($token, $generatedTokens[$tokenNumber]['tokenId']);
  257. $this->assertEquals(
  258. $generatedTokens[$tokenNumber]['tokenId'],
  259. $token->getId(),
  260. "Token {$tokenNumber} was NOT expected to be deleted after clean up"
  261. );
  262. }
  263. }
  264. }