LostControllerTest.php 28 KB

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