0
0
Fork 0
mirror of https://github.com/nextcloud/server.git synced 2025-02-27 10:06:31 +00:00

Pass paging information directly to search and get rid of adapter

Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
This commit is contained in:
Côme Chilliet 2022-09-08 14:44:42 +02:00
parent 14804d9677
commit 50a52ac2a5
No known key found for this signature in database
GPG key ID: A3E2F658B28C760A
5 changed files with 19 additions and 188 deletions

View file

@ -1094,13 +1094,13 @@ class Access extends LDAPUtility {
//check whether paged search should be attempted
try {
$pagedSearchOK = $this->initPagedSearch($filter, $base, $attr, (int)$pageSize, (int)$offset);
[$pagedSearchOK, $pageSize, $cookie] = $this->initPagedSearch($filter, $base, $attr, (int)$pageSize, (int)$offset);
} catch (NoMoreResults $e) {
// beyond last results page
return false;
}
$sr = $this->invokeLDAPMethod('search', $base, $filter, $attr);
$sr = $this->invokeLDAPMethod('search', $base, $filter, $attr, 0, 0, $pageSize, $cookie);
$error = $this->ldap->errno($this->connection->getConnectionResource());
if (!$this->ldap->isResource($sr) || $error !== 0) {
$this->logger->error('Attempt for Paging? ' . print_r($pagedSearchOK, true), ['app' => 'user_ldap']);
@ -1892,7 +1892,6 @@ class Access extends LDAPUtility {
if ($this->lastCookie === '') {
return;
}
$this->invokeLDAPMethod('controlPagedResult', 0, false);
$this->getPagedSearchResultState();
$this->lastCookie = '';
}
@ -1933,11 +1932,11 @@ class Access extends LDAPUtility {
* Prepares a paged search, if possible
*
* @param string $filter the LDAP filter for the search
* @param string[] $bases an array containing the LDAP subtree(s) that shall be searched
* @param string $base the LDAP subtree that shall be searched
* @param string[] $attr optional, when a certain attribute shall be filtered outside
* @param int $limit
* @param int $offset
* @return bool|true
* @return array{bool, int, string}
* @throws ServerNotAvailableException
* @throws NoMoreResults
*/
@ -1947,7 +1946,7 @@ class Access extends LDAPUtility {
?array $attr,
int $pageSize,
int $offset
): bool {
): array {
$pagedSearchOK = false;
if ($pageSize !== 0) {
$this->logger->debug(
@ -1978,9 +1977,8 @@ class Access extends LDAPUtility {
//since offset = 0, this is a new search. We abandon other searches that might be ongoing.
$this->abandonPagedSearch();
}
$pagedSearchOK = true;
$this->invokeLDAPMethod('controlPagedResult', $pageSize, false, $this->lastCookie);
$this->logger->debug('Ready for a paged search', ['app' => 'user_ldap']);
return [true, $pageSize, $this->lastCookie];
/* ++ Fixing RHDS searches with pages with zero results ++
* We couldn't get paged searches working with our RHDS for login ($limit = 0),
* due to pages with zero results.
@ -1995,11 +1993,10 @@ class Access extends LDAPUtility {
// in case someone set it to 0 … use 500, otherwise no results will
// be returned.
$pageSize = (int)$this->connection->ldapPagingSize > 0 ? (int)$this->connection->ldapPagingSize : 500;
$pagedSearchOK = true;
$this->invokeLDAPMethod('controlPagedResult', $pageSize, false, $this->lastCookie);
return [true, $pageSize, $this->lastCookie];
}
return $pagedSearchOK;
return [false, $pageSize, ''];
}
/**

View file

@ -52,15 +52,6 @@ interface ILDAPWrapper {
*/
public function connect($host, $port);
/**
* Send LDAP pagination control
* @param resource|\LDAP\Connection $link LDAP link resource
* @param int $pageSize number of results per page
* @param bool $isCritical Indicates whether the pagination is critical of not.
* @param string $cookie structure sent by LDAP server
*/
public function controlPagedResult($link, $pageSize, $isCritical): void;
/**
* Retrieve the LDAP pagination cookie
* @param resource|\LDAP\Connection $link LDAP link resource

View file

@ -37,21 +37,15 @@ use OCP\Profiler\IProfiler;
use OC\ServerNotAvailableException;
use OCA\User_LDAP\DataCollector\LdapDataCollector;
use OCA\User_LDAP\Exceptions\ConstraintViolationException;
use OCA\User_LDAP\PagedResults\IAdapter;
use OCA\User_LDAP\PagedResults\Php73;
class LDAP implements ILDAPWrapper {
protected $logFile = '';
protected $curFunc = '';
protected $curArgs = [];
/** @var IAdapter */
protected $pagedResultsAdapter;
private ?LdapDataCollector $dataCollector = null;
public function __construct(string $logFile = '') {
$this->pagedResultsAdapter = new Php73();
$this->logFile = $logFile;
/** @var IProfiler $profiler */
@ -106,13 +100,6 @@ class LDAP implements ILDAPWrapper {
return $success;
}
/**
* {@inheritDoc}
*/
public function controlPagedResult($link, $pageSize, $isCritical): void {
$this->pagedResultsAdapter->setRequestParameters($link, $pageSize, $isCritical);
}
/**
* {@inheritDoc}
*/
@ -190,7 +177,16 @@ class LDAP implements ILDAPWrapper {
/**
* {@inheritDoc}
*/
public function search($link, $baseDN, $filter, $attr, $attrsOnly = 0, $limit = 0) {
public function search($link, $baseDN, $filter, $attr, $attrsOnly = 0, $limit = 0, int $pageSize = 0, string $cookie = '') {
$serverControls = [[
'oid' => LDAP_CONTROL_PAGEDRESULTS,
'value' => [
'size' => $pageSize,
'cookie' => $cookie,
],
'iscritical' => false,
]];
$oldHandler = set_error_handler(function ($no, $message, $file, $line) use (&$oldHandler) {
if (strpos($message, 'Partial search results returned: Sizelimit exceeded') !== false) {
return true;
@ -199,8 +195,7 @@ class LDAP implements ILDAPWrapper {
return true;
});
try {
$this->pagedResultsAdapter->setSearchArgs($link, $baseDN, $filter, $attr, $attrsOnly, $limit);
$result = $this->invokeLDAPMethod('search', ...$this->pagedResultsAdapter->getSearchArgs($link));
$result = $this->invokeLDAPMethod('search', $link, $baseDN, $filter, $attr, $attrsOnly, $limit, -1, LDAP_DEREF_NEVER, $serverControls);
restore_error_handler();
return $result;

View file

@ -1,59 +0,0 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\User_LDAP\PagedResults;
interface IAdapter {
/**
* Methods for initiating Paged Results Control
*/
/**
* The adapter receives paged result parameters from the client. It may
* store the parameters for later use.
*/
public function setRequestParameters($link, int $pageSize, bool $isCritical, string $cookie = ''): void;
/**
* The adapter receives the parameters that were passed to a search
* operation. Typically it wants to save the them for the call proper later
* on.
*/
public function setSearchArgs(
$link,
string $baseDN,
string $filter,
array $attr,
int $attrsOnly,
int $limit
): void;
/**
* The adapter shall report which arguments shall be passed to the
* ldap_search function.
*/
public function getSearchArgs($link): array;
}

View file

@ -1,93 +0,0 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\User_LDAP\PagedResults;
/**
* Class Php73
*
* implements paged results support with PHP APIs available from PHP 7.3
*
* @package OCA\User_LDAP\PagedResults
*/
class Php73 implements IAdapter {
use TLinkId;
/** @var array */
protected $linkData = [];
public function setRequestParameters($link, int $pageSize, bool $isCritical, string $cookie = ''): void {
$linkId = $this->getLinkId($link);
if (!isset($this->linkData[$linkId])) {
$this->linkData[$linkId] = [];
}
$this->linkData[$linkId]['requestArgs'] = [];
$this->linkData[$linkId]['requestArgs']['pageSize'] = $pageSize;
$this->linkData[$linkId]['requestArgs']['isCritical'] = $isCritical;
$this->linkData[$linkId]['requestArgs']['cookie'] = $cookie;
}
public function setSearchArgs(
$link,
string $baseDN,
string $filter,
array $attr,
int $attrsOnly,
int $limit
): void {
$linkId = $this->getLinkId($link);
if (!isset($this->linkData[$linkId])) {
$this->linkData[$linkId] = [];
}
$this->linkData[$linkId]['searchArgs'] = func_get_args();
$this->preparePagesResultsArgs($linkId, 'searchArgs');
}
public function getSearchArgs($link): array {
$linkId = $this->getLinkId($link);
return $this->linkData[$linkId]['searchArgs'];
}
protected function preparePagesResultsArgs(int $linkId, string $methodKey): void {
if (!isset($this->linkData[$linkId]['requestArgs'])) {
return;
}
$serverControls = [[
'oid' => LDAP_CONTROL_PAGEDRESULTS,
'value' => [
'size' => $this->linkData[$linkId]['requestArgs']['pageSize'],
'cookie' => $this->linkData[$linkId]['requestArgs']['cookie'],
],
'iscritical' => $this->linkData[$linkId]['requestArgs']['isCritical'],
]];
$this->linkData[$linkId][$methodKey][] = -1; // timelimit
$this->linkData[$linkId][$methodKey][] = LDAP_DEREF_NEVER;
$this->linkData[$linkId][$methodKey][] = $serverControls;
}
}