1
0

User_LDAPTest.php 44 KB

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