1
0

User_LDAPTest.php 44 KB

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