mirror of
https://github.com/nextcloud/server.git
synced 2026-05-25 02:34:12 -04:00
test(dav): add integration test for principal property search
Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
This commit is contained in:
parent
e6b26612fa
commit
dbbacb488d
8 changed files with 211 additions and 0 deletions
|
|
@ -12,6 +12,7 @@ return array(
|
|||
'OCA\\Testing\\Controller\\ConfigController' => $baseDir . '/../lib/Controller/ConfigController.php',
|
||||
'OCA\\Testing\\Controller\\LockingController' => $baseDir . '/../lib/Controller/LockingController.php',
|
||||
'OCA\\Testing\\Controller\\RateLimitTestController' => $baseDir . '/../lib/Controller/RateLimitTestController.php',
|
||||
'OCA\\Testing\\HiddenGroupBackend' => $baseDir . '/../lib/HiddenGroupBackend.php',
|
||||
'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => $baseDir . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',
|
||||
'OCA\\Testing\\Listener\\RegisterDeclarativeSettingsListener' => $baseDir . '/../lib/Listener/RegisterDeclarativeSettingsListener.php',
|
||||
'OCA\\Testing\\Listener\\SetDeclarativeSettingsValueListener' => $baseDir . '/../lib/Listener/SetDeclarativeSettingsValueListener.php',
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ class ComposerStaticInitTesting
|
|||
'OCA\\Testing\\Controller\\ConfigController' => __DIR__ . '/..' . '/../lib/Controller/ConfigController.php',
|
||||
'OCA\\Testing\\Controller\\LockingController' => __DIR__ . '/..' . '/../lib/Controller/LockingController.php',
|
||||
'OCA\\Testing\\Controller\\RateLimitTestController' => __DIR__ . '/..' . '/../lib/Controller/RateLimitTestController.php',
|
||||
'OCA\\Testing\\HiddenGroupBackend' => __DIR__ . '/..' . '/../lib/HiddenGroupBackend.php',
|
||||
'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => __DIR__ . '/..' . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',
|
||||
'OCA\\Testing\\Listener\\RegisterDeclarativeSettingsListener' => __DIR__ . '/..' . '/../lib/Listener/RegisterDeclarativeSettingsListener.php',
|
||||
'OCA\\Testing\\Listener\\SetDeclarativeSettingsValueListener' => __DIR__ . '/..' . '/../lib/Listener/SetDeclarativeSettingsValueListener.php',
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
namespace OCA\Testing\AppInfo;
|
||||
|
||||
use OCA\Testing\AlternativeHomeUserBackend;
|
||||
use OCA\Testing\HiddenGroupBackend;
|
||||
use OCA\Testing\Listener\GetDeclarativeSettingsValueListener;
|
||||
use OCA\Testing\Listener\RegisterDeclarativeSettingsListener;
|
||||
use OCA\Testing\Listener\SetDeclarativeSettingsValueListener;
|
||||
|
|
@ -26,6 +27,7 @@ use OCP\AppFramework\App;
|
|||
use OCP\AppFramework\Bootstrap\IBootContext;
|
||||
use OCP\AppFramework\Bootstrap\IBootstrap;
|
||||
use OCP\AppFramework\Bootstrap\IRegistrationContext;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
|
||||
use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent;
|
||||
use OCP\Settings\Events\DeclarativeSettingsSetValueEvent;
|
||||
|
|
@ -66,5 +68,8 @@ class Application extends App implements IBootstrap {
|
|||
$userManager->clearBackends();
|
||||
$userManager->registerBackend($context->getAppContainer()->get(AlternativeHomeUserBackend::class));
|
||||
}
|
||||
|
||||
$groupManager = $server->get(IGroupManager::class);
|
||||
$groupManager->addBackend($server->get(HiddenGroupBackend::class));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
47
apps/testing/lib/HiddenGroupBackend.php
Normal file
47
apps/testing/lib/HiddenGroupBackend.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Testing;
|
||||
|
||||
use OCP\Group\Backend\ABackend;
|
||||
use OCP\Group\Backend\IHideFromCollaborationBackend;
|
||||
|
||||
class HiddenGroupBackend extends ABackend implements IHideFromCollaborationBackend {
|
||||
private string $groupName;
|
||||
|
||||
public function __construct(
|
||||
string $groupName = 'hidden_group',
|
||||
) {
|
||||
$this->groupName = $groupName;
|
||||
}
|
||||
|
||||
public function inGroup($uid, $gid): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getUserGroups($uid): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getGroups($search = '', $limit = -1, $offset = 0): array {
|
||||
return $offset === 0 ? [$this->groupName] : [];
|
||||
}
|
||||
|
||||
public function groupExists($gid): bool {
|
||||
return $gid === $this->groupName;
|
||||
}
|
||||
|
||||
public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
public function hideGroup(string $groupId): bool {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -80,6 +80,8 @@ default:
|
|||
- CommandLineContext:
|
||||
baseUrl: http://localhost:8080
|
||||
ocPath: ../../
|
||||
- PrincipalPropertySearchContext:
|
||||
baseUrl: http://localhost:8080
|
||||
federation:
|
||||
paths:
|
||||
- "%paths.base%/../federation_features"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
Feature: principal-property-search
|
||||
Background:
|
||||
Given user "user0" exists
|
||||
Given As an "admin"
|
||||
Given invoking occ with "app:enable --force testing"
|
||||
|
||||
Scenario: Find a principal by a given displayname
|
||||
When searching for a principal matching "user0"
|
||||
Then The search HTTP status code should be "207"
|
||||
And The search response should contain "<d:href>/remote.php/dav/principals/users/user0/</d:href>"
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use GuzzleHttp\BodySummarizer;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Middleware;
|
||||
use GuzzleHttp\Utils;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class PrincipalPropertySearchContext implements Context {
|
||||
private string $baseUrl;
|
||||
private Client $client;
|
||||
private ResponseInterface $response;
|
||||
|
||||
public function __construct(string $baseUrl) {
|
||||
$this->baseUrl = $baseUrl;
|
||||
|
||||
// in case of ci deployment we take the server url from the environment
|
||||
$testServerUrl = getenv('TEST_SERVER_URL');
|
||||
if ($testServerUrl !== false) {
|
||||
$this->baseUrl = substr($testServerUrl, 0, -5);
|
||||
}
|
||||
}
|
||||
|
||||
/** @BeforeScenario */
|
||||
public function setUpScenario(): void {
|
||||
$this->client = $this->createGuzzleInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Guzzle client with a higher truncateAt value to read full error responses.
|
||||
*/
|
||||
private function createGuzzleInstance(): Client {
|
||||
$bodySummarizer = new BodySummarizer(2048);
|
||||
|
||||
$stack = new HandlerStack(Utils::chooseHandler());
|
||||
$stack->push(Middleware::httpErrors($bodySummarizer), 'http_errors');
|
||||
$stack->push(Middleware::redirect(), 'allow_redirects');
|
||||
$stack->push(Middleware::cookies(), 'cookies');
|
||||
$stack->push(Middleware::prepareBody(), 'prepare_body');
|
||||
|
||||
return new Client(['handler' => $stack]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When searching for a principal matching :match
|
||||
* @param string $match
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function principalPropertySearch(string $match) {
|
||||
$davUrl = $this->baseUrl . '/remote.php/dav/';
|
||||
$user = 'admin';
|
||||
$password = 'admin';
|
||||
|
||||
$this->response = $this->client->request(
|
||||
'REPORT',
|
||||
$davUrl,
|
||||
[
|
||||
'body' => '<x0:principal-property-search xmlns:x0="DAV:" test="anyof">
|
||||
<x0:property-search>
|
||||
<x0:prop>
|
||||
<x0:displayname/>
|
||||
<x2:email-address xmlns:x2="http://sabredav.org/ns"/>
|
||||
</x0:prop>
|
||||
<x0:match>' . $match . '</x0:match>
|
||||
</x0:property-search>
|
||||
<x0:prop>
|
||||
<x0:displayname/>
|
||||
<x1:calendar-user-type xmlns:x1="urn:ietf:params:xml:ns:caldav"/>
|
||||
<x1:calendar-user-address-set xmlns:x1="urn:ietf:params:xml:ns:caldav"/>
|
||||
<x0:principal-URL/>
|
||||
<x0:alternate-URI-set/>
|
||||
<x2:email-address xmlns:x2="http://sabredav.org/ns"/>
|
||||
<x3:language xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x1:calendar-home-set xmlns:x1="urn:ietf:params:xml:ns:caldav"/>
|
||||
<x1:schedule-inbox-URL xmlns:x1="urn:ietf:params:xml:ns:caldav"/>
|
||||
<x1:schedule-outbox-URL xmlns:x1="urn:ietf:params:xml:ns:caldav"/>
|
||||
<x1:schedule-default-calendar-URL xmlns:x1="urn:ietf:params:xml:ns:caldav"/>
|
||||
<x3:resource-type xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:resource-vehicle-type xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:resource-vehicle-make xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:resource-vehicle-model xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:resource-vehicle-is-electric xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:resource-vehicle-range xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:resource-vehicle-seating-capacity xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:resource-contact-person xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:resource-contact-person-vcard xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:room-type xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:room-seating-capacity xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:room-building-address xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:room-building-story xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:room-building-room-number xmlns:x3="http://nextcloud.com/ns"/>
|
||||
<x3:room-features xmlns:x3="http://nextcloud.com/ns"/>
|
||||
</x0:prop>
|
||||
<x0:apply-to-principal-collection-set/>
|
||||
</x0:principal-property-search>
|
||||
',
|
||||
'auth' => [
|
||||
$user,
|
||||
$password,
|
||||
],
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/xml; charset=UTF-8',
|
||||
'Depth' => '0',
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then The search HTTP status code should be :code
|
||||
* @param string $code
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function theHttpStatusCodeShouldBe(string $code): void {
|
||||
if ((int) $code !== $this->response->getStatusCode()) {
|
||||
throw new \Exception('Expected ' . (int) $code . ' got ' . $this->response->getStatusCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then The search response should contain :needle
|
||||
* @param string $needle
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function theResponseShouldContain(string $needle): void {
|
||||
$body = $this->response->getBody()->getContents();
|
||||
|
||||
if (str_contains($body, $needle) === false) {
|
||||
throw new \Exception('Response does not contain "' . $needle . '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -450,6 +450,7 @@ Feature: provisioning
|
|||
Then groups returned are
|
||||
| España |
|
||||
| admin |
|
||||
| hidden_group |
|
||||
| new-group |
|
||||
|
||||
Scenario: create a subadmin
|
||||
|
|
|
|||
Loading…
Reference in a new issue