User_LDAPTest.php 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. * @author Joas Schilling <coding@schilljs.com>
  8. * @author Jörn Friedrich Dreyer <jfd@butonic.de>
  9. * @author Lukas Reschke <lukas@statuscode.ch>
  10. * @author Morris Jobke <hey@morrisjobke.de>
  11. * @author Robin McCorkell <robin@mccorkell.me.uk>
  12. * @author Roeland Jago Douma <roeland@famdouma.nl>
  13. * @author Roger Szabo <roger.szabo@web.de>
  14. * @author Thomas Müller <thomas.mueller@tmit.eu>
  15. * @author Vinicius Cubas Brand <vinicius@eita.org.br>
  16. *
  17. * @license AGPL-3.0
  18. *
  19. * This code is free software: you can redistribute it and/or modify
  20. * it under the terms of the GNU Affero General Public License, version 3,
  21. * as published by the Free Software Foundation.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU Affero General Public License for more details.
  27. *
  28. * You should have received a copy of the GNU Affero General Public License, version 3,
  29. * along with this program. If not, see <http://www.gnu.org/licenses/>
  30. *
  31. */
  32. namespace OCA\User_LDAP\Tests;
  33. use OC\User\Backend;
  34. use OCA\User_LDAP\Access;
  35. use OCA\User_LDAP\Connection;
  36. use OCA\User_LDAP\Mapping\AbstractMapping;
  37. use OCA\User_LDAP\Mapping\UserMapping;
  38. use OCA\User_LDAP\User\DeletedUsersIndex;
  39. use OCA\User_LDAP\User\Manager;
  40. use OCA\User_LDAP\User\OfflineUser;
  41. use OCA\User_LDAP\User\User;
  42. use OCA\User_LDAP\User_LDAP;
  43. use OCA\User_LDAP\User_LDAP as UserLDAP;
  44. use OCA\User_LDAP\UserPluginManager;
  45. use OCP\HintException;
  46. use OCP\IUser;
  47. use OCP\Notification\IManager as INotificationManager;
  48. use PHPUnit\Framework\MockObject\MockObject;
  49. use Psr\Log\LoggerInterface;
  50. use Test\TestCase;
  51. /**
  52. * Class Test_User_Ldap_Direct
  53. *
  54. * @group DB
  55. *
  56. * @package OCA\User_LDAP\Tests
  57. */
  58. class User_LDAPTest extends TestCase {
  59. /** @var User_LDAP */
  60. protected $backend;
  61. /** @var Access|MockObject */
  62. protected $access;
  63. /** @var OfflineUser|MockObject */
  64. protected $offlineUser;
  65. /** @var INotificationManager|MockObject */
  66. protected $notificationManager;
  67. /** @var UserPluginManager|MockObject */
  68. protected $pluginManager;
  69. /** @var Connection|MockObject */
  70. protected $connection;
  71. /** @var Manager|MockObject */
  72. protected $userManager;
  73. /** @var LoggerInterface|MockObject */
  74. protected $logger;
  75. /** @var DeletedUsersIndex|MockObject */
  76. protected $deletedUsersIndex;
  77. protected function setUp(): void {
  78. parent::setUp();
  79. \OC_User::clearBackends();
  80. \OC::$server->getGroupManager()->clearBackends();
  81. $this->connection = $this->createMock(Connection::class);
  82. $this->userManager = $this->createMock(Manager::class);
  83. $this->access = $this->createMock(Access::class);
  84. $this->access->connection = $this->connection;
  85. $this->access->userManager = $this->userManager;
  86. $this->notificationManager = $this->createMock(INotificationManager::class);
  87. $this->pluginManager = $this->createMock(UserPluginManager::class);
  88. $this->logger = $this->createMock(LoggerInterface::class);
  89. $this->deletedUsersIndex = $this->createMock(DeletedUsersIndex::class);
  90. $this->backend = new User_LDAP(
  91. $this->access,
  92. $this->notificationManager,
  93. $this->pluginManager,
  94. $this->logger,
  95. $this->deletedUsersIndex,
  96. );
  97. }
  98. private function prepareMockForUserExists() {
  99. $this->access->expects($this->any())
  100. ->method('username2dn')
  101. ->willReturnCallback(function ($uid) {
  102. switch ($uid) {
  103. case 'gunslinger':
  104. return 'dnOfRoland,dc=test';
  105. break;
  106. case 'formerUser':
  107. return 'dnOfFormerUser,dc=test';
  108. break;
  109. case 'newyorker':
  110. return 'dnOfNewYorker,dc=test';
  111. break;
  112. case 'ladyofshadows':
  113. return 'dnOfLadyOfShadows,dc=test';
  114. break;
  115. default:
  116. return false;
  117. }
  118. });
  119. $this->access->method('fetchUsersByLoginName')
  120. ->willReturn([]);
  121. }
  122. /**
  123. * Prepares the Access mock for checkPassword tests
  124. * @param bool $noDisplayName
  125. * @return void
  126. */
  127. private function prepareAccessForCheckPassword($noDisplayName = false) {
  128. $this->connection->expects($this->any())
  129. ->method('__get')
  130. ->willReturnCallback(function ($name) {
  131. if ($name === 'ldapLoginFilter') {
  132. return '%uid';
  133. }
  134. return null;
  135. });
  136. $this->access->expects($this->any())
  137. ->method('fetchListOfUsers')
  138. ->willReturnCallback(function ($filter) {
  139. if ($filter === 'roland') {
  140. return [['dn' => ['dnOfRoland,dc=test']]];
  141. }
  142. return [];
  143. });
  144. $this->access->expects($this->any())
  145. ->method('fetchUsersByLoginName')
  146. ->willReturnCallback(function ($uid) {
  147. if ($uid === 'roland') {
  148. return [['dn' => ['dnOfRoland,dc=test']]];
  149. }
  150. return [];
  151. });
  152. $retVal = 'gunslinger';
  153. if ($noDisplayName === true) {
  154. $retVal = false;
  155. }
  156. $this->access->expects($this->any())
  157. ->method('dn2username')
  158. ->with($this->equalTo('dnOfRoland,dc=test'))
  159. ->willReturn($retVal);
  160. $this->access->expects($this->any())
  161. ->method('stringResemblesDN')
  162. ->with($this->equalTo('dnOfRoland,dc=test'))
  163. ->willReturn(true);
  164. $this->access->expects($this->any())
  165. ->method('areCredentialsValid')
  166. ->willReturnCallback(function ($dn, $pwd) {
  167. if ($pwd === 'dt19') {
  168. return true;
  169. }
  170. return false;
  171. });
  172. $this->userManager->expects($this->any())
  173. ->method('getAttributes')
  174. ->willReturn(['dn', 'uid', 'mail', 'displayname']);
  175. }
  176. public function testCheckPasswordUidReturn() {
  177. $user = $this->createMock(User::class);
  178. $user->expects($this->any())
  179. ->method('getUsername')
  180. ->willReturn('gunslinger');
  181. $this->prepareAccessForCheckPassword();
  182. $this->userManager->expects($this->any())
  183. ->method('get')
  184. ->willReturn($user);
  185. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  186. \OC_User::useBackend($backend);
  187. $result = $backend->checkPassword('roland', 'dt19');
  188. $this->assertEquals('gunslinger', $result);
  189. }
  190. public function testCheckPasswordWrongPassword() {
  191. $this->prepareAccessForCheckPassword();
  192. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  193. \OC_User::useBackend($backend);
  194. $result = $backend->checkPassword('roland', 'wrong');
  195. $this->assertFalse($result);
  196. }
  197. public function testCheckPasswordWrongUser() {
  198. $this->prepareAccessForCheckPassword();
  199. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  200. \OC_User::useBackend($backend);
  201. $result = $backend->checkPassword('mallory', 'evil');
  202. $this->assertFalse($result);
  203. }
  204. public function testCheckPasswordNoDisplayName() {
  205. $this->prepareAccessForCheckPassword(true);
  206. $this->prepareAccessForCheckPassword();
  207. $this->userManager->expects($this->atLeastOnce())
  208. ->method('get')
  209. ->willReturn(null);
  210. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  211. \OC_User::useBackend($backend);
  212. $result = $backend->checkPassword('roland', 'dt19');
  213. $this->assertFalse($result);
  214. }
  215. public function testCheckPasswordPublicAPI() {
  216. $user = $this->createMock(User::class);
  217. $user->expects($this->any())
  218. ->method('getUsername')
  219. ->willReturn('gunslinger');
  220. $this->prepareAccessForCheckPassword();
  221. $this->userManager->expects($this->any())
  222. ->method('get')
  223. ->willReturn($user);
  224. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  225. \OC_User::useBackend($backend);
  226. $user = \OC::$server->getUserManager()->checkPassword('roland', 'dt19');
  227. $result = false;
  228. if ($user !== false) {
  229. $result = $user->getUID();
  230. }
  231. $this->assertEquals('gunslinger', $result);
  232. }
  233. public function testCheckPasswordPublicAPIWrongPassword() {
  234. $this->prepareAccessForCheckPassword();
  235. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  236. \OC_User::useBackend($backend);
  237. $user = \OC::$server->getUserManager()->checkPassword('roland', 'wrong');
  238. $result = false;
  239. if ($user !== false) {
  240. $result = $user->getUID();
  241. }
  242. $this->assertFalse($result);
  243. }
  244. public function testCheckPasswordPublicAPIWrongUser() {
  245. $this->prepareAccessForCheckPassword();
  246. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  247. \OC_User::useBackend($backend);
  248. $user = \OC::$server->getUserManager()->checkPassword('mallory', 'evil');
  249. $result = false;
  250. if ($user !== false) {
  251. $result = $user->getUID();
  252. }
  253. $this->assertFalse($result);
  254. }
  255. public function testDeleteUserCancel() {
  256. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  257. $result = $backend->deleteUser('notme');
  258. $this->assertFalse($result);
  259. }
  260. public function testDeleteUserSuccess() {
  261. $uid = 'jeremy';
  262. $home = '/var/vhome/jdings/';
  263. $mapping = $this->createMock(UserMapping::class);
  264. $mapping->expects($this->once())
  265. ->method('unmap')
  266. ->willReturn(true);
  267. $this->access->expects($this->once())
  268. ->method('getUserMapper')
  269. ->willReturn($mapping);
  270. $this->connection->expects($this->any())
  271. ->method('getConnectionResource')
  272. ->willReturn('this is an ldap link');
  273. $this->deletedUsersIndex->expects($this->once())
  274. ->method('isUserMarked')
  275. ->with($uid)
  276. ->willReturn(true);
  277. $offlineUser = $this->createMock(OfflineUser::class);
  278. $offlineUser->expects($this->once())
  279. ->method('getHomePath')
  280. ->willReturn($home);
  281. $this->userManager->expects($this->atLeastOnce())
  282. ->method('get')
  283. ->willReturn($offlineUser);
  284. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  285. $result = $backend->deleteUser($uid);
  286. $this->assertTrue($result);
  287. /** @noinspection PhpUnhandledExceptionInspection */
  288. $this->assertSame($backend->getHome($uid), $home);
  289. }
  290. public function testDeleteUserWithPlugin() {
  291. $this->pluginManager->expects($this->once())
  292. ->method('canDeleteUser')
  293. ->willReturn(true);
  294. $this->pluginManager->expects($this->once())
  295. ->method('deleteUser')
  296. ->with('uid')
  297. ->willReturn(true);
  298. $this->deletedUsersIndex->expects($this->once())
  299. ->method('isUserMarked')
  300. ->with('uid')
  301. ->willReturn(true);
  302. $mapper = $this->createMock(UserMapping::class);
  303. $mapper->expects($this->once())
  304. ->method('unmap')
  305. ->with('uid');
  306. $this->access->expects($this->atLeastOnce())
  307. ->method('getUserMapper')
  308. ->willReturn($mapper);
  309. $this->userManager->expects($this->once())
  310. ->method('invalidate')
  311. ->with('uid');
  312. $this->assertEquals(true, $this->backend->deleteUser('uid'));
  313. }
  314. /**
  315. * Prepares the Access mock for getUsers tests
  316. */
  317. private function prepareAccessForGetUsers() {
  318. $this->access->expects($this->once())
  319. ->method('escapeFilterPart')
  320. ->willReturnCallback(function ($search) {
  321. return $search;
  322. });
  323. $this->access->expects($this->any())
  324. ->method('getFilterPartForUserSearch')
  325. ->willReturnCallback(function ($search) {
  326. return $search;
  327. });
  328. $this->access->expects($this->any())
  329. ->method('combineFilterWithAnd')
  330. ->willReturnCallback(function ($param) {
  331. return $param[2];
  332. });
  333. $this->access->expects($this->any())
  334. ->method('fetchListOfUsers')
  335. ->willReturnCallback(function ($search, $a, $l, $o) {
  336. $users = ['gunslinger', 'newyorker', 'ladyofshadows'];
  337. if (empty($search)) {
  338. $result = $users;
  339. } else {
  340. $result = [];
  341. foreach ($users as $user) {
  342. if (stripos($user, $search) !== false) {
  343. $result[] = $user;
  344. }
  345. }
  346. }
  347. if (!is_null($l) || !is_null($o)) {
  348. $result = array_slice($result, $o, $l);
  349. }
  350. return $result;
  351. });
  352. $this->access->expects($this->any())
  353. ->method('nextcloudUserNames')
  354. ->willReturnArgument(0);
  355. $this->access->method('fetchUsersByLoginName')
  356. ->willReturn([]);
  357. $this->access->userManager->expects($this->any())
  358. ->method('getAttributes')
  359. ->willReturn(['dn', 'uid', 'mail', 'displayname']);
  360. }
  361. public function testGetUsersNoParam() {
  362. $this->prepareAccessForGetUsers();
  363. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  364. $result = $backend->getUsers();
  365. $this->assertEquals(3, count($result));
  366. }
  367. public function testGetUsersLimitOffset() {
  368. $this->prepareAccessForGetUsers();
  369. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  370. $result = $backend->getUsers('', 1, 2);
  371. $this->assertEquals(1, count($result));
  372. }
  373. public function testGetUsersLimitOffset2() {
  374. $this->prepareAccessForGetUsers();
  375. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  376. $result = $backend->getUsers('', 2, 1);
  377. $this->assertEquals(2, count($result));
  378. }
  379. public function testGetUsersSearchWithResult() {
  380. $this->prepareAccessForGetUsers();
  381. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  382. $result = $backend->getUsers('yo');
  383. $this->assertEquals(2, count($result));
  384. }
  385. public function testGetUsersSearchEmptyResult() {
  386. $this->prepareAccessForGetUsers();
  387. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  388. $result = $backend->getUsers('nix');
  389. $this->assertEquals(0, count($result));
  390. }
  391. private function getUsers($search = '', $limit = null, $offset = null) {
  392. $users = \OC::$server->getUserManager()->search($search, $limit, $offset);
  393. $uids = array_map(function (IUser $user) {
  394. return $user->getUID();
  395. }, $users);
  396. return $uids;
  397. }
  398. public function testGetUsersViaAPINoParam() {
  399. $this->prepareAccessForGetUsers();
  400. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  401. \OC_User::useBackend($backend);
  402. $result = $this->getUsers();
  403. $this->assertEquals(3, count($result));
  404. }
  405. public function testGetUsersViaAPILimitOffset() {
  406. $this->prepareAccessForGetUsers();
  407. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  408. \OC_User::useBackend($backend);
  409. $result = $this->getUsers('', 1, 2);
  410. $this->assertEquals(1, count($result));
  411. }
  412. public function testGetUsersViaAPILimitOffset2() {
  413. $this->prepareAccessForGetUsers();
  414. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  415. \OC_User::useBackend($backend);
  416. $result = $this->getUsers('', 2, 1);
  417. $this->assertEquals(2, count($result));
  418. }
  419. public function testGetUsersViaAPISearchWithResult() {
  420. $this->prepareAccessForGetUsers();
  421. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  422. \OC_User::useBackend($backend);
  423. $result = $this->getUsers('yo');
  424. $this->assertEquals(2, count($result));
  425. }
  426. public function testGetUsersViaAPISearchEmptyResult() {
  427. $this->prepareAccessForGetUsers();
  428. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  429. \OC_User::useBackend($backend);
  430. $result = $this->getUsers('nix');
  431. $this->assertEquals(0, count($result));
  432. }
  433. public function testUserExists() {
  434. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  435. $this->prepareMockForUserExists();
  436. $user = $this->createMock(User::class);
  437. $this->userManager->expects($this->atLeastOnce())
  438. ->method('get')
  439. ->willReturn($user);
  440. $this->access->expects($this->any())
  441. ->method('getUserMapper')
  442. ->willReturn($this->createMock(UserMapping::class));
  443. //test for existing user
  444. /** @noinspection PhpUnhandledExceptionInspection */
  445. $result = $backend->userExists('gunslinger');
  446. $this->assertTrue($result);
  447. }
  448. public function testUserExistsForDeleted() {
  449. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  450. $this->prepareMockForUserExists();
  451. $mapper = $this->createMock(UserMapping::class);
  452. $mapper->expects($this->any())
  453. ->method('getUUIDByDN')
  454. ->with('dnOfFormerUser,dc=test')
  455. ->willReturn('45673458748');
  456. $this->access->expects($this->any())
  457. ->method('getUserMapper')
  458. ->willReturn($mapper);
  459. $user = $this->createMock(User::class);
  460. $this->userManager->expects($this->atLeastOnce())
  461. ->method('get')
  462. ->willReturn($user);
  463. //test for deleted user – always returns true as long as we have the user in DB
  464. $this->assertTrue($backend->userExists('formerUser'));
  465. }
  466. public function testUserExistsForNeverExisting() {
  467. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  468. $this->prepareMockForUserExists();
  469. $this->access->expects($this->any())
  470. ->method('readAttribute')
  471. ->willReturnCallback(function ($dn) {
  472. if ($dn === 'dnOfRoland,dc=test') {
  473. return [];
  474. }
  475. return false;
  476. });
  477. //test for never-existing user
  478. /** @noinspection PhpUnhandledExceptionInspection */
  479. $result = $backend->userExists('mallory');
  480. $this->assertFalse($result);
  481. }
  482. public function testUserExistsPublicAPI() {
  483. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  484. $this->prepareMockForUserExists();
  485. \OC_User::useBackend($backend);
  486. $user = $this->createMock(User::class);
  487. $user->expects($this->any())
  488. ->method('getDN')
  489. ->willReturn('dnOfRoland,dc=test');
  490. $this->access->expects($this->any())
  491. ->method('readAttribute')
  492. ->willReturnCallback(function ($dn) {
  493. if ($dn === 'dnOfRoland,dc=test') {
  494. return [];
  495. }
  496. return false;
  497. });
  498. $this->userManager->expects($this->atLeastOnce())
  499. ->method('get')
  500. ->willReturn($user);
  501. $this->access->expects($this->any())
  502. ->method('getUserMapper')
  503. ->willReturn($this->createMock(UserMapping::class));
  504. //test for existing user
  505. $result = \OC::$server->getUserManager()->userExists('gunslinger');
  506. $this->assertTrue($result);
  507. }
  508. public function testDeleteUserExisting() {
  509. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  510. //we do not support deleting existing users at all
  511. $result = $backend->deleteUser('gunslinger');
  512. $this->assertFalse($result);
  513. }
  514. public function testGetHomeAbsolutePath() {
  515. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  516. $this->prepareMockForUserExists();
  517. $this->connection->expects($this->any())
  518. ->method('__get')
  519. ->willReturnCallback(function ($name) {
  520. if ($name === 'homeFolderNamingRule') {
  521. return 'attr:testAttribute';
  522. }
  523. return null;
  524. });
  525. $this->access->expects($this->any())
  526. ->method('readAttribute')
  527. ->willReturnCallback(function ($dn, $attr) {
  528. switch ($dn) {
  529. case 'dnOfRoland,dc=test':
  530. if ($attr === 'testAttribute') {
  531. return ['/tmp/rolandshome/'];
  532. }
  533. return [];
  534. break;
  535. default:
  536. return false;
  537. }
  538. });
  539. $user = $this->createMock(User::class);
  540. $user->expects($this->any())
  541. ->method('getUsername')
  542. ->willReturn('gunslinger');
  543. $user->expects($this->any())
  544. ->method('getDN')
  545. ->willReturn('dnOfRoland,dc=test');
  546. $user->expects($this->any())
  547. ->method('getHomePath')
  548. ->willReturn('/tmp/rolandshome/');
  549. $this->userManager->expects($this->atLeastOnce())
  550. ->method('get')
  551. ->willReturn($user);
  552. //absolute path
  553. /** @noinspection PhpUnhandledExceptionInspection */
  554. $result = $backend->getHome('gunslinger');
  555. $this->assertEquals('/tmp/rolandshome/', $result);
  556. }
  557. public function testGetHomeRelative() {
  558. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  559. $this->prepareMockForUserExists();
  560. $dataDir = \OC::$server->getConfig()->getSystemValue(
  561. 'datadirectory', \OC::$SERVERROOT.'/data');
  562. $this->connection->expects($this->any())
  563. ->method('__get')
  564. ->willReturnCallback(function ($name) {
  565. if ($name === 'homeFolderNamingRule') {
  566. return 'attr:testAttribute';
  567. }
  568. return null;
  569. });
  570. $this->access->expects($this->any())
  571. ->method('readAttribute')
  572. ->willReturnCallback(function ($dn, $attr) {
  573. switch ($dn) {
  574. case 'dnOfLadyOfShadows,dc=test':
  575. if ($attr === 'testAttribute') {
  576. return ['susannah/'];
  577. }
  578. return [];
  579. break;
  580. default:
  581. return false;
  582. }
  583. });
  584. $user = $this->createMock(User::class);
  585. $user->expects($this->any())
  586. ->method('getUsername')
  587. ->willReturn('ladyofshadows');
  588. $user->expects($this->any())
  589. ->method('getDN')
  590. ->willReturn('dnOfLadyOfShadows,dc=test');
  591. $user->expects($this->any())
  592. ->method('getHomePath')
  593. ->willReturn($dataDir.'/susannah/');
  594. $this->userManager->expects($this->atLeastOnce())
  595. ->method('get')
  596. ->willReturn($user);
  597. /** @noinspection PhpUnhandledExceptionInspection */
  598. $result = $backend->getHome('ladyofshadows');
  599. $this->assertEquals($dataDir.'/susannah/', $result);
  600. }
  601. public function testGetHomeNoPath() {
  602. $this->expectException(\Exception::class);
  603. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  604. $this->prepareMockForUserExists();
  605. $this->connection->expects($this->any())
  606. ->method('__get')
  607. ->willReturnCallback(function ($name) {
  608. if ($name === 'homeFolderNamingRule') {
  609. return 'attr:testAttribute';
  610. }
  611. return null;
  612. });
  613. $this->access->expects($this->any())
  614. ->method('readAttribute')
  615. ->willReturnCallback(function ($dn, $attr) {
  616. switch ($dn) {
  617. default:
  618. return false;
  619. }
  620. });
  621. $this->access->connection->expects($this->any())
  622. ->method('getFromCache')
  623. ->willReturnCallback(function ($key) {
  624. if ($key === 'userExistsnewyorker') {
  625. return true;
  626. }
  627. return null;
  628. });
  629. $user = $this->createMock(User::class);
  630. $user->expects($this->any())
  631. ->method('getUsername')
  632. ->willReturn('newyorker');
  633. $user->expects($this->any())
  634. ->method('getHomePath')
  635. ->willThrowException(new \Exception());
  636. $this->userManager->expects($this->atLeastOnce())
  637. ->method('get')
  638. ->willReturn($user);
  639. //no path at all – triggers OC default behaviour
  640. $result = $backend->getHome('newyorker');
  641. $this->assertFalse($result);
  642. }
  643. public function testGetHomeDeletedUser() {
  644. $uid = 'newyorker';
  645. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  646. $this->prepareMockForUserExists();
  647. $this->connection->expects($this->any())
  648. ->method('__get')
  649. ->willReturnCallback(function ($name) {
  650. if ($name === 'homeFolderNamingRule') {
  651. return 'attr:testAttribute';
  652. }
  653. return null;
  654. });
  655. $this->access->expects($this->any())
  656. ->method('readAttribute')
  657. ->willReturn([]);
  658. $userMapper = $this->createMock(UserMapping::class);
  659. $this->access->expects($this->any())
  660. ->method('getUserMapper')
  661. ->willReturn($userMapper);
  662. $offlineUser = $this->createMock(OfflineUser::class);
  663. $offlineUser->expects($this->atLeastOnce())
  664. ->method('getHomePath')
  665. ->willReturn('');
  666. $this->userManager->expects($this->atLeastOnce())
  667. ->method('get')
  668. ->willReturn($offlineUser);
  669. $result = $backend->getHome($uid);
  670. $this->assertFalse($result);
  671. }
  672. public function testGetHomeWithPlugin() {
  673. $this->pluginManager->expects($this->once())
  674. ->method('implementsActions')
  675. ->with(Backend::GET_HOME)
  676. ->willReturn(true);
  677. $this->pluginManager->expects($this->once())
  678. ->method('getHome')
  679. ->with('uid')
  680. ->willReturn('result');
  681. $this->connection->expects($this->any())
  682. ->method('getFromCache')
  683. ->willReturnCallback(function ($uid) {
  684. return true;
  685. });
  686. /** @noinspection PhpUnhandledExceptionInspection */
  687. $this->assertEquals($this->backend->getHome('uid'), 'result');
  688. }
  689. private function prepareAccessForGetDisplayName() {
  690. $this->connection->expects($this->any())
  691. ->method('__get')
  692. ->willReturnCallback(function ($name) {
  693. if ($name === 'ldapUserDisplayName') {
  694. return 'displayname';
  695. } elseif ($name === 'ldapUserDisplayName2') {
  696. return 'displayname2';
  697. }
  698. return null;
  699. });
  700. $this->access->expects($this->any())
  701. ->method('readAttribute')
  702. ->willReturnCallback(function ($dn, $attr) {
  703. switch ($dn) {
  704. case 'dnOfRoland,dc=test':
  705. if ($attr === 'displayname') {
  706. return ['Roland Deschain'];
  707. }
  708. return [];
  709. break;
  710. default:
  711. return false;
  712. }
  713. });
  714. $this->access->method('fetchUsersByLoginName')
  715. ->willReturn([]);
  716. }
  717. public function testGetDisplayName() {
  718. $this->prepareAccessForGetDisplayName();
  719. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  720. $this->prepareMockForUserExists();
  721. $this->connection->expects($this->any())
  722. ->method('getConnectionResource')
  723. ->willReturnCallback(function () {
  724. return true;
  725. });
  726. $user1 = $this->createMock(User::class);
  727. $user1->expects($this->once())
  728. ->method('composeAndStoreDisplayName')
  729. ->willReturn('Roland Deschain');
  730. $user1->expects($this->any())
  731. ->method('getDN')
  732. ->willReturn('dnOfRoland,dc=test');
  733. $user2 = $this->createMock(User::class);
  734. $user2->expects($this->never())
  735. ->method('composeAndStoreDisplayName');
  736. $user2->expects($this->any())
  737. ->method('getDN')
  738. ->willReturn('another DN');
  739. $mapper = $this->createMock(UserMapping::class);
  740. $mapper->expects($this->any())
  741. ->method('getUUIDByDN')
  742. ->willReturnCallback(function ($dn) {
  743. return $dn;
  744. });
  745. $this->userManager->expects($this->any())
  746. ->method('get')
  747. ->willReturnCallback(function ($uid) use ($user1, $user2) {
  748. if ($uid === 'gunslinger') {
  749. return $user1;
  750. } elseif ($uid === 'newyorker') {
  751. return $user2;
  752. }
  753. return null;
  754. });
  755. $this->access->expects($this->any())
  756. ->method('getUserMapper')
  757. ->willReturn($mapper);
  758. $this->access->expects($this->any())
  759. ->method('getUserDnByUuid')
  760. ->willReturnCallback(function ($uuid) {
  761. return $uuid . '1';
  762. });
  763. //with displayName
  764. $result = $backend->getDisplayName('gunslinger');
  765. $this->assertEquals('Roland Deschain', $result);
  766. //empty displayname retrieved
  767. $result = $backend->getDisplayName('newyorker');
  768. $this->assertEquals(null, $result);
  769. }
  770. public function testGetDisplayNamePublicAPI() {
  771. $this->access->expects($this->any())
  772. ->method('username2dn')
  773. ->willReturnCallback(function ($uid) {
  774. switch ($uid) {
  775. case 'gunslinger':
  776. return 'dnOfRoland,dc=test';
  777. break;
  778. case 'formerUser':
  779. return 'dnOfFormerUser,dc=test';
  780. break;
  781. case 'newyorker':
  782. return 'dnOfNewYorker,dc=test';
  783. break;
  784. case 'ladyofshadows':
  785. return 'dnOfLadyOfShadows,dc=test';
  786. break;
  787. default:
  788. return false;
  789. }
  790. });
  791. $this->prepareAccessForGetDisplayName();
  792. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  793. $this->prepareMockForUserExists();
  794. $this->connection->expects($this->any())
  795. ->method('getConnectionResource')
  796. ->willReturnCallback(function () {
  797. return true;
  798. });
  799. \OC_User::useBackend($backend);
  800. $user1 = $this->createMock(User::class);
  801. $user1->expects($this->once())
  802. ->method('composeAndStoreDisplayName')
  803. ->willReturn('Roland Deschain');
  804. $user1->expects($this->any())
  805. ->method('getDN')
  806. ->willReturn('dnOfRoland,dc=test');
  807. $user2 = $this->createMock(User::class);
  808. $user2->expects($this->never())
  809. ->method('composeAndStoreDisplayName');
  810. $user2->expects($this->any())
  811. ->method('getDN')
  812. ->willReturn('another DN');
  813. $mapper = $this->createMock(UserMapping::class);
  814. $mapper->expects($this->any())
  815. ->method('getUUIDByDN')
  816. ->willReturnCallback(function ($dn) {
  817. return $dn;
  818. });
  819. $this->userManager->expects($this->any())
  820. ->method('get')
  821. ->willReturnCallback(function ($uid) use ($user1, $user2) {
  822. if ($uid === 'gunslinger') {
  823. return $user1;
  824. } elseif ($uid === 'newyorker') {
  825. return $user2;
  826. }
  827. return null;
  828. });
  829. $this->access->expects($this->any())
  830. ->method('getUserMapper')
  831. ->willReturn($mapper);
  832. $this->access->expects($this->any())
  833. ->method('getUserDnByUuid')
  834. ->willReturnCallback(function ($uuid) {
  835. return $uuid . '1';
  836. });
  837. //with displayName
  838. $result = \OC::$server->getUserManager()->get('gunslinger')->getDisplayName();
  839. $this->assertEquals('Roland Deschain', $result);
  840. //empty displayname retrieved
  841. $result = \OC::$server->getUserManager()->get('newyorker') === null ? 'newyorker' : \OC::$server->getUserManager()->get('newyorker')->getDisplayName();
  842. $this->assertEquals('newyorker', $result);
  843. }
  844. public function testGetDisplayNameWithPlugin() {
  845. $this->pluginManager->expects($this->once())
  846. ->method('implementsActions')
  847. ->with(Backend::GET_DISPLAYNAME)
  848. ->willReturn(true);
  849. $this->pluginManager->expects($this->once())
  850. ->method('getDisplayName')
  851. ->with('uid')
  852. ->willReturn('result');
  853. $this->assertEquals($this->backend->getDisplayName('uid'), 'result');
  854. }
  855. //no test for getDisplayNames, because it just invokes getUsers and
  856. //getDisplayName
  857. public function testCountUsers() {
  858. $this->access->expects($this->once())
  859. ->method('countUsers')
  860. ->willReturn(5);
  861. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  862. $result = $backend->countUsers();
  863. $this->assertEquals(5, $result);
  864. }
  865. public function testCountUsersFailing() {
  866. $this->access->expects($this->once())
  867. ->method('countUsers')
  868. ->willReturn(false);
  869. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  870. $result = $backend->countUsers();
  871. $this->assertFalse($result);
  872. }
  873. public function testCountUsersWithPlugin() {
  874. $this->pluginManager->expects($this->once())
  875. ->method('implementsActions')
  876. ->with(Backend::COUNT_USERS)
  877. ->willReturn(true);
  878. $this->pluginManager->expects($this->once())
  879. ->method('countUsers')
  880. ->willReturn(42);
  881. $this->assertEquals($this->backend->countUsers(), 42);
  882. }
  883. public function testLoginName2UserNameSuccess() {
  884. $loginName = 'Alice';
  885. $username = 'alice';
  886. $dn = 'uid=alice,dc=what,dc=ever';
  887. $this->access->expects($this->once())
  888. ->method('fetchUsersByLoginName')
  889. ->with($this->equalTo($loginName))
  890. ->willReturn([['dn' => [$dn]]]);
  891. $this->access->expects($this->any())
  892. ->method('stringResemblesDN')
  893. ->with($this->equalTo($dn))
  894. ->willReturn(true);
  895. $this->access->expects($this->any())
  896. ->method('dn2username')
  897. ->with($this->equalTo($dn))
  898. ->willReturn($username);
  899. $this->connection->expects($this->exactly(2))
  900. ->method('getFromCache')
  901. ->with($this->equalTo('loginName2UserName-'.$loginName))
  902. ->willReturnOnConsecutiveCalls(null, $username);
  903. $this->connection->expects($this->once())
  904. ->method('writeToCache')
  905. ->with($this->equalTo('loginName2UserName-'.$loginName), $this->equalTo($username));
  906. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  907. $user = $this->createMock(User::class);
  908. $user->expects($this->any())
  909. ->method('getUsername')
  910. ->willReturn('alice');
  911. $this->userManager->expects($this->atLeastOnce())
  912. ->method('get')
  913. ->with($dn)
  914. ->willReturn($user);
  915. $this->userManager->expects($this->any())
  916. ->method('getAttributes')
  917. ->willReturn(['dn', 'uid', 'mail', 'displayname']);
  918. $name = $backend->loginName2UserName($loginName);
  919. $this->assertSame($username, $name);
  920. // and once again to verify that caching works
  921. $backend->loginName2UserName($loginName);
  922. }
  923. public function testLoginName2UserNameNoUsersOnLDAP() {
  924. $loginName = 'Loki';
  925. $this->access->expects($this->once())
  926. ->method('fetchUsersByLoginName')
  927. ->with($this->equalTo($loginName))
  928. ->willReturn([]);
  929. $this->access->expects($this->never())
  930. ->method('stringResemblesDN');
  931. $this->access->expects($this->never())
  932. ->method('dn2username');
  933. $this->connection->expects($this->exactly(2))
  934. ->method('getFromCache')
  935. ->with($this->equalTo('loginName2UserName-'.$loginName))
  936. ->willReturnOnConsecutiveCalls(null, false);
  937. $this->connection->expects($this->once())
  938. ->method('writeToCache')
  939. ->with($this->equalTo('loginName2UserName-'.$loginName), false);
  940. $this->userManager->expects($this->any())
  941. ->method('getAttributes')
  942. ->willReturn(['dn', 'uid', 'mail', 'displayname']);
  943. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  944. $name = $backend->loginName2UserName($loginName);
  945. $this->assertSame(false, $name);
  946. // and once again to verify that caching works
  947. $backend->loginName2UserName($loginName);
  948. }
  949. public function testLoginName2UserNameOfflineUser() {
  950. $loginName = 'Alice';
  951. $dn = 'uid=alice,dc=what,dc=ever';
  952. $offlineUser = $this->getMockBuilder(OfflineUser::class)
  953. ->disableOriginalConstructor()
  954. ->getMock();
  955. $this->access->expects($this->once())
  956. ->method('fetchUsersByLoginName')
  957. ->with($this->equalTo($loginName))
  958. ->willReturn([['dn' => [$dn]]]);
  959. $this->connection->expects($this->exactly(2))
  960. ->method('getFromCache')
  961. ->with($this->equalTo('loginName2UserName-'.$loginName))
  962. ->willReturnOnConsecutiveCalls(null, false);
  963. $this->connection->expects($this->once())
  964. ->method('writeToCache')
  965. ->with($this->equalTo('loginName2UserName-'.$loginName), $this->equalTo(false));
  966. $this->userManager->expects($this->any())
  967. ->method('get')
  968. ->with($dn)
  969. ->willReturn($offlineUser);
  970. $this->userManager->expects($this->any())
  971. ->method('getAttributes')
  972. ->willReturn(['dn', 'uid', 'mail', 'displayname']);
  973. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  974. $name = $backend->loginName2UserName($loginName);
  975. $this->assertSame(false, $name);
  976. // and once again to verify that caching works
  977. $backend->loginName2UserName($loginName);
  978. }
  979. /**
  980. * Prepares the Access mock for setPassword tests
  981. *
  982. * @param bool $enablePasswordChange
  983. */
  984. private function prepareAccessForSetPassword($enablePasswordChange = true) {
  985. $this->connection->expects($this->any())
  986. ->method('__get')
  987. ->willReturnCallback(function ($name) use (&$enablePasswordChange) {
  988. if ($name === 'ldapLoginFilter') {
  989. return '%uid';
  990. }
  991. if ($name === 'turnOnPasswordChange') {
  992. return $enablePasswordChange?1:0;
  993. }
  994. return null;
  995. });
  996. $this->connection->expects($this->any())
  997. ->method('getFromCache')
  998. ->willReturnCallback(function ($uid) {
  999. if ($uid === 'userExists'.'roland') {
  1000. return true;
  1001. }
  1002. return null;
  1003. });
  1004. $this->access->expects($this->any())
  1005. ->method('fetchListOfUsers')
  1006. ->willReturnCallback(function ($filter) {
  1007. if ($filter === 'roland') {
  1008. return [['dn' => ['dnOfRoland,dc=test']]];
  1009. }
  1010. return [];
  1011. });
  1012. $this->access->expects($this->any())
  1013. ->method('fetchUsersByLoginName')
  1014. ->willReturnCallback(function ($uid) {
  1015. if ($uid === 'roland') {
  1016. return [['dn' => ['dnOfRoland,dc=test']]];
  1017. }
  1018. return [];
  1019. });
  1020. $this->access->expects($this->any())
  1021. ->method('dn2username')
  1022. ->with($this->equalTo('dnOfRoland,dc=test'))
  1023. ->willReturn('roland');
  1024. $this->access->expects($this->any())
  1025. ->method('stringResemblesDN')
  1026. ->with($this->equalTo('dnOfRoland,dc=test'))
  1027. ->willReturn(true);
  1028. $this->access->expects($this->any())
  1029. ->method('setPassword')
  1030. ->willReturnCallback(function ($uid, $password) {
  1031. if (strlen($password) <= 5) {
  1032. throw new HintException('Password fails quality checking policy', '', 19);
  1033. }
  1034. return true;
  1035. });
  1036. }
  1037. public function testSetPasswordInvalid() {
  1038. $this->expectException(\OCP\HintException::class);
  1039. $this->expectExceptionMessage('Password fails quality checking policy');
  1040. $this->prepareAccessForSetPassword($this->access);
  1041. $this->userManager->expects($this->atLeastOnce())
  1042. ->method('get')
  1043. ->willReturn($this->createMock(User::class));
  1044. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  1045. \OC_User::useBackend($backend);
  1046. $this->assertTrue(\OC_User::setPassword('roland', 'dt'));
  1047. }
  1048. public function testSetPasswordValid() {
  1049. $this->prepareAccessForSetPassword($this->access);
  1050. $this->userManager->expects($this->any())
  1051. ->method('get')
  1052. ->willReturn($this->createMock(User::class));
  1053. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  1054. $this->userManager->expects($this->any())
  1055. ->method('get')
  1056. ->willReturn($this->createMock(User::class));
  1057. \OC_User::useBackend($backend);
  1058. $this->assertTrue(\OC_User::setPassword('roland', 'dt12234$'));
  1059. }
  1060. public function testSetPasswordValidDisabled() {
  1061. $this->userManager->expects($this->any())
  1062. ->method('get')
  1063. ->willReturn($this->createMock(User::class));
  1064. $this->prepareAccessForSetPassword(false);
  1065. $backend = new UserLDAP($this->access, $this->notificationManager, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
  1066. \OC_User::useBackend($backend);
  1067. $this->assertFalse(\OC_User::setPassword('roland', 'dt12234$'));
  1068. }
  1069. public function testSetPasswordWithInvalidUser() {
  1070. $this->expectException(\Exception::class);
  1071. $this->expectExceptionMessage('LDAP setPassword: Could not get user object for uid NotExistingUser. Maybe the LDAP entry has no set display name attribute?');
  1072. $this->userManager
  1073. ->expects($this->once())
  1074. ->method('get')
  1075. ->with('NotExistingUser')
  1076. ->willReturn(null);
  1077. $this->backend->setPassword('NotExistingUser', 'Password');
  1078. }
  1079. public function testSetPasswordWithUsernameFalse() {
  1080. $user = $this->createMock(User::class);
  1081. $user
  1082. ->expects($this->once())
  1083. ->method('getUsername')
  1084. ->willReturn(false);
  1085. $this->userManager
  1086. ->expects($this->once())
  1087. ->method('get')
  1088. ->with('NotExistingUser')
  1089. ->willReturn($user);
  1090. /** @noinspection PhpUnhandledExceptionInspection */
  1091. $this->assertFalse($this->backend->setPassword('NotExistingUser', 'Password'));
  1092. }
  1093. public function testSetPasswordWithPlugin() {
  1094. $this->pluginManager->expects($this->once())
  1095. ->method('implementsActions')
  1096. ->with(Backend::SET_PASSWORD)
  1097. ->willReturn(true);
  1098. $this->pluginManager->expects($this->once())
  1099. ->method('setPassword')
  1100. ->with('uid', 'password')
  1101. ->willReturn('result');
  1102. /** @noinspection PhpUnhandledExceptionInspection */
  1103. $this->assertEquals($this->backend->setPassword('uid', 'password'), 'result');
  1104. }
  1105. public function avatarDataProvider() {
  1106. return [
  1107. [ 'validImageData', false ],
  1108. [ 'corruptImageData', true ],
  1109. [ false, true]
  1110. ];
  1111. }
  1112. /** @dataProvider avatarDataProvider */
  1113. public function testCanChangeAvatar($imageData, $expected) {
  1114. $isValidImage = str_starts_with((string)$imageData, 'valid');
  1115. $user = $this->createMock(User::class);
  1116. $user->expects($this->once())
  1117. ->method('getAvatarImage')
  1118. ->willReturn($imageData);
  1119. $user->expects($this->atMost(1))
  1120. ->method('updateAvatar')
  1121. ->willReturn($isValidImage);
  1122. $this->userManager->expects($this->atLeastOnce())
  1123. ->method('get')
  1124. ->willReturn($user);
  1125. /** @noinspection PhpUnhandledExceptionInspection */
  1126. $this->assertSame($expected, $this->backend->canChangeAvatar('uid'));
  1127. }
  1128. public function testCanChangeAvatarWithPlugin() {
  1129. $this->pluginManager->expects($this->once())
  1130. ->method('implementsActions')
  1131. ->with(Backend::PROVIDE_AVATAR)
  1132. ->willReturn(true);
  1133. $this->pluginManager->expects($this->once())
  1134. ->method('canChangeAvatar')
  1135. ->with('uid')
  1136. ->willReturn('result');
  1137. $this->assertEquals($this->backend->canChangeAvatar('uid'), 'result');
  1138. }
  1139. public function testSetDisplayNameWithPlugin() {
  1140. $newDisplayName = 'J. Baker';
  1141. $this->pluginManager->expects($this->once())
  1142. ->method('implementsActions')
  1143. ->with(Backend::SET_DISPLAYNAME)
  1144. ->willReturn(true);
  1145. $this->pluginManager->expects($this->once())
  1146. ->method('setDisplayName')
  1147. ->with('uid', $newDisplayName)
  1148. ->willReturn($newDisplayName);
  1149. $this->access->expects($this->once())
  1150. ->method('cacheUserDisplayName');
  1151. $this->assertEquals($newDisplayName, $this->backend->setDisplayName('uid', $newDisplayName));
  1152. }
  1153. public function testSetDisplayNameErrorWithPlugin() {
  1154. $this->expectException(\OCP\HintException::class);
  1155. $newDisplayName = 'J. Baker';
  1156. $this->pluginManager->expects($this->once())
  1157. ->method('implementsActions')
  1158. ->with(Backend::SET_DISPLAYNAME)
  1159. ->willReturn(true);
  1160. $this->pluginManager->expects($this->once())
  1161. ->method('setDisplayName')
  1162. ->with('uid', $newDisplayName)
  1163. ->willThrowException(new HintException('something happned'));
  1164. $this->access->expects($this->never())
  1165. ->method('cacheUserDisplayName');
  1166. $this->backend->setDisplayName('uid', $newDisplayName);
  1167. }
  1168. public function testSetDisplayNameFailing() {
  1169. $this->pluginManager->expects($this->once())
  1170. ->method('implementsActions')
  1171. ->with(Backend::SET_DISPLAYNAME)
  1172. ->willReturn(false);
  1173. $this->access->expects($this->never())
  1174. ->method('cacheUserDisplayName');
  1175. $this->assertFalse($this->backend->setDisplayName('uid', 'displayName'));
  1176. }
  1177. public function testCreateUserWithPlugin() {
  1178. $uid = 'alien6372';
  1179. $uuid = '123-2345-36756-123-2345234-4431';
  1180. $pwd = 'passwørd';
  1181. $this->pluginManager->expects($this->once())
  1182. ->method('implementsActions')
  1183. ->with(Backend::CREATE_USER)
  1184. ->willReturn(true);
  1185. $this->pluginManager->expects($this->once())
  1186. ->method('createUser')
  1187. ->with($uid, $pwd)
  1188. ->willReturn('result');
  1189. $this->access->expects($this->atLeastOnce())
  1190. ->method('getUUID')
  1191. ->willReturn($uuid);
  1192. $this->access->expects($this->once())
  1193. ->method('mapAndAnnounceIfApplicable')
  1194. ->with($this->isInstanceOf(AbstractMapping::class), $this->anything(), $uid, $uuid, true);
  1195. $this->access->expects($this->any())
  1196. ->method('getUserMapper')
  1197. ->willReturn($this->createMock(UserMapping::class));
  1198. $this->assertEquals($this->backend->createUser($uid, $pwd), true);
  1199. }
  1200. public function testCreateUserFailing() {
  1201. $this->pluginManager->expects($this->once())
  1202. ->method('implementsActions')
  1203. ->with(Backend::CREATE_USER)
  1204. ->willReturn(false);
  1205. $this->assertFalse($this->backend->createUser('uid', 'password'));
  1206. }
  1207. public function actionProvider() {
  1208. return [
  1209. [ 'ldapUserAvatarRule', 'default', Backend::PROVIDE_AVATAR, true] ,
  1210. [ 'ldapUserAvatarRule', 'data:selfiePhoto', Backend::PROVIDE_AVATAR, true],
  1211. [ 'ldapUserAvatarRule', 'none', Backend::PROVIDE_AVATAR, false],
  1212. [ 'turnOnPasswordChange', 0, Backend::SET_PASSWORD, false],
  1213. [ 'turnOnPasswordChange', 1, Backend::SET_PASSWORD, true],
  1214. ];
  1215. }
  1216. /**
  1217. * @dataProvider actionProvider
  1218. */
  1219. public function testImplementsAction($configurable, $value, $actionCode, $expected) {
  1220. $this->pluginManager->expects($this->once())
  1221. ->method('getImplementedActions')
  1222. ->willReturn(0);
  1223. $this->connection->expects($this->any())
  1224. ->method('__get')
  1225. ->willReturnMap([
  1226. [$configurable, $value],
  1227. ]);
  1228. $this->assertSame($expected, $this->backend->implementsActions($actionCode));
  1229. }
  1230. }