Group_LDAPTest.php 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Frédéric Fortier <frederic.fortier@oronospolytechnique.com>
  7. * @author Joas Schilling <coding@schilljs.com>
  8. * @author Lukas Reschke <lukas@statuscode.ch>
  9. * @author Morris Jobke <hey@morrisjobke.de>
  10. * @author Roeland Jago Douma <roeland@famdouma.nl>
  11. * @author Thomas Müller <thomas.mueller@tmit.eu>
  12. * @author Victor Dubiniuk <dubiniuk@owncloud.com>
  13. * @author Vincent Petry <pvince81@owncloud.com>
  14. * @author Vinicius Cubas Brand <vinicius@eita.org.br>
  15. * @author Xuanwo <xuanwo@yunify.com>
  16. *
  17. * @license AGPL-3.0
  18. *
  19. * This code is free software: you can redistribute it and/or modify
  20. * it under the terms of the GNU Affero General Public License, version 3,
  21. * as published by the Free Software Foundation.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU Affero General Public License for more details.
  27. *
  28. * You should have received a copy of the GNU Affero General Public License, version 3,
  29. * along with this program. If not, see <http://www.gnu.org/licenses/>
  30. *
  31. */
  32. namespace OCA\User_LDAP\Tests;
  33. use OCA\User_LDAP\GroupPluginManager;
  34. use OCP\GroupInterface;
  35. use OCA\User_LDAP\Access;
  36. use OCA\User_LDAP\Connection;
  37. use OCA\User_LDAP\Group_LDAP as GroupLDAP;
  38. use OCA\User_LDAP\ILDAPWrapper;
  39. use OCA\User_LDAP\User\Manager;
  40. use Test\TestCase;
  41. /**
  42. * Class GroupLDAPTest
  43. *
  44. * @group DB
  45. *
  46. * @package OCA\User_LDAP\Tests
  47. */
  48. class Group_LDAPTest extends TestCase {
  49. /**
  50. * @return \PHPUnit_Framework_MockObject_MockObject|Access
  51. */
  52. private function getAccessMock() {
  53. static $conMethods;
  54. static $accMethods;
  55. if(is_null($conMethods) || is_null($accMethods)) {
  56. $conMethods = get_class_methods('\OCA\User_LDAP\Connection');
  57. $accMethods = get_class_methods('\OCA\User_LDAP\Access');
  58. }
  59. $lw = $this->createMock(ILDAPWrapper::class);
  60. $connector = $this->getMockBuilder('\OCA\User_LDAP\Connection')
  61. ->setMethods($conMethods)
  62. ->setConstructorArgs([$lw, null, null])
  63. ->getMock();
  64. $access = $this->createMock(Access::class);
  65. $access->expects($this->any())
  66. ->method('getConnection')
  67. ->will($this->returnValue($connector));
  68. return $access;
  69. }
  70. private function getPluginManagerMock() {
  71. return $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')->getMock();
  72. }
  73. /**
  74. * @param Access|\PHPUnit_Framework_MockObject_MockObject $access
  75. */
  76. private function enableGroups($access) {
  77. $access->connection = $this->createMock(Connection::class);
  78. $access->connection->expects($this->any())
  79. ->method('__get')
  80. ->will($this->returnCallback(function($name) {
  81. if($name === 'ldapDynamicGroupMemberURL') {
  82. return '';
  83. }
  84. return 1;
  85. }));
  86. }
  87. public function testCountEmptySearchString() {
  88. $access = $this->getAccessMock();
  89. $pluginManager = $this->getPluginManagerMock();
  90. $groupDN = 'cn=group,dc=foo,dc=bar';
  91. $this->enableGroups($access);
  92. $access->expects($this->any())
  93. ->method('groupname2dn')
  94. ->will($this->returnValue($groupDN));
  95. $access->expects($this->any())
  96. ->method('readAttribute')
  97. ->willReturnCallback(function($dn) use ($groupDN) {
  98. if($dn === $groupDN) {
  99. return [
  100. 'uid=u11,ou=users,dc=foo,dc=bar',
  101. 'uid=u22,ou=users,dc=foo,dc=bar',
  102. 'uid=u33,ou=users,dc=foo,dc=bar',
  103. 'uid=u34,ou=users,dc=foo,dc=bar'
  104. ];
  105. }
  106. return [];
  107. });
  108. // for primary groups
  109. $access->expects($this->once())
  110. ->method('countUsers')
  111. ->will($this->returnValue(2));
  112. $groupBackend = new GroupLDAP($access, $pluginManager);
  113. $users = $groupBackend->countUsersInGroup('group');
  114. $this->assertSame(6, $users);
  115. }
  116. public function testCountWithSearchString() {
  117. $access = $this->getAccessMock();
  118. $pluginManager = $this->getPluginManagerMock();
  119. $this->enableGroups($access);
  120. $access->expects($this->any())
  121. ->method('groupname2dn')
  122. ->will($this->returnValue('cn=group,dc=foo,dc=bar'));
  123. $access->expects($this->any())
  124. ->method('fetchListOfUsers')
  125. ->will($this->returnValue([]));
  126. $access->expects($this->any())
  127. ->method('readAttribute')
  128. ->will($this->returnCallback(function($name) {
  129. //the search operation will call readAttribute, thus we need
  130. //to anaylze the "dn". All other times we just need to return
  131. //something that is neither null or false, but once an array
  132. //with the users in the group – so we do so all other times for
  133. //simplicicity.
  134. if(strpos($name, 'u') === 0) {
  135. return strpos($name, '3');
  136. }
  137. return ['u11', 'u22', 'u33', 'u34'];
  138. }));
  139. $access->expects($this->any())
  140. ->method('dn2username')
  141. ->will($this->returnCallback(function() {
  142. return 'foobar' . \OC::$server->getSecureRandom()->generate(7);
  143. }));
  144. $groupBackend = new GroupLDAP($access,$pluginManager);
  145. $users = $groupBackend->countUsersInGroup('group', '3');
  146. $this->assertSame(2, $users);
  147. }
  148. public function testCountUsersWithPlugin() {
  149. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  150. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  151. ->setMethods(['implementsActions','countUsersInGroup'])
  152. ->getMock();
  153. $pluginManager->expects($this->once())
  154. ->method('implementsActions')
  155. ->with(GroupInterface::COUNT_USERS)
  156. ->willReturn(true);
  157. $pluginManager->expects($this->once())
  158. ->method('countUsersInGroup')
  159. ->with('gid', 'search')
  160. ->willReturn(42);
  161. $access = $this->getAccessMock();
  162. $access->connection = $this->createMock(Connection::class);
  163. $ldap = new GroupLDAP($access, $pluginManager);
  164. $this->assertEquals($ldap->countUsersInGroup('gid', 'search'),42);
  165. }
  166. public function testGidNumber2NameSuccess() {
  167. $access = $this->getAccessMock();
  168. $pluginManager = $this->getPluginManagerMock();
  169. $this->enableGroups($access);
  170. $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';
  171. $access->expects($this->once())
  172. ->method('searchGroups')
  173. ->will($this->returnValue([['dn' => ['cn=foo,dc=barfoo,dc=bar']]]));
  174. $access->expects($this->once())
  175. ->method('dn2groupname')
  176. ->with('cn=foo,dc=barfoo,dc=bar')
  177. ->will($this->returnValue('MyGroup'));
  178. $groupBackend = new GroupLDAP($access, $pluginManager);
  179. $group = $groupBackend->gidNumber2Name('3117', $userDN);
  180. $this->assertSame('MyGroup', $group);
  181. }
  182. public function testGidNumberID2NameNoGroup() {
  183. $access = $this->getAccessMock();
  184. $pluginManager = $this->getPluginManagerMock();
  185. $this->enableGroups($access);
  186. $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';
  187. $access->expects($this->once())
  188. ->method('searchGroups')
  189. ->will($this->returnValue(array()));
  190. $access->expects($this->never())
  191. ->method('dn2groupname');
  192. $groupBackend = new GroupLDAP($access, $pluginManager);
  193. $group = $groupBackend->gidNumber2Name('3117', $userDN);
  194. $this->assertSame(false, $group);
  195. }
  196. public function testGidNumberID2NameNoName() {
  197. $access = $this->getAccessMock();
  198. $pluginManager = $this->getPluginManagerMock();
  199. $this->enableGroups($access);
  200. $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';
  201. $access->expects($this->once())
  202. ->method('searchGroups')
  203. ->will($this->returnValue([['dn' => ['cn=foo,dc=barfoo,dc=bar']]]));
  204. $access->expects($this->once())
  205. ->method('dn2groupname')
  206. ->will($this->returnValue(false));
  207. $groupBackend = new GroupLDAP($access, $pluginManager);
  208. $group = $groupBackend->gidNumber2Name('3117', $userDN);
  209. $this->assertSame(false, $group);
  210. }
  211. public function testGetEntryGidNumberValue() {
  212. $access = $this->getAccessMock();
  213. $pluginManager = $this->getPluginManagerMock();
  214. $this->enableGroups($access);
  215. $dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
  216. $attr = 'gidNumber';
  217. $access->expects($this->once())
  218. ->method('readAttribute')
  219. ->with($dn, $attr)
  220. ->will($this->returnValue(array('3117')));
  221. $groupBackend = new GroupLDAP($access, $pluginManager);
  222. $gid = $groupBackend->getGroupGidNumber($dn);
  223. $this->assertSame('3117', $gid);
  224. }
  225. public function testGetEntryGidNumberNoValue() {
  226. $access = $this->getAccessMock();
  227. $pluginManager = $this->getPluginManagerMock();
  228. $this->enableGroups($access);
  229. $dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
  230. $attr = 'gidNumber';
  231. $access->expects($this->once())
  232. ->method('readAttribute')
  233. ->with($dn, $attr)
  234. ->will($this->returnValue(false));
  235. $groupBackend = new GroupLDAP($access, $pluginManager);
  236. $gid = $groupBackend->getGroupGidNumber($dn);
  237. $this->assertSame(false, $gid);
  238. }
  239. public function testPrimaryGroupID2NameSuccess() {
  240. $access = $this->getAccessMock();
  241. $pluginManager = $this->getPluginManagerMock();
  242. $this->enableGroups($access);
  243. $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';
  244. $access->expects($this->once())
  245. ->method('getSID')
  246. ->with($userDN)
  247. ->will($this->returnValue('S-1-5-21-249921958-728525901-1594176202'));
  248. $access->expects($this->once())
  249. ->method('searchGroups')
  250. ->will($this->returnValue([['dn' => ['cn=foo,dc=barfoo,dc=bar']]]));
  251. $access->expects($this->once())
  252. ->method('dn2groupname')
  253. ->with('cn=foo,dc=barfoo,dc=bar')
  254. ->will($this->returnValue('MyGroup'));
  255. $groupBackend = new GroupLDAP($access, $pluginManager);
  256. $group = $groupBackend->primaryGroupID2Name('3117', $userDN);
  257. $this->assertSame('MyGroup', $group);
  258. }
  259. public function testPrimaryGroupID2NameNoSID() {
  260. $access = $this->getAccessMock();
  261. $pluginManager = $this->getPluginManagerMock();
  262. $this->enableGroups($access);
  263. $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';
  264. $access->expects($this->once())
  265. ->method('getSID')
  266. ->with($userDN)
  267. ->will($this->returnValue(false));
  268. $access->expects($this->never())
  269. ->method('searchGroups');
  270. $access->expects($this->never())
  271. ->method('dn2groupname');
  272. $groupBackend = new GroupLDAP($access, $pluginManager);
  273. $group = $groupBackend->primaryGroupID2Name('3117', $userDN);
  274. $this->assertSame(false, $group);
  275. }
  276. public function testPrimaryGroupID2NameNoGroup() {
  277. $access = $this->getAccessMock();
  278. $pluginManager = $this->getPluginManagerMock();
  279. $this->enableGroups($access);
  280. $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';
  281. $access->expects($this->once())
  282. ->method('getSID')
  283. ->with($userDN)
  284. ->will($this->returnValue('S-1-5-21-249921958-728525901-1594176202'));
  285. $access->expects($this->once())
  286. ->method('searchGroups')
  287. ->will($this->returnValue(array()));
  288. $access->expects($this->never())
  289. ->method('dn2groupname');
  290. $groupBackend = new GroupLDAP($access, $pluginManager);
  291. $group = $groupBackend->primaryGroupID2Name('3117', $userDN);
  292. $this->assertSame(false, $group);
  293. }
  294. public function testPrimaryGroupID2NameNoName() {
  295. $access = $this->getAccessMock();
  296. $pluginManager = $this->getPluginManagerMock();
  297. $this->enableGroups($access);
  298. $userDN = 'cn=alice,cn=foo,dc=barfoo,dc=bar';
  299. $access->expects($this->once())
  300. ->method('getSID')
  301. ->with($userDN)
  302. ->will($this->returnValue('S-1-5-21-249921958-728525901-1594176202'));
  303. $access->expects($this->once())
  304. ->method('searchGroups')
  305. ->will($this->returnValue([['dn' => ['cn=foo,dc=barfoo,dc=bar']]]));
  306. $access->expects($this->once())
  307. ->method('dn2groupname')
  308. ->will($this->returnValue(false));
  309. $groupBackend = new GroupLDAP($access, $pluginManager);
  310. $group = $groupBackend->primaryGroupID2Name('3117', $userDN);
  311. $this->assertSame(false, $group);
  312. }
  313. public function testGetEntryGroupIDValue() {
  314. //tests getEntryGroupID via getGroupPrimaryGroupID
  315. //which is basically identical to getUserPrimaryGroupIDs
  316. $access = $this->getAccessMock();
  317. $pluginManager = $this->getPluginManagerMock();
  318. $this->enableGroups($access);
  319. $dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
  320. $attr = 'primaryGroupToken';
  321. $access->expects($this->once())
  322. ->method('readAttribute')
  323. ->with($dn, $attr)
  324. ->will($this->returnValue(array('3117')));
  325. $groupBackend = new GroupLDAP($access, $pluginManager);
  326. $gid = $groupBackend->getGroupPrimaryGroupID($dn);
  327. $this->assertSame('3117', $gid);
  328. }
  329. public function testGetEntryGroupIDNoValue() {
  330. //tests getEntryGroupID via getGroupPrimaryGroupID
  331. //which is basically identical to getUserPrimaryGroupIDs
  332. $access = $this->getAccessMock();
  333. $pluginManager = $this->getPluginManagerMock();
  334. $this->enableGroups($access);
  335. $dn = 'cn=foobar,cn=foo,dc=barfoo,dc=bar';
  336. $attr = 'primaryGroupToken';
  337. $access->expects($this->once())
  338. ->method('readAttribute')
  339. ->with($dn, $attr)
  340. ->will($this->returnValue(false));
  341. $groupBackend = new GroupLDAP($access, $pluginManager);
  342. $gid = $groupBackend->getGroupPrimaryGroupID($dn);
  343. $this->assertSame(false, $gid);
  344. }
  345. /**
  346. * tests whether Group Backend behaves correctly when cache with uid and gid
  347. * is hit
  348. */
  349. public function testInGroupHitsUidGidCache() {
  350. $access = $this->getAccessMock();
  351. $pluginManager = $this->getPluginManagerMock();
  352. $this->enableGroups($access);
  353. $uid = 'someUser';
  354. $gid = 'someGroup';
  355. $cacheKey = 'inGroup'.$uid.':'.$gid;
  356. $access->connection->expects($this->once())
  357. ->method('getFromCache')
  358. ->with($cacheKey)
  359. ->will($this->returnValue(true));
  360. $access->expects($this->never())
  361. ->method('username2dn');
  362. $groupBackend = new GroupLDAP($access, $pluginManager);
  363. $groupBackend->inGroup($uid, $gid);
  364. }
  365. public function testGetGroupsWithOffset() {
  366. $access = $this->getAccessMock();
  367. $pluginManager = $this->getPluginManagerMock();
  368. $this->enableGroups($access);
  369. $access->expects($this->once())
  370. ->method('nextcloudGroupNames')
  371. ->will($this->returnValue(array('group1', 'group2')));
  372. $groupBackend = new GroupLDAP($access, $pluginManager);
  373. $groups = $groupBackend->getGroups('', 2, 2);
  374. $this->assertSame(2, count($groups));
  375. }
  376. /**
  377. * tests that a user listing is complete, if all it's members have the group
  378. * as their primary.
  379. */
  380. public function testUsersInGroupPrimaryMembersOnly() {
  381. $access = $this->getAccessMock();
  382. $pluginManager = $this->getPluginManagerMock();
  383. $this->enableGroups($access);
  384. $access->connection->expects($this->any())
  385. ->method('getFromCache')
  386. ->will($this->returnValue(null));
  387. $access->expects($this->any())
  388. ->method('readAttribute')
  389. ->will($this->returnCallback(function($dn, $attr) {
  390. if($attr === 'primaryGroupToken') {
  391. return array(1337);
  392. } else if($attr === 'gidNumber') {
  393. return [4211];
  394. }
  395. return array();
  396. }));
  397. $access->expects($this->any())
  398. ->method('groupname2dn')
  399. ->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
  400. $access->expects($this->exactly(2))
  401. ->method('nextcloudUserNames')
  402. ->willReturnOnConsecutiveCalls(['lisa', 'bart', 'kira', 'brad'], ['walle', 'dino', 'xenia']);
  403. $access->userManager = $this->createMock(Manager::class);
  404. $groupBackend = new GroupLDAP($access, $pluginManager);
  405. $users = $groupBackend->usersInGroup('foobar');
  406. $this->assertSame(7, count($users));
  407. }
  408. /**
  409. * tests that a user listing is complete, if all it's members have the group
  410. * as their primary.
  411. */
  412. public function testUsersInGroupPrimaryAndUnixMembers() {
  413. $access = $this->getAccessMock();
  414. $pluginManager = $this->getPluginManagerMock();
  415. $this->enableGroups($access);
  416. $access->connection->expects($this->any())
  417. ->method('getFromCache')
  418. ->will($this->returnValue(null));
  419. $access->expects($this->any())
  420. ->method('readAttribute')
  421. ->will($this->returnCallback(function($dn, $attr) {
  422. if($attr === 'primaryGroupToken') {
  423. return array(1337);
  424. }
  425. return array();
  426. }));
  427. $access->expects($this->any())
  428. ->method('groupname2dn')
  429. ->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
  430. $access->expects($this->once())
  431. ->method('nextcloudUserNames')
  432. ->will($this->returnValue(array('lisa', 'bart', 'kira', 'brad')));
  433. $access->userManager = $this->createMock(Manager::class);
  434. $groupBackend = new GroupLDAP($access, $pluginManager);
  435. $users = $groupBackend->usersInGroup('foobar');
  436. $this->assertSame(4, count($users));
  437. }
  438. /**
  439. * tests that a user counting is complete, if all it's members have the group
  440. * as their primary.
  441. */
  442. public function testCountUsersInGroupPrimaryMembersOnly() {
  443. $access = $this->getAccessMock();
  444. $pluginManager = $this->getPluginManagerMock();
  445. $this->enableGroups($access);
  446. $access->connection->expects($this->any())
  447. ->method('getFromCache')
  448. ->will($this->returnValue(null));
  449. $access->expects($this->any())
  450. ->method('readAttribute')
  451. ->will($this->returnCallback(function($dn, $attr) {
  452. if($attr === 'primaryGroupToken') {
  453. return array(1337);
  454. }
  455. return array();
  456. }));
  457. $access->expects($this->any())
  458. ->method('groupname2dn')
  459. ->will($this->returnValue('cn=foobar,dc=foo,dc=bar'));
  460. $access->expects($this->once())
  461. ->method('countUsers')
  462. ->will($this->returnValue(4));
  463. $groupBackend = new GroupLDAP($access, $pluginManager);
  464. $users = $groupBackend->countUsersInGroup('foobar');
  465. $this->assertSame(4, $users);
  466. }
  467. public function testGetUserGroupsMemberOf() {
  468. $access = $this->getAccessMock();
  469. $pluginManager = $this->getPluginManagerMock();
  470. $this->enableGroups($access);
  471. $dn = 'cn=userX,dc=foobar';
  472. $access->connection->hasPrimaryGroups = false;
  473. $access->connection->hasGidNumber = false;
  474. $access->expects($this->any())
  475. ->method('username2dn')
  476. ->will($this->returnValue($dn));
  477. $access->expects($this->exactly(3))
  478. ->method('readAttribute')
  479. ->will($this->onConsecutiveCalls(['cn=groupA,dc=foobar', 'cn=groupB,dc=foobar'], [], []));
  480. $access->expects($this->exactly(2))
  481. ->method('dn2groupname')
  482. ->will($this->returnArgument(0));
  483. $access->expects($this->exactly(1))
  484. ->method('groupsMatchFilter')
  485. ->will($this->returnArgument(0));
  486. $groupBackend = new GroupLDAP($access, $pluginManager);
  487. $groups = $groupBackend->getUserGroups('userX');
  488. $this->assertSame(2, count($groups));
  489. }
  490. public function testGetUserGroupsMemberOfDisabled() {
  491. $access = $this->getAccessMock();
  492. $pluginManager = $this->getPluginManagerMock();
  493. $access->connection = $this->createMock(Connection::class);
  494. $access->connection->expects($this->any())
  495. ->method('__get')
  496. ->will($this->returnCallback(function($name) {
  497. if($name === 'useMemberOfToDetectMembership') {
  498. return 0;
  499. } else if($name === 'ldapDynamicGroupMemberURL') {
  500. return '';
  501. }
  502. return 1;
  503. }));
  504. $dn = 'cn=userX,dc=foobar';
  505. $access->connection->hasPrimaryGroups = false;
  506. $access->connection->hasGidNumber = false;
  507. $access->expects($this->once())
  508. ->method('username2dn')
  509. ->will($this->returnValue($dn));
  510. $access->expects($this->never())
  511. ->method('readAttribute')
  512. ->with($dn, 'memberOf');
  513. $access->expects($this->once())
  514. ->method('nextcloudGroupNames')
  515. ->will($this->returnValue([]));
  516. $access->expects($this->any())
  517. ->method('groupsMatchFilter')
  518. ->willReturnArgument(0);
  519. $groupBackend = new GroupLDAP($access, $pluginManager);
  520. $groupBackend->getUserGroups('userX');
  521. }
  522. public function testGetGroupsByMember() {
  523. $access = $this->getAccessMock();
  524. $pluginManager = $this->getPluginManagerMock();
  525. $access->connection = $this->createMock(Connection::class);
  526. $access->connection->expects($this->any())
  527. ->method('__get')
  528. ->will($this->returnCallback(function($name) {
  529. switch($name) {
  530. case 'useMemberOfToDetectMembership':
  531. return 0;
  532. case 'ldapDynamicGroupMemberURL':
  533. return '';
  534. case 'ldapNestedGroups':
  535. return false;
  536. case 'ldapGroupMemberAssocAttr':
  537. return 'member';
  538. }
  539. return 1;
  540. }));
  541. $dn = 'cn=userX,dc=foobar';
  542. $access->connection->hasPrimaryGroups = false;
  543. $access->connection->hasGidNumber = false;
  544. $access->expects($this->exactly(2))
  545. ->method('username2dn')
  546. ->will($this->returnValue($dn));
  547. $access->expects($this->never())
  548. ->method('readAttribute')
  549. ->with($dn, 'memberOf');
  550. $group1 = [
  551. 'cn' => 'group1',
  552. 'dn' => ['cn=group1,ou=groups,dc=domain,dc=com'],
  553. ];
  554. $group2 = [
  555. 'cn' => 'group2',
  556. 'dn' => ['cn=group2,ou=groups,dc=domain,dc=com'],
  557. ];
  558. $access->expects($this->once())
  559. ->method('nextcloudGroupNames')
  560. ->with([$group1, $group2])
  561. ->will($this->returnValue(['group1', 'group2']));
  562. $access->expects($this->once())
  563. ->method('fetchListOfGroups')
  564. ->will($this->returnValue([$group1, $group2]));
  565. $access->expects($this->any())
  566. ->method('groupsMatchFilter')
  567. ->willReturnArgument(0);
  568. $groupBackend = new GroupLDAP($access, $pluginManager);
  569. $groups = $groupBackend->getUserGroups('userX');
  570. $this->assertEquals(['group1', 'group2'], $groups);
  571. $groupsAgain = $groupBackend->getUserGroups('userX');
  572. $this->assertEquals(['group1', 'group2'], $groupsAgain);
  573. }
  574. public function testCreateGroupWithPlugin() {
  575. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  576. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  577. ->setMethods(['implementsActions','createGroup'])
  578. ->getMock();
  579. $pluginManager->expects($this->once())
  580. ->method('implementsActions')
  581. ->with(GroupInterface::CREATE_GROUP)
  582. ->willReturn(true);
  583. $pluginManager->expects($this->once())
  584. ->method('createGroup')
  585. ->with('gid')
  586. ->willReturn('result');
  587. $access = $this->getAccessMock();
  588. $access->connection = $this->createMock(Connection::class);
  589. $ldap = new GroupLDAP($access, $pluginManager);
  590. $this->assertEquals($ldap->createGroup('gid'),true);
  591. }
  592. /**
  593. * @expectedException \Exception
  594. */
  595. public function testCreateGroupFailing() {
  596. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  597. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  598. ->setMethods(['implementsActions', 'createGroup'])
  599. ->getMock();
  600. $pluginManager->expects($this->once())
  601. ->method('implementsActions')
  602. ->with(GroupInterface::CREATE_GROUP)
  603. ->willReturn(false);
  604. $access = $this->getAccessMock();
  605. $access->connection = $this->createMock(Connection::class);
  606. $ldap = new GroupLDAP($access, $pluginManager);
  607. $ldap->createGroup('gid');
  608. }
  609. public function testDeleteGroupWithPlugin() {
  610. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  611. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  612. ->setMethods(['implementsActions','deleteGroup'])
  613. ->getMock();
  614. $pluginManager->expects($this->once())
  615. ->method('implementsActions')
  616. ->with(GroupInterface::DELETE_GROUP)
  617. ->willReturn(true);
  618. $pluginManager->expects($this->once())
  619. ->method('deleteGroup')
  620. ->with('gid')
  621. ->willReturn('result');
  622. $mapper = $this->getMockBuilder('\OCA\User_LDAP\Mapping\GroupMapping')
  623. ->setMethods(['unmap'])
  624. ->disableOriginalConstructor()
  625. ->getMock();
  626. $access = $this->getAccessMock();
  627. $access->expects($this->any())
  628. ->method('getGroupMapper')
  629. ->will($this->returnValue($mapper));
  630. $access->connection = $this->createMock(Connection::class);
  631. $ldap = new GroupLDAP($access, $pluginManager);
  632. $this->assertEquals($ldap->deleteGroup('gid'),'result');
  633. }
  634. /**
  635. * @expectedException \Exception
  636. */
  637. public function testDeleteGroupFailing() {
  638. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  639. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  640. ->setMethods(['implementsActions', 'deleteGroup'])
  641. ->getMock();
  642. $pluginManager->expects($this->once())
  643. ->method('implementsActions')
  644. ->with(GroupInterface::DELETE_GROUP)
  645. ->willReturn(false);
  646. $access = $this->getAccessMock();
  647. $access->connection = $this->createMock(Connection::class);
  648. $ldap = new GroupLDAP($access, $pluginManager);
  649. $ldap->deleteGroup('gid');
  650. }
  651. public function testAddToGroupWithPlugin() {
  652. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  653. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  654. ->setMethods(['implementsActions','addToGroup'])
  655. ->getMock();
  656. $pluginManager->expects($this->once())
  657. ->method('implementsActions')
  658. ->with(GroupInterface::ADD_TO_GROUP)
  659. ->willReturn(true);
  660. $pluginManager->expects($this->once())
  661. ->method('addToGroup')
  662. ->with('uid', 'gid')
  663. ->willReturn('result');
  664. $access = $this->getAccessMock();
  665. $access->connection = $this->createMock(Connection::class);
  666. $ldap = new GroupLDAP($access, $pluginManager);
  667. $this->assertEquals($ldap->addToGroup('uid', 'gid'),'result');
  668. }
  669. /**
  670. * @expectedException \Exception
  671. */
  672. public function testAddToGroupFailing() {
  673. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  674. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  675. ->setMethods(['implementsActions', 'addToGroup'])
  676. ->getMock();
  677. $pluginManager->expects($this->once())
  678. ->method('implementsActions')
  679. ->with(GroupInterface::ADD_TO_GROUP)
  680. ->willReturn(false);
  681. $access = $this->getAccessMock();
  682. $access->connection = $this->createMock(Connection::class);
  683. $ldap = new GroupLDAP($access, $pluginManager);
  684. $ldap->addToGroup('uid', 'gid');
  685. }
  686. public function testRemoveFromGroupWithPlugin() {
  687. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  688. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  689. ->setMethods(['implementsActions','removeFromGroup'])
  690. ->getMock();
  691. $pluginManager->expects($this->once())
  692. ->method('implementsActions')
  693. ->with(GroupInterface::REMOVE_FROM_GROUP)
  694. ->willReturn(true);
  695. $pluginManager->expects($this->once())
  696. ->method('removeFromGroup')
  697. ->with('uid', 'gid')
  698. ->willReturn('result');
  699. $access = $this->getAccessMock();
  700. $access->connection = $this->createMock(Connection::class);
  701. $ldap = new GroupLDAP($access, $pluginManager);
  702. $this->assertEquals($ldap->removeFromGroup('uid', 'gid'),'result');
  703. }
  704. /**
  705. * @expectedException \Exception
  706. */
  707. public function testRemoveFromGroupFailing() {
  708. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  709. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  710. ->setMethods(['implementsActions', 'removeFromGroup'])
  711. ->getMock();
  712. $pluginManager->expects($this->once())
  713. ->method('implementsActions')
  714. ->with(GroupInterface::REMOVE_FROM_GROUP)
  715. ->willReturn(false);
  716. $access = $this->getAccessMock();
  717. $access->connection = $this->createMock(Connection::class);
  718. $ldap = new GroupLDAP($access, $pluginManager);
  719. $ldap->removeFromGroup('uid', 'gid');
  720. }
  721. public function testGetGroupDetailsWithPlugin() {
  722. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  723. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  724. ->setMethods(['implementsActions','getGroupDetails'])
  725. ->getMock();
  726. $pluginManager->expects($this->once())
  727. ->method('implementsActions')
  728. ->with(GroupInterface::GROUP_DETAILS)
  729. ->willReturn(true);
  730. $pluginManager->expects($this->once())
  731. ->method('getGroupDetails')
  732. ->with('gid')
  733. ->willReturn('result');
  734. $access = $this->getAccessMock();
  735. $access->connection = $this->createMock(Connection::class);
  736. $ldap = new GroupLDAP($access, $pluginManager);
  737. $this->assertEquals($ldap->getGroupDetails('gid'),'result');
  738. }
  739. /**
  740. * @expectedException \Exception
  741. */
  742. public function testGetGroupDetailsFailing() {
  743. /** @var GroupPluginManager|\PHPUnit_Framework_MockObject_MockObject $pluginManager */
  744. $pluginManager = $this->getMockBuilder('\OCA\User_LDAP\GroupPluginManager')
  745. ->setMethods(['implementsActions', 'getGroupDetails'])
  746. ->getMock();
  747. $pluginManager->expects($this->once())
  748. ->method('implementsActions')
  749. ->with(GroupInterface::GROUP_DETAILS)
  750. ->willReturn(false);
  751. $access = $this->getAccessMock();
  752. $access->connection = $this->createMock(Connection::class);
  753. $ldap = new GroupLDAP($access, $pluginManager);
  754. $ldap->getGroupDetails('gid');
  755. }
  756. public function groupMemberProvider() {
  757. $base = 'dc=species,dc=earth';
  758. $groups0 = [
  759. 'uid=3723,' . $base,
  760. 'uid=8372,' . $base,
  761. 'uid=8427,' . $base,
  762. 'uid=2333,' . $base,
  763. 'uid=4754,' . $base,
  764. ];
  765. $groups1 = [
  766. '3723',
  767. '8372',
  768. '8427',
  769. '2333',
  770. '4754',
  771. ];
  772. $groups2Nested = ['6642', '1424'];
  773. $expGroups2 = array_merge($groups1, $groups2Nested);
  774. return [
  775. [ #0 – test DNs
  776. 'cn=Birds,' . $base,
  777. $groups0,
  778. ['cn=Birds,' . $base => $groups0]
  779. ],
  780. [ #1 – test uids
  781. 'cn=Birds,' . $base,
  782. $groups1,
  783. ['cn=Birds,' . $base => $groups1]
  784. ],
  785. ];
  786. }
  787. /**
  788. * @param string $groupDN
  789. * @param string[] $expectedMembers
  790. * @param array $groupsInfo
  791. * @dataProvider groupMemberProvider
  792. */
  793. public function testGroupMembers($groupDN, $expectedMembers, $groupsInfo = null) {
  794. $access = $this->getAccessMock();
  795. $access->expects($this->any())
  796. ->method('readAttribute')
  797. ->willReturnCallback(function($group) use ($groupDN, $expectedMembers, $groupsInfo) {
  798. if(isset($groupsInfo[$group])) {
  799. return $groupsInfo[$group];
  800. }
  801. return [];
  802. });
  803. $access->connection = $this->createMock(Connection::class);
  804. if(count($groupsInfo) > 1) {
  805. $access->connection->expects($this->any())
  806. ->method('__get')
  807. ->willReturnCallback(function($name) {
  808. if($name === 'ldapNestedGroups') {
  809. return 1;
  810. }
  811. return null;
  812. });
  813. }
  814. /** @var GroupPluginManager $pluginManager */
  815. $pluginManager = $this->createMock(GroupPluginManager::class);
  816. $ldap = new GroupLDAP($access, $pluginManager);
  817. $resultingMembers = $this->invokePrivate($ldap, '_groupMembers', [$groupDN]);
  818. $this->assertEquals($expectedMembers, $resultingMembers, '', 0.0, 10, true);
  819. }
  820. public function displayNameProvider() {
  821. return [
  822. ['Graphic Novelists', ['Graphic Novelists']],
  823. ['', false],
  824. ];
  825. }
  826. /**
  827. * @dataProvider displayNameProvider
  828. */
  829. public function testGetDisplayName(string $expected, $ldapResult) {
  830. $gid = 'graphic_novelists';
  831. $access = $this->getAccessMock();
  832. $access->expects($this->atLeastOnce())
  833. ->method('readAttribute')
  834. ->willReturn($ldapResult);
  835. $access->connection = $this->createMock(Connection::class);
  836. $access->connection->expects($this->any())
  837. ->method('__get')
  838. ->willReturnCallback(function($name) {
  839. if($name === 'ldapGroupMemberAssocAttr') {
  840. return 'member';
  841. } else if($name === 'ldapGroupFilter') {
  842. return 'objectclass=nextcloudGroup';
  843. } else if($name === 'ldapGroupDisplayName') {
  844. return 'cn';
  845. }
  846. return null;
  847. });
  848. /** @var GroupPluginManager $pluginManager */
  849. $pluginManager = $this->createMock(GroupPluginManager::class);
  850. $ldap = new GroupLDAP($access, $pluginManager);
  851. $this->assertSame($expected, $ldap->getDisplayName($gid));
  852. }
  853. }