From b38149edaa5fea26704c15ba4f0313302e837819 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 14 Jan 2021 16:51:13 +0100 Subject: [PATCH] extend ILDAPProvider to allow reading arbitrairy ldap attributes for users Signed-off-by: Robin Appelman --- apps/user_ldap/lib/LDAPProvider.php | 53 +++++++++++++++++++++++------ lib/public/LDAP/ILDAPProvider.php | 24 +++++++++---- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/apps/user_ldap/lib/LDAPProvider.php b/apps/user_ldap/lib/LDAPProvider.php index 370cc3e282..c63bca9724 100644 --- a/apps/user_ldap/lib/LDAPProvider.php +++ b/apps/user_ldap/lib/LDAPProvider.php @@ -42,7 +42,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { private $logger; private $helper; private $deletedUsersIndex; - + /** * Create new LDAPProvider * @param \OCP\IServerContainer $serverContainer @@ -77,7 +77,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { throw new \Exception('To use the LDAPProvider, user_ldap app must be enabled'); } } - + /** * Translate an user id to LDAP DN * @param string $uid user id @@ -126,7 +126,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { } return $result; } - + /** * Convert a stored DN so it can be used as base parameter for LDAP queries. * @param string $dn the DN in question @@ -135,7 +135,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { public function DNasBaseParameter($dn) { return $this->helper->DNasBaseParameter($dn); } - + /** * Sanitize a DN received from the LDAP server. * @param array $dn the DN in question @@ -144,7 +144,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { public function sanitizeDN($dn) { return $this->helper->sanitizeDN($dn); } - + /** * Return a new LDAP connection resource for the specified user. * The connection must be closed manually. @@ -172,7 +172,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { } return $this->groupBackend->getNewLDAPConnection($gid); } - + /** * Get the LDAP base for users. * @param string $uid user id @@ -202,7 +202,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { ); return array_shift($bases); } - + /** * Get the LDAP base for groups. * @param string $uid user id @@ -216,7 +216,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { $bases = $this->userBackend->getLDAPAccess($uid)->getConnection()->ldapBaseGroups; return array_shift($bases); } - + /** * Clear the cache if a cache is used, otherwise do nothing. * @param string $uid user id @@ -241,7 +241,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { } $this->groupBackend->getLDAPAccess($gid)->getConnection()->clearCache(); } - + /** * Check whether a LDAP DN exists * @param string $dn LDAP DN @@ -251,7 +251,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { $result = $this->userBackend->dn2UserName($dn); return !$result ? false : true; } - + /** * Flag record for deletion. * @param string $uid user id @@ -259,7 +259,7 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { public function flagRecord($uid) { $this->deletedUsersIndex->markUser($uid); } - + /** * Unflag record for deletion. * @param string $uid user id @@ -306,4 +306,35 @@ class LDAPProvider implements ILDAPProvider, IDeletionFlagSupport { } return $this->groupBackend->getLDAPAccess($gid)->getConnection()->getConfiguration()['ldap_group_member_assoc_attribute']; } + + /** + * Get an LDAP attribute for a nextcloud user + * @param string $uid the nextcloud user id to get the attribute for + * @param string $attribute the name of the attribute to read + * @return string|null + * @throws \Exception if user id was not found in LDAP + */ + public function getUserAttribute(string $uid, string $attribute): ?string { + if (!$this->userBackend->userExists($uid)) { + throw new \Exception('User id not found in LDAP'); + } + $access = $this->userBackend->getLDAPAccess($uid); + $connection = $access->getConnection(); + $key = $uid . "::" . $attribute; + $cached = $connection->getFromCache($key); + + if ($cached !== null) { + return $cached; + } + + $value = $access->readAttribute($access->username2dn($uid), $attribute); + if (is_array($value) && count($value) > 0) { + $value = current($value); + } else { + return null; + } + $connection->writeToCache($key, $value); + + return $value; + } } diff --git a/lib/public/LDAP/ILDAPProvider.php b/lib/public/LDAP/ILDAPProvider.php index d33e585893..cbd5c353c5 100644 --- a/lib/public/LDAP/ILDAPProvider.php +++ b/lib/public/LDAP/ILDAPProvider.php @@ -58,7 +58,7 @@ interface ILDAPProvider { * @since 11.0.0 */ public function getUserName($dn); - + /** * Convert a stored DN so it can be used as base parameter for LDAP queries. * @param string $dn the DN @@ -66,7 +66,7 @@ interface ILDAPProvider { * @since 11.0.0 */ public function DNasBaseParameter($dn); - + /** * Sanitize a DN received from the LDAP server. * @param array $dn the DN in question @@ -74,7 +74,7 @@ interface ILDAPProvider { * @since 11.0.0 */ public function sanitizeDN($dn); - + /** * Return a new LDAP connection resource for the specified user. * @param string $uid user id @@ -90,7 +90,7 @@ interface ILDAPProvider { * @since 13.0.0 */ public function getGroupLDAPConnection($gid); - + /** * Get the LDAP base for users. * @param string $uid user id @@ -99,7 +99,7 @@ interface ILDAPProvider { * @since 11.0.0 */ public function getLDAPBaseUsers($uid); - + /** * Get the LDAP base for groups. * @param string $uid user id @@ -108,7 +108,7 @@ interface ILDAPProvider { * @since 11.0.0 */ public function getLDAPBaseGroups($uid); - + /** * Check whether a LDAP DN exists * @param string $dn LDAP DN @@ -116,7 +116,7 @@ interface ILDAPProvider { * @since 11.0.0 */ public function dnExists($dn); - + /** * Clear the cache if a cache is used, otherwise do nothing. * @param string $uid user id @@ -157,4 +157,14 @@ interface ILDAPProvider { * @since 13.0.0 */ public function getLDAPGroupMemberAssoc($gid); + + /** + * Get an LDAP attribute for a nextcloud user + * @param string $uid the nextcloud user id to get the attribute for + * @param string $attribute the name of the attribute to read + * @return string|null + * @throws \Exception if user id was not found in LDAP + * @since 22.0.0 + */ + public function getUserAttribute(string $uid, string $attribute): ?string; }