AccountManagerTest.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. <?php
  2. /**
  3. * @author Björn Schießle <schiessle@owncloud.com>
  4. *
  5. * @copyright Copyright (c) 2016, 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 Test\Accounts;
  22. use OC\Accounts\Account;
  23. use OC\Accounts\AccountManager;
  24. use OCA\Settings\BackgroundJobs\VerifyUserData;
  25. use OCP\Accounts\IAccountManager;
  26. use OCP\BackgroundJob\IJobList;
  27. use OCP\Defaults;
  28. use OCP\IConfig;
  29. use OCP\IDBConnection;
  30. use OCP\IURLGenerator;
  31. use OCP\IUser;
  32. use OCP\L10N\IFactory;
  33. use OCP\Mail\IMailer;
  34. use OCP\Security\ICrypto;
  35. use OCP\Security\VerificationToken\IVerificationToken;
  36. use PHPUnit\Framework\MockObject\MockObject;
  37. use Psr\Log\LoggerInterface;
  38. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  39. use Symfony\Component\EventDispatcher\GenericEvent;
  40. use Test\TestCase;
  41. /**
  42. * Class AccountManagerTest
  43. *
  44. * @group DB
  45. * @package Test\Accounts
  46. */
  47. class AccountManagerTest extends TestCase {
  48. /** @var IVerificationToken|MockObject */
  49. protected $verificationToken;
  50. /** @var IMailer|MockObject */
  51. protected $mailer;
  52. /** @var ICrypto|MockObject */
  53. protected $crypto;
  54. /** @var IURLGenerator|MockObject */
  55. protected $urlGenerator;
  56. /** @var Defaults|MockObject */
  57. protected $defaults;
  58. /** @var IFactory|MockObject */
  59. protected $l10nFactory;
  60. /** @var \OCP\IDBConnection */
  61. private $connection;
  62. /** @var IConfig|MockObject */
  63. private $config;
  64. /** @var EventDispatcherInterface|MockObject */
  65. private $eventDispatcher;
  66. /** @var IJobList|MockObject */
  67. private $jobList;
  68. /** @var string accounts table name */
  69. private $table = 'accounts';
  70. /** @var LoggerInterface|MockObject */
  71. private $logger;
  72. /** @var AccountManager */
  73. private $accountManager;
  74. protected function setUp(): void {
  75. parent::setUp();
  76. $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
  77. $this->connection = \OC::$server->get(IDBConnection::class);
  78. $this->config = $this->createMock(IConfig::class);
  79. $this->jobList = $this->createMock(IJobList::class);
  80. $this->logger = $this->createMock(LoggerInterface::class);
  81. $this->verificationToken = $this->createMock(IVerificationToken::class);
  82. $this->mailer = $this->createMock(IMailer::class);
  83. $this->defaults = $this->createMock(Defaults::class);
  84. $this->l10nFactory = $this->createMock(IFactory::class);
  85. $this->urlGenerator = $this->createMock(IURLGenerator::class);
  86. $this->crypto = $this->createMock(ICrypto::class);
  87. $this->accountManager = new AccountManager(
  88. $this->connection,
  89. $this->config,
  90. $this->eventDispatcher,
  91. $this->jobList,
  92. $this->logger,
  93. $this->verificationToken,
  94. $this->mailer,
  95. $this->defaults,
  96. $this->l10nFactory,
  97. $this->urlGenerator,
  98. $this->crypto
  99. );
  100. }
  101. protected function tearDown(): void {
  102. parent::tearDown();
  103. $query = $this->connection->getQueryBuilder();
  104. $query->delete($this->table)->execute();
  105. }
  106. protected function makeUser(string $uid, string $name, string $email = null): IUser {
  107. $user = $this->createMock(IUser::class);
  108. $user->expects($this->any())
  109. ->method('getUid')
  110. ->willReturn($uid);
  111. $user->expects($this->any())
  112. ->method('getDisplayName')
  113. ->willReturn($name);
  114. if ($email !== null) {
  115. $user->expects($this->any())
  116. ->method('getEMailAddress')
  117. ->willReturn($email);
  118. }
  119. return $user;
  120. }
  121. protected function populateOrUpdate(): void {
  122. $users = [
  123. [
  124. 'user' => $this->makeUser('j.doe', 'Jane Doe', 'jane.doe@acme.com'),
  125. 'data' => [
  126. [
  127. 'name' => IAccountManager::PROPERTY_DISPLAYNAME,
  128. 'value' => 'Jane Doe',
  129. 'scope' => IAccountManager::SCOPE_PUBLISHED
  130. ],
  131. [
  132. 'name' => IAccountManager::PROPERTY_EMAIL,
  133. 'value' => 'jane.doe@acme.com',
  134. 'scope' => IAccountManager::SCOPE_LOCAL
  135. ],
  136. [
  137. 'name' => IAccountManager::PROPERTY_TWITTER,
  138. 'value' => '@sometwitter',
  139. 'scope' => IAccountManager::SCOPE_PUBLISHED
  140. ],
  141. [
  142. 'name' => IAccountManager::PROPERTY_PHONE,
  143. 'value' => '+491601231212',
  144. 'scope' => IAccountManager::SCOPE_FEDERATED
  145. ],
  146. [
  147. 'name' => IAccountManager::PROPERTY_ADDRESS,
  148. 'value' => 'some street',
  149. 'scope' => IAccountManager::SCOPE_LOCAL
  150. ],
  151. [
  152. 'name' => IAccountManager::PROPERTY_WEBSITE,
  153. 'value' => 'https://acme.com',
  154. 'scope' => IAccountManager::SCOPE_PRIVATE
  155. ],
  156. [
  157. 'name' => IAccountManager::PROPERTY_ORGANISATION,
  158. 'value' => 'Some organisation',
  159. 'scope' => IAccountManager::SCOPE_LOCAL
  160. ],
  161. [
  162. 'name' => IAccountManager::PROPERTY_ROLE,
  163. 'value' => 'Human',
  164. 'scope' => IAccountManager::SCOPE_LOCAL
  165. ],
  166. [
  167. 'name' => IAccountManager::PROPERTY_HEADLINE,
  168. 'value' => 'Hi',
  169. 'scope' => IAccountManager::SCOPE_LOCAL
  170. ],
  171. [
  172. 'name' => IAccountManager::PROPERTY_BIOGRAPHY,
  173. 'value' => 'Biography',
  174. 'scope' => IAccountManager::SCOPE_LOCAL
  175. ],
  176. ],
  177. ],
  178. [
  179. 'user' => $this->makeUser('a.allison', 'Alice Allison', 'a.allison@example.org'),
  180. 'data' => [
  181. [
  182. 'name' => IAccountManager::PROPERTY_DISPLAYNAME,
  183. 'value' => 'Alice Allison',
  184. 'scope' => IAccountManager::SCOPE_LOCAL
  185. ],
  186. [
  187. 'name' => IAccountManager::PROPERTY_EMAIL,
  188. 'value' => 'a.allison@example.org',
  189. 'scope' => IAccountManager::SCOPE_LOCAL
  190. ],
  191. [
  192. 'name' => IAccountManager::PROPERTY_TWITTER,
  193. 'value' => '@a_alice',
  194. 'scope' => IAccountManager::SCOPE_FEDERATED
  195. ],
  196. [
  197. 'name' => IAccountManager::PROPERTY_PHONE,
  198. 'value' => '+491602312121',
  199. 'scope' => IAccountManager::SCOPE_LOCAL
  200. ],
  201. [
  202. 'name' => IAccountManager::PROPERTY_ADDRESS,
  203. 'value' => 'Dundee Road 45',
  204. 'scope' => IAccountManager::SCOPE_LOCAL
  205. ],
  206. [
  207. 'name' => IAccountManager::PROPERTY_WEBSITE,
  208. 'value' => 'https://example.org',
  209. 'scope' => IAccountManager::SCOPE_LOCAL
  210. ],
  211. [
  212. 'name' => IAccountManager::PROPERTY_ORGANISATION,
  213. 'value' => 'Another organisation',
  214. 'scope' => IAccountManager::SCOPE_FEDERATED
  215. ],
  216. [
  217. 'name' => IAccountManager::PROPERTY_ROLE,
  218. 'value' => 'Alien',
  219. 'scope' => IAccountManager::SCOPE_FEDERATED
  220. ],
  221. [
  222. 'name' => IAccountManager::PROPERTY_HEADLINE,
  223. 'value' => 'Hello',
  224. 'scope' => IAccountManager::SCOPE_FEDERATED
  225. ],
  226. [
  227. 'name' => IAccountManager::PROPERTY_BIOGRAPHY,
  228. 'value' => 'Different biography',
  229. 'scope' => IAccountManager::SCOPE_FEDERATED
  230. ],
  231. ],
  232. ],
  233. [
  234. 'user' => $this->makeUser('b32c5a5b-1084-4380-8856-e5223b16de9f', 'Armel Oliseh', 'oliseh@example.com'),
  235. 'data' => [
  236. [
  237. 'name' => IAccountManager::PROPERTY_DISPLAYNAME,
  238. 'value' => 'Armel Oliseh',
  239. 'scope' => IAccountManager::SCOPE_PUBLISHED
  240. ],
  241. [
  242. 'name' => IAccountManager::PROPERTY_EMAIL,
  243. 'value' => 'oliseh@example.com',
  244. 'scope' => IAccountManager::SCOPE_PUBLISHED
  245. ],
  246. [
  247. 'name' => IAccountManager::PROPERTY_TWITTER,
  248. 'value' => '',
  249. 'scope' => IAccountManager::SCOPE_LOCAL
  250. ],
  251. [
  252. 'name' => IAccountManager::PROPERTY_PHONE,
  253. 'value' => '+491603121212',
  254. 'scope' => IAccountManager::SCOPE_PUBLISHED
  255. ],
  256. [
  257. 'name' => IAccountManager::PROPERTY_ADDRESS,
  258. 'value' => 'Sunflower Blvd. 77',
  259. 'scope' => IAccountManager::SCOPE_PUBLISHED
  260. ],
  261. [
  262. 'name' => IAccountManager::PROPERTY_WEBSITE,
  263. 'value' => 'https://example.com',
  264. 'scope' => IAccountManager::SCOPE_PUBLISHED
  265. ],
  266. [
  267. 'name' => IAccountManager::PROPERTY_ORGANISATION,
  268. 'value' => 'Yet another organisation',
  269. 'scope' => IAccountManager::SCOPE_PUBLISHED
  270. ],
  271. [
  272. 'name' => IAccountManager::PROPERTY_ROLE,
  273. 'value' => 'Being',
  274. 'scope' => IAccountManager::SCOPE_PUBLISHED
  275. ],
  276. [
  277. 'name' => IAccountManager::PROPERTY_HEADLINE,
  278. 'value' => 'This is a headline',
  279. 'scope' => IAccountManager::SCOPE_PUBLISHED
  280. ],
  281. [
  282. 'name' => IAccountManager::PROPERTY_BIOGRAPHY,
  283. 'value' => 'Some long biography',
  284. 'scope' => IAccountManager::SCOPE_PUBLISHED
  285. ],
  286. ],
  287. ],
  288. [
  289. 'user' => $this->makeUser('31b5316a-9b57-4b17-970a-315a4cbe73eb', 'K. Cheng', 'cheng@emca.com'),
  290. 'data' => [
  291. [
  292. 'name' => IAccountManager::PROPERTY_DISPLAYNAME,
  293. 'value' => 'K. Cheng',
  294. 'scope' => IAccountManager::SCOPE_FEDERATED
  295. ],
  296. [
  297. 'name' => IAccountManager::PROPERTY_EMAIL,
  298. 'value' => 'cheng@emca.com',
  299. 'scope' => IAccountManager::SCOPE_FEDERATED
  300. ],
  301. [
  302. 'name' => IAccountManager::PROPERTY_TWITTER,
  303. 'value' => '', '
  304. scope' => IAccountManager::SCOPE_LOCAL
  305. ],
  306. [
  307. 'name' => IAccountManager::PROPERTY_PHONE,
  308. 'value' => '+71601212123',
  309. 'scope' => IAccountManager::SCOPE_LOCAL
  310. ],
  311. [
  312. 'name' => IAccountManager::PROPERTY_ADDRESS,
  313. 'value' => 'Pinapple Street 22',
  314. 'scope' => IAccountManager::SCOPE_LOCAL
  315. ],
  316. [
  317. 'name' => IAccountManager::PROPERTY_WEBSITE,
  318. 'value' => 'https://emca.com',
  319. 'scope' => IAccountManager::SCOPE_FEDERATED
  320. ],
  321. [
  322. 'name' => IAccountManager::PROPERTY_ORGANISATION,
  323. 'value' => 'Organisation A',
  324. 'scope' => IAccountManager::SCOPE_LOCAL
  325. ],
  326. [
  327. 'name' => IAccountManager::PROPERTY_ROLE,
  328. 'value' => 'Animal',
  329. 'scope' => IAccountManager::SCOPE_LOCAL
  330. ],
  331. [
  332. 'name' => IAccountManager::PROPERTY_HEADLINE,
  333. 'value' => 'My headline',
  334. 'scope' => IAccountManager::SCOPE_LOCAL
  335. ],
  336. [
  337. 'name' => IAccountManager::PROPERTY_BIOGRAPHY,
  338. 'value' => 'Short biography',
  339. 'scope' => IAccountManager::SCOPE_LOCAL
  340. ],
  341. [
  342. 'name' => IAccountManager::COLLECTION_EMAIL,
  343. 'value' => 'k.cheng@emca.com',
  344. 'scope' => IAccountManager::SCOPE_LOCAL
  345. ],
  346. [
  347. 'name' => IAccountManager::COLLECTION_EMAIL,
  348. 'value' => 'kai.cheng@emca.com',
  349. 'scope' => IAccountManager::SCOPE_LOCAL
  350. ],
  351. ],
  352. ],
  353. [
  354. 'user' => $this->makeUser('goodpal@elpmaxe.org', 'Goodpal, Kim', 'goodpal@elpmaxe.org'),
  355. 'data' => [
  356. [
  357. 'name' => IAccountManager::PROPERTY_DISPLAYNAME,
  358. 'value' => 'Goodpal, Kim',
  359. 'scope' => IAccountManager::SCOPE_PUBLISHED
  360. ],
  361. [
  362. 'name' => IAccountManager::PROPERTY_EMAIL,
  363. 'value' => 'goodpal@elpmaxe.org',
  364. 'scope' => IAccountManager::SCOPE_PUBLISHED
  365. ],
  366. [
  367. 'name' => IAccountManager::PROPERTY_TWITTER,
  368. 'value' => '',
  369. 'scope' => IAccountManager::SCOPE_LOCAL
  370. ],
  371. [
  372. 'name' => IAccountManager::PROPERTY_PHONE,
  373. 'value' => '+71602121231',
  374. 'scope' => IAccountManager::SCOPE_FEDERATED
  375. ],
  376. [
  377. 'name' => IAccountManager::PROPERTY_ADDRESS,
  378. 'value' => 'Octopus Ave 17',
  379. 'scope' => IAccountManager::SCOPE_FEDERATED
  380. ],
  381. [
  382. 'name' => IAccountManager::PROPERTY_WEBSITE,
  383. 'value' => 'https://elpmaxe.org',
  384. 'scope' => IAccountManager::SCOPE_PUBLISHED
  385. ],
  386. [
  387. 'name' => IAccountManager::PROPERTY_ORGANISATION,
  388. 'value' => 'Organisation B',
  389. 'scope' => IAccountManager::SCOPE_FEDERATED
  390. ],
  391. [
  392. 'name' => IAccountManager::PROPERTY_ROLE,
  393. 'value' => 'Organism',
  394. 'scope' => IAccountManager::SCOPE_FEDERATED
  395. ],
  396. [
  397. 'name' => IAccountManager::PROPERTY_HEADLINE,
  398. 'value' => 'Best headline',
  399. 'scope' => IAccountManager::SCOPE_FEDERATED
  400. ],
  401. [
  402. 'name' => IAccountManager::PROPERTY_BIOGRAPHY,
  403. 'value' => 'Autobiography',
  404. 'scope' => IAccountManager::SCOPE_FEDERATED
  405. ],
  406. ],
  407. ],
  408. ];
  409. foreach ($users as $userInfo) {
  410. $this->invokePrivate($this->accountManager, 'updateUser', [$userInfo['user'], $userInfo['data'], false]);
  411. }
  412. }
  413. /**
  414. * get a instance of the accountManager
  415. *
  416. * @param array $mockedMethods list of methods which should be mocked
  417. * @return MockObject | AccountManager
  418. */
  419. public function getInstance($mockedMethods = null) {
  420. return $this->getMockBuilder(AccountManager::class)
  421. ->setConstructorArgs([
  422. $this->connection,
  423. $this->config,
  424. $this->eventDispatcher,
  425. $this->jobList,
  426. $this->logger,
  427. $this->verificationToken,
  428. $this->mailer,
  429. $this->defaults,
  430. $this->l10nFactory,
  431. $this->urlGenerator,
  432. $this->crypto
  433. ])
  434. ->setMethods($mockedMethods)
  435. ->getMock();
  436. }
  437. /**
  438. * @dataProvider dataTrueFalse
  439. *
  440. * @param array $newData
  441. * @param array $oldData
  442. * @param bool $insertNew
  443. * @param bool $updateExisting
  444. */
  445. public function testUpdateUser($newData, $oldData, $insertNew, $updateExisting) {
  446. $accountManager = $this->getInstance(['getUser', 'insertNewUser', 'updateExistingUser']);
  447. /** @var IUser $user */
  448. $user = $this->createMock(IUser::class);
  449. // FIXME: should be an integration test instead of this abomination
  450. $accountManager->expects($this->once())->method('getUser')->with($user)->willReturn($oldData);
  451. if ($updateExisting) {
  452. $accountManager->expects($this->once())->method('updateExistingUser')
  453. ->with($user, $newData);
  454. $accountManager->expects($this->never())->method('insertNewUser');
  455. }
  456. if ($insertNew) {
  457. $accountManager->expects($this->once())->method('insertNewUser')
  458. ->with($user, $newData);
  459. $accountManager->expects($this->never())->method('updateExistingUser');
  460. }
  461. if (!$insertNew && !$updateExisting) {
  462. $accountManager->expects($this->never())->method('updateExistingUser');
  463. $accountManager->expects($this->never())->method('insertNewUser');
  464. $this->eventDispatcher->expects($this->never())->method('dispatch');
  465. } else {
  466. $this->eventDispatcher->expects($this->once())->method('dispatch')
  467. ->willReturnCallback(
  468. function ($eventName, $event) use ($user, $newData) {
  469. $this->assertSame('OC\AccountManager::userUpdated', $eventName);
  470. $this->assertInstanceOf(GenericEvent::class, $event);
  471. /** @var GenericEvent $event */
  472. $this->assertSame($user, $event->getSubject());
  473. $this->assertSame($newData, $event->getArguments());
  474. }
  475. );
  476. }
  477. $this->invokePrivate($accountManager, 'updateUser', [$user, $newData]);
  478. }
  479. public function dataTrueFalse() {
  480. return [
  481. #$newData | $oldData | $insertNew | $updateExisting
  482. [['myProperty' => ['value' => 'newData']], ['myProperty' => ['value' => 'oldData']], false, true],
  483. [['myProperty' => ['value' => 'oldData']], ['myProperty' => ['value' => 'oldData']], false, false]
  484. ];
  485. }
  486. public function testAddMissingDefaults() {
  487. $user = $this->createMock(IUser::class);
  488. $this->config
  489. ->expects($this->once())
  490. ->method('getAppValue')
  491. ->with('settings', 'profile_enabled_by_default', '1')
  492. ->willReturn('1');
  493. $input = [
  494. [
  495. 'name' => IAccountManager::PROPERTY_DISPLAYNAME,
  496. 'value' => 'bob',
  497. 'verified' => IAccountManager::NOT_VERIFIED,
  498. ],
  499. [
  500. 'name' => IAccountManager::PROPERTY_EMAIL,
  501. 'value' => 'bob@bob.bob',
  502. ],
  503. ];
  504. $expected = [
  505. [
  506. 'name' => IAccountManager::PROPERTY_DISPLAYNAME,
  507. 'value' => 'bob',
  508. 'scope' => IAccountManager::SCOPE_FEDERATED,
  509. 'verified' => IAccountManager::NOT_VERIFIED,
  510. ],
  511. [
  512. 'name' => IAccountManager::PROPERTY_EMAIL,
  513. 'value' => 'bob@bob.bob',
  514. 'scope' => IAccountManager::SCOPE_FEDERATED,
  515. 'verified' => IAccountManager::NOT_VERIFIED,
  516. ],
  517. [
  518. 'name' => IAccountManager::PROPERTY_ADDRESS,
  519. 'value' => '',
  520. 'scope' => IAccountManager::SCOPE_LOCAL,
  521. 'verified' => IAccountManager::NOT_VERIFIED,
  522. ],
  523. [
  524. 'name' => IAccountManager::PROPERTY_WEBSITE,
  525. 'value' => '',
  526. 'scope' => IAccountManager::SCOPE_LOCAL,
  527. 'verified' => IAccountManager::NOT_VERIFIED,
  528. ],
  529. [
  530. 'name' => IAccountManager::PROPERTY_AVATAR,
  531. 'scope' => IAccountManager::SCOPE_FEDERATED
  532. ],
  533. [
  534. 'name' => IAccountManager::PROPERTY_PHONE,
  535. 'value' => '',
  536. 'scope' => IAccountManager::SCOPE_LOCAL,
  537. 'verified' => IAccountManager::NOT_VERIFIED,
  538. ],
  539. [
  540. 'name' => IAccountManager::PROPERTY_TWITTER,
  541. 'value' => '',
  542. 'scope' => IAccountManager::SCOPE_LOCAL,
  543. 'verified' => IAccountManager::NOT_VERIFIED,
  544. ],
  545. [
  546. 'name' => IAccountManager::PROPERTY_ORGANISATION,
  547. 'value' => '',
  548. 'scope' => IAccountManager::SCOPE_LOCAL,
  549. ],
  550. [
  551. 'name' => IAccountManager::PROPERTY_ROLE,
  552. 'value' => '',
  553. 'scope' => IAccountManager::SCOPE_LOCAL,
  554. ],
  555. [
  556. 'name' => IAccountManager::PROPERTY_HEADLINE,
  557. 'value' => '',
  558. 'scope' => IAccountManager::SCOPE_LOCAL,
  559. ],
  560. [
  561. 'name' => IAccountManager::PROPERTY_BIOGRAPHY,
  562. 'value' => '',
  563. 'scope' => IAccountManager::SCOPE_LOCAL,
  564. ],
  565. [
  566. 'name' => IAccountManager::PROPERTY_PROFILE_ENABLED,
  567. 'value' => '1',
  568. ],
  569. ];
  570. $defaultUserRecord = $this->invokePrivate($this->accountManager, 'buildDefaultUserRecord', [$user]);
  571. $result = $this->invokePrivate($this->accountManager, 'addMissingDefaultValues', [$input, $defaultUserRecord]);
  572. $this->assertSame($expected, $result);
  573. }
  574. private function addDummyValuesToTable($uid, $data) {
  575. $query = $this->connection->getQueryBuilder();
  576. $query->insert($this->table)
  577. ->values(
  578. [
  579. 'uid' => $query->createNamedParameter($uid),
  580. 'data' => $query->createNamedParameter(json_encode($data)),
  581. ]
  582. )
  583. ->execute();
  584. }
  585. public function testGetAccount() {
  586. $accountManager = $this->getInstance(['getUser']);
  587. /** @var IUser $user */
  588. $user = $this->createMock(IUser::class);
  589. $data = [
  590. [
  591. 'value' => '@twitterhandle',
  592. 'scope' => IAccountManager::SCOPE_LOCAL,
  593. 'verified' => IAccountManager::NOT_VERIFIED,
  594. 'name' => IAccountManager::PROPERTY_TWITTER,
  595. ],
  596. [
  597. 'value' => 'test@example.com',
  598. 'scope' => IAccountManager::SCOPE_PUBLISHED,
  599. 'verified' => IAccountManager::VERIFICATION_IN_PROGRESS,
  600. 'name' => IAccountManager::PROPERTY_EMAIL,
  601. ],
  602. [
  603. 'value' => 'https://example.com',
  604. 'scope' => IAccountManager::SCOPE_FEDERATED,
  605. 'verified' => IAccountManager::VERIFIED,
  606. 'name' => IAccountManager::PROPERTY_WEBSITE,
  607. ],
  608. ];
  609. $expected = new Account($user);
  610. $expected->setProperty(IAccountManager::PROPERTY_TWITTER, '@twitterhandle', IAccountManager::SCOPE_LOCAL, IAccountManager::NOT_VERIFIED);
  611. $expected->setProperty(IAccountManager::PROPERTY_EMAIL, 'test@example.com', IAccountManager::SCOPE_PUBLISHED, IAccountManager::VERIFICATION_IN_PROGRESS);
  612. $expected->setProperty(IAccountManager::PROPERTY_WEBSITE, 'https://example.com', IAccountManager::SCOPE_FEDERATED, IAccountManager::VERIFIED);
  613. $accountManager->expects($this->once())
  614. ->method('getUser')
  615. ->willReturn($data);
  616. $this->assertEquals($expected, $accountManager->getAccount($user));
  617. }
  618. public function dataParsePhoneNumber(): array {
  619. return [
  620. ['0711 / 25 24 28-90', 'DE', '+4971125242890'],
  621. ['0711 / 25 24 28-90', '', null],
  622. ['+49 711 / 25 24 28-90', '', '+4971125242890'],
  623. ];
  624. }
  625. /**
  626. * @dataProvider dataParsePhoneNumber
  627. * @param string $phoneInput
  628. * @param string $defaultRegion
  629. * @param string|null $phoneNumber
  630. */
  631. public function testParsePhoneNumber(string $phoneInput, string $defaultRegion, ?string $phoneNumber): void {
  632. $this->config->method('getSystemValueString')
  633. ->willReturn($defaultRegion);
  634. if ($phoneNumber === null) {
  635. $this->expectException(\InvalidArgumentException::class);
  636. self::invokePrivate($this->accountManager, 'parsePhoneNumber', [$phoneInput]);
  637. } else {
  638. self::assertEquals($phoneNumber, self::invokePrivate($this->accountManager, 'parsePhoneNumber', [$phoneInput]));
  639. }
  640. }
  641. public function dataParseWebsite(): array {
  642. return [
  643. ['https://nextcloud.com', 'https://nextcloud.com'],
  644. ['http://nextcloud.com', 'http://nextcloud.com'],
  645. ['ftp://nextcloud.com', null],
  646. ['//nextcloud.com/', null],
  647. ['https:///?query', null],
  648. ];
  649. }
  650. /**
  651. * @dataProvider dataParseWebsite
  652. * @param string $websiteInput
  653. * @param string|null $websiteOutput
  654. */
  655. public function testParseWebsite(string $websiteInput, ?string $websiteOutput): void {
  656. if ($websiteOutput === null) {
  657. $this->expectException(\InvalidArgumentException::class);
  658. self::invokePrivate($this->accountManager, 'parseWebsite', [$websiteInput]);
  659. } else {
  660. self::assertEquals($websiteOutput, self::invokePrivate($this->accountManager, 'parseWebsite', [$websiteInput]));
  661. }
  662. }
  663. /**
  664. * @dataProvider searchDataProvider
  665. */
  666. public function testSearchUsers(string $property, array $values, array $expected): void {
  667. $this->populateOrUpdate();
  668. $matchedUsers = $this->accountManager->searchUsers($property, $values);
  669. foreach ($expected as $expectedEntry) {
  670. $this->assertContains($expectedEntry, $matchedUsers);
  671. }
  672. if (empty($expected)) {
  673. $this->assertEmpty($matchedUsers);
  674. }
  675. }
  676. public function searchDataProvider(): array {
  677. return [
  678. [ #0 Search for an existing name
  679. IAccountManager::PROPERTY_DISPLAYNAME,
  680. ['Jane Doe'],
  681. ['Jane Doe' => 'j.doe']
  682. ],
  683. [ #1 Search for part of a name (no result)
  684. IAccountManager::PROPERTY_DISPLAYNAME,
  685. ['Jane'],
  686. []
  687. ],
  688. [ #2 Search for part of a name (no result, test wildcard)
  689. IAccountManager::PROPERTY_DISPLAYNAME,
  690. ['Jane%'],
  691. []
  692. ],
  693. [ #3 Search for phone
  694. IAccountManager::PROPERTY_PHONE,
  695. ['+491603121212'],
  696. ['+491603121212' => 'b32c5a5b-1084-4380-8856-e5223b16de9f'],
  697. ],
  698. [ #4 Search for twitter handles
  699. IAccountManager::PROPERTY_TWITTER,
  700. ['@sometwitter', '@a_alice', '@unseen'],
  701. ['@sometwitter' => 'j.doe', '@a_alice' => 'a.allison'],
  702. ],
  703. [ #5 Search for email
  704. IAccountManager::PROPERTY_EMAIL,
  705. ['cheng@emca.com'],
  706. ['cheng@emca.com' => '31b5316a-9b57-4b17-970a-315a4cbe73eb'],
  707. ],
  708. [ #6 Search for email by additional email
  709. IAccountManager::PROPERTY_EMAIL,
  710. ['kai.cheng@emca.com'],
  711. ['kai.cheng@emca.com' => '31b5316a-9b57-4b17-970a-315a4cbe73eb'],
  712. ],
  713. [ #7 Search for additional email
  714. IAccountManager::COLLECTION_EMAIL,
  715. ['kai.cheng@emca.com', 'cheng@emca.com'],
  716. ['kai.cheng@emca.com' => '31b5316a-9b57-4b17-970a-315a4cbe73eb'],
  717. ],
  718. [ #8 Search for email by additional email (two valid search values, but the same user)
  719. IAccountManager::PROPERTY_EMAIL,
  720. ['kai.cheng@emca.com', 'cheng@emca.com'],
  721. [
  722. 'kai.cheng@emca.com' => '31b5316a-9b57-4b17-970a-315a4cbe73eb',
  723. ],
  724. ],
  725. ];
  726. }
  727. public function dataCheckEmailVerification(): array {
  728. return [
  729. [$this->makeUser('steve', 'Steve Smith', 'steve@steve.steve'), null],
  730. [$this->makeUser('emma', 'Emma Morales', 'emma@emma.com'), 'emma@morales.com'],
  731. [$this->makeUser('sarah@web.org', 'Sarah Foster', 'sarah@web.org'), null],
  732. [$this->makeUser('cole@web.org', 'Cole Harrison', 'cole@web.org'), 'cole@example.com'],
  733. [$this->makeUser('8d29e358-cf69-4849-bbf9-28076c0b908b', 'Alice McPherson', 'alice@example.com'), 'alice@mcpherson.com'],
  734. [$this->makeUser('11da2744-3f4d-4c17-8c13-4c057a379237', 'James Loranger', 'james@example.com'), ''],
  735. ];
  736. }
  737. /**
  738. * @dataProvider dataCheckEmailVerification
  739. */
  740. public function testCheckEmailVerification(IUser $user, ?string $newEmail): void {
  741. $account = $this->accountManager->getAccount($user);
  742. $emailUpdated = false;
  743. if (!empty($newEmail)) {
  744. $account->getProperty(IAccountManager::PROPERTY_EMAIL)->setValue($newEmail);
  745. $emailUpdated = true;
  746. }
  747. if ($emailUpdated) {
  748. $this->jobList->expects($this->once())
  749. ->method('add')
  750. ->with(VerifyUserData::class);
  751. } else {
  752. $this->jobList->expects($this->never())
  753. ->method('add')
  754. ->with(VerifyUserData::class);
  755. }
  756. /** @var array $oldData */
  757. $oldData = $this->invokePrivate($this->accountManager, 'getUser', [$user, false]);
  758. $this->invokePrivate($this->accountManager, 'checkEmailVerification', [$account, $oldData]);
  759. }
  760. }