Skip to content

Commit

Permalink
Revert search modification and implement batch groupExists and
Browse files Browse the repository at this point in the history
groupDetails method

Signed-off-by: Carl Schwan <carl@carlschwan.eu>
  • Loading branch information
CarlSchwan committed Jun 13, 2022
1 parent 063fc51 commit 6e00901
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 20 deletions.
25 changes: 24 additions & 1 deletion apps/user_ldap/lib/Group_Proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
use OCP\Group\Backend\ABackend;
use OCP\Group\Backend\IDeleteGroupBackend;
use OCP\Group\Backend\IGetDisplayNameBackend;
use OCP\Group\Backend\IGroupDetailsBackend;
use OCP\Group\Backend\INamedBackend;
use OCP\Group\Backend\IAddToGroupBackend;
use OCP\Group\Backend\ICountUsersBackend;
use OCP\Group\Backend\IGroupDetailsBackend;
use OCP\Group\Backend\IRemoveFromGroupBackend;
use OCP\GroupInterface;

Expand Down Expand Up @@ -233,6 +233,18 @@ public function getGroupDetails(string $gid): array {
$gid, 'getGroupDetails', [$gid]);
}

public function getGroupsDetails(array $gids): array {
if (!($this instanceof IGroupDetailsBackend || $this->implementsActions(GroupInterface::GROUP_DETAILS))) {
throw new \Exception("Should not have been called");
}

$groupData = [];
foreach ($gids as $gid) {
$groupData[$gid] = $this->handleRequest($gid, 'getGroupDetails', [$gid]);
}
return $groupData;
}

/**
* get a list of all groups
*
Expand Down Expand Up @@ -263,6 +275,17 @@ public function groupExists($gid) {
return $this->handleRequest($gid, 'groupExists', [$gid]);
}

public function groupsExists(array $gids): array {
$existingGroups = [];
foreach ($gids as $gid) {
$exits = $this->handleRequest($gid, 'groupExists', [$gid]);
if ($exits) {
$existingGroups[] = $gid;
}
}
return $existingGroups;
}

/**
* Check if backend implements actions
*
Expand Down
10 changes: 9 additions & 1 deletion apps/user_ldap/lib/LDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,15 @@ private function preFunctionCall(string $functionName, array $args): void {
$this->curArgs = $args;

if ($this->dataCollector !== null) {
$args = array_map(fn ($item) => (!$this->isResource($item) ? $item : '(resource)'), $this->curArgs);
$args = array_map(function ($item) {
if ($this->isResource($item)) {
return '(resource)';
}
if (isset($item[0]['value']['cookie'])) {
$item[0]['value']['cookie'] = "";
}
return $item;
}, $this->curArgs);

$this->dataCollector->startLdapRequest($this->curFunc, $args);
}
Expand Down
36 changes: 30 additions & 6 deletions lib/private/Group/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,9 @@ class Database extends ABackend implements
ISetDisplayNameBackend,
INamedBackend {

/** @var string[] */
private $groupCache = [];

/** @var IDBConnection */
private $dbConn;
/** @var array<string, array{gid: string, displayname: string}> */
private array $groupCache = [];
private ?IDBConnection $dbConn;

/**
* \OC\Group\Database constructor.
Expand Down Expand Up @@ -270,7 +268,7 @@ public function getGroups($search = '', $limit = null, $offset = null) {
$this->fixDI();

$query = $this->dbConn->getQueryBuilder();
$query->select('gid')
$query->select('gid', 'displayname')
->from('groups')
->orderBy('gid', 'ASC');

Expand All @@ -289,6 +287,10 @@ public function getGroups($search = '', $limit = null, $offset = null) {

$groups = [];
while ($row = $result->fetch()) {
$this->groupCache[$row['gid']] = [
'displayname' => $row['displayname'],
'gid' => $row['gid'],
];
$groups[] = $row['gid'];
}
$result->closeCursor();
Expand Down Expand Up @@ -529,6 +531,28 @@ public function getGroupDetails(string $gid): array {
return [];
}

public function getGroupsDetails(array $gid): array {
$details = [];
foreach (array_chunk($gid, 1000) as $chunk) {
$query = $this->dbConn->getQueryBuilder();
$query->select('gid', 'displayname')
->from('groups')
->where($query->expr()->in('gid', $query->createNamedParameter($chunk, IQueryBuilder::PARAM_STR_ARRAY)));

$result = $query->executeQuery();
while ($row = $result->fetch()) {
$details[$row['gid']] = $row['displayname'];
$this->groupCache[$row['gid']] = [
'displayname' => $row['displayname'],
'gid' => $row['gid'],
];
}
$result->closeCursor();
}

return $details;
}

public function setDisplayName(string $gid, string $displayName): bool {
if (!$this->groupExists($gid)) {
return false;
Expand Down
91 changes: 80 additions & 11 deletions lib/private/Group/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ class Manager extends PublicEmitter implements IGroupManager {
private $dispatcher;
private LoggerInterface $logger;

/** @var \OC\Group\Group[] */
private $cachedGroups = [];
/** @var array<string, IGroup> */
private array $cachedGroups = [];

/** @var (string[])[] */
/** @var array<string, list<string> */
private $cachedUserGroups = [];

/** @var \OC\SubAdmin */
Expand Down Expand Up @@ -202,6 +202,51 @@ protected function getGroupObject($gid, $displayName = null) {
return $this->cachedGroups[$gid];
}

/**
* @param list<string> $gids List of groupIds for which we want to create a IGroup object
* @param array<string, string> $displayNames Array containing already know display name for a groupId
* @return array<string, IGroup>
*/
protected function getGroupsObject($gids, $displayNames = []) {
$backends = [];
$groups = [];
foreach ($gids as $gid) {
$backends[$gid] = [];
if (!isset($displayNames[$gid])) {
$displayNames[$gid] = null;
}
}
foreach ($this->backends as $backend) {
if ($backend instanceof IGroupDetailsBackend || $backend->implementsActions(GroupInterface::GROUP_DETAILS)) {
/** @var IGroupDetailsBackend $backend */
$groupDatas = $backend->getGroupsDetails($gids);
foreach ($groupDatas as $gid => $groupData) {
if (!empty($groupData)) {
// take the display name from the first backend that has a non-null one
if (isset($groupData['displayName'])) {
$displayNames[$gid] = $groupData['displayName'];
}
$backends[$gid][] = $backend;
}
}
} else {
$existingGroups = $backend->groupsExists($gids);
foreach ($existingGroups as $group) {
$backends[$group][] = $backend;
}
}
}
foreach ($gids as $gid) {
if (count($backends[$gid]) === 0) {
continue;
}
/** @var GroupInterface[] $backends */
$this->cachedGroups[$gid] = new Group($gid, $backends[$gid], $this->dispatcher, $this->userManager, $this, $displayNames[$gid]);
$groups[$gid] = $this->cachedGroups[$gid];
}
return $groups;
}

/**
* @param string $gid
* @return bool
Expand Down Expand Up @@ -245,13 +290,9 @@ public function search($search, $limit = null, $offset = null) {
$groups = [];
foreach ($this->backends as $backend) {
$groupIds = $backend->getGroups($search, $limit, $offset);
foreach ($groupIds as $groupId) {
$aGroup = $this->get($groupId);
if ($aGroup instanceof IGroup) {
$groups[$groupId] = $aGroup;
} else {
$this->logger->debug('Group "' . $groupId . '" was returned by search but not found through direct access', ['app' => 'core']);
}
$newGroups = $this->getGroupsObject($groupIds);
foreach ($newGroups as $groupId => $group) {
$groups[$groupId] = $group;
}
if (!is_null($limit) and $limit <= 0) {
return array_values($groups);
Expand Down Expand Up @@ -374,7 +415,35 @@ public function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0
if (is_null($group)) {
return [];
}
$groupUsers = $group->searchUsers($search, $limit, $offset);
$search = trim($search);
$groupUsers = [];

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 = 500;
}

do {
$filteredUsers = $this->userManager->searchDisplayName($search, $searchLimit, $searchOffset);
foreach ($filteredUsers as $filteredUser) {
if ($group->inGroup($filteredUser)) {
$groupUsers[] = $filteredUser;
}
}
$searchOffset += $searchLimit;
} while (count($groupUsers) < $searchLimit + $offset && count($filteredUsers) >= $searchLimit);

if ($limit === -1) {
$groupUsers = array_slice($groupUsers, $offset);
} else {
$groupUsers = array_slice($groupUsers, $offset, $limit);
}
} else {
$groupUsers = $group->searchUsers('', $limit, $offset);
}

$matchingUsers = [];
foreach ($groupUsers as $groupUser) {
Expand Down
23 changes: 23 additions & 0 deletions lib/public/Group/Backend/ABackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,27 @@ public function searchInGroup(string $gid, string $search = '', int $limit = -1,
}
return $users;
}

public function groupsExists(array $gids): array {
$existingGroups = [];
foreach ($gids as $gid) {
$exists = $this->groupExists($gid);
if ($exits) {
$existringGroups[] = $gid;
}
}
return $existingGroups;
}

public function getGroupsDetails(array $gids): array {
if (!($this instanceof IGroupDetailsBackend || $this->implementsActions(GroupInterface::GROUP_DETAILS))) {
throw \Exception("Should not have been called");
}

$groupData = [];
foreach ($gids as $gid) {
$groupData[$gid] = $this->getGroupDetails($gid);
}
return $groupData;
}
}
12 changes: 11 additions & 1 deletion lib/public/GroupInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public function getUserGroups($uid);
* @return array an array of group names
* @since 4.5.0
*
* Returns a list with all groups
* @deprecated since 25.0.0 use getGroupObjects as it is more efficient
*/
public function getGroups($search = '', $limit = -1, $offset = 0);

Expand All @@ -106,6 +106,14 @@ public function getGroups($search = '', $limit = -1, $offset = 0);
*/
public function groupExists($gid);

/**
* Check if a list of groups exists
* @param list<string> $gids
* @return list<string> The list of group that exists
* @since 25.0.0
*/
public function groupsExists(array $gids): array;

/**
* @brief Get a list of user ids in a group matching the given search parameters.
*
Expand Down Expand Up @@ -138,4 +146,6 @@ public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0);
* @since 25.0.0
*/
public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array;

public function getGroupsDetails(array $gids): array;
}

0 comments on commit 6e00901

Please sign in to comment.