Skip to content

Commit e858b2b

Browse files
committed
Add method to read multi-value attributes from ldap.
Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
1 parent eb4e4c4 commit e858b2b

File tree

3 files changed

+228
-10
lines changed

3 files changed

+228
-10
lines changed

apps/user_ldap/lib/LDAPProvider.php

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -315,26 +315,42 @@ public function getLDAPGroupMemberAssoc($gid) {
315315
* @throws \Exception if user id was not found in LDAP
316316
*/
317317
public function getUserAttribute(string $uid, string $attribute): ?string {
318+
$values = $this->getMultiValueUserAttribute($uid, $attribute);
319+
if (count($values) === 0) {
320+
return null;
321+
}
322+
return current($values);
323+
}
324+
325+
/**
326+
* Get a multi-value LDAP attribute for a nextcloud user
327+
*
328+
* @param string $uid
329+
* @param string $attribute
330+
* @return mixed
331+
* @throws \Exception if user id was not found in LDAP
332+
* @since 22.0.0
333+
*/
334+
public function getMultiValueUserAttribute(string $uid, string $attribute): array {
318335
if (!$this->userBackend->userExists($uid)) {
319336
throw new \Exception('User id not found in LDAP');
320337
}
338+
321339
$access = $this->userBackend->getLDAPAccess($uid);
322340
$connection = $access->getConnection();
323-
$key = $uid . "::" . $attribute;
324-
$cached = $connection->getFromCache($key);
341+
$key = $uid . '-' . $attribute;
325342

326-
if ($cached !== null) {
343+
$cached = $connection->getFromCache($key);
344+
if (is_array($cached)) {
327345
return $cached;
328346
}
329347

330-
$value = $access->readAttribute($access->username2dn($uid), $attribute);
331-
if (is_array($value) && count($value) > 0) {
332-
$value = current($value);
333-
} else {
334-
return null;
348+
$values = $access->readAttribute($access->username2dn($uid), $attribute);
349+
if ($values === false) {
350+
$values = [];
335351
}
336-
$connection->writeToCache($key, $value);
337352

338-
return $value;
353+
$connection->writeToCache($key, $values);
354+
return $values;
339355
}
340356
}

apps/user_ldap/tests/LDAPProviderTest.php

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
use OC\User\Manager;
3232
use OCA\User_LDAP\Access;
3333
use OCA\User_LDAP\Connection;
34+
use OCA\User_LDAP\Group_LDAP;
3435
use OCA\User_LDAP\IGroupLDAP;
3536
use OCA\User_LDAP\IUserLDAP;
37+
use OCA\User_LDAP\User_LDAP;
3638
use OCP\EventDispatcher\IEventDispatcher;
3739
use OCP\ICacheFactory;
3840
use OCP\IConfig;
@@ -697,4 +699,193 @@ public function testgetLDAPGroupMemberAssoc() {
697699
$ldapProvider = $this->getLDAPProvider($server);
698700
$this->assertEquals('assoc_type', $ldapProvider->getLDAPGroupMemberAssoc('existing_group'));
699701
}
702+
703+
public function testGetMultiValueUserAttributeUserNotFound() {
704+
$this->expectException(\Exception::class);
705+
$this->expectExceptionMessage('User id not found in LDAP');
706+
707+
$userBackend = $this->createMock(User_LDAP::class);
708+
$userBackend->expects(self::once())
709+
->method('userExists')
710+
->with('admin')
711+
->willReturn(false);
712+
$groupBackend = $this->createMock(Group_LDAP::class);
713+
$server = $this->getServerMock($userBackend, $groupBackend);
714+
715+
$ldapProvider = $this->getLDAPProvider($server);
716+
$ldapProvider->getMultiValueUserAttribute('admin', 'mailAlias');
717+
}
718+
719+
public function testGetMultiValueUserAttributeCacheHit() {
720+
$connection = $this->createMock(Connection::class);
721+
$connection->expects(self::once())
722+
->method('getFromCache')
723+
->with('admin-mailAlias')
724+
->willReturn(['aliasA@test.local', 'aliasB@test.local']);
725+
$access = $this->createMock(Access::class);
726+
$access->expects(self::once())
727+
->method('getConnection')
728+
->willReturn($connection);
729+
$userBackend = $this->createMock(User_LDAP::class);
730+
$userBackend->expects(self::once())
731+
->method('userExists')
732+
->with('admin')
733+
->willReturn(true);
734+
$userBackend->expects(self::once())
735+
->method('getLDAPAccess')
736+
->willReturn($access);
737+
$groupBackend = $this->createMock(Group_LDAP::class);
738+
$server = $this->getServerMock($userBackend, $groupBackend);
739+
740+
$ldapProvider = $this->getLDAPProvider($server);
741+
$ldapProvider->getMultiValueUserAttribute('admin', 'mailAlias');
742+
}
743+
744+
public function testGetMultiValueUserAttributeLdapError() {
745+
$connection = $this->createMock(Connection::class);
746+
$connection->expects(self::once())
747+
->method('getFromCache')
748+
->with('admin-mailAlias')
749+
->willReturn(null);
750+
$access = $this->createMock(Access::class);
751+
$access->expects(self::once())
752+
->method('getConnection')
753+
->willReturn($connection);
754+
$access->expects(self::once())
755+
->method('username2dn')
756+
->with('admin')
757+
->willReturn('admin');
758+
$access->expects(self::once())
759+
->method('readAttribute')
760+
->with('admin', 'mailAlias')
761+
->willReturn(false);
762+
$userBackend = $this->getMockBuilder(User_LDAP::class)
763+
->disableOriginalConstructor()
764+
->getMock();
765+
$userBackend->method('userExists')
766+
->with('admin')
767+
->willReturn(true);
768+
$userBackend->method('getLDAPAccess')
769+
->willReturn($access);
770+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
771+
->disableOriginalConstructor()
772+
->getMock();
773+
$server = $this->getServerMock($userBackend, $groupBackend);
774+
775+
$ldapProvider = $this->getLDAPProvider($server);
776+
$values = $ldapProvider->getMultiValueUserAttribute('admin', 'mailAlias');
777+
778+
self::assertCount(0, $values);
779+
}
780+
781+
public function testGetMultiValueUserAttribute() {
782+
$connection = $this->createMock(Connection::class);
783+
$connection->expects(self::once())
784+
->method('getFromCache')
785+
->with('admin-mailAlias')
786+
->willReturn(null);
787+
$access = $this->createMock(Access::class);
788+
$access->expects(self::once())
789+
->method('getConnection')
790+
->willReturn($connection);
791+
$access->expects(self::once())
792+
->method('username2dn')
793+
->with('admin')
794+
->willReturn('admin');
795+
$access->expects(self::once())
796+
->method('readAttribute')
797+
->with('admin', 'mailAlias')
798+
->willReturn(['aliasA@test.local', 'aliasB@test.local']);
799+
$userBackend = $this->getMockBuilder(User_LDAP::class)
800+
->disableOriginalConstructor()
801+
->getMock();
802+
$userBackend->method('userExists')
803+
->with('admin')
804+
->willReturn(true);
805+
$userBackend->method('getLDAPAccess')
806+
->willReturn($access);
807+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
808+
->disableOriginalConstructor()
809+
->getMock();
810+
$server = $this->getServerMock($userBackend, $groupBackend);
811+
812+
$ldapProvider = $this->getLDAPProvider($server);
813+
$values = $ldapProvider->getMultiValueUserAttribute('admin', 'mailAlias');
814+
815+
self::assertCount(2, $values);
816+
}
817+
818+
public function testGetUserAttributeLdapError() {
819+
$connection = $this->createMock(Connection::class);
820+
$connection->expects(self::once())
821+
->method('getFromCache')
822+
->with('admin-mailAlias')
823+
->willReturn(null);
824+
$access = $this->createMock(Access::class);
825+
$access->expects(self::once())
826+
->method('getConnection')
827+
->willReturn($connection);
828+
$access->expects(self::once())
829+
->method('username2dn')
830+
->with('admin')
831+
->willReturn('admin');
832+
$access->expects(self::once())
833+
->method('readAttribute')
834+
->with('admin', 'mailAlias')
835+
->willReturn(false);
836+
$userBackend = $this->getMockBuilder(User_LDAP::class)
837+
->disableOriginalConstructor()
838+
->getMock();
839+
$userBackend->method('userExists')
840+
->with('admin')
841+
->willReturn(true);
842+
$userBackend->method('getLDAPAccess')
843+
->willReturn($access);
844+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
845+
->disableOriginalConstructor()
846+
->getMock();
847+
$server = $this->getServerMock($userBackend, $groupBackend);
848+
849+
$ldapProvider = $this->getLDAPProvider($server);
850+
$value = $ldapProvider->getUserAttribute('admin', 'mailAlias');
851+
852+
self::assertNull($value);
853+
}
854+
855+
public function testGetUserAttribute() {
856+
$connection = $this->createMock(Connection::class);
857+
$connection->expects(self::once())
858+
->method('getFromCache')
859+
->with('admin-mailAlias')
860+
->willReturn(null);
861+
$access = $this->createMock(Access::class);
862+
$access->expects(self::once())
863+
->method('getConnection')
864+
->willReturn($connection);
865+
$access->expects(self::once())
866+
->method('username2dn')
867+
->with('admin')
868+
->willReturn('admin');
869+
$access->expects(self::once())
870+
->method('readAttribute')
871+
->with('admin', 'mailAlias')
872+
->willReturn(['aliasA@test.local', 'aliasB@test.local']);
873+
$userBackend = $this->getMockBuilder(User_LDAP::class)
874+
->disableOriginalConstructor()
875+
->getMock();
876+
$userBackend->method('userExists')
877+
->with('admin')
878+
->willReturn(true);
879+
$userBackend->method('getLDAPAccess')
880+
->willReturn($access);
881+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
882+
->disableOriginalConstructor()
883+
->getMock();
884+
$server = $this->getServerMock($userBackend, $groupBackend);
885+
886+
$ldapProvider = $this->getLDAPProvider($server);
887+
$value = $ldapProvider->getUserAttribute('admin', 'mailAlias');
888+
889+
self::assertEquals('aliasA@test.local', $value);
890+
}
700891
}

lib/public/LDAP/ILDAPProvider.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,15 @@ public function getLDAPGroupMemberAssoc($gid);
168168
* @since 21.0.0
169169
*/
170170
public function getUserAttribute(string $uid, string $attribute): ?string;
171+
172+
/**
173+
* Get a multi-value LDAP attribute for a nextcloud user
174+
*
175+
* @param string $uid
176+
* @param string $attribute
177+
* @return mixed
178+
* @throws \Exception if user id was not found in LDAP
179+
* @since 22.0.0
180+
*/
181+
public function getMultiValueUserAttribute(string $uid, string $attribute): array;
171182
}

0 commit comments

Comments
 (0)