Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Wrong handling of orWhere in emulator #606

Open
acharseth opened this issue Oct 18, 2023 · 6 comments
Open

[Bug] Wrong handling of orWhere in emulator #606

acharseth opened this issue Oct 18, 2023 · 6 comments
Assignees
Labels
bug Something isn't working

Comments

@acharseth
Copy link

Environment:

  • LDAP Server Type: Development: Built in emulator. Test and prod: ActiveDirectory
  • PHP Version: 8.1

Describe the bug:
I wanted a scope requiring to be member of one or more groups.
I therefore created a scope with an initial where for one group and two more orWhere for 2 other groups. Something like this:

$builder->where('memberof', '=', 'cn=Group1');
$builder->orWhere('memberof', '=', 'cn=Group2');
$builder->orWhere('memberof', '=', 'cn=Group3');

With experience from SQL this makes sense but does not in LDAP.
This creates the following LDAP filter (as decoded from the log):

(&...
(memberof=CN=Group1)
(|(memberof=CN=Group2)(memberof=CN=Group3)))

This means that you have to be member of both Group1 and (Group2 or Groups 3), which is not what I intended. Still using the built in LDAP emulator I could be member of eg. Group3 only and still get included. In the test environment, however, I did not get included. The correct implementation for the scope is to use orWhere on all 3 groups like this:

$builder->orWhere('memberof', '=', 'cn=Group1');
$builder->orWhere('memberof', '=', 'cn=Group2');
$builder->orWhere('memberof', '=', 'cn=Group3');

This will create a correct LDAP-filter:

(&...
(|(memberof=CN=Group1)(memberof=CN=Group2)(memberof=CN=Group3)))

To my understanding ActiveDirectoy has a correct implementation of the filter and the built in emulator does not.
Agree?

@acharseth acharseth added the bug Something isn't working label Oct 18, 2023
@stevebauman stevebauman transferred this issue from DirectoryTree/LdapRecord Nov 10, 2023
@stevebauman
Copy link
Member

stevebauman commented Feb 4, 2024

Thanks @acharseth, apologies for the long reply here. Yes I agree, the emulator is the one not working properly. The query builder is working as expected. I'm able to reproduce this locally. Working on a patch -- haven't found a solution yet. Will report here once I do 👍

@stevebauman stevebauman changed the title [Bug]Wrong handling of where in emulator [Bug] Wrong handling of orWhere in emulator Feb 4, 2024
@sakihl
Copy link

sakihl commented Aug 28, 2024

Hi @stevebauman, I have the same problem with orWhereContains.

I have a query

$searchQuery = 'aaa';

$results = User::orWhereContains('samaccountname', $searchQuery)
	->orWhereContains('givenname', $searchQuery)
	->get();

If I use ->getUnescapedQuery() I can confirm it builds the correct filter

(&(objectclass=top)(objectclass=person)(objectclass=organizationalperson)(objectclass=user)(!(objectclass=computer))(|(samaccountname=*aaa*)(givenname=*aaa*)))

The equivalent query (a bit more complex in my application) seems to work querying the real AD directory but not in the emulator, making it difficult to test.

I am hoping your patch when it comes will handle orWhereContains as well as orWhere.

@stevebauman
Copy link
Member

Apologies for the delay here, I think this show now be resolved in release v3.3.3 from PR #665. Can you composer update and try again?

@stevebauman
Copy link
Member

Scratch that, that was resolving a different issue. Will look at this this week 👍

@stevebauman stevebauman self-assigned this Sep 24, 2024
@stevebauman
Copy link
Member

stevebauman commented Oct 15, 2024

I've discovered the issue of this, and it's due to how and when global scopes are applied (in the ActiveDirectory\User model case, the $objectClasses of the user, and the rejection of the computer objectclass).

Though as a workaround, I've discovered you can resolve this by nesting the orWhere's inside of an andFilter, which would yield the same LDAP results, and also work with the emulator which creates appropriate SQL query under the hood:

$query->andFilter(function ($query) {
    $query->orWhere('memberof', '=', 'cn=Group1');
    $query->orWhere('memberof', '=', 'cn=Group2');
    $query->orWhere('memberof', '=', 'cn=Group3');
});

This is still a bug though, but I know why and where it's happening so I'll keep you updated here 👍

@dereknutile
Copy link

@stevebauman, it could be unrelated, but this Laravel issue titled "[11.28.0] ->orWhere() behaviour changed with array input" could be of interest: laravel/framework#53184.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants