feat(user_ldap): add function to find a user in ldap#56721
feat(user_ldap): add function to find a user in ldap#56721thpiron wants to merge 6 commits intonextcloud:masterfrom
Conversation
|
Hello there, We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process. Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6 Thank you for contributing to Nextcloud and we hope to hear from you soon! (If you believe you should not receive this message, you can add yourself to the blocklist.) |
| * | ||
| * @return IUser|null Returns a IUser if found in ldap using the configured ldap filter | ||
| * @throws \Exception if multiple users has been found (search query should not allow this) | ||
| */ |
There was a problem hiding this comment.
On the API, we note down @since annotations
| */ | |
| * @since 33.0.0 | |
| */ |
lib/public/LDAP/ILDAPProvider.php
Outdated
| * Search for a single user in ldap | ||
| * | ||
| * @return IUser|null Returns a IUser if found in ldap using the configured ldap filter | ||
| * @throws \Exception if multiple users has been found (search query should not allow this) |
There was a problem hiding this comment.
Please don't throw the general \Exception but create a specific one, e.g. MultipleUsersReturnedException in the same namespace.
apps/user_ldap/lib/LDAPProvider.php
Outdated
| /** | ||
| * Search for a single user in ldap | ||
| * | ||
| * @return IUser|null Returns a IUser if found in ldap using the configured ldap filter | ||
| * @throws \Exception if multiple users has been found (search query should not allow this) | ||
| */ |
There was a problem hiding this comment.
this docblock can be left out as it is provided by the interface.
| * @return IUser |null Returns an IUser if found in LDAP using the configured LDAP filter, or null if no user is found. | ||
| */ | ||
| public function getUserFromCustomAttribute(string $filter, string $attribute, string $searchTerm): ?IUser { | ||
| if ($filter === null || $filter === '') { |
There was a problem hiding this comment.
$filter cannot be null, as the signature demands a string.
There was a problem hiding this comment.
Noted, I'll change this when reworking the interface function(s), keeping this as unresolved for now.
| public function getUserFromCustomAttribute(string $filter, string $attribute, string $searchTerm): ?IUser { | ||
| if ($filter === null || $filter === '') { | ||
| $searchTerm = $this->access->escapeFilterPart($searchTerm); | ||
| $filter = "($attribute=$searchTerm)"; |
There was a problem hiding this comment.
The filter should always be an and-combination of the user list filter, otherwise it might pull in users without access.
(Technically the login filter would be more correct semantically, but it might not resolve on such setups by configuration to avoid direct login.)
There was a problem hiding this comment.
Noted, I'll change this when reworking the interface function(s), keeping this as unresolved for now.
apps/user_ldap/lib/User_Proxy.php
Outdated
| foreach ($this->backends as $backend) { | ||
| if (method_exists($backend, 'getUserFromCustomAttribute')) { | ||
| $user = $backend->getUserFromCustomAttribute($filter, $attribute, $searchTerm); | ||
| return $user; |
There was a problem hiding this comment.
Only the first LDAP configuration would be considered, as there is an immediate return statement. Also, the method_exists should not be necessary?
This can be solved in two ways:
- return the first result, that is not null. This might be faster, especially when there is not hit. But it might ignore users from other LDAP configurations, that then will not result in the exception.
- Run through all backends, and return that one user, if found, and throw the
MultipleUsersReturnedExceptionas soon as there are two results.
The broad search operations goes against all configurations as well, so going with #2 should be fine and not impacting the performance compared to the status quo.
There was a problem hiding this comment.
2 is safer indeed, I only throw an exception if the the user are different, but I'm not sure if this makes sense, Maybe I should always throw the exception if two users found even if it's the same on nextcloud? I don't know if there is a safeguard somewhere to make this case impossible.
| * @return IUser|null Returns a IUser if found in ldap using the configured ldap filter | ||
| * @throws \Exception if multiple users has been found (search query should not allow this) | ||
| */ | ||
| public function findOneUser(string $filter, string $attribute, string $searchTerm): ?IUser; |
There was a problem hiding this comment.
The signature requires all parameters be set, contrary to the spec (it could have been written more precise, i take that) and I think contrary to your suggestion.
Two ways how to solve it:
- Use nullable and optional parameters:
?string $filter = null, ?string $attribute = null, ?string $searchTerm = null. The downside is that the usage does not become clear by the parameters and it is easy to use the methods wrongly. - Split it into two methods:
findOneUserByLdapFilter(string $filter): ?IUserandfindOneUserByAttributeValue(string $attribute, string $searchTerm): ?IUser.
I prefer the latter.
We can also go a step back and agree on one solution, either the filter (which actually is a filter part, could pronounce this as well and clarify that this is and-connected to the user list filter, as per my comment further above), or the attribute-value pair.
Due to
Other login backends that may rely on LDAP, like the SAML/SSO or OIDC backend, will get an additional configuration option to specify an attribute to which the received user id is being compared.
leaving out the filter (I am also a bit nervous about that: to easy to make a mistake) and only accepting the attribute name and the search value. What do you think?
There was a problem hiding this comment.
I'm not happy with this function signature either, splitting it in to function is indeed better I think.
For most cases I think that only the attribute/searchTerm part would be enough, but maybe an having an "expert" config with the filter could be useful in complex configurations.
This would also be consistent with the way user_ldap config works, where it is almost always possible to edit the filter manually.
Maybe adding in the findOneUserByLdapFilter docstring that it should be used carefully by the other apps (as an advanced setting)?
Signed-off-by: Thibault Piron <thibault.a.piron@gmail.com>
Signed-off-by: Thibault Piron <thibault.a.piron@gmail.com>
Signed-off-by: Thibault Piron <thibault.a.piron@gmail.com>
Signed-off-by: Thibault Piron <thibault.a.piron@gmail.com>
Signed-off-by: Thibault Piron <thibault.a.piron@gmail.com>
Signed-off-by: Thibault Piron <thibault.a.piron@gmail.com>
084e1ab to
b430068
Compare
Summary
Add a findOneUser function to LDAPProvider
Checklist
3. to review, feature component)stable32)