LostControllerTest.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. <?php
  2. /**
  3. * @author Lukas Reschke <lukas@owncloud.com>
  4. *
  5. * @copyright Copyright (c) 2015, ownCloud, Inc.
  6. * @license AGPL-3.0
  7. *
  8. * This code is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License, version 3,
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License, version 3,
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>
  19. *
  20. */
  21. namespace Tests\Core\Controller;
  22. use OC\Core\Controller\LostController;
  23. use OC\Mail\Message;
  24. use OCP\AppFramework\Http\JSONResponse;
  25. use OCP\AppFramework\Http\TemplateResponse;
  26. use OCP\AppFramework\Utility\ITimeFactory;
  27. use OCP\Defaults;
  28. use OCP\Encryption\IEncryptionModule;
  29. use OCP\Encryption\IManager;
  30. use OCP\IConfig;
  31. use OCP\IL10N;
  32. use OCP\IRequest;
  33. use OCP\IURLGenerator;
  34. use OCP\IUser;
  35. use OCP\IUserManager;
  36. use OCP\Mail\IEMailTemplate;
  37. use OCP\Mail\IMailer;
  38. use OCP\Security\ICrypto;
  39. use OCP\Security\ISecureRandom;
  40. use PHPUnit_Framework_MockObject_MockObject;
  41. /**
  42. * Class LostControllerTest
  43. *
  44. * @package OC\Core\Controller
  45. */
  46. class LostControllerTest extends \Test\TestCase {
  47. /** @var LostController */
  48. private $lostController;
  49. /** @var IUser */
  50. private $existingUser;
  51. /** @var IURLGenerator | PHPUnit_Framework_MockObject_MockObject */
  52. private $urlGenerator;
  53. /** @var IL10N */
  54. private $l10n;
  55. /** @var IUserManager | PHPUnit_Framework_MockObject_MockObject */
  56. private $userManager;
  57. /** @var Defaults */
  58. private $defaults;
  59. /** @var IConfig | PHPUnit_Framework_MockObject_MockObject */
  60. private $config;
  61. /** @var IMailer | PHPUnit_Framework_MockObject_MockObject */
  62. private $mailer;
  63. /** @var ISecureRandom | PHPUnit_Framework_MockObject_MockObject */
  64. private $secureRandom;
  65. /** @var IManager|PHPUnit_Framework_MockObject_MockObject */
  66. private $encryptionManager;
  67. /** @var ITimeFactory | PHPUnit_Framework_MockObject_MockObject */
  68. private $timeFactory;
  69. /** @var IRequest */
  70. private $request;
  71. /** @var ICrypto|\PHPUnit_Framework_MockObject_MockObject */
  72. private $crypto;
  73. protected function setUp() {
  74. parent::setUp();
  75. $this->existingUser = $this->createMock(IUser::class);
  76. $this->existingUser->expects($this->any())
  77. ->method('getEMailAddress')
  78. ->willReturn('test@example.com');
  79. $this->existingUser->expects($this->any())
  80. ->method('getUID')
  81. ->willReturn('ExistingUser');
  82. $this->existingUser->expects($this->any())
  83. ->method('isEnabled')
  84. ->willReturn(true);
  85. $this->config = $this->createMock(IConfig::class);
  86. $this->config->expects($this->any())
  87. ->method('getSystemValue')
  88. ->willReturnMap([
  89. ['secret', null, 'SECRET'],
  90. ['secret', '', 'SECRET'],
  91. ['lost_password_link', '', ''],
  92. ]);
  93. $this->l10n = $this->createMock(IL10N::class);
  94. $this->l10n
  95. ->expects($this->any())
  96. ->method('t')
  97. ->will($this->returnCallback(function($text, $parameters = array()) {
  98. return vsprintf($text, $parameters);
  99. }));
  100. $this->defaults = $this->getMockBuilder('\OCP\Defaults')
  101. ->disableOriginalConstructor()->getMock();
  102. $this->userManager = $this->getMockBuilder(IUserManager::class)
  103. ->disableOriginalConstructor()->getMock();
  104. $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)
  105. ->disableOriginalConstructor()->getMock();
  106. $this->mailer = $this->getMockBuilder('\OCP\Mail\IMailer')
  107. ->disableOriginalConstructor()->getMock();
  108. $this->secureRandom = $this->getMockBuilder('\OCP\Security\ISecureRandom')
  109. ->disableOriginalConstructor()->getMock();
  110. $this->timeFactory = $this->getMockBuilder('\OCP\AppFramework\Utility\ITimeFactory')
  111. ->disableOriginalConstructor()->getMock();
  112. $this->request = $this->getMockBuilder(IRequest::class)
  113. ->disableOriginalConstructor()->getMock();
  114. $this->encryptionManager = $this->getMockBuilder(IManager::class)
  115. ->disableOriginalConstructor()->getMock();
  116. $this->encryptionManager->expects($this->any())
  117. ->method('isEnabled')
  118. ->willReturn(true);
  119. $this->crypto = $this->createMock(ICrypto::class);
  120. $this->lostController = new LostController(
  121. 'Core',
  122. $this->request,
  123. $this->urlGenerator,
  124. $this->userManager,
  125. $this->defaults,
  126. $this->l10n,
  127. $this->config,
  128. $this->secureRandom,
  129. 'lostpassword-noreply@localhost',
  130. $this->encryptionManager,
  131. $this->mailer,
  132. $this->timeFactory,
  133. $this->crypto
  134. );
  135. }
  136. public function testResetFormWithNotExistingUser() {
  137. $this->userManager->method('get')
  138. ->with('NotExistingUser')
  139. ->willReturn(null);
  140. $expectedResponse = new TemplateResponse(
  141. 'core',
  142. 'error',
  143. [
  144. 'errors' => [
  145. ['error' => 'Couldn\'t reset password because the token is invalid'],
  146. ]
  147. ],
  148. 'guest'
  149. );
  150. $this->assertEquals($expectedResponse, $this->lostController->resetform('MySecretToken', 'NotExistingUser'));
  151. }
  152. public function testResetFormInvalidTokenMatch() {
  153. $this->config->method('getUserValue')
  154. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  155. ->willReturn('encryptedToken');
  156. $this->existingUser->method('getLastLogin')
  157. ->will($this->returnValue(12344));
  158. $this->userManager->method('get')
  159. ->with('ValidTokenUser')
  160. ->willReturn($this->existingUser);
  161. $this->crypto->method('decrypt')
  162. ->with(
  163. $this->equalTo('encryptedToken'),
  164. $this->equalTo('test@example.comSECRET')
  165. )->willReturn('12345:TheOnlyAndOnlyOneTokenToResetThePassword');
  166. $response = $this->lostController->resetform('12345:MySecretToken', 'ValidTokenUser');
  167. $expectedResponse = new TemplateResponse('core',
  168. 'error',
  169. [
  170. 'errors' => [
  171. ['error' => 'Couldn\'t reset password because the token is invalid'],
  172. ]
  173. ],
  174. 'guest');
  175. $this->assertEquals($expectedResponse, $response);
  176. }
  177. public function testResetFormExpiredToken() {
  178. $this->userManager->method('get')
  179. ->with('ValidTokenUser')
  180. ->willReturn($this->existingUser);
  181. $this->config
  182. ->expects($this->once())
  183. ->method('getUserValue')
  184. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  185. ->will($this->returnValue('encryptedToken'));
  186. $this->crypto->method('decrypt')
  187. ->with(
  188. $this->equalTo('encryptedToken'),
  189. $this->equalTo('test@example.comSECRET')
  190. )->willReturn('12345:TheOnlyAndOnlyOneTokenToResetThePassword');
  191. $this->timeFactory
  192. ->expects($this->once())
  193. ->method('getTime')
  194. ->willReturn(999999);
  195. $response = $this->lostController->resetform('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser');
  196. $expectedResponse = new TemplateResponse('core',
  197. 'error',
  198. [
  199. 'errors' => [
  200. ['error' => 'Couldn\'t reset password because the token is expired'],
  201. ]
  202. ],
  203. 'guest');
  204. $this->assertEquals($expectedResponse, $response);
  205. }
  206. public function testResetFormValidToken() {
  207. $this->existingUser->method('getLastLogin')
  208. ->willReturn(12344);
  209. $this->userManager->method('get')
  210. ->with('ValidTokenUser')
  211. ->willReturn($this->existingUser);
  212. $this->timeFactory
  213. ->expects($this->once())
  214. ->method('getTime')
  215. ->willReturn(12348);
  216. $this->config->method('getUserValue')
  217. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  218. ->willReturn('encryptedToken');
  219. $this->crypto->method('decrypt')
  220. ->with(
  221. $this->equalTo('encryptedToken'),
  222. $this->equalTo('test@example.comSECRET')
  223. )->willReturn('12345:TheOnlyAndOnlyOneTokenToResetThePassword');
  224. $this->urlGenerator
  225. ->expects($this->once())
  226. ->method('linkToRouteAbsolute')
  227. ->with('core.lost.setPassword', array('userId' => 'ValidTokenUser', 'token' => 'TheOnlyAndOnlyOneTokenToResetThePassword'))
  228. ->will($this->returnValue('https://example.tld/index.php/lostpassword/'));
  229. $response = $this->lostController->resetform('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser');
  230. $expectedResponse = new TemplateResponse('core',
  231. 'lostpassword/resetpassword',
  232. array(
  233. 'link' => 'https://example.tld/index.php/lostpassword/',
  234. ),
  235. 'guest');
  236. $this->assertEquals($expectedResponse, $response);
  237. }
  238. public function testEmailUnsuccessful() {
  239. $existingUser = 'ExistingUser';
  240. $nonExistingUser = 'NonExistingUser';
  241. $this->userManager
  242. ->expects($this->any())
  243. ->method('userExists')
  244. ->will($this->returnValueMap(array(
  245. array(true, $existingUser),
  246. array(false, $nonExistingUser)
  247. )));
  248. $this->userManager
  249. ->method('getByEmail')
  250. ->willReturn([]);
  251. // With a non existing user
  252. $response = $this->lostController->email($nonExistingUser);
  253. $expectedResponse = new JSONResponse([
  254. 'status' => 'error',
  255. 'msg' => 'Couldn\'t send reset email. Please make sure your username is correct.'
  256. ]);
  257. $expectedResponse->throttle();
  258. $this->assertEquals($expectedResponse, $response);
  259. // With no mail address
  260. $this->config
  261. ->expects($this->any())
  262. ->method('getUserValue')
  263. ->with($existingUser, 'settings', 'email')
  264. ->will($this->returnValue(null));
  265. $response = $this->lostController->email($existingUser);
  266. $expectedResponse = new JSONResponse([
  267. 'status' => 'error',
  268. 'msg' => 'Couldn\'t send reset email. Please make sure your username is correct.'
  269. ]);
  270. $expectedResponse->throttle();
  271. $this->assertEquals($expectedResponse, $response);
  272. }
  273. public function testEmailSuccessful() {
  274. $this->secureRandom
  275. ->expects($this->once())
  276. ->method('generate')
  277. ->with('21')
  278. ->will($this->returnValue('ThisIsMaybeANotSoSecretToken!'));
  279. $this->userManager
  280. ->expects($this->any())
  281. ->method('get')
  282. ->with('ExistingUser')
  283. ->willReturn($this->existingUser);
  284. $this->timeFactory
  285. ->expects($this->once())
  286. ->method('getTime')
  287. ->will($this->returnValue(12348));
  288. $this->config
  289. ->expects($this->once())
  290. ->method('setUserValue')
  291. ->with('ExistingUser', 'core', 'lostpassword', 'encryptedToken');
  292. $this->urlGenerator
  293. ->expects($this->once())
  294. ->method('linkToRouteAbsolute')
  295. ->with('core.lost.resetform', array('userId' => 'ExistingUser', 'token' => 'ThisIsMaybeANotSoSecretToken!'))
  296. ->will($this->returnValue('https://example.tld/index.php/lostpassword/'));
  297. $message = $this->getMockBuilder('\OC\Mail\Message')
  298. ->disableOriginalConstructor()->getMock();
  299. $message
  300. ->expects($this->at(0))
  301. ->method('setTo')
  302. ->with(['test@example.com' => 'ExistingUser']);
  303. $message
  304. ->expects($this->at(1))
  305. ->method('setFrom')
  306. ->with(['lostpassword-noreply@localhost' => null]);
  307. $emailTemplate = $this->createMock(IEMailTemplate::class);
  308. $emailTemplate->expects($this->any())
  309. ->method('renderHtml')
  310. ->willReturn('HTML body');
  311. $emailTemplate->expects($this->any())
  312. ->method('renderText')
  313. ->willReturn('text body');
  314. $message
  315. ->expects($this->at(2))
  316. ->method('useTemplate')
  317. ->with($emailTemplate);
  318. $this->mailer
  319. ->expects($this->at(0))
  320. ->method('createEMailTemplate')
  321. ->willReturn($emailTemplate);
  322. $this->mailer
  323. ->expects($this->at(1))
  324. ->method('createMessage')
  325. ->will($this->returnValue($message));
  326. $this->mailer
  327. ->expects($this->at(2))
  328. ->method('send')
  329. ->with($message);
  330. $this->crypto->method('encrypt')
  331. ->with(
  332. $this->equalTo('12348:ThisIsMaybeANotSoSecretToken!'),
  333. $this->equalTo('test@example.comSECRET')
  334. )->willReturn('encryptedToken');
  335. $response = $this->lostController->email('ExistingUser');
  336. $expectedResponse = new JSONResponse(['status' => 'success']);
  337. $expectedResponse->throttle();
  338. $this->assertEquals($expectedResponse, $response);
  339. }
  340. public function testEmailWithMailSuccessful() {
  341. $this->secureRandom
  342. ->expects($this->once())
  343. ->method('generate')
  344. ->with('21')
  345. ->will($this->returnValue('ThisIsMaybeANotSoSecretToken!'));
  346. $this->userManager
  347. ->expects($this->any())
  348. ->method('get')
  349. ->with('test@example.com')
  350. ->willReturn(null);
  351. $this->userManager
  352. ->expects($this->any())
  353. ->method('getByEmail')
  354. ->with('test@example.com')
  355. ->willReturn([$this->existingUser]);
  356. $this->timeFactory
  357. ->expects($this->once())
  358. ->method('getTime')
  359. ->will($this->returnValue(12348));
  360. $this->config
  361. ->expects($this->once())
  362. ->method('setUserValue')
  363. ->with('ExistingUser', 'core', 'lostpassword', 'encryptedToken');
  364. $this->urlGenerator
  365. ->expects($this->once())
  366. ->method('linkToRouteAbsolute')
  367. ->with('core.lost.resetform', array('userId' => 'ExistingUser', 'token' => 'ThisIsMaybeANotSoSecretToken!'))
  368. ->will($this->returnValue('https://example.tld/index.php/lostpassword/'));
  369. $message = $this->getMockBuilder('\OC\Mail\Message')
  370. ->disableOriginalConstructor()->getMock();
  371. $message
  372. ->expects($this->at(0))
  373. ->method('setTo')
  374. ->with(['test@example.com' => 'ExistingUser']);
  375. $message
  376. ->expects($this->at(1))
  377. ->method('setFrom')
  378. ->with(['lostpassword-noreply@localhost' => null]);
  379. $emailTemplate = $this->createMock(IEMailTemplate::class);
  380. $emailTemplate->expects($this->any())
  381. ->method('renderHtml')
  382. ->willReturn('HTML body');
  383. $emailTemplate->expects($this->any())
  384. ->method('renderText')
  385. ->willReturn('text body');
  386. $message
  387. ->expects($this->at(2))
  388. ->method('useTemplate')
  389. ->with($emailTemplate);
  390. $this->mailer
  391. ->expects($this->at(0))
  392. ->method('createEMailTemplate')
  393. ->willReturn($emailTemplate);
  394. $this->mailer
  395. ->expects($this->at(1))
  396. ->method('createMessage')
  397. ->will($this->returnValue($message));
  398. $this->mailer
  399. ->expects($this->at(2))
  400. ->method('send')
  401. ->with($message);
  402. $this->crypto->method('encrypt')
  403. ->with(
  404. $this->equalTo('12348:ThisIsMaybeANotSoSecretToken!'),
  405. $this->equalTo('test@example.comSECRET')
  406. )->willReturn('encryptedToken');
  407. $response = $this->lostController->email('test@example.com');
  408. $expectedResponse = new JSONResponse(['status' => 'success']);
  409. $expectedResponse->throttle();
  410. $this->assertEquals($expectedResponse, $response);
  411. }
  412. public function testEmailCantSendException() {
  413. $this->secureRandom
  414. ->expects($this->once())
  415. ->method('generate')
  416. ->with('21')
  417. ->will($this->returnValue('ThisIsMaybeANotSoSecretToken!'));
  418. $this->userManager
  419. ->expects($this->any())
  420. ->method('get')
  421. ->with('ExistingUser')
  422. ->willReturn($this->existingUser);
  423. $this->config
  424. ->expects($this->once())
  425. ->method('setUserValue')
  426. ->with('ExistingUser', 'core', 'lostpassword', 'encryptedToken');
  427. $this->timeFactory
  428. ->expects($this->once())
  429. ->method('getTime')
  430. ->will($this->returnValue(12348));
  431. $this->urlGenerator
  432. ->expects($this->once())
  433. ->method('linkToRouteAbsolute')
  434. ->with('core.lost.resetform', array('userId' => 'ExistingUser', 'token' => 'ThisIsMaybeANotSoSecretToken!'))
  435. ->will($this->returnValue('https://example.tld/index.php/lostpassword/'));
  436. $message = $this->createMock(Message::class);
  437. $message
  438. ->expects($this->at(0))
  439. ->method('setTo')
  440. ->with(['test@example.com' => 'ExistingUser']);
  441. $message
  442. ->expects($this->at(1))
  443. ->method('setFrom')
  444. ->with(['lostpassword-noreply@localhost' => null]);
  445. $emailTemplate = $this->createMock(IEMailTemplate::class);
  446. $emailTemplate->expects($this->any())
  447. ->method('renderHtml')
  448. ->willReturn('HTML body');
  449. $emailTemplate->expects($this->any())
  450. ->method('renderText')
  451. ->willReturn('text body');
  452. $message
  453. ->expects($this->at(2))
  454. ->method('useTemplate')
  455. ->with($emailTemplate);
  456. $this->mailer
  457. ->expects($this->at(0))
  458. ->method('createEMailTemplate')
  459. ->willReturn($emailTemplate);
  460. $this->mailer
  461. ->expects($this->at(1))
  462. ->method('createMessage')
  463. ->will($this->returnValue($message));
  464. $this->mailer
  465. ->expects($this->at(2))
  466. ->method('send')
  467. ->with($message)
  468. ->will($this->throwException(new \Exception()));
  469. $this->crypto->method('encrypt')
  470. ->with(
  471. $this->equalTo('12348:ThisIsMaybeANotSoSecretToken!'),
  472. $this->equalTo('test@example.comSECRET')
  473. )->willReturn('encryptedToken');
  474. $response = $this->lostController->email('ExistingUser');
  475. $expectedResponse = new JSONResponse(['status' => 'error', 'msg' => 'Couldn\'t send reset email. Please contact your administrator.']);
  476. $expectedResponse->throttle();
  477. $this->assertEquals($expectedResponse, $response);
  478. }
  479. public function testSetPasswordUnsuccessful() {
  480. $this->config->method('getUserValue')
  481. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  482. ->willReturn('encryptedData');
  483. $this->existingUser->method('getLastLogin')
  484. ->will($this->returnValue(12344));
  485. $this->existingUser->expects($this->once())
  486. ->method('setPassword')
  487. ->with('NewPassword')
  488. ->willReturn(false);
  489. $this->userManager->method('get')
  490. ->with('ValidTokenUser')
  491. ->willReturn($this->existingUser);
  492. $this->config->expects($this->never())
  493. ->method('deleteUserValue');
  494. $this->timeFactory->method('getTime')
  495. ->will($this->returnValue(12348));
  496. $this->crypto->method('decrypt')
  497. ->with(
  498. $this->equalTo('encryptedData'),
  499. $this->equalTo('test@example.comSECRET')
  500. )->willReturn('12345:TheOnlyAndOnlyOneTokenToResetThePassword');
  501. $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true);
  502. $expectedResponse = array('status' => 'error', 'msg' => '');
  503. $this->assertSame($expectedResponse, $response);
  504. }
  505. public function testSetPasswordSuccessful() {
  506. $this->config->method('getUserValue')
  507. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  508. ->willReturn('encryptedData');
  509. $this->existingUser->method('getLastLogin')
  510. ->will($this->returnValue(12344));
  511. $this->existingUser->expects($this->once())
  512. ->method('setPassword')
  513. ->with('NewPassword')
  514. ->willReturn(true);
  515. $this->userManager->method('get')
  516. ->with('ValidTokenUser')
  517. ->willReturn($this->existingUser);
  518. $this->config->expects($this->once())
  519. ->method('deleteUserValue')
  520. ->with('ValidTokenUser', 'core', 'lostpassword');
  521. $this->timeFactory->method('getTime')
  522. ->will($this->returnValue(12348));
  523. $this->crypto->method('decrypt')
  524. ->with(
  525. $this->equalTo('encryptedData'),
  526. $this->equalTo('test@example.comSECRET')
  527. )->willReturn('12345:TheOnlyAndOnlyOneTokenToResetThePassword');
  528. $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true);
  529. $expectedResponse = array('user' => 'ValidTokenUser', 'status' => 'success');
  530. $this->assertSame($expectedResponse, $response);
  531. }
  532. public function testSetPasswordExpiredToken() {
  533. $this->config->method('getUserValue')
  534. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  535. ->willReturn('encryptedData');
  536. $this->userManager->method('get')
  537. ->with('ValidTokenUser')
  538. ->willReturn($this->existingUser);
  539. $this->timeFactory->method('getTime')
  540. ->willReturn(617146);
  541. $this->crypto->method('decrypt')
  542. ->with(
  543. $this->equalTo('encryptedData'),
  544. $this->equalTo('test@example.comSECRET')
  545. )->willReturn('12345:TheOnlyAndOnlyOneTokenToResetThePassword');
  546. $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true);
  547. $expectedResponse = [
  548. 'status' => 'error',
  549. 'msg' => 'Couldn\'t reset password because the token is expired',
  550. ];
  551. $this->assertSame($expectedResponse, $response);
  552. }
  553. public function testSetPasswordInvalidDataInDb() {
  554. $this->config->method('getUserValue')
  555. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  556. ->willReturn('invalidEncryptedData');
  557. $this->userManager
  558. ->method('get')
  559. ->with('ValidTokenUser')
  560. ->willReturn($this->existingUser);
  561. $this->crypto->method('decrypt')
  562. ->with(
  563. $this->equalTo('invalidEncryptedData'),
  564. $this->equalTo('test@example.comSECRET')
  565. )->willReturn('TheOnlyAndOnlyOneTokenToResetThePassword');
  566. $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true);
  567. $expectedResponse = [
  568. 'status' => 'error',
  569. 'msg' => 'Couldn\'t reset password because the token is invalid',
  570. ];
  571. $this->assertSame($expectedResponse, $response);
  572. }
  573. public function testSetPasswordExpiredTokenDueToLogin() {
  574. $this->config->method('getUserValue')
  575. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  576. ->willReturn('encryptedData');
  577. $this->existingUser->method('getLastLogin')
  578. ->will($this->returnValue(12346));
  579. $this->userManager
  580. ->method('get')
  581. ->with('ValidTokenUser')
  582. ->willReturn($this->existingUser);
  583. $this->timeFactory
  584. ->method('getTime')
  585. ->will($this->returnValue(12345));
  586. $this->crypto->method('decrypt')
  587. ->with(
  588. $this->equalTo('encryptedData'),
  589. $this->equalTo('test@example.comSECRET')
  590. )->willReturn('12345:TheOnlyAndOnlyOneTokenToResetThePassword');
  591. $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true);
  592. $expectedResponse = [
  593. 'status' => 'error',
  594. 'msg' => 'Couldn\'t reset password because the token is expired',
  595. ];
  596. $this->assertSame($expectedResponse, $response);
  597. }
  598. public function testIsSetPasswordWithoutTokenFailing() {
  599. $this->config->method('getUserValue')
  600. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  601. ->willReturn('aValidtoken');
  602. $this->userManager->method('get')
  603. ->with('ValidTokenUser')
  604. ->willReturn($this->existingUser);
  605. $this->crypto->method('decrypt')
  606. ->with(
  607. $this->equalTo('aValidtoken'),
  608. $this->equalTo('test@example.comSECRET')
  609. )->willThrowException(new \Exception());
  610. $response = $this->lostController->setPassword('', 'ValidTokenUser', 'NewPassword', true);
  611. $expectedResponse = [
  612. 'status' => 'error',
  613. 'msg' => 'Couldn\'t reset password because the token is invalid'
  614. ];
  615. $this->assertSame($expectedResponse, $response);
  616. }
  617. public function testSetPasswordForDisabledUser() {
  618. $user = $this->createMock(IUser::class);
  619. $user->expects($this->any())
  620. ->method('isEnabled')
  621. ->willReturn(false);
  622. $user->expects($this->never())
  623. ->method('setPassword');
  624. $this->config->method('getUserValue')
  625. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  626. ->willReturn('encryptedData');
  627. $this->userManager->method('get')
  628. ->with('DisabledUser')
  629. ->willReturn($this->existingUser);
  630. $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'DisabledUser', 'NewPassword', true);
  631. $expectedResponse = [
  632. 'status' => 'error',
  633. 'msg' => 'Couldn\'t reset password because the token is invalid'
  634. ];
  635. $this->assertSame($expectedResponse, $response);
  636. }
  637. public function testSendEmailNoEmail() {
  638. $user = $this->createMock(IUser::class);
  639. $user->expects($this->any())
  640. ->method('isEnabled')
  641. ->willReturn(true);
  642. $this->userManager->method('userExists')
  643. ->with('ExistingUser')
  644. ->willReturn(true);
  645. $this->userManager->method('get')
  646. ->with('ExistingUser')
  647. ->willReturn($user);
  648. $response = $this->lostController->email('ExistingUser');
  649. $expectedResponse = new JSONResponse(['status' => 'error', 'msg' => 'Could not send reset email because there is no email address for this username. Please contact your administrator.']);
  650. $expectedResponse->throttle();
  651. $this->assertEquals($expectedResponse, $response);
  652. }
  653. public function testSetPasswordEncryptionDontProceedPerUserKey() {
  654. /** @var IEncryptionModule|PHPUnit_Framework_MockObject_MockObject $encryptionModule */
  655. $encryptionModule = $this->createMock(IEncryptionModule::class);
  656. $encryptionModule->expects($this->once())->method('needDetailedAccessList')->willReturn(true);
  657. $this->encryptionManager->expects($this->once())->method('getEncryptionModules')
  658. ->willReturn([0 => ['callback' => function() use ($encryptionModule) { return $encryptionModule; }]]);
  659. $response = $this->lostController->setPassword('myToken', 'user', 'newpass', false);
  660. $expectedResponse = ['status' => 'error', 'msg' => '', 'encryption' => true];
  661. $this->assertSame($expectedResponse, $response);
  662. }
  663. public function testSetPasswordDontProceedMasterKey() {
  664. $encryptionModule = $this->createMock(IEncryptionModule::class);
  665. $encryptionModule->expects($this->once())->method('needDetailedAccessList')->willReturn(false);
  666. $this->encryptionManager->expects($this->once())->method('getEncryptionModules')
  667. ->willReturn([0 => ['callback' => function() use ($encryptionModule) { return $encryptionModule; }]]);
  668. $this->config->method('getUserValue')
  669. ->with('ValidTokenUser', 'core', 'lostpassword', null)
  670. ->willReturn('encryptedData');
  671. $this->existingUser->method('getLastLogin')
  672. ->will($this->returnValue(12344));
  673. $this->existingUser->expects($this->once())
  674. ->method('setPassword')
  675. ->with('NewPassword')
  676. ->willReturn(true);
  677. $this->userManager->method('get')
  678. ->with('ValidTokenUser')
  679. ->willReturn($this->existingUser);
  680. $this->config->expects($this->once())
  681. ->method('deleteUserValue')
  682. ->with('ValidTokenUser', 'core', 'lostpassword');
  683. $this->timeFactory->method('getTime')
  684. ->will($this->returnValue(12348));
  685. $this->crypto->method('decrypt')
  686. ->with(
  687. $this->equalTo('encryptedData'),
  688. $this->equalTo('test@example.comSECRET')
  689. )->willReturn('12345:TheOnlyAndOnlyOneTokenToResetThePassword');
  690. $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', false);
  691. $expectedResponse = array('user' => 'ValidTokenUser', 'status' => 'success');
  692. $this->assertSame($expectedResponse, $response);
  693. }
  694. public function testTwoUsersWithSameEmail() {
  695. $user1 = $this->createMock(IUser::class);
  696. $user1->expects($this->any())
  697. ->method('getEMailAddress')
  698. ->willReturn('test@example.com');
  699. $user1->expects($this->any())
  700. ->method('getUID')
  701. ->willReturn('User1');
  702. $user1->expects($this->any())
  703. ->method('isEnabled')
  704. ->willReturn(true);
  705. $user2 = $this->createMock(IUser::class);
  706. $user2->expects($this->any())
  707. ->method('getEMailAddress')
  708. ->willReturn('test@example.com');
  709. $user2->expects($this->any())
  710. ->method('getUID')
  711. ->willReturn('User2');
  712. $user2->expects($this->any())
  713. ->method('isEnabled')
  714. ->willReturn(true);
  715. $this->userManager
  716. ->method('get')
  717. ->willReturn(null);
  718. $this->userManager
  719. ->method('getByEmail')
  720. ->willReturn([$user1, $user2]);
  721. // request password reset for test@example.com
  722. $response = $this->lostController->email('test@example.com');
  723. $expectedResponse = new JSONResponse([
  724. 'status' => 'error',
  725. 'msg' => 'Couldn\'t send reset email. Please make sure your username is correct.'
  726. ]);
  727. $expectedResponse->throttle();
  728. $this->assertEquals($expectedResponse, $response);
  729. }
  730. public function testTwoUsersWithSameEmailOneDisabled() {
  731. $user1 = $this->createMock(IUser::class);
  732. $user1->expects($this->any())
  733. ->method('getEMailAddress')
  734. ->willReturn('test@example.com');
  735. $user1->expects($this->any())
  736. ->method('getUID')
  737. ->willReturn('User1');
  738. $user1->expects($this->any())
  739. ->method('isEnabled')
  740. ->willReturn(true);
  741. $user2 = $this->createMock(IUser::class);
  742. $user2->expects($this->any())
  743. ->method('getEMailAddress')
  744. ->willReturn('test@example.com');
  745. $user2->expects($this->any())
  746. ->method('getUID')
  747. ->willReturn('User2');
  748. $user2->expects($this->any())
  749. ->method('isEnabled')
  750. ->willReturn(false);
  751. $this->userManager
  752. ->method('get')
  753. ->willReturn(null);
  754. $this->userManager
  755. ->method('getByEmail')
  756. ->willReturn([$user1, $user2]);
  757. // request password reset for test@example.com
  758. $response = $this->lostController->email('test@example.com');
  759. $expectedResponse = new JSONResponse([
  760. 'status' => 'success'
  761. ]);
  762. $expectedResponse->throttle();
  763. $this->assertEquals($expectedResponse, $response);
  764. }
  765. }