diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index 8a6084b6c8..e8d268d3df 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -34,6 +34,11 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { */ protected $cachedGroupMembers = array(); + /** + * @var string[] $cachedGroupsByMember array of groups with uid as key + */ + protected $cachedGroupsByMember = array(); + public function __construct(Access $access) { parent::__construct($access); $filter = $this->access->connection->ldapGroupFilter; @@ -98,16 +103,28 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { } //extra work if we don't get back user DNs - //TODO: this can be done with one LDAP query if(strtolower($this->access->connection->ldapGroupMemberAssocAttr) === 'memberuid') { $dns = array(); + $filterParts = array(); + $bytes = 0; foreach($members as $mid) { $filter = str_replace('%uid', $mid, $this->access->connection->ldapLoginFilter); - $ldap_users = $this->access->fetchListOfUsers($filter, 'dn'); - if(count($ldap_users) < 1) { - continue; + $filterParts[] = $filter; + $bytes += strlen($filter); + if($bytes >= 9000000) { + // AD has a default input buffer of 10 MB, we do not want + // to take even the chance to exceed it + $filter = $this->access->combineFilterWithOr($filterParts); + $bytes = 0; + $filterParts = array(); + $users = $this->access->fetchListOfUsers($filter, 'dn', count($filterParts)); + $dns = array_merge($dns, $users); } - $dns[] = $ldap_users[0]; + } + if(count($filterParts) > 0) { + $filter = $this->access->combineFilterWithOr($filterParts); + $users = $this->access->fetchListOfUsers($filter, 'dn', count($filterParts)); + $dns = array_merge($dns, $users); } $members = $dns; } @@ -316,8 +333,13 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { $uid = $userDN; } - $groups = array_values($this->getGroupsByMember($uid)); - $groups = $this->access->ownCloudGroupNames($groups); + if(isset($this->cachedGroupsByMember[$uid])) { + $groups = $this->cachedGroupsByMember[$uid]; + } else { + $groups = array_values($this->getGroupsByMember($uid)); + $groups = $this->access->ownCloudGroupNames($groups); + $this->cachedGroupsByMember[$uid] = $groups; + } $primaryGroup = $this->getUserPrimaryGroup($userDN); if($primaryGroup !== false) { diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 159b0d7300..44162e32d4 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -1359,7 +1359,7 @@ class Access extends LDAPUtility implements user\IUserTools { * @param string[] $bases array containing the allowed base DN or DNs * @return bool */ - private function isDNPartOfBase($dn, $bases) { + public function isDNPartOfBase($dn, $bases) { $belongsToBase = false; $bases = $this->sanitizeDN($bases); diff --git a/lib/private/group/manager.php b/lib/private/group/manager.php index 33a1904ddd..417be79ab3 100644 --- a/lib/private/group/manager.php +++ b/lib/private/group/manager.php @@ -223,10 +223,9 @@ class Manager extends PublicEmitter implements IGroupManager { if(!empty($search)) { // only user backends have the capability to do a complex search for users $searchOffset = 0; + $searchLimit = $limit * 100; if($limit === -1) { - $searchLimit = $group->count(''); - } else { - $searchLimit = $limit * 2; + $searchLimit = 500; } do {