@@ -727,23 +727,36 @@ public function testGetUserGroupsMemberOfDisabled() {
727727 $ groupBackend ->getUserGroups ('userX ' );
728728 }
729729
730- public function testGetGroupsByMember () {
730+ public function nestedGroupsProvider (): array {
731+ return [
732+ [ true ],
733+ [ false ],
734+ ];
735+ }
736+
737+ /**
738+ * @dataProvider nestedGroupsProvider
739+ */
740+ public function testGetGroupsByMember (bool $ nestedGroups ) {
731741 $ access = $ this ->getAccessMock ();
732742 $ pluginManager = $ this ->getPluginManagerMock ();
733743
744+ $ groupFilter = '(&(objectclass=nextcloudGroup)(nextcloudEnabled=TRUE)) ' ;
734745 $ access ->connection = $ this ->createMock (Connection::class);
735746 $ access ->connection ->expects ($ this ->any ())
736747 ->method ('__get ' )
737- ->willReturnCallback (function ($ name ) {
748+ ->willReturnCallback (function ($ name ) use ( $ nestedGroups , $ groupFilter ) {
738749 switch ($ name ) {
739750 case 'useMemberOfToDetectMembership ' :
740751 return 0 ;
741752 case 'ldapDynamicGroupMemberURL ' :
742753 return '' ;
743754 case 'ldapNestedGroups ' :
744- return false ;
755+ return $ nestedGroups ;
745756 case 'ldapGroupMemberAssocAttr ' :
746757 return 'member ' ;
758+ case 'ldapGroupFilter ' :
759+ return $ groupFilter ;
747760 }
748761 return 1 ;
749762 });
@@ -756,10 +769,15 @@ public function testGetGroupsByMember() {
756769 $ access ->expects ($ this ->exactly (2 ))
757770 ->method ('username2dn ' )
758771 ->willReturn ($ dn );
759-
760772 $ access ->expects ($ this ->any ())
761773 ->method ('readAttribute ' )
762774 ->willReturn ([]);
775+ $ access ->expects ($ this ->any ())
776+ ->method ('combineFilterWithAnd ' )
777+ ->willReturnCallback (function (array $ filterParts ) {
778+ // ⚠ returns a pseudo-filter only, not real LDAP Filter syntax
779+ return implode ('& ' , $ filterParts );
780+ });
763781
764782 $ group1 = [
765783 'cn ' => 'group1 ' ,
@@ -774,9 +792,21 @@ public function testGetGroupsByMember() {
774792 ->method ('nextcloudGroupNames ' )
775793 ->with ([$ group1 , $ group2 ])
776794 ->willReturn (['group1 ' , 'group2 ' ]);
777- $ access ->expects ($ this ->once ())
795+ $ access ->expects ($ nestedGroups ? $ this -> atLeastOnce () : $ this ->once ())
778796 ->method ('fetchListOfGroups ' )
779- ->willReturn ([$ group1 , $ group2 ]);
797+ ->willReturnCallback (function ($ filter , $ attr , $ limit , $ offset ) use ($ nestedGroups , $ groupFilter , $ group1 , $ group2 ) {
798+ static $ firstRun = true ;
799+ if (!$ nestedGroups ) {
800+ // When nested groups are enabled, groups cannot be filtered early as it would
801+ // exclude intermediate groups. But we can, and should, when working with flat groups.
802+ $ this ->assertTrue (strpos ($ filter , $ groupFilter ) !== false );
803+ }
804+ if ($ firstRun ) {
805+ $ firstRun = false ;
806+ return [$ group1 , $ group2 ];
807+ }
808+ return [];
809+ });
780810 $ access ->expects ($ this ->any ())
781811 ->method ('dn2groupname ' )
782812 ->willReturnCallback (function (string $ dn ) {
0 commit comments