Rate limit contact search, skip short queries

The contact-search endpoint had no request-rate limit and ran
an address-book search even for an empty or single-character
query, the most expensive case. Authenticated users could
trigger repeated scans with simple scripted requests.

Apply the framework's per-user UserRateLimit attribute (120
requests per minute) and return an empty result without
touching the address book for fragments under two characters.
The unfiltered datalist on the confirm page is unchanged.
This commit is contained in:
stefan.tollkuehn committed 2026-10-26 13:43:58 +01:00
1 parent 2b3e96e50a
commit 9446f128c9
2 files changed
+56

No files matched your search

+29
View File
@@ -9,6 +9,7 @@ use OCP\App\IAppManager;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\Attribute\UserRateLimit;
use OCP\Calendar\ICalendar;
use OCP\Calendar\ICalendarEventBuilder;
use OCP\Calendar\ICreateFromString;
@@ -1085,6 +1086,34 @@ class CalendarControllerTest extends TestCase
$this->assertCount(50, $response->getData());
}
/*
* searchContacts(): trivial queries must not reach the
* address book
*/
public function testSearchContactsSkipsShortQueries(): void
{
$this->contactsManager->expects($this->never())->method('search');
$c = $this->newController();
$this->assertSame([], $c->searchContacts('')->getData());
$this->assertSame([], $c->searchContacts('a')->getData());
$this->assertSame([], $c->searchContacts(' b ')->getData());
}
public function testSearchContactsIsRateLimited(): void
{
$method = new \ReflectionMethod(CalendarController::class, 'searchContacts');
$attributes = $method->getAttributes(UserRateLimit::class);
$this->assertCount(1, $attributes);
$limit = $attributes[0]->newInstance();
$this->assertSame(120, $limit->getLimit());
$this->assertSame(60, $limit->getPeriod());
}
public function testSearchContactsTruncatesQuery(): void
{
$this->contactsManager->expects($this->once())->method('search')