User_LDAPTest.php 43 KB

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