Skip to content

Commit 15f4ff4

Browse files
committed
feat(ldap): Allow to search one user by one of its LDAP attribute
Signed-off-by: Carl Schwan <carlschwan@kde.org>
1 parent aa904b2 commit 15f4ff4

7 files changed

Lines changed: 158 additions & 81 deletions

File tree

apps/user_ldap/lib/IUserLDAP.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
*/
99
namespace OCA\User_LDAP;
1010

11+
use OCP\IUser;
12+
use OCP\LDAP\Exceptions\MultipleUsersReturnedException;
13+
1114
interface IUserLDAP {
1215

1316
//Functions used by LDAPProvider
@@ -32,4 +35,14 @@ public function getNewLDAPConnection($uid);
3235
* @return string|false with the username
3336
*/
3437
public function dn2UserName($dn);
38+
39+
/**
40+
* Fetches one user from LDAP based on a filter or a custom attribute and search term.
41+
*
42+
* @param string $attribute The LDAP attribute name to search against (e.g., 'mail', 'cn', 'uid').
43+
* @param string $searchTerm The search term to match against the attribute. Will be escaped for LDAP filter safety.
44+
* @return IUser|null Returns an IUser if found in LDAP using the configured LDAP filter, or null if no user is found.
45+
* @throws MultipleUsersReturnedException if multiple users have been found (search query should not allow this)
46+
*/
47+
public function getUserFromCustomAttribute(string $attribute, string $searchTerm): ?IUser;
3548
}

apps/user_ldap/lib/LDAPProvider.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use OCA\User_LDAP\User\DeletedUsersIndex;
1313
use OCP\GroupInterface;
1414
use OCP\IGroupManager;
15+
use OCP\IUser;
1516
use OCP\IUserManager;
1617
use OCP\LDAP\IDeletionFlagSupport;
1718
use OCP\LDAP\ILDAPProvider;
@@ -301,4 +302,8 @@ public function getMultiValueUserAttribute(string $uid, string $attribute): arra
301302
$connection->writeToCache($key, $values);
302303
return $values;
303304
}
305+
306+
public function findOneUserByAttributeValue(string $attribute, string $searchTerm): ?IUser {
307+
return $this->userBackend->getUserFromCustomAttribute($attribute, $searchTerm);
308+
}
304309
}

apps/user_ldap/lib/User_LDAP.php

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,27 @@
1515
use OCA\User_LDAP\User\OfflineUser;
1616
use OCA\User_LDAP\User\User;
1717
use OCP\Accounts\IAccountManager;
18+
use OCP\IUser;
1819
use OCP\IUserBackend;
20+
use OCP\IUserManager;
21+
use OCP\LDAP\Exceptions\MultipleUsersReturnedException;
1922
use OCP\Notification\IManager as INotificationManager;
2023
use OCP\User\Backend\ICountMappedUsersBackend;
2124
use OCP\User\Backend\ILimitAwareCountUsersBackend;
2225
use OCP\User\Backend\IPropertyPermissionBackend;
2326
use OCP\User\Backend\IProvideEnabledStateBackend;
2427
use OCP\UserInterface;
28+
use Override;
2529
use Psr\Log\LoggerInterface;
2630

2731
class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, IUserLDAP, ILimitAwareCountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend, IPropertyPermissionBackend {
2832
public function __construct(
2933
Access $access,
30-
protected INotificationManager $notificationManager,
31-
protected UserPluginManager $userPluginManager,
32-
protected LoggerInterface $logger,
33-
protected DeletedUsersIndex $deletedUsersIndex,
34+
protected readonly INotificationManager $notificationManager,
35+
protected readonly UserPluginManager $userPluginManager,
36+
protected readonly LoggerInterface $logger,
37+
protected readonly DeletedUsersIndex $deletedUsersIndex,
38+
protected readonly IuserManager $userManager,
3439
) {
3540
parent::__construct($access);
3641
}
@@ -684,4 +689,23 @@ public function canEditProperty(string $uid, string $property): bool {
684689
default => true,
685690
};
686691
}
692+
693+
#[Override]
694+
public function getUserFromCustomAttribute(string $attribute, string $searchTerm): ?IUser {
695+
$searchTerm = $this->access->escapeFilterPart($searchTerm);
696+
$filter = "($attribute=$searchTerm)";
697+
698+
$records = $this->access->searchUsers($filter, ['dn']);
699+
if (count($records) === 1) {
700+
$ldapUser = $this->access->userManager->get($records[0]['dn'][0]);
701+
return $this->userManager->get($ldapUser->getUsername());
702+
} elseif (count($records) > 1) {
703+
$this->logger->error(
704+
'Multiple users found for filter: ' . $filter,
705+
['app' => 'user_ldap']
706+
);
707+
throw new MultipleUsersReturnedException();
708+
}
709+
return null;
710+
}
687711
}

apps/user_ldap/lib/User_Proxy.php

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
use OCA\User_LDAP\User\DeletedUsersIndex;
1111
use OCA\User_LDAP\User\OfflineUser;
1212
use OCA\User_LDAP\User\User;
13+
use OCP\IUser;
1314
use OCP\IUserBackend;
15+
use OCP\IUserManager;
16+
use OCP\LDAP\Exceptions\MultipleUsersReturnedException;
1417
use OCP\Notification\IManager as INotificationManager;
1518
use OCP\User\Backend\ICountMappedUsersBackend;
1619
use OCP\User\Backend\IGetDisplayNameBackend;
@@ -25,13 +28,14 @@
2528
*/
2629
class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP, ILimitAwareCountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend, IGetDisplayNameBackend, IPropertyPermissionBackend {
2730
public function __construct(
28-
private Helper $helper,
31+
Helper $helper,
2932
ILDAPWrapper $ldap,
3033
AccessFactory $accessFactory,
31-
private INotificationManager $notificationManager,
32-
private UserPluginManager $userPluginManager,
33-
private LoggerInterface $logger,
34-
private DeletedUsersIndex $deletedUsersIndex,
34+
private readonly INotificationManager $notificationManager,
35+
private readonly UserPluginManager $userPluginManager,
36+
private readonly LoggerInterface $logger,
37+
private readonly DeletedUsersIndex $deletedUsersIndex,
38+
private readonly IUserManager $userManager,
3539
) {
3640
parent::__construct($helper, $ldap, $accessFactory);
3741
}
@@ -43,6 +47,7 @@ protected function newInstance(string $configPrefix): User_LDAP {
4347
$this->userPluginManager,
4448
$this->logger,
4549
$this->deletedUsersIndex,
50+
$this->userManager,
4651
);
4752
}
4853

@@ -437,4 +442,18 @@ public function getDisabledUserList(?int $limit = null, int $offset = 0, string
437442
public function canEditProperty(string $uid, string $property): bool {
438443
return $this->handleRequest($uid, 'canEditProperty', [$uid, $property]);
439444
}
445+
446+
public function getUserFromCustomAttribute(string $attribute, string $searchTerm): ?IUser {
447+
$this->setup();
448+
$user = null;
449+
foreach ($this->backends as $backend) {
450+
$fetchUser = $backend->getUserFromCustomAttribute($attribute, $searchTerm);
451+
// if we found a different user, no need to continue
452+
if ($user !== null && $fetchUser !== null && $fetchUser->getUID() !== $user->getUID()) {
453+
throw new MultipleUsersReturnedException('Multiple users found for custom attribute search');
454+
}
455+
$user = $fetchUser; // may be null
456+
}
457+
return $user;
458+
}
440459
}

0 commit comments

Comments
 (0)