mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-05 11:51:16 -06:00
537 lines
16 KiB
PHP
537 lines
16 KiB
PHP
<?php
|
|
|
|
use Behat\Behat\Context\Context;
|
|
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
use TestHelpers\HttpRequestHelper;
|
|
use TestHelpers\SetupHelper;
|
|
use PHPUnit\Framework\Assert;
|
|
use \Behat\Gherkin\Node\TableNode;
|
|
|
|
require_once 'bootstrap.php';
|
|
|
|
/**
|
|
* Context for ocis spaces specific steps
|
|
*/
|
|
class SpacesContext implements Context {
|
|
|
|
/**
|
|
* @var FeatureContext
|
|
*/
|
|
private FeatureContext $featureContext;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
private array $availableSpaces;
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getAvailableSpaces(): array
|
|
{
|
|
return $this->availableSpaces;
|
|
}
|
|
|
|
/**
|
|
* @param array $availableSpaces
|
|
*/
|
|
public function setAvailableSpaces(array $availableSpaces): void
|
|
{
|
|
$this->availableSpaces = $availableSpaces;
|
|
}
|
|
|
|
/**
|
|
* response content parsed from XML to an array
|
|
*
|
|
* @var array
|
|
*/
|
|
private array $responseXml = [];
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getResponseXml(): array
|
|
{
|
|
return $this->responseXml;
|
|
}
|
|
|
|
/**
|
|
* @param array $responseXml
|
|
*/
|
|
public function setResponseXml(array $responseXml): void
|
|
{
|
|
$this->responseXml = $responseXml;
|
|
}
|
|
|
|
/**
|
|
* space id from last propfind request
|
|
*
|
|
* @var string
|
|
*/
|
|
private $responseSpaceId;
|
|
|
|
/**
|
|
* @param string $responseSpaceId
|
|
*/
|
|
public function setResponseSpaceId(string $responseSpaceId): void
|
|
{
|
|
$this->responseSpaceId = $responseSpaceId;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getResponseSpaceId(): string
|
|
{
|
|
return $this->responseSpaceId;
|
|
}
|
|
|
|
/**
|
|
* @BeforeScenario
|
|
*
|
|
* @param BeforeScenarioScope $scope
|
|
*
|
|
* @return void
|
|
* @throws Exception
|
|
*/
|
|
public function setUpScenario(BeforeScenarioScope $scope): void
|
|
{
|
|
// Get the environment
|
|
$environment = $scope->getEnvironment();
|
|
// Get all the contexts you need in this context
|
|
$this->featureContext = $environment->getContext('FeatureContext');
|
|
SetupHelper::init(
|
|
$this->featureContext->getAdminUsername(),
|
|
$this->featureContext->getAdminPassword(),
|
|
$this->featureContext->getBaseUrl(),
|
|
$this->featureContext->getOcPath()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Send Graph List Spaces Request
|
|
*
|
|
* @param $baseUrl
|
|
* @param $user
|
|
* @param $password
|
|
* @param $arguments
|
|
* @param string $xRequestId
|
|
* @param array $body
|
|
* @param array $headers
|
|
* @return ResponseInterface
|
|
*/
|
|
public function listSpacesRequest(
|
|
$baseUrl,
|
|
$user,
|
|
$password,
|
|
$arguments,
|
|
string $xRequestId = '',
|
|
array $body = [],
|
|
array $headers = []
|
|
) {
|
|
$fullUrl = $baseUrl;
|
|
if (!str_ends_with($fullUrl, '/')) {
|
|
$fullUrl .= '/';
|
|
}
|
|
$fullUrl .= "graph/v1.0/me/drives/" . $arguments;
|
|
|
|
return HttpRequestHelper::get($fullUrl, $xRequestId, $user, $password, $headers, $body);
|
|
}
|
|
|
|
/**
|
|
* Send Graph Create Space Request
|
|
*
|
|
* @param $baseUrl
|
|
* @param $user
|
|
* @param $password
|
|
* @param string $body
|
|
* @param string $xRequestId
|
|
* @param array $headers
|
|
* @return ResponseInterface
|
|
*/
|
|
public function sendCreateSpaceRequest(
|
|
$baseUrl,
|
|
$user,
|
|
$password,
|
|
string $body,
|
|
string $xRequestId = '',
|
|
array $headers = []
|
|
): ResponseInterface
|
|
{
|
|
$fullUrl = $baseUrl;
|
|
if (!str_ends_with($fullUrl, '/')) {
|
|
$fullUrl .= '/';
|
|
}
|
|
$fullUrl .= "graph/v1.0/drives/";
|
|
|
|
return HttpRequestHelper::post($fullUrl, $xRequestId, $user, $password, $headers, $body);
|
|
}
|
|
|
|
/**
|
|
* Send Propfind Request to Url
|
|
*
|
|
* @param $fullUrl
|
|
* @param $user
|
|
* @param $password
|
|
* @param string $xRequestId
|
|
* @param array $headers
|
|
* @return ResponseInterface
|
|
*/
|
|
public function sendPropfindRequestToUrl(
|
|
$fullUrl,
|
|
$user,
|
|
$password,
|
|
string $xRequestId = '',
|
|
array $headers = []
|
|
): ResponseInterface
|
|
{
|
|
return HttpRequestHelper::sendRequest($fullUrl, $xRequestId, 'PROPFIND', $user, $password, $headers);
|
|
}
|
|
|
|
/**
|
|
* @When /^user "([^"]*)" lists all available spaces via the GraphApi$/
|
|
*
|
|
* @param $user
|
|
* @return void
|
|
*/
|
|
public function theUserListsAllHisAvailableSpacesUsingTheGraphApi($user): void
|
|
{
|
|
$this->featureContext->setResponse(
|
|
$this->listSpacesRequest(
|
|
$this->featureContext->getBaseUrl(),
|
|
$user,
|
|
$this->featureContext->getPasswordForUser($user),
|
|
"",
|
|
""
|
|
)
|
|
);
|
|
$this->rememberTheAvailableSpaces();
|
|
}
|
|
|
|
/**
|
|
* @When /^user "([^"]*)" creates a space "([^"]*)" of type "([^"]*)" with the default quota using the GraphApi$/
|
|
*
|
|
* @param $user string
|
|
* @param $spaceName string
|
|
* @param $spaceType string
|
|
*
|
|
* @return void
|
|
*/
|
|
public function theUserCreatesASpaceUsingTheGraphApi($user, $spaceName, $spaceType): void
|
|
{
|
|
$space = ["Name" => $spaceName, "driveType" => $spaceType];
|
|
$body = json_encode($space);
|
|
$this->featureContext->setResponse(
|
|
$this->sendCreateSpaceRequest(
|
|
$this->featureContext->getBaseUrl(),
|
|
$user,
|
|
$this->featureContext->getPasswordForUser($user),
|
|
$body,
|
|
""
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @When /^user "([^"]*)" creates a space "([^"]*)" of type "([^"]*)" with quota "([^"]*)" using the GraphApi$/
|
|
*
|
|
* @param $user string
|
|
* @param $spaceName string
|
|
* @param $spaceType string
|
|
* @param $quota int
|
|
*
|
|
* @return void
|
|
* @throws JsonException
|
|
*/
|
|
public function theUserCreatesASpaceWithQuotaUsingTheGraphApi($user, $spaceName, $spaceType, $quota): void
|
|
{
|
|
$space = ["Name" => $spaceName, "driveType" => $spaceType, "quota" => ["total" => (int) $quota]];
|
|
$body = json_encode($space);
|
|
$this->featureContext->setResponse(
|
|
$this->sendCreateSpaceRequest(
|
|
$this->featureContext->getBaseUrl(),
|
|
$user,
|
|
$this->featureContext->getPasswordForUser($user),
|
|
$body,
|
|
""
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @When /^the administrator gives "([^"]*)" the role "([^"]*)" using the settings api$/
|
|
*
|
|
* @param $user string
|
|
* @param $role string
|
|
*
|
|
* @return void
|
|
*/
|
|
public function theAdministratorGivesUserTheRole(string $user, string $role): void
|
|
{
|
|
$admin = $this->featureContext->getAdminUsername();
|
|
$password = $this->featureContext->getAdminPassword();
|
|
$headers = [];
|
|
|
|
$baseUrl = $this->featureContext->getBaseUrl();
|
|
if (!str_ends_with($baseUrl, '/')) {
|
|
$baseUrl .= '/';
|
|
}
|
|
// get the roles list first
|
|
$fullUrl = $baseUrl . "api/v0/settings/roles-list";
|
|
$this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, "{}"));
|
|
if ($this->featureContext->getResponse()) {
|
|
$rawBody = $this->featureContext->getResponse()->getBody()->getContents();
|
|
}
|
|
$bundles = [];
|
|
if (isset(\json_decode($rawBody, true)["bundles"])) {
|
|
$bundles = \json_decode($rawBody, true)["bundles"];
|
|
}
|
|
$roleToAssign = "";
|
|
foreach($bundles as $bundle => $value) {
|
|
// find the selected role
|
|
if ($value["displayName"] === $role) {
|
|
$roleToAssign = $value;
|
|
}
|
|
}
|
|
Assert::assertNotEmpty($roleToAssign, "The selected role $role could not be found");
|
|
|
|
// get the accounts list first
|
|
$fullUrl = $baseUrl . "api/v0/accounts/accounts-list";
|
|
$this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, "{}"));
|
|
if ($this->featureContext->getResponse()) {
|
|
$rawBody = $this->featureContext->getResponse()->getBody()->getContents();
|
|
}
|
|
$accounts = [];
|
|
if (isset(\json_decode($rawBody, true)["accounts"])) {
|
|
$accounts = \json_decode($rawBody, true)["accounts"];
|
|
}
|
|
$accountToChange = "";
|
|
foreach($accounts as $account) {
|
|
// find the selected user
|
|
if ($account["preferredName"] === $user) {
|
|
$accountToChange = $account;
|
|
}
|
|
}
|
|
Assert::assertNotEmpty($accountToChange, "The seleted account $user does not exist");
|
|
|
|
// set the new role
|
|
$fullUrl = $baseUrl . "api/v0/settings/assignments-add";
|
|
$body = json_encode(["account_uuid" => $accountToChange["id"], "role_id" => $roleToAssign["id"]]);
|
|
|
|
$this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, $body));
|
|
if ($this->featureContext->getResponse()) {
|
|
$rawBody = $this->featureContext->getResponse()->getBody()->getContents();
|
|
}
|
|
|
|
$assignment = [];
|
|
if (isset(\json_decode($rawBody, true)["assignment"])) {
|
|
$assignment = \json_decode($rawBody, true)["assignment"];
|
|
}
|
|
|
|
Assert::assertEquals($accountToChange["id"], $assignment["accountUuid"]);
|
|
Assert::assertEquals($roleToAssign["id"], $assignment["roleId"]);
|
|
}
|
|
|
|
|
|
/**
|
|
* Remember the available Spaces
|
|
*
|
|
* @return void
|
|
*/
|
|
public function rememberTheAvailableSpaces(): void
|
|
{
|
|
$rawBody = $this->featureContext->getResponse()->getBody()->getContents();
|
|
$drives = json_decode($rawBody, true);
|
|
if (isset($drives["value"])) {
|
|
$drives = $drives["value"];
|
|
}
|
|
|
|
Assert::assertArrayHasKey(0, $drives, "No drives were found on that endpoint");
|
|
$spaces = [];
|
|
foreach($drives as $drive) {
|
|
$spaces[$drive["name"]] = $drive;
|
|
}
|
|
$this->setAvailableSpaces($spaces);
|
|
Assert::assertNotEmpty($spaces, "No spaces have been found");
|
|
}
|
|
|
|
/**
|
|
* @When /^user "([^"]*)" lists the content of the space with the name "([^"]*)" using the WebDav Api$/
|
|
*
|
|
* @param $user
|
|
* @param $name
|
|
* @return void
|
|
*/
|
|
public function theUserListsTheContentOfAPersonalSpaceRootUsingTheWebDAvApi($user, $name): void
|
|
{
|
|
$spaceId = $this->getAvailableSpaces()[$name]["id"];
|
|
$spaceWebDavUrl = $this->getAvailableSpaces()[$name]["root"]["webDavUrl"];
|
|
$this->featureContext->setResponse(
|
|
$this->sendPropfindRequestToUrl(
|
|
$spaceWebDavUrl,
|
|
$user,
|
|
$this->featureContext->getPasswordForUser($user),
|
|
"",
|
|
[],
|
|
[],
|
|
[]
|
|
)
|
|
);
|
|
$this->setResponseSpaceId($spaceId);
|
|
$this->setResponseXml(HttpRequestHelper::parseResponseAsXml($this->featureContext->getResponse())
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @Then /^the (?:propfind|search) result of the space should (not|)\s?contain these (?:files|entries):$/
|
|
*
|
|
* @param string $user
|
|
* @param string $shouldOrNot (not|)
|
|
* @param TableNode $expectedFiles
|
|
*
|
|
* @return void
|
|
* @throws Exception
|
|
*/
|
|
public function thePropfindResultShouldContainEntries(
|
|
$shouldOrNot,
|
|
TableNode $expectedFiles
|
|
) {
|
|
$this->propfindResultShouldContainEntries(
|
|
$shouldOrNot,
|
|
$expectedFiles,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @Then the json responded should contain these key and value pairs
|
|
*
|
|
* @param TableNode $table
|
|
*
|
|
* @return void
|
|
*/
|
|
public function jsonRespondedShouldContain(TableNode $table) {
|
|
$this->featureContext->verifyTableNodeColumns($table, ['key', 'value']);
|
|
$responseJson = json_decode($this->featureContext->getResponse()->getBody(), true);
|
|
foreach ($table->getHash() as $row) {
|
|
$expected = [$row["key"] => $row["value"]];
|
|
Assert::assertEquals($row["value"], $responseJson[$row["key"]]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $shouldOrNot (not|)
|
|
* @param TableNode $expectedFiles
|
|
* @param string|null $user
|
|
*
|
|
* @return void
|
|
* @throws Exception
|
|
*/
|
|
public function propfindResultShouldContainEntries(
|
|
$shouldOrNot,
|
|
TableNode $expectedFiles
|
|
) {
|
|
$this->verifyTableNodeColumnsCount($expectedFiles, 1);
|
|
$elementRows = $expectedFiles->getRows();
|
|
$should = ($shouldOrNot !== "not");
|
|
|
|
foreach ($elementRows as $expectedFile) {
|
|
$fileFound = $this->findEntryFromPropfindResponse(
|
|
$expectedFile[0]
|
|
);
|
|
if ($should) {
|
|
Assert::assertNotEmpty(
|
|
$fileFound,
|
|
"response does not contain the entry '$expectedFile[0]'"
|
|
);
|
|
} else {
|
|
Assert::assertFalse(
|
|
$fileFound,
|
|
"response does contain the entry '$expectedFile[0]' but should not"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Verify that the tableNode contains expected number of columns
|
|
*
|
|
* @param TableNode $table
|
|
* @param int $count
|
|
*
|
|
* @return void
|
|
* @throws Exception
|
|
*/
|
|
public function verifyTableNodeColumnsCount($table, $count) {
|
|
if (!($table instanceof TableNode)) {
|
|
throw new Exception("TableNode expected but got " . \gettype($table));
|
|
}
|
|
if (\count($table->getRows()) < 1) {
|
|
throw new Exception("Table should have at least one row.");
|
|
}
|
|
$rowCount = \count($table->getRows()[0]);
|
|
if ($count !== $rowCount) {
|
|
throw new Exception("Table expected to have $count rows but found $rowCount");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* parses a PROPFIND response from $this->response into xml
|
|
* and returns found search results if found else returns false
|
|
*
|
|
* @param string|null $entryNameToSearch
|
|
* @return string|array|boolean
|
|
* string if $entryNameToSearch is given and is found
|
|
* array if $entryNameToSearch is not given
|
|
* boolean false if $entryNameToSearch is given and is not found
|
|
*/
|
|
public function findEntryFromPropfindResponse(
|
|
string $entryNameToSearch = null
|
|
) {
|
|
$spaceId = $this->getResponseSpaceId();
|
|
//if we are using that step the second time in a scenario e.g. 'But ... should not'
|
|
//then don't parse the result again, because the result in a ResponseInterface
|
|
if (empty($this->getResponseXml())) {
|
|
$this->setResponseXml(
|
|
HttpRequestHelper::parseResponseAsXml($this->featureContext->getResponse())
|
|
);
|
|
}
|
|
Assert::assertNotEmpty($this->getResponseXml(), __METHOD__ . ' Response is empty');
|
|
Assert::assertNotEmpty($spaceId, __METHOD__ . ' SpaceId is empty');
|
|
|
|
// trim any leading "/" passed by the caller, we can just match the "raw" name
|
|
$trimmedEntryNameToSearch = \trim($entryNameToSearch, "/");
|
|
|
|
// topWebDavPath should be something like /remote.php/webdav/ or
|
|
// /remote.php/dav/files/alice/
|
|
$topWebDavPath = "/" . "dav/spaces/" . $spaceId . "/";
|
|
|
|
Assert::assertIsArray(
|
|
$this->responseXml,
|
|
__METHOD__ . " responseXml for space $spaceId is not an array"
|
|
);
|
|
Assert::assertArrayHasKey(
|
|
"value",
|
|
$this->responseXml,
|
|
__METHOD__ . " responseXml for space $spaceId does not have key 'value'"
|
|
);
|
|
$multistatusResults = $this->responseXml["value"];
|
|
$results = [];
|
|
if ($multistatusResults !== null) {
|
|
foreach ($multistatusResults as $multistatusResult) {
|
|
$entryPath = $multistatusResult['value'][0]['value'];
|
|
$entryName = \str_replace($topWebDavPath, "", $entryPath);
|
|
$entryName = \rawurldecode($entryName);
|
|
$entryName = \trim($entryName, "/");
|
|
if ($trimmedEntryNameToSearch === $entryName) {
|
|
return $multistatusResult;
|
|
}
|
|
$results[] = $entryName;
|
|
}
|
|
}
|
|
if ($entryNameToSearch === null) {
|
|
return $results;
|
|
}
|
|
return false;
|
|
}
|
|
}
|