Merge pull request #24659 from nextcloud/enh/noid/dav-honour-sharing.maxAutocompleteResults

dav principal search to honour sharing.maxAutocompleteResults setting
This commit is contained in:
Roeland Jago Douma 2020-12-16 10:47:32 +01:00 committed by GitHub
commit 1d4c8961ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 77 additions and 20 deletions

View File

@ -39,6 +39,7 @@ use OCA\DAV\CalDAV\Proxy\ProxyMapper;
use OCA\DAV\Traits\PrincipalProxyTrait; use OCA\DAV\Traits\PrincipalProxyTrait;
use OCP\App\IAppManager; use OCP\App\IAppManager;
use OCP\AppFramework\QueryException; use OCP\AppFramework\QueryException;
use OCP\Constants;
use OCP\IConfig; use OCP\IConfig;
use OCP\IGroupManager; use OCP\IGroupManager;
use OCP\IUser; use OCP\IUser;
@ -270,6 +271,10 @@ class Principal implements BackendInterface {
} }
} }
$searchLimit = $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT);
if ($searchLimit <= 0) {
$searchLimit = null;
}
foreach ($searchProperties as $prop => $value) { foreach ($searchProperties as $prop => $value) {
switch ($prop) { switch ($prop) {
case '{http://sabredav.org/ns}email-address': case '{http://sabredav.org/ns}email-address':
@ -305,7 +310,7 @@ class Principal implements BackendInterface {
break; break;
case '{DAV:}displayname': case '{DAV:}displayname':
$users = $this->userManager->searchDisplayName($value); $users = $this->userManager->searchDisplayName($value, $searchLimit);
if (!$allowEnumeration) { if (!$allowEnumeration) {
$users = \array_filter($users, static function (IUser $user) use ($value) { $users = \array_filter($users, static function (IUser $user) use ($value) {

View File

@ -27,6 +27,8 @@
namespace OCA\DAV\DAV; namespace OCA\DAV\DAV;
use OCP\Constants;
use OCP\IConfig;
use OCP\IGroup; use OCP\IGroup;
use OCP\IGroupManager; use OCP\IGroupManager;
use OCP\IUser; use OCP\IUser;
@ -47,18 +49,24 @@ class GroupPrincipalBackend implements BackendInterface {
/** @var IShareManager */ /** @var IShareManager */
private $shareManager; private $shareManager;
/** @var IConfig */
private $config;
/** /**
* @param IGroupManager $IGroupManager * @param IGroupManager $IGroupManager
* @param IUserSession $userSession * @param IUserSession $userSession
* @param IShareManager $shareManager * @param IShareManager $shareManager
*/ */
public function __construct(IGroupManager $IGroupManager, public function __construct(
IUserSession $userSession, IGroupManager $IGroupManager,
IShareManager $shareManager) { IUserSession $userSession,
IShareManager $shareManager,
IConfig $config
) {
$this->groupManager = $IGroupManager; $this->groupManager = $IGroupManager;
$this->userSession = $userSession; $this->userSession = $userSession;
$this->shareManager = $shareManager; $this->shareManager = $shareManager;
$this->config = $config;
} }
/** /**
@ -205,10 +213,14 @@ class GroupPrincipalBackend implements BackendInterface {
$restrictGroups = $this->groupManager->getUserGroupIds($user); $restrictGroups = $this->groupManager->getUserGroupIds($user);
} }
$searchLimit = $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT);
if ($searchLimit <= 0) {
$searchLimit = null;
}
foreach ($searchProperties as $prop => $value) { foreach ($searchProperties as $prop => $value) {
switch ($prop) { switch ($prop) {
case '{DAV:}displayname': case '{DAV:}displayname':
$groups = $this->groupManager->search($value); $groups = $this->groupManager->search($value, $searchLimit);
$results[] = array_reduce($groups, function (array $carry, IGroup $group) use ($restrictGroups) { $results[] = array_reduce($groups, function (array $carry, IGroup $group) use ($restrictGroups) {
$gid = $group->getGID(); $gid = $group->getGID();

View File

@ -72,7 +72,7 @@ class RootCollection extends SimpleCollection {
$proxyMapper, $proxyMapper,
\OC::$server->getConfig() \OC::$server->getConfig()
); );
$groupPrincipalBackend = new GroupPrincipalBackend($groupManager, $userSession, $shareManager); $groupPrincipalBackend = new GroupPrincipalBackend($groupManager, $userSession, $shareManager, $config);
$calendarResourcePrincipalBackend = new ResourcePrincipalBackend($db, $userSession, $groupManager, $logger, $proxyMapper); $calendarResourcePrincipalBackend = new ResourcePrincipalBackend($db, $userSession, $groupManager, $logger, $proxyMapper);
$calendarRoomPrincipalBackend = new RoomPrincipalBackend($db, $userSession, $groupManager, $logger, $proxyMapper); $calendarRoomPrincipalBackend = new RoomPrincipalBackend($db, $userSession, $groupManager, $logger, $proxyMapper);
// as soon as debug mode is enabled we allow listing of principals // as soon as debug mode is enabled we allow listing of principals

View File

@ -31,6 +31,7 @@ namespace OCA\DAV\Tests\unit\DAV;
use OC\Group\Group; use OC\Group\Group;
use OCA\DAV\DAV\GroupPrincipalBackend; use OCA\DAV\DAV\GroupPrincipalBackend;
use OCP\IConfig;
use OCP\IGroup; use OCP\IGroup;
use OCP\IGroupManager; use OCP\IGroupManager;
use OCP\IUser; use OCP\IUser;
@ -39,6 +40,8 @@ use OCP\Share\IManager;
use Sabre\DAV\PropPatch; use Sabre\DAV\PropPatch;
class GroupPrincipalTest extends \Test\TestCase { class GroupPrincipalTest extends \Test\TestCase {
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
private $config;
/** @var IGroupManager | \PHPUnit\Framework\MockObject\MockObject */ /** @var IGroupManager | \PHPUnit\Framework\MockObject\MockObject */
private $groupManager; private $groupManager;
@ -56,11 +59,14 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->groupManager = $this->createMock(IGroupManager::class); $this->groupManager = $this->createMock(IGroupManager::class);
$this->userSession = $this->createMock(IUserSession::class); $this->userSession = $this->createMock(IUserSession::class);
$this->shareManager = $this->createMock(IManager::class); $this->shareManager = $this->createMock(IManager::class);
$this->config = $this->createMock(IConfig::class);
$this->connector = new GroupPrincipalBackend( $this->connector = new GroupPrincipalBackend(
$this->groupManager, $this->groupManager,
$this->userSession, $this->userSession,
$this->shareManager); $this->shareManager,
$this->config
);
parent::setUp(); parent::setUp();
} }
@ -167,6 +173,23 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertSame($expectedResponse, $response); $this->assertSame($expectedResponse, $response);
} }
public function testGetPrincipalsByPathGroupWithHash() {
$group1 = $this->mockGroup('foo#bar');
$this->groupManager
->expects($this->once())
->method('get')
->with('foo#bar')
->willReturn($group1);
$expectedResponse = [
'uri' => 'principals/groups/foo%23bar',
'{DAV:}displayname' => 'Group foo#bar',
'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
];
$response = $this->connector->getPrincipalByPath('principals/groups/foo#bar');
$this->assertSame($expectedResponse, $response);
}
public function testGetGroupMemberSet() { public function testGetGroupMemberSet() {
$response = $this->connector->getGroupMemberSet('principals/groups/foo'); $response = $this->connector->getGroupMemberSet('principals/groups/foo');
$this->assertSame([], $response); $this->assertSame([], $response);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -36,6 +36,7 @@ declare(strict_types=1);
namespace OCA\Files_Sharing\Controller; namespace OCA\Files_Sharing\Controller;
use OCP\Constants;
use function array_slice; use function array_slice;
use function array_values; use function array_values;
use Generator; use Generator;
@ -148,7 +149,7 @@ class ShareesAPIController extends OCSController {
} }
// never return more than the max. number of results configured in the config.php // never return more than the max. number of results configured in the config.php
$maxResults = (int)$this->config->getSystemValue('sharing.maxAutocompleteResults', 0); $maxResults = $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT);
if ($maxResults > 0) { if ($maxResults > 0) {
$perPage = min($perPage, $maxResults); $perPage = min($perPage, $maxResults);
} }

View File

@ -248,7 +248,7 @@ export default class Config {
* @memberof Config * @memberof Config
*/ */
get maxAutocompleteResults() { get maxAutocompleteResults() {
return parseInt(OC.config['sharing.maxAutocompleteResults'], 10) || 200 return parseInt(OC.config['sharing.maxAutocompleteResults'], 10) || 25
} }
/** /**

View File

@ -1410,10 +1410,17 @@ $CONFIG = [
'sharing.managerFactory' => '\OC\Share20\ProviderFactory', 'sharing.managerFactory' => '\OC\Share20\ProviderFactory',
/** /**
* Define max number of results returned by the user search for auto-completion * Define max number of results returned by the search for auto-completion of
* Default is unlimited (value set to 0). * users, groups, etc. The value must not be lower than 0 (for unlimited).
*
* If more, different sources are requested (e.g. different user backends; or
* both users and groups), the value is applied per source and might not be
* truncated after collecting the results. I.e. more results can appear than
* configured here.
*
* Default is 25.
*/ */
'sharing.maxAutocompleteResults' => 0, 'sharing.maxAutocompleteResults' => 25,
/** /**
* Define the minimum length of the search string before we start auto-completion * Define the minimum length of the search string before we start auto-completion

View File

@ -27,6 +27,7 @@
namespace OC\Contacts\ContactsMenu; namespace OC\Contacts\ContactsMenu;
use OCP\App\IAppManager; use OCP\App\IAppManager;
use OCP\Constants;
use OCP\Contacts\ContactsMenu\IEntry; use OCP\Contacts\ContactsMenu\IEntry;
use OCP\IConfig; use OCP\IConfig;
use OCP\IUser; use OCP\IUser;
@ -63,7 +64,7 @@ class Manager {
* @return array * @return array
*/ */
public function getEntries(IUser $user, $filter) { public function getEntries(IUser $user, $filter) {
$maxAutocompleteResults = $this->config->getSystemValueInt('sharing.maxAutocompleteResults', 25); $maxAutocompleteResults = max(0, $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT));
$minSearchStringLength = $this->config->getSystemValueInt('sharing.minSearchStringLength', 0); $minSearchStringLength = $this->config->getSystemValueInt('sharing.minSearchStringLength', 0);
$topEntries = []; $topEntries = [];
if (strlen($filter) >= $minSearchStringLength) { if (strlen($filter) >= $minSearchStringLength) {

View File

@ -33,6 +33,7 @@ namespace OC\Template;
use bantu\IniGetWrapper\IniGetWrapper; use bantu\IniGetWrapper\IniGetWrapper;
use OC\CapabilitiesManager; use OC\CapabilitiesManager;
use OCP\App\IAppManager; use OCP\App\IAppManager;
use OCP\Constants;
use OCP\Defaults; use OCP\Defaults;
use OCP\IConfig; use OCP\IConfig;
use OCP\IGroupManager; use OCP\IGroupManager;
@ -189,8 +190,8 @@ class JSConfigHelper {
'enable_avatars' => true, // here for legacy reasons - to not crash existing code that relies on this value 'enable_avatars' => true, // here for legacy reasons - to not crash existing code that relies on this value
'lost_password_link' => $this->config->getSystemValue('lost_password_link', null), 'lost_password_link' => $this->config->getSystemValue('lost_password_link', null),
'modRewriteWorking' => $this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true', 'modRewriteWorking' => $this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true',
'sharing.maxAutocompleteResults' => (int)$this->config->getSystemValue('sharing.maxAutocompleteResults', 0), 'sharing.maxAutocompleteResults' => max(0, $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT)),
'sharing.minSearchStringLength' => (int)$this->config->getSystemValue('sharing.minSearchStringLength', 0), 'sharing.minSearchStringLength' => $this->config->getSystemValueInt('sharing.minSearchStringLength', 0),
'blacklist_files_regex' => \OCP\Files\FileInfo::BLACKLIST_FILES_REGEX, 'blacklist_files_regex' => \OCP\Files\FileInfo::BLACKLIST_FILES_REGEX,
]; ];

View File

@ -52,4 +52,10 @@ class Constants {
* longer support windows as server platform. * longer support windows as server platform.
*/ */
public const FILENAME_INVALID_CHARS = "\\/"; public const FILENAME_INVALID_CHARS = "\\/";
/**
* @since 21.0.0 default value for autocomplete/search results limit,
* cf. sharing.maxAutocompleteResults in config.sample.php.
*/
public const SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT = 25;
} }

View File

@ -28,6 +28,7 @@ use OC\Contacts\ContactsMenu\ActionProviderStore;
use OC\Contacts\ContactsMenu\ContactsStore; use OC\Contacts\ContactsMenu\ContactsStore;
use OC\Contacts\ContactsMenu\Manager; use OC\Contacts\ContactsMenu\Manager;
use OCP\App\IAppManager; use OCP\App\IAppManager;
use OCP\Constants;
use OCP\Contacts\ContactsMenu\IEntry; use OCP\Contacts\ContactsMenu\IEntry;
use OCP\Contacts\ContactsMenu\IProvider; use OCP\Contacts\ContactsMenu\IProvider;
use OCP\IConfig; use OCP\IConfig;
@ -82,7 +83,7 @@ class ManagerTest extends TestCase {
$this->config->expects($this->at(0)) $this->config->expects($this->at(0))
->method('getSystemValueInt') ->method('getSystemValueInt')
->with('sharing.maxAutocompleteResults', 25) ->with('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT)
->willReturn(25); ->willReturn(25);
$this->config->expects($this->at(1)) $this->config->expects($this->at(1))
->method('getSystemValueInt') ->method('getSystemValueInt')
@ -120,7 +121,7 @@ class ManagerTest extends TestCase {
$this->config->expects($this->at(0)) $this->config->expects($this->at(0))
->method('getSystemValueInt') ->method('getSystemValueInt')
->with('sharing.maxAutocompleteResults', 25) ->with('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT)
->willReturn(3); ->willReturn(3);
$this->config->expects($this->at(1)) $this->config->expects($this->at(1))
->method('getSystemValueInt') ->method('getSystemValueInt')
@ -157,7 +158,7 @@ class ManagerTest extends TestCase {
$this->config->expects($this->at(0)) $this->config->expects($this->at(0))
->method('getSystemValueInt') ->method('getSystemValueInt')
->with('sharing.maxAutocompleteResults', 25) ->with('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT)
->willReturn(3); ->willReturn(3);
$this->config->expects($this->at(1)) $this->config->expects($this->at(1))
->method('getSystemValueInt') ->method('getSystemValueInt')