AdminSessionsManagerTest.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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;
  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\AdminSessionsManager;
  11. use Magento\Security\Model\ConfigInterface;
  12. /**
  13. * Test class for AdminSessionsManager testing
  14. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  15. */
  16. class AdminSessionsManagerTest extends \PHPUnit\Framework\TestCase
  17. {
  18. /** @var AdminSessionsManager */
  19. protected $model;
  20. /** @var \Magento\Security\Model\AdminSessionInfo */
  21. protected $currentSessionMock;
  22. /** @var \Magento\Backend\Model\Auth\Session */
  23. protected $authSessionMock;
  24. /** @var ConfigInterface */
  25. protected $securityConfigMock;
  26. /** @var \Magento\User\Model\User */
  27. protected $userMock;
  28. /** @var \Magento\Security\Model\ResourceModel\AdminSessionInfo\CollectionFactory */
  29. protected $adminSessionInfoCollectionFactoryMock;
  30. /** @var \Magento\Security\Model\ResourceModel\AdminSessionInfo\Collection */
  31. protected $adminSessionInfoCollectionMock;
  32. /** @var \Magento\Security\Model\AdminSessionInfoFactory */
  33. protected $adminSessionInfoFactoryMock;
  34. /**
  35. * @var DateTime
  36. */
  37. protected $dateTimeMock;
  38. /** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */
  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->authSessionMock = $this->createPartialMock(
  52. \Magento\Backend\Model\Auth\Session::class,
  53. ['isActive', 'getStatus', 'getUser', 'getId', 'getSessionId', 'getUpdatedAt']
  54. );
  55. $this->adminSessionInfoCollectionFactoryMock = $this->createPartialMock(
  56. \Magento\Security\Model\ResourceModel\AdminSessionInfo\CollectionFactory::class,
  57. ['create']
  58. );
  59. $this->adminSessionInfoCollectionMock = $this->createPartialMock(
  60. \Magento\Security\Model\ResourceModel\AdminSessionInfo\Collection::class,
  61. [
  62. 'filterByUser',
  63. 'filterExpiredSessions',
  64. 'loadData',
  65. 'setDataToAll',
  66. 'save',
  67. 'updateActiveSessionsStatus',
  68. 'deleteSessionsOlderThen'
  69. ]
  70. );
  71. $this->adminSessionInfoFactoryMock = $this->createPartialMock(
  72. \Magento\Security\Model\AdminSessionInfoFactory::class,
  73. ['create']
  74. );
  75. $this->currentSessionMock = $this->createPartialMock(\Magento\Security\Model\AdminSessionInfo::class, [
  76. 'isActive',
  77. 'getStatus',
  78. 'load',
  79. 'setData',
  80. 'setIsOtherSessionsTerminated',
  81. 'save',
  82. 'getUserId',
  83. 'getSessionId',
  84. 'getUpdatedAt'
  85. ]);
  86. $this->securityConfigMock = $this->getMockBuilder(\Magento\Security\Model\ConfigInterface::class)
  87. ->disableOriginalConstructor()
  88. ->getMock();
  89. $this->userMock = $this->createPartialMock(\Magento\User\Model\User::class, ['getId']);
  90. $this->dateTimeMock = $this->getMockBuilder(DateTime::class)
  91. ->disableOriginalConstructor()
  92. ->getMock();
  93. $this->remoteAddressMock = $this->getMockBuilder(RemoteAddress::class)
  94. ->disableOriginalConstructor()
  95. ->getMock();
  96. $this->model = $this->objectManager->getObject(
  97. \Magento\Security\Model\AdminSessionsManager::class,
  98. [
  99. 'securityConfig' => $this->securityConfigMock,
  100. 'authSession' => $this->authSessionMock,
  101. 'adminSessionInfoFactory' => $this->adminSessionInfoFactoryMock,
  102. 'adminSessionInfoCollectionFactory' => $this->adminSessionInfoCollectionFactoryMock,
  103. 'dateTime' => $this->dateTimeMock,
  104. 'remoteAddress' => $this->remoteAddressMock
  105. ]
  106. );
  107. }
  108. /**
  109. * @return void
  110. */
  111. public function testProcessLogin()
  112. {
  113. $useId = 1;
  114. $sessionLifetime = 100;
  115. $ip = 12345;
  116. $sessionId = 50;
  117. $timestamp = time();
  118. $olderThen = $timestamp - $sessionLifetime;
  119. $this->adminSessionInfoFactoryMock->expects($this->exactly(2))
  120. ->method('create')
  121. ->willReturn($this->currentSessionMock);
  122. $this->authSessionMock->expects($this->exactly(2))
  123. ->method('getSessionId')
  124. ->willReturn($sessionId);
  125. $this->authSessionMock->expects($this->once())
  126. ->method('getUser')
  127. ->willReturn($this->userMock);
  128. $this->userMock->expects($this->once())
  129. ->method('getId')
  130. ->willReturn($useId);
  131. $this->remoteAddressMock->expects($this->once())
  132. ->method('getRemoteAddress')
  133. ->willReturn($ip);
  134. $this->currentSessionMock->expects($this->once())
  135. ->method('setData')
  136. ->willReturnSelf();
  137. $this->currentSessionMock->expects($this->once())
  138. ->method('save')
  139. ->willReturnSelf();
  140. $this->dateTimeMock->expects($this->once())
  141. ->method('gmtTimestamp')
  142. ->willReturn($timestamp);
  143. $this->securityConfigMock->expects($this->once())
  144. ->method('getAdminSessionLifetime')
  145. ->willReturn($sessionLifetime);
  146. $this->securityConfigMock->expects($this->once())
  147. ->method('isAdminAccountSharingEnabled')
  148. ->willReturn(0);
  149. $this->currentSessionMock->expects($this->once())
  150. ->method('getUserId')
  151. ->willReturn($useId);
  152. $this->currentSessionMock->expects($this->once())
  153. ->method('getSessionId')
  154. ->willReturn($sessionId);
  155. $this->adminSessionInfoCollectionFactoryMock->expects($this->once())
  156. ->method('create')
  157. ->willReturn($this->adminSessionInfoCollectionMock);
  158. $this->adminSessionInfoCollectionMock->expects($this->once())->method('updateActiveSessionsStatus')
  159. ->with(
  160. \Magento\Security\Model\AdminSessionInfo::LOGGED_OUT_BY_LOGIN,
  161. $useId,
  162. $sessionId,
  163. $olderThen
  164. )
  165. ->willReturn(1);
  166. $this->currentSessionMock->expects($this->once())
  167. ->method('setIsOtherSessionsTerminated')
  168. ->with(true)
  169. ->willReturnSelf();
  170. $this->model->processLogin();
  171. }
  172. /**
  173. * @return void
  174. */
  175. public function testProcessProlong()
  176. {
  177. $sessionId = 50;
  178. $lastUpdatedAt = '2015-12-31 23:59:59';
  179. $newUpdatedAt = '2016-01-01 00:00:30';
  180. $this->adminSessionInfoFactoryMock->expects($this->any())
  181. ->method('create')
  182. ->willReturn($this->currentSessionMock);
  183. $this->authSessionMock->expects($this->once())
  184. ->method('getSessionId')
  185. ->willReturn($sessionId);
  186. $this->currentSessionMock->expects($this->once())
  187. ->method('load')
  188. ->willReturnSelf();
  189. $this->currentSessionMock->expects($this->once())
  190. ->method('getUpdatedAt')
  191. ->willReturn($lastUpdatedAt);
  192. $this->authSessionMock->expects($this->exactly(2))
  193. ->method('getUpdatedAt')
  194. ->willReturn(strtotime($newUpdatedAt));
  195. $this->securityConfigMock->expects($this->once())
  196. ->method('getAdminSessionLifetime')
  197. ->willReturn(100);
  198. $this->currentSessionMock->expects($this->once())
  199. ->method('setData')
  200. ->with('updated_at', $newUpdatedAt)
  201. ->willReturnSelf();
  202. $this->currentSessionMock->expects($this->once())
  203. ->method('save')
  204. ->willReturnSelf();
  205. $this->model->processProlong();
  206. }
  207. /**
  208. * @return void
  209. */
  210. public function testProcessLogout()
  211. {
  212. $sessionId = 50;
  213. $this->adminSessionInfoFactoryMock->expects($this->any())
  214. ->method('create')
  215. ->willReturn($this->currentSessionMock);
  216. $this->authSessionMock->expects($this->once())
  217. ->method('getSessionId')
  218. ->willReturn($sessionId);
  219. $this->currentSessionMock->expects($this->once())
  220. ->method('load')
  221. ->willReturnSelf();
  222. $this->currentSessionMock->expects($this->once())
  223. ->method('setData')
  224. ->with('status', \Magento\Security\Model\AdminSessionInfo::LOGGED_OUT)
  225. ->willReturnSelf();
  226. $this->currentSessionMock->expects($this->once())
  227. ->method('save')
  228. ->willReturnSelf();
  229. $this->model->processLogout();
  230. }
  231. /**
  232. * @return void
  233. */
  234. public function testGetCurrentSession()
  235. {
  236. $sessionId = 50;
  237. $this->adminSessionInfoFactoryMock->expects($this->any())
  238. ->method('create')
  239. ->willReturn($this->currentSessionMock);
  240. $this->authSessionMock->expects($this->once())
  241. ->method('getSessionId')
  242. ->willReturn($sessionId);
  243. $this->currentSessionMock->expects($this->once())
  244. ->method('load')
  245. ->willReturnSelf();
  246. $this->assertEquals($this->currentSessionMock, $this->model->getCurrentSession());
  247. }
  248. /**
  249. * @return void
  250. */
  251. public function testCleanExpiredSessions()
  252. {
  253. $timestamp = time();
  254. $this->adminSessionInfoCollectionFactoryMock->expects($this->once())
  255. ->method('create')
  256. ->willReturn($this->adminSessionInfoCollectionMock);
  257. $this->dateTimeMock->expects($this->once())
  258. ->method('gmtTimestamp')
  259. ->willReturn($timestamp);
  260. $this->adminSessionInfoCollectionMock->expects($this->once())->method('deleteSessionsOlderThen')
  261. ->with($timestamp - AdminSessionsManager::ADMIN_SESSION_LIFETIME)
  262. ->willReturnSelf();
  263. $this->model->cleanExpiredSessions();
  264. }
  265. /**
  266. * @param string $expectedResult
  267. * @param int $sessionStatus
  268. * @dataProvider dataProviderLogoutReasonMessage
  269. */
  270. public function testGetLogoutReasonMessage($expectedResult, $sessionStatus)
  271. {
  272. $this->adminSessionInfoFactoryMock->expects($this->once())
  273. ->method('create')
  274. ->willReturn($this->currentSessionMock);
  275. $this->currentSessionMock->expects($this->once())
  276. ->method('getStatus')
  277. ->will($this->returnValue($sessionStatus));
  278. $this->assertEquals($expectedResult, $this->model->getLogoutReasonMessage());
  279. }
  280. /**
  281. * @return array
  282. */
  283. public function dataProviderLogoutReasonMessage()
  284. {
  285. return [
  286. [
  287. 'expectedResult' => __(
  288. 'Someone logged into this account from another device or browser.'
  289. . ' Your current session is terminated.'
  290. ),
  291. 'sessionStatus' => \Magento\Security\Model\AdminSessionInfo::LOGGED_OUT_BY_LOGIN
  292. ],
  293. [
  294. 'expectedResult' => __('Your current session is terminated by another user of this account.'),
  295. 'sessionStatus' => \Magento\Security\Model\AdminSessionInfo::LOGGED_OUT_MANUALLY
  296. ],
  297. [
  298. 'expectedResult' => __('Your current session has been expired.'),
  299. 'sessionStatus' => \Magento\Security\Model\AdminSessionInfo::LOGGED_OUT
  300. ],
  301. [
  302. 'expectedResult' => __('Your account is temporarily disabled. Please try again later.'),
  303. 'sessionStatus' => \Magento\Security\Model\AdminSessionsManager::LOGOUT_REASON_USER_LOCKED
  304. ],
  305. [
  306. 'expectedResult' => '',
  307. 'sessionStatus' => \Magento\Security\Model\AdminSessionInfo::LOGGED_IN
  308. ]
  309. ];
  310. }
  311. /**
  312. * @return void
  313. */
  314. public function testGetSessionsForCurrentUser()
  315. {
  316. $useId = 1;
  317. $sessionLifetime = 100;
  318. $this->adminSessionInfoCollectionFactoryMock->expects($this->once())
  319. ->method('create')
  320. ->willReturn($this->adminSessionInfoCollectionMock);
  321. $this->authSessionMock->expects($this->once())
  322. ->method('getUser')
  323. ->willReturn($this->userMock);
  324. $this->userMock->expects($this->once())
  325. ->method('getId')
  326. ->willReturn($useId);
  327. $this->adminSessionInfoCollectionMock->expects($this->once())->method('filterByUser')
  328. ->with($useId, \Magento\Security\Model\AdminSessionInfo::LOGGED_IN)
  329. ->willReturnSelf();
  330. $this->securityConfigMock->expects($this->once())
  331. ->method('getAdminSessionLifetime')
  332. ->willReturn($sessionLifetime);
  333. $this->adminSessionInfoCollectionMock->expects($this->once())
  334. ->method('filterExpiredSessions')
  335. ->with($sessionLifetime)
  336. ->willReturnSelf();
  337. $this->adminSessionInfoCollectionMock->expects($this->once())
  338. ->method('loadData')
  339. ->willReturnSelf();
  340. $this->assertSame($this->adminSessionInfoCollectionMock, $this->model->getSessionsForCurrentUser());
  341. }
  342. /**
  343. * @return void
  344. */
  345. public function testLogoutOtherUserSessions()
  346. {
  347. $useId = 1;
  348. $sessionLifetime = 100;
  349. $sessionId = 50;
  350. $this->adminSessionInfoCollectionFactoryMock->expects($this->once())
  351. ->method('create')
  352. ->willReturn($this->adminSessionInfoCollectionMock);
  353. $this->authSessionMock->expects($this->once())
  354. ->method('getUser')
  355. ->willReturn($this->userMock);
  356. $this->authSessionMock->expects($this->once())
  357. ->method('getSessionId')
  358. ->willReturn($sessionId);
  359. $this->userMock->expects($this->once())
  360. ->method('getId')
  361. ->willReturn($useId);
  362. $this->adminSessionInfoCollectionMock->expects($this->once())
  363. ->method('filterByUser')
  364. ->with($useId, \Magento\Security\Model\AdminSessionInfo::LOGGED_IN, $sessionId)
  365. ->willReturnSelf();
  366. $this->securityConfigMock->expects($this->once())
  367. ->method('getAdminSessionLifetime')
  368. ->willReturn($sessionLifetime);
  369. $this->adminSessionInfoCollectionMock->expects($this->once())
  370. ->method('filterExpiredSessions')
  371. ->with($sessionLifetime)
  372. ->willReturnSelf();
  373. $this->adminSessionInfoCollectionMock->expects($this->once())
  374. ->method('loadData')
  375. ->willReturnSelf();
  376. $this->adminSessionInfoCollectionMock->expects($this->once())
  377. ->method('setDataToAll')
  378. ->with($this->equalTo('status'), \Magento\Security\Model\AdminSessionInfo::LOGGED_OUT_MANUALLY)
  379. ->willReturnSelf();
  380. $this->adminSessionInfoCollectionMock->expects($this->once())
  381. ->method('save');
  382. $this->model->logoutOtherUserSessions();
  383. }
  384. }