You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

session.php 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. <?php
  2. /**
  3. * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace Test\User;
  9. use OC\Session\Memory;
  10. use OC\User\User;
  11. /**
  12. * @group DB
  13. * @package Test\User
  14. */
  15. class Session extends \Test\TestCase {
  16. /** @var \OCP\AppFramework\Utility\ITimeFactory */
  17. private $timeFactory;
  18. /** @var \OC\Authentication\Token\DefaultTokenProvider */
  19. protected $defaultProvider;
  20. protected function setUp() {
  21. parent::setUp();
  22. $this->timeFactory = $this->getMock('\OCP\AppFramework\Utility\ITimeFactory');
  23. $this->timeFactory->expects($this->any())
  24. ->method('getTime')
  25. ->will($this->returnValue(10000));
  26. $this->defaultProvider = $this->getMockBuilder('\OC\Authentication\Token\DefaultTokenProvider')
  27. ->disableOriginalConstructor()
  28. ->getMock();
  29. }
  30. public function testGetUser() {
  31. $token = new \OC\Authentication\Token\DefaultToken();
  32. $expectedUser = new User('foo', null);
  33. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  34. $session->expects($this->at(0))
  35. ->method('get')
  36. ->with('user_id')
  37. ->will($this->returnValue($expectedUser->getUID()));
  38. $sessionId = 'abcdef12345';
  39. $manager = $this->getMockBuilder('\OC\User\Manager')
  40. ->disableOriginalConstructor()
  41. ->getMock();
  42. $session->expects($this->once())
  43. ->method('getId')
  44. ->will($this->returnValue($sessionId));
  45. $this->defaultProvider->expects($this->once())
  46. ->method('getToken')
  47. ->will($this->returnValue($token));
  48. $session->expects($this->at(2))
  49. ->method('get')
  50. ->with('last_login_check')
  51. ->will($this->returnValue(null)); // No check has been run yet
  52. $this->defaultProvider->expects($this->once())
  53. ->method('getPassword')
  54. ->with($token, $sessionId)
  55. ->will($this->returnValue('password123'));
  56. $manager->expects($this->once())
  57. ->method('checkPassword')
  58. ->with($expectedUser->getUID(), 'password123')
  59. ->will($this->returnValue(true));
  60. $session->expects($this->at(3))
  61. ->method('set')
  62. ->with('last_login_check', 10000);
  63. $session->expects($this->at(4))
  64. ->method('get')
  65. ->with('last_token_update')
  66. ->will($this->returnValue(null)); // No check run so far
  67. $this->defaultProvider->expects($this->once())
  68. ->method('updateToken')
  69. ->with($token);
  70. $session->expects($this->at(5))
  71. ->method('set')
  72. ->with('last_token_update', $this->equalTo(10000));
  73. $manager->expects($this->any())
  74. ->method('get')
  75. ->with($expectedUser->getUID())
  76. ->will($this->returnValue($expectedUser));
  77. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]);
  78. $user = $userSession->getUser();
  79. $this->assertSame($expectedUser, $user);
  80. }
  81. public function isLoggedInData() {
  82. return [
  83. [true],
  84. [false],
  85. ];
  86. }
  87. /**
  88. * @dataProvider isLoggedInData
  89. */
  90. public function testIsLoggedIn($isLoggedIn) {
  91. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  92. $manager = $this->getMockBuilder('\OC\User\Manager')
  93. ->disableOriginalConstructor()
  94. ->getMock();
  95. $userSession = $this->getMockBuilder('\OC\User\Session')
  96. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]])
  97. ->setMethods([
  98. 'getUser'
  99. ])
  100. ->getMock();
  101. $user = new User('sepp', null);
  102. $userSession->expects($this->once())
  103. ->method('getUser')
  104. ->will($this->returnValue($isLoggedIn ? $user : null));
  105. $this->assertEquals($isLoggedIn, $userSession->isLoggedIn());
  106. }
  107. public function testSetUser() {
  108. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  109. $session->expects($this->once())
  110. ->method('set')
  111. ->with('user_id', 'foo');
  112. $manager = $this->getMock('\OC\User\Manager');
  113. $backend = $this->getMock('\Test\Util\User\Dummy');
  114. $user = $this->getMock('\OC\User\User', array(), array('foo', $backend));
  115. $user->expects($this->once())
  116. ->method('getUID')
  117. ->will($this->returnValue('foo'));
  118. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]);
  119. $userSession->setUser($user);
  120. }
  121. public function testLoginValidPasswordEnabled() {
  122. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  123. $session->expects($this->once())
  124. ->method('regenerateId');
  125. $session->expects($this->exactly(2))
  126. ->method('set')
  127. ->with($this->callback(function ($key) {
  128. switch ($key) {
  129. case 'user_id':
  130. case 'loginname':
  131. return true;
  132. break;
  133. default:
  134. return false;
  135. break;
  136. }
  137. }, 'foo'));
  138. $managerMethods = get_class_methods('\OC\User\Manager');
  139. //keep following methods intact in order to ensure hooks are
  140. //working
  141. $doNotMock = array('__construct', 'emit', 'listen');
  142. foreach ($doNotMock as $methodName) {
  143. $i = array_search($methodName, $managerMethods, true);
  144. if ($i !== false) {
  145. unset($managerMethods[$i]);
  146. }
  147. }
  148. $manager = $this->getMock('\OC\User\Manager', $managerMethods, array());
  149. $backend = $this->getMock('\Test\Util\User\Dummy');
  150. $user = $this->getMock('\OC\User\User', array(), array('foo', $backend));
  151. $user->expects($this->any())
  152. ->method('isEnabled')
  153. ->will($this->returnValue(true));
  154. $user->expects($this->any())
  155. ->method('getUID')
  156. ->will($this->returnValue('foo'));
  157. $user->expects($this->once())
  158. ->method('updateLastLoginTimestamp');
  159. $manager->expects($this->once())
  160. ->method('checkPassword')
  161. ->with('foo', 'bar')
  162. ->will($this->returnValue($user));
  163. $userSession = $this->getMockBuilder('\OC\User\Session')
  164. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]])
  165. ->setMethods([
  166. 'prepareUserLogin'
  167. ])
  168. ->getMock();
  169. $userSession->expects($this->once())
  170. ->method('prepareUserLogin');
  171. $userSession->login('foo', 'bar');
  172. $this->assertEquals($user, $userSession->getUser());
  173. }
  174. /**
  175. * @expectedException \OC\User\LoginException
  176. */
  177. public function testLoginValidPasswordDisabled() {
  178. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  179. $session->expects($this->never())
  180. ->method('set');
  181. $session->expects($this->once())
  182. ->method('regenerateId');
  183. $managerMethods = get_class_methods('\OC\User\Manager');
  184. //keep following methods intact in order to ensure hooks are
  185. //working
  186. $doNotMock = array('__construct', 'emit', 'listen');
  187. foreach ($doNotMock as $methodName) {
  188. $i = array_search($methodName, $managerMethods, true);
  189. if ($i !== false) {
  190. unset($managerMethods[$i]);
  191. }
  192. }
  193. $manager = $this->getMock('\OC\User\Manager', $managerMethods, array());
  194. $backend = $this->getMock('\Test\Util\User\Dummy');
  195. $user = $this->getMock('\OC\User\User', array(), array('foo', $backend));
  196. $user->expects($this->any())
  197. ->method('isEnabled')
  198. ->will($this->returnValue(false));
  199. $user->expects($this->never())
  200. ->method('updateLastLoginTimestamp');
  201. $manager->expects($this->once())
  202. ->method('checkPassword')
  203. ->with('foo', 'bar')
  204. ->will($this->returnValue($user));
  205. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]);
  206. $userSession->login('foo', 'bar');
  207. }
  208. public function testLoginInvalidPassword() {
  209. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  210. $session->expects($this->never())
  211. ->method('set');
  212. $session->expects($this->once())
  213. ->method('regenerateId');
  214. $managerMethods = get_class_methods('\OC\User\Manager');
  215. //keep following methods intact in order to ensure hooks are
  216. //working
  217. $doNotMock = array('__construct', 'emit', 'listen');
  218. foreach ($doNotMock as $methodName) {
  219. $i = array_search($methodName, $managerMethods, true);
  220. if ($i !== false) {
  221. unset($managerMethods[$i]);
  222. }
  223. }
  224. $manager = $this->getMock('\OC\User\Manager', $managerMethods, array());
  225. $backend = $this->getMock('\Test\Util\User\Dummy');
  226. $user = $this->getMock('\OC\User\User', array(), array('foo', $backend));
  227. $user->expects($this->never())
  228. ->method('isEnabled');
  229. $user->expects($this->never())
  230. ->method('updateLastLoginTimestamp');
  231. $manager->expects($this->once())
  232. ->method('checkPassword')
  233. ->with('foo', 'bar')
  234. ->will($this->returnValue(false));
  235. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]);
  236. $userSession->login('foo', 'bar');
  237. }
  238. public function testLoginNonExisting() {
  239. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  240. $session->expects($this->never())
  241. ->method('set');
  242. $session->expects($this->once())
  243. ->method('regenerateId');
  244. $manager = $this->getMock('\OC\User\Manager');
  245. $backend = $this->getMock('\Test\Util\User\Dummy');
  246. $manager->expects($this->once())
  247. ->method('checkPassword')
  248. ->with('foo', 'bar')
  249. ->will($this->returnValue(false));
  250. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]);
  251. $userSession->login('foo', 'bar');
  252. }
  253. public function testRememberLoginValidToken() {
  254. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  255. $session->expects($this->exactly(1))
  256. ->method('set')
  257. ->with($this->callback(function ($key) {
  258. switch ($key) {
  259. case 'user_id':
  260. return true;
  261. default:
  262. return false;
  263. }
  264. }, 'foo'));
  265. $session->expects($this->once())
  266. ->method('regenerateId');
  267. $managerMethods = get_class_methods('\OC\User\Manager');
  268. //keep following methods intact in order to ensure hooks are
  269. //working
  270. $doNotMock = array('__construct', 'emit', 'listen');
  271. foreach ($doNotMock as $methodName) {
  272. $i = array_search($methodName, $managerMethods, true);
  273. if ($i !== false) {
  274. unset($managerMethods[$i]);
  275. }
  276. }
  277. $manager = $this->getMock('\OC\User\Manager', $managerMethods, array());
  278. $backend = $this->getMock('\Test\Util\User\Dummy');
  279. $user = $this->getMock('\OC\User\User', array(), array('foo', $backend));
  280. $user->expects($this->any())
  281. ->method('getUID')
  282. ->will($this->returnValue('foo'));
  283. $user->expects($this->once())
  284. ->method('updateLastLoginTimestamp');
  285. $manager->expects($this->once())
  286. ->method('get')
  287. ->with('foo')
  288. ->will($this->returnValue($user));
  289. //prepare login token
  290. $token = 'goodToken';
  291. \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time());
  292. $userSession = $this->getMock(
  293. '\OC\User\Session',
  294. //override, otherwise tests will fail because of setcookie()
  295. array('setMagicInCookie'),
  296. //there are passed as parameters to the constructor
  297. array($manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]));
  298. $granted = $userSession->loginWithCookie('foo', $token);
  299. $this->assertSame($granted, true);
  300. }
  301. public function testRememberLoginInvalidToken() {
  302. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  303. $session->expects($this->never())
  304. ->method('set');
  305. $session->expects($this->once())
  306. ->method('regenerateId');
  307. $managerMethods = get_class_methods('\OC\User\Manager');
  308. //keep following methods intact in order to ensure hooks are
  309. //working
  310. $doNotMock = array('__construct', 'emit', 'listen');
  311. foreach ($doNotMock as $methodName) {
  312. $i = array_search($methodName, $managerMethods, true);
  313. if ($i !== false) {
  314. unset($managerMethods[$i]);
  315. }
  316. }
  317. $manager = $this->getMock('\OC\User\Manager', $managerMethods, array());
  318. $backend = $this->getMock('\Test\Util\User\Dummy');
  319. $user = $this->getMock('\OC\User\User', array(), array('foo', $backend));
  320. $user->expects($this->any())
  321. ->method('getUID')
  322. ->will($this->returnValue('foo'));
  323. $user->expects($this->never())
  324. ->method('updateLastLoginTimestamp');
  325. $manager->expects($this->once())
  326. ->method('get')
  327. ->with('foo')
  328. ->will($this->returnValue($user));
  329. //prepare login token
  330. $token = 'goodToken';
  331. \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time());
  332. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]);
  333. $granted = $userSession->loginWithCookie('foo', 'badToken');
  334. $this->assertSame($granted, false);
  335. }
  336. public function testRememberLoginInvalidUser() {
  337. $session = $this->getMock('\OC\Session\Memory', array(), array(''));
  338. $session->expects($this->never())
  339. ->method('set');
  340. $session->expects($this->once())
  341. ->method('regenerateId');
  342. $managerMethods = get_class_methods('\OC\User\Manager');
  343. //keep following methods intact in order to ensure hooks are
  344. //working
  345. $doNotMock = array('__construct', 'emit', 'listen');
  346. foreach ($doNotMock as $methodName) {
  347. $i = array_search($methodName, $managerMethods, true);
  348. if ($i !== false) {
  349. unset($managerMethods[$i]);
  350. }
  351. }
  352. $manager = $this->getMock('\OC\User\Manager', $managerMethods, array());
  353. $backend = $this->getMock('\Test\Util\User\Dummy');
  354. $user = $this->getMock('\OC\User\User', array(), array('foo', $backend));
  355. $user->expects($this->never())
  356. ->method('getUID');
  357. $user->expects($this->never())
  358. ->method('updateLastLoginTimestamp');
  359. $manager->expects($this->once())
  360. ->method('get')
  361. ->with('foo')
  362. ->will($this->returnValue(null));
  363. //prepare login token
  364. $token = 'goodToken';
  365. \OC::$server->getConfig()->setUserValue('foo', 'login_token', $token, time());
  366. $userSession = new \OC\User\Session($manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]);
  367. $granted = $userSession->loginWithCookie('foo', $token);
  368. $this->assertSame($granted, false);
  369. }
  370. public function testActiveUserAfterSetSession() {
  371. $users = array(
  372. 'foo' => new User('foo', null),
  373. 'bar' => new User('bar', null)
  374. );
  375. $manager = $this->getMockBuilder('\OC\User\Manager')
  376. ->disableOriginalConstructor()
  377. ->getMock();
  378. $manager->expects($this->any())
  379. ->method('get')
  380. ->will($this->returnCallback(function ($uid) use ($users) {
  381. return $users[$uid];
  382. }));
  383. $session = new Memory('');
  384. $session->set('user_id', 'foo');
  385. $userSession = $this->getMockBuilder('\OC\User\Session')
  386. ->setConstructorArgs([$manager, $session, $this->timeFactory, $this->defaultProvider, [$this->defaultProvider]])
  387. ->setMethods([
  388. 'validateSession'
  389. ])
  390. ->getMock();
  391. $userSession->expects($this->any())
  392. ->method('validateSession');
  393. $this->assertEquals($users['foo'], $userSession->getUser());
  394. $session2 = new Memory('');
  395. $session2->set('user_id', 'bar');
  396. $userSession->setSession($session2);
  397. $this->assertEquals($users['bar'], $userSession->getUser());
  398. }
  399. }