UsersControllerTest.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. <?php
  2. /**
  3. * @author Lukas Reschke
  4. * @copyright 2014-2015 Lukas Reschke lukas@owncloud.com
  5. *
  6. * This file is licensed under the Affero General Public License version 3 or
  7. * later.
  8. * See the COPYING-README file.
  9. */
  10. namespace Tests\Settings\Controller;
  11. use OC\Accounts\AccountManager;
  12. use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
  13. use OC\Group\Group;
  14. use OC\Group\Manager;
  15. use OC\Settings\Controller\UsersController;
  16. use OC\Settings\Mailer\NewUserMailHelper;
  17. use OC\SubAdmin;
  18. use OCP\App\IAppManager;
  19. use OCP\AppFramework\Http;
  20. use OCP\AppFramework\Http\DataResponse;
  21. use OCP\BackgroundJob\IJobList;
  22. use OCP\Files\Config\IUserMountCache;
  23. use OCP\Encryption\IEncryptionModule;
  24. use OCP\Encryption\IManager;
  25. use OCP\IAvatar;
  26. use OCP\IAvatarManager;
  27. use OCP\IConfig;
  28. use OCP\IGroup;
  29. use OCP\IGroupManager;
  30. use OCP\IL10N;
  31. use OCP\ILogger;
  32. use OCP\IRequest;
  33. use OCP\IUser;
  34. use OCP\IUserManager;
  35. use OCP\IUserSession;
  36. use OCP\L10N\IFactory;
  37. use OCP\Mail\IEMailTemplate;
  38. use OCP\Mail\IMailer;
  39. use OCP\Security\ISecureRandom;
  40. use OC\User\User;
  41. use Test\Util\User\Dummy;
  42. /**
  43. * @group DB
  44. *
  45. * @package Tests\Settings\Controller
  46. */
  47. class UsersControllerTest extends \Test\TestCase {
  48. /** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
  49. private $groupManager;
  50. /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
  51. private $userManager;
  52. /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
  53. private $userSession;
  54. /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
  55. private $config;
  56. /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
  57. private $logger;
  58. /** @var IMailer|\PHPUnit_Framework_MockObject_MockObject */
  59. private $mailer;
  60. /** @var IFactory|\PHPUnit_Framework_MockObject_MockObject */
  61. private $l10nFactory;
  62. /** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */
  63. private $appManager;
  64. /** @var IAvatarManager|\PHPUnit_Framework_MockObject_MockObject */
  65. private $avatarManager;
  66. /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
  67. private $l;
  68. /** @var AccountManager | \PHPUnit_Framework_MockObject_MockObject */
  69. private $accountManager;
  70. /** @var ISecureRandom | \PHPUnit_Framework_MockObject_MockObject */
  71. private $secureRandom;
  72. /** @var NewUserMailHelper|\PHPUnit_Framework_MockObject_MockObject */
  73. private $newUserMailHelper;
  74. /** @var IJobList | \PHPUnit_Framework_MockObject_MockObject */
  75. private $jobList;
  76. /** @var \OC\Security\IdentityProof\Manager |\PHPUnit_Framework_MockObject_MockObject */
  77. private $securityManager;
  78. /** @var IManager | \PHPUnit_Framework_MockObject_MockObject */
  79. private $encryptionManager;
  80. /** @var IEncryptionModule | \PHPUnit_Framework_MockObject_MockObject */
  81. private $encryptionModule;
  82. protected function setUp() {
  83. parent::setUp();
  84. $this->userManager = $this->createMock(IUserManager::class);
  85. $this->groupManager = $this->createMock(Manager::class);
  86. $this->userSession = $this->createMock(IUserSession::class);
  87. $this->config = $this->createMock(IConfig::class);
  88. $this->l = $this->createMock(IL10N::class);
  89. $this->mailer = $this->createMock(IMailer::class);
  90. $this->l10nFactory = $this->createMock(IFactory::class);
  91. $this->appManager = $this->createMock(IAppManager::class);
  92. $this->accountManager = $this->createMock(AccountManager::class);
  93. $this->securityManager = $this->getMockBuilder(\OC\Security\IdentityProof\Manager::class)->disableOriginalConstructor()->getMock();
  94. $this->jobList = $this->createMock(IJobList::class);
  95. $this->encryptionManager = $this->createMock(IManager::class);
  96. $this->l->method('t')
  97. ->will($this->returnCallback(function ($text, $parameters = []) {
  98. return vsprintf($text, $parameters);
  99. }));
  100. $this->encryptionModule = $this->createMock(IEncryptionModule::class);
  101. $this->encryptionManager->expects($this->any())->method('getEncryptionModules')
  102. ->willReturn(['encryptionModule' => ['callback' => function() { return $this->encryptionModule;}]]);
  103. }
  104. /**
  105. * @param bool $isAdmin
  106. * @return UsersController | \PHPUnit_Framework_MockObject_MockObject
  107. */
  108. protected function getController($isAdmin = false, $mockedMethods = []) {
  109. if (empty($mockedMethods)) {
  110. return new UsersController(
  111. 'settings',
  112. $this->createMock(IRequest::class),
  113. $this->userManager,
  114. $this->groupManager,
  115. $this->userSession,
  116. $this->config,
  117. $isAdmin,
  118. $this->l,
  119. $this->mailer,
  120. $this->l10nFactory,
  121. $this->appManager,
  122. $this->accountManager,
  123. $this->securityManager,
  124. $this->jobList,
  125. $this->encryptionManager
  126. );
  127. } else {
  128. return $this->getMockBuilder(UsersController::class)
  129. ->setConstructorArgs(
  130. [
  131. 'settings',
  132. $this->createMock(IRequest::class),
  133. $this->userManager,
  134. $this->groupManager,
  135. $this->userSession,
  136. $this->config,
  137. $isAdmin,
  138. $this->l,
  139. $this->mailer,
  140. $this->l10nFactory,
  141. $this->appManager,
  142. $this->accountManager,
  143. $this->securityManager,
  144. $this->jobList,
  145. $this->encryptionManager
  146. ]
  147. )->setMethods($mockedMethods)->getMock();
  148. }
  149. }
  150. /**
  151. * @dataProvider dataTestSetUserSettings
  152. *
  153. * @param string $email
  154. * @param bool $validEmail
  155. * @param $expectedStatus
  156. */
  157. public function testSetUserSettings($email, $validEmail, $expectedStatus) {
  158. $controller = $this->getController(false, ['saveUserSettings']);
  159. $user = $this->createMock(IUser::class);
  160. $this->userSession->method('getUser')->willReturn($user);
  161. if (!empty($email) && $validEmail) {
  162. $this->mailer->expects($this->once())->method('validateMailAddress')
  163. ->willReturn($validEmail);
  164. }
  165. $saveData = (!empty($email) && $validEmail) || empty($email);
  166. if ($saveData) {
  167. $this->accountManager->expects($this->once())
  168. ->method('getUser')
  169. ->with($user)
  170. ->willReturn([
  171. AccountManager::PROPERTY_DISPLAYNAME =>
  172. [
  173. 'value' => 'Display name',
  174. 'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
  175. 'verified' => AccountManager::NOT_VERIFIED,
  176. ],
  177. AccountManager::PROPERTY_ADDRESS =>
  178. [
  179. 'value' => '',
  180. 'scope' => AccountManager::VISIBILITY_PRIVATE,
  181. 'verified' => AccountManager::NOT_VERIFIED,
  182. ],
  183. AccountManager::PROPERTY_WEBSITE =>
  184. [
  185. 'value' => '',
  186. 'scope' => AccountManager::VISIBILITY_PRIVATE,
  187. 'verified' => AccountManager::NOT_VERIFIED,
  188. ],
  189. AccountManager::PROPERTY_EMAIL =>
  190. [
  191. 'value' => '',
  192. 'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY,
  193. 'verified' => AccountManager::NOT_VERIFIED,
  194. ],
  195. AccountManager::PROPERTY_AVATAR =>
  196. [
  197. 'scope' => AccountManager::VISIBILITY_CONTACTS_ONLY
  198. ],
  199. AccountManager::PROPERTY_PHONE =>
  200. [
  201. 'value' => '',
  202. 'scope' => AccountManager::VISIBILITY_PRIVATE,
  203. 'verified' => AccountManager::NOT_VERIFIED,
  204. ],
  205. AccountManager::PROPERTY_TWITTER =>
  206. [
  207. 'value' => '',
  208. 'scope' => AccountManager::VISIBILITY_PRIVATE,
  209. 'verified' => AccountManager::NOT_VERIFIED,
  210. ],
  211. ]);
  212. $controller->expects($this->once())->method('saveUserSettings');
  213. } else {
  214. $controller->expects($this->never())->method('saveUserSettings');
  215. }
  216. $result = $controller->setUserSettings(
  217. AccountManager::VISIBILITY_CONTACTS_ONLY,
  218. 'displayName',
  219. AccountManager::VISIBILITY_CONTACTS_ONLY,
  220. '47658468',
  221. AccountManager::VISIBILITY_CONTACTS_ONLY,
  222. $email,
  223. AccountManager::VISIBILITY_CONTACTS_ONLY,
  224. 'nextcloud.com',
  225. AccountManager::VISIBILITY_CONTACTS_ONLY,
  226. 'street and city',
  227. AccountManager::VISIBILITY_CONTACTS_ONLY,
  228. '@nextclouders',
  229. AccountManager::VISIBILITY_CONTACTS_ONLY
  230. );
  231. $this->assertSame($expectedStatus, $result->getStatus());
  232. }
  233. public function dataTestSetUserSettings() {
  234. return [
  235. ['', true, Http::STATUS_OK],
  236. ['', false, Http::STATUS_OK],
  237. ['example.com', false, Http::STATUS_UNPROCESSABLE_ENTITY],
  238. ['john@example.com', true, Http::STATUS_OK],
  239. ];
  240. }
  241. /**
  242. * @dataProvider dataTestSaveUserSettings
  243. *
  244. * @param array $data
  245. * @param string $oldEmailAddress
  246. * @param string $oldDisplayName
  247. */
  248. public function testSaveUserSettings($data,
  249. $oldEmailAddress,
  250. $oldDisplayName
  251. ) {
  252. $controller = $this->getController();
  253. $user = $this->createMock(IUser::class);
  254. $user->method('getDisplayName')->willReturn($oldDisplayName);
  255. $user->method('getEMailAddress')->willReturn($oldEmailAddress);
  256. $user->method('canChangeDisplayName')->willReturn(true);
  257. if ($data[AccountManager::PROPERTY_EMAIL]['value'] === $oldEmailAddress ||
  258. ($oldEmailAddress === null && $data[AccountManager::PROPERTY_EMAIL]['value'] === '')) {
  259. $user->expects($this->never())->method('setEMailAddress');
  260. } else {
  261. $user->expects($this->once())->method('setEMailAddress')
  262. ->with($data[AccountManager::PROPERTY_EMAIL]['value'])
  263. ->willReturn(true);
  264. }
  265. if ($data[AccountManager::PROPERTY_DISPLAYNAME]['value'] === $oldDisplayName ||
  266. ($oldDisplayName === null && $data[AccountManager::PROPERTY_DISPLAYNAME]['value'] === '')) {
  267. $user->expects($this->never())->method('setDisplayName');
  268. } else {
  269. $user->expects($this->once())->method('setDisplayName')
  270. ->with($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
  271. ->willReturn(true);
  272. }
  273. $this->accountManager->expects($this->once())->method('updateUser')
  274. ->with($user, $data);
  275. $this->invokePrivate($controller, 'saveUserSettings', [$user, $data]);
  276. }
  277. public function dataTestSaveUserSettings() {
  278. return [
  279. [
  280. [
  281. AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
  282. AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
  283. ],
  284. 'john@example.com',
  285. 'john doe'
  286. ],
  287. [
  288. [
  289. AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
  290. AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
  291. ],
  292. 'johnNew@example.com',
  293. 'john New doe'
  294. ],
  295. [
  296. [
  297. AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
  298. AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
  299. ],
  300. 'johnNew@example.com',
  301. 'john doe'
  302. ],
  303. [
  304. [
  305. AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
  306. AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
  307. ],
  308. 'john@example.com',
  309. 'john New doe'
  310. ],
  311. [
  312. [
  313. AccountManager::PROPERTY_EMAIL => ['value' => ''],
  314. AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
  315. ],
  316. null,
  317. 'john New doe'
  318. ],
  319. [
  320. [
  321. AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
  322. AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
  323. ],
  324. 'john@example.com',
  325. null
  326. ],
  327. ];
  328. }
  329. /**
  330. * @dataProvider dataTestSaveUserSettingsException
  331. *
  332. * @param array $data
  333. * @param string $oldEmailAddress
  334. * @param string $oldDisplayName
  335. * @param bool $setDisplayNameResult
  336. * @param bool $canChangeEmail
  337. *
  338. * @expectedException \OC\ForbiddenException
  339. */
  340. public function testSaveUserSettingsException($data,
  341. $oldEmailAddress,
  342. $oldDisplayName,
  343. $setDisplayNameResult,
  344. $canChangeEmail
  345. ) {
  346. $controller = $this->getController();
  347. $user = $this->createMock(IUser::class);
  348. $user->method('getDisplayName')->willReturn($oldDisplayName);
  349. $user->method('getEMailAddress')->willReturn($oldEmailAddress);
  350. if ($data[AccountManager::PROPERTY_EMAIL]['value'] !== $oldEmailAddress) {
  351. $user->method('canChangeDisplayName')
  352. ->willReturn($canChangeEmail);
  353. }
  354. if ($data[AccountManager::PROPERTY_DISPLAYNAME]['value'] !== $oldDisplayName) {
  355. $user->method('setDisplayName')
  356. ->with($data[AccountManager::PROPERTY_DISPLAYNAME]['value'])
  357. ->willReturn($setDisplayNameResult);
  358. }
  359. $this->invokePrivate($controller, 'saveUserSettings', [$user, $data]);
  360. }
  361. public function dataTestSaveUserSettingsException() {
  362. return [
  363. [
  364. [
  365. AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
  366. AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
  367. ],
  368. 'johnNew@example.com',
  369. 'john New doe',
  370. true,
  371. false
  372. ],
  373. [
  374. [
  375. AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
  376. AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
  377. ],
  378. 'johnNew@example.com',
  379. 'john New doe',
  380. false,
  381. true
  382. ],
  383. [
  384. [
  385. AccountManager::PROPERTY_EMAIL => ['value' => 'john@example.com'],
  386. AccountManager::PROPERTY_DISPLAYNAME => ['value' => 'john doe'],
  387. ],
  388. 'johnNew@example.com',
  389. 'john New doe',
  390. false,
  391. false
  392. ],
  393. ];
  394. }
  395. /**
  396. * @param string $account
  397. * @param string $type
  398. * @param array $dataBefore
  399. * @param array $expectedData
  400. *
  401. * @dataProvider dataTestGetVerificationCode
  402. */
  403. public function testGetVerificationCode($account, $type, $dataBefore, $expectedData, $onlyVerificationCode) {
  404. $message = 'Use my Federated Cloud ID to share with me: user@nextcloud.com';
  405. $signature = 'theSignature';
  406. $code = $message . ' ' . $signature;
  407. if($type === AccountManager::PROPERTY_TWITTER) {
  408. $code = $message . ' ' . md5($signature);
  409. }
  410. $controller = $this->getController(false, ['signMessage', 'getCurrentTime']);
  411. $user = $this->createMock(IUser::class);
  412. $this->userSession->expects($this->once())->method('getUser')->willReturn($user);
  413. $this->accountManager->expects($this->once())->method('getUser')->with($user)->willReturn($dataBefore);
  414. $user->expects($this->any())->method('getCloudId')->willReturn('user@nextcloud.com');
  415. $user->expects($this->any())->method('getUID')->willReturn('uid');
  416. $controller->expects($this->once())->method('signMessage')->with($user, $message)->willReturn($signature);
  417. $controller->expects($this->any())->method('getCurrentTime')->willReturn(1234567);
  418. if ($onlyVerificationCode === false) {
  419. $this->accountManager->expects($this->once())->method('updateUser')->with($user, $expectedData);
  420. $this->jobList->expects($this->once())->method('add')
  421. ->with('OC\Settings\BackgroundJobs\VerifyUserData',
  422. [
  423. 'verificationCode' => $code,
  424. 'data' => $dataBefore[$type]['value'],
  425. 'type' => $type,
  426. 'uid' => 'uid',
  427. 'try' => 0,
  428. 'lastRun' => 1234567
  429. ]);
  430. }
  431. $result = $controller->getVerificationCode($account, $onlyVerificationCode);
  432. $data = $result->getData();
  433. $this->assertSame(Http::STATUS_OK, $result->getStatus());
  434. $this->assertSame($code, $data['code']);
  435. }
  436. public function dataTestGetVerificationCode() {
  437. $accountDataBefore = [
  438. AccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::NOT_VERIFIED],
  439. AccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::NOT_VERIFIED, 'signature' => 'theSignature'],
  440. ];
  441. $accountDataAfterWebsite = [
  442. AccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::VERIFICATION_IN_PROGRESS, 'signature' => 'theSignature'],
  443. AccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::NOT_VERIFIED, 'signature' => 'theSignature'],
  444. ];
  445. $accountDataAfterTwitter = [
  446. AccountManager::PROPERTY_WEBSITE => ['value' => 'https://nextcloud.com', 'verified' => AccountManager::NOT_VERIFIED],
  447. AccountManager::PROPERTY_TWITTER => ['value' => '@nextclouders', 'verified' => AccountManager::VERIFICATION_IN_PROGRESS, 'signature' => 'theSignature'],
  448. ];
  449. return [
  450. ['verify-twitter', AccountManager::PROPERTY_TWITTER, $accountDataBefore, $accountDataAfterTwitter, false],
  451. ['verify-website', AccountManager::PROPERTY_WEBSITE, $accountDataBefore, $accountDataAfterWebsite, false],
  452. ['verify-twitter', AccountManager::PROPERTY_TWITTER, $accountDataBefore, $accountDataAfterTwitter, true],
  453. ['verify-website', AccountManager::PROPERTY_WEBSITE, $accountDataBefore, $accountDataAfterWebsite, true],
  454. ];
  455. }
  456. /**
  457. * test get verification code in case no valid user was given
  458. */
  459. public function testGetVerificationCodeInvalidUser() {
  460. $controller = $this->getController();
  461. $this->userSession->expects($this->once())->method('getUser')->willReturn(null);
  462. $result = $controller->getVerificationCode('account', false);
  463. $this->assertSame(Http::STATUS_BAD_REQUEST, $result->getStatus());
  464. }
  465. /**
  466. * @dataProvider dataTestCanAdminChangeUserPasswords
  467. *
  468. * @param bool $encryptionEnabled
  469. * @param bool $encryptionModuleLoaded
  470. * @param bool $masterKeyEnabled
  471. * @param bool $expected
  472. */
  473. public function testCanAdminChangeUserPasswords($encryptionEnabled,
  474. $encryptionModuleLoaded,
  475. $masterKeyEnabled,
  476. $expected) {
  477. $controller = $this->getController();
  478. $this->encryptionManager->expects($this->any())
  479. ->method('isEnabled')
  480. ->willReturn($encryptionEnabled);
  481. $this->encryptionManager->expects($this->any())
  482. ->method('getEncryptionModule')
  483. ->willReturnCallback(function() use ($encryptionModuleLoaded) {
  484. if ($encryptionModuleLoaded) return $this->encryptionModule;
  485. else throw new ModuleDoesNotExistsException();
  486. });
  487. $this->encryptionModule->expects($this->any())
  488. ->method('needDetailedAccessList')
  489. ->willReturn(!$masterKeyEnabled);
  490. $result = $this->invokePrivate($controller, 'canAdminChangeUserPasswords', []);
  491. $this->assertSame($expected, $result);
  492. }
  493. public function dataTestCanAdminChangeUserPasswords() {
  494. return [
  495. // encryptionEnabled, encryptionModuleLoaded, masterKeyEnabled, expectedResult
  496. [true, true, true, true],
  497. [false, true, true, true],
  498. [true, false, true, false],
  499. [false, false, true, true],
  500. [true, true, false, false],
  501. [false, true, false, false],
  502. [true, false, false, false],
  503. [false, false, false, true],
  504. ];
  505. }
  506. }