Skip to content

Commit 610a240

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

3 files changed

Lines changed: 231 additions & 10 deletions

File tree

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: 194 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,196 @@ 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->getMockBuilder(User_LDAP::class)
708+
->disableOriginalConstructor()
709+
->getMock();
710+
$userBackend->method('userExists')
711+
->with('admin')
712+
->willReturn(false);
713+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
714+
->disableOriginalConstructor()
715+
->getMock();
716+
$server = $this->getServerMock($userBackend, $groupBackend);
717+
718+
$ldapProvider = $this->getLDAPProvider($server);
719+
$ldapProvider->getMultiValueUserAttribute('admin', 'mailAlias');
720+
}
721+
722+
public function testGetMultiValueUserAttributeCacheHit() {
723+
$connection = $this->createMock(Connection::class);
724+
$connection->method('getFromCache')
725+
->with('admin-mailAlias')
726+
->willReturn(['aliasA@test.local', 'aliasB@test.local']);
727+
$access = $this->createMock(Access::class);
728+
$access->method('getConnection')
729+
->willReturn($connection);
730+
$userBackend = $this->getMockBuilder(User_LDAP::class)
731+
->disableOriginalConstructor()
732+
->getMock();
733+
$userBackend->method('userExists')
734+
->with('admin')
735+
->willReturn(true);
736+
$userBackend->method('getLDAPAccess')
737+
->willReturn($access);
738+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
739+
->disableOriginalConstructor()
740+
->getMock();
741+
$server = $this->getServerMock($userBackend, $groupBackend);
742+
743+
$ldapProvider = $this->getLDAPProvider($server);
744+
$ldapProvider->getMultiValueUserAttribute('admin', 'mailAlias');
745+
}
746+
747+
public function testGetMultiValueUserAttributeLdapError() {
748+
$connection = $this->createMock(Connection::class);
749+
$connection->expects(self::once())
750+
->method('getFromCache')
751+
->with('admin-mailAlias')
752+
->willReturn(null);
753+
$access = $this->createMock(Access::class);
754+
$access->expects(self::once())
755+
->method('getConnection')
756+
->willReturn($connection);
757+
$access->expects(self::once())
758+
->method('username2dn')
759+
->with('admin')
760+
->willReturn('admin');
761+
$access->expects(self::once())
762+
->method('readAttribute')
763+
->with('admin', 'mailAlias')
764+
->willReturn(false);
765+
$userBackend = $this->getMockBuilder(User_LDAP::class)
766+
->disableOriginalConstructor()
767+
->getMock();
768+
$userBackend->method('userExists')
769+
->with('admin')
770+
->willReturn(true);
771+
$userBackend->method('getLDAPAccess')
772+
->willReturn($access);
773+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
774+
->disableOriginalConstructor()
775+
->getMock();
776+
$server = $this->getServerMock($userBackend, $groupBackend);
777+
778+
$ldapProvider = $this->getLDAPProvider($server);
779+
$values = $ldapProvider->getMultiValueUserAttribute('admin', 'mailAlias');
780+
781+
self::assertCount(0, $values);
782+
}
783+
784+
public function testGetMultiValueUserAttribute() {
785+
$connection = $this->createMock(Connection::class);
786+
$connection->expects(self::once())
787+
->method('getFromCache')
788+
->with('admin-mailAlias')
789+
->willReturn(null);
790+
$access = $this->createMock(Access::class);
791+
$access->expects(self::once())
792+
->method('getConnection')
793+
->willReturn($connection);
794+
$access->expects(self::once())
795+
->method('username2dn')
796+
->with('admin')
797+
->willReturn('admin');
798+
$access->expects(self::once())
799+
->method('readAttribute')
800+
->with('admin', 'mailAlias')
801+
->willReturn(['aliasA@test.local', 'aliasB@test.local']);
802+
$userBackend = $this->getMockBuilder(User_LDAP::class)
803+
->disableOriginalConstructor()
804+
->getMock();
805+
$userBackend->method('userExists')
806+
->with('admin')
807+
->willReturn(true);
808+
$userBackend->method('getLDAPAccess')
809+
->willReturn($access);
810+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
811+
->disableOriginalConstructor()
812+
->getMock();
813+
$server = $this->getServerMock($userBackend, $groupBackend);
814+
815+
$ldapProvider = $this->getLDAPProvider($server);
816+
$values = $ldapProvider->getMultiValueUserAttribute('admin', 'mailAlias');
817+
818+
self::assertCount(2, $values);
819+
}
820+
821+
public function testGetUserAttributeLdapError() {
822+
$connection = $this->createMock(Connection::class);
823+
$connection->expects(self::once())
824+
->method('getFromCache')
825+
->with('admin-mailAlias')
826+
->willReturn(null);
827+
$access = $this->createMock(Access::class);
828+
$access->expects(self::once())
829+
->method('getConnection')
830+
->willReturn($connection);
831+
$access->expects(self::once())
832+
->method('username2dn')
833+
->with('admin')
834+
->willReturn('admin');
835+
$access->expects(self::once())
836+
->method('readAttribute')
837+
->with('admin', 'mailAlias')
838+
->willReturn(false);
839+
$userBackend = $this->getMockBuilder(User_LDAP::class)
840+
->disableOriginalConstructor()
841+
->getMock();
842+
$userBackend->method('userExists')
843+
->with('admin')
844+
->willReturn(true);
845+
$userBackend->method('getLDAPAccess')
846+
->willReturn($access);
847+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
848+
->disableOriginalConstructor()
849+
->getMock();
850+
$server = $this->getServerMock($userBackend, $groupBackend);
851+
852+
$ldapProvider = $this->getLDAPProvider($server);
853+
$value = $ldapProvider->getUserAttribute('admin', 'mailAlias');
854+
855+
self::assertNull($value);
856+
}
857+
858+
public function testGetUserAttribute() {
859+
$connection = $this->createMock(Connection::class);
860+
$connection->expects(self::once())
861+
->method('getFromCache')
862+
->with('admin-mailAlias')
863+
->willReturn(null);
864+
$access = $this->createMock(Access::class);
865+
$access->expects(self::once())
866+
->method('getConnection')
867+
->willReturn($connection);
868+
$access->expects(self::once())
869+
->method('username2dn')
870+
->with('admin')
871+
->willReturn('admin');
872+
$access->expects(self::once())
873+
->method('readAttribute')
874+
->with('admin', 'mailAlias')
875+
->willReturn(['aliasA@test.local', 'aliasB@test.local']);
876+
$userBackend = $this->getMockBuilder(User_LDAP::class)
877+
->disableOriginalConstructor()
878+
->getMock();
879+
$userBackend->method('userExists')
880+
->with('admin')
881+
->willReturn(true);
882+
$userBackend->method('getLDAPAccess')
883+
->willReturn($access);
884+
$groupBackend = $this->getMockBuilder(Group_LDAP::class)
885+
->disableOriginalConstructor()
886+
->getMock();
887+
$server = $this->getServerMock($userBackend, $groupBackend);
888+
889+
$ldapProvider = $this->getLDAPProvider($server);
890+
$value = $ldapProvider->getUserAttribute('admin', 'mailAlias');
891+
892+
self::assertEquals('aliasA@test.local', $value);
893+
}
700894
}

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)