Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions apps/user_ldap/lib/IUserLDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
*/
namespace OCA\User_LDAP;

use OCP\IUser;
use OCP\LDAP\Exceptions\MultipleUsersReturnedException;

interface IUserLDAP {

//Functions used by LDAPProvider
Expand All @@ -32,4 +35,14 @@ public function getNewLDAPConnection($uid);
* @return string|false with the username
*/
public function dn2UserName($dn);

/**
* Fetches one user from LDAP based on a filter or a custom attribute and search term.
*
* @param string $attribute The LDAP attribute name to search against (e.g., 'mail', 'cn', 'uid').
* @param string $searchTerm The search term to match against the attribute. Will be escaped for LDAP filter safety.
* @return IUser|null Returns an IUser if found in LDAP using the configured LDAP filter, or null if no user is found.
* @throws MultipleUsersReturnedException if multiple users have been found (search query should not allow this)
*/
public function getUserFromCustomAttribute(string $attribute, string $searchTerm): ?IUser;
}
5 changes: 5 additions & 0 deletions apps/user_ldap/lib/LDAPProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCP\GroupInterface;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;
use OCP\LDAP\IDeletionFlagSupport;
use OCP\LDAP\ILDAPProvider;
Expand Down Expand Up @@ -301,4 +302,8 @@ public function getMultiValueUserAttribute(string $uid, string $attribute): arra
$connection->writeToCache($key, $values);
return $values;
}

public function findOneUserByAttributeValue(string $attribute, string $searchTerm): ?IUser {
return $this->userBackend->getUserFromCustomAttribute($attribute, $searchTerm);
}
}
32 changes: 28 additions & 4 deletions apps/user_ldap/lib/User_LDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,27 @@
use OCA\User_LDAP\User\OfflineUser;
use OCA\User_LDAP\User\User;
use OCP\Accounts\IAccountManager;
use OCP\IUser;
use OCP\IUserBackend;
use OCP\IUserManager;
use OCP\LDAP\Exceptions\MultipleUsersReturnedException;
use OCP\Notification\IManager as INotificationManager;
use OCP\User\Backend\ICountMappedUsersBackend;
use OCP\User\Backend\ILimitAwareCountUsersBackend;
use OCP\User\Backend\IPropertyPermissionBackend;
use OCP\User\Backend\IProvideEnabledStateBackend;
use OCP\UserInterface;
use Override;
use Psr\Log\LoggerInterface;

class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, IUserLDAP, ILimitAwareCountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend, IPropertyPermissionBackend {
public function __construct(
Access $access,
protected INotificationManager $notificationManager,
protected UserPluginManager $userPluginManager,
protected LoggerInterface $logger,
protected DeletedUsersIndex $deletedUsersIndex,
protected readonly INotificationManager $notificationManager,
protected readonly UserPluginManager $userPluginManager,
protected readonly LoggerInterface $logger,
protected readonly DeletedUsersIndex $deletedUsersIndex,
protected readonly IuserManager $userManager,
) {
parent::__construct($access);
}
Expand Down Expand Up @@ -684,4 +689,23 @@ public function canEditProperty(string $uid, string $property): bool {
default => true,
};
}

#[Override]
public function getUserFromCustomAttribute(string $attribute, string $searchTerm): ?IUser {
$searchTerm = $this->access->escapeFilterPart($searchTerm);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should $attribute be escaped or validated 🤔

$filter = "($attribute=$searchTerm)";

$records = $this->access->searchUsers($filter, ['dn']);
if (count($records) === 1) {
$ldapUser = $this->access->userManager->get($records[0]['dn'][0]);
return $this->userManager->get($ldapUser->getUsername());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should return the uid as a string to be consistent with the rest of the class and avoid having to inject UserManager in there.
Then LDAPProvider can wrap the UID in an IUser using IUserManager->getExistingUser.

} elseif (count($records) > 1) {
$this->logger->error(
'Multiple users found for filter: ' . $filter,
['app' => 'user_ldap']
);
throw new MultipleUsersReturnedException();
}
return null;
}
}
29 changes: 24 additions & 5 deletions apps/user_ldap/lib/User_Proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User\OfflineUser;
use OCA\User_LDAP\User\User;
use OCP\IUser;
use OCP\IUserBackend;
use OCP\IUserManager;
use OCP\LDAP\Exceptions\MultipleUsersReturnedException;
use OCP\Notification\IManager as INotificationManager;
use OCP\User\Backend\ICountMappedUsersBackend;
use OCP\User\Backend\IGetDisplayNameBackend;
Expand All @@ -25,13 +28,14 @@
*/
class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP, ILimitAwareCountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend, IGetDisplayNameBackend, IPropertyPermissionBackend {
public function __construct(
private Helper $helper,
Helper $helper,
ILDAPWrapper $ldap,
AccessFactory $accessFactory,
private INotificationManager $notificationManager,
private UserPluginManager $userPluginManager,
private LoggerInterface $logger,
private DeletedUsersIndex $deletedUsersIndex,
private readonly INotificationManager $notificationManager,
private readonly UserPluginManager $userPluginManager,
private readonly LoggerInterface $logger,
private readonly DeletedUsersIndex $deletedUsersIndex,
private readonly IUserManager $userManager,
) {
parent::__construct($helper, $ldap, $accessFactory);
}
Expand All @@ -43,6 +47,7 @@ protected function newInstance(string $configPrefix): User_LDAP {
$this->userPluginManager,
$this->logger,
$this->deletedUsersIndex,
$this->userManager,
);
}

Expand Down Expand Up @@ -437,4 +442,18 @@ public function getDisabledUserList(?int $limit = null, int $offset = 0, string
public function canEditProperty(string $uid, string $property): bool {
return $this->handleRequest($uid, 'canEditProperty', [$uid, $property]);
}

public function getUserFromCustomAttribute(string $attribute, string $searchTerm): ?IUser {
$this->setup();
$user = null;
foreach ($this->backends as $backend) {
$fetchUser = $backend->getUserFromCustomAttribute($attribute, $searchTerm);
// if we found a different user, no need to continue
if ($user !== null && $fetchUser !== null && $fetchUser->getUID() !== $user->getUID()) {
throw new MultipleUsersReturnedException('Multiple users found for custom attribute search');
}
$user = $fetchUser; // may be null
}
return $user;
}
}
Loading
Loading