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:
parent
14804d9677
commit
50a52ac2a5
5 changed files with 19 additions and 188 deletions
apps/user_ldap/lib
|
@ -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, ''];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue