mirror of
https://github.com/nextcloud/server.git
synced 2026-02-03 20:41:22 -05:00
This allows the admin to control the behavior whether link shares with READ permissions should be extended to also gain SHARE permissions, allowing users (public share receivers) to add the share to their cloud. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
741 lines
22 KiB
PHP
741 lines
22 KiB
PHP
<?php
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
|
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
use Behat\Gherkin\Node\TableNode;
|
|
use GuzzleHttp\Client;
|
|
use PHPUnit\Framework\Assert;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
|
|
require __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
|
|
|
|
trait Sharing {
|
|
use Provisioning;
|
|
|
|
/** @var int */
|
|
private $sharingApiVersion = 1;
|
|
|
|
/** @var SimpleXMLElement */
|
|
private $lastShareData = null;
|
|
|
|
/** @var SimpleXMLElement[] */
|
|
private $storedShareData = [];
|
|
|
|
/** @var int */
|
|
private $savedShareId = null;
|
|
|
|
/** @var ResponseInterface */
|
|
private $response;
|
|
|
|
/**
|
|
* @Given /^as "([^"]*)" creating a share with$/
|
|
* @param string $user
|
|
* @param TableNode|null $body
|
|
*/
|
|
public function asCreatingAShareWith($user, $body) {
|
|
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares";
|
|
$client = new Client();
|
|
$options = [
|
|
'headers' => [
|
|
'OCS-APIREQUEST' => 'true',
|
|
],
|
|
];
|
|
if ($user === 'admin') {
|
|
$options['auth'] = $this->adminUser;
|
|
} else {
|
|
$options['auth'] = [$user, $this->regularUser];
|
|
}
|
|
|
|
if ($body instanceof TableNode) {
|
|
$fd = $body->getRowsHash();
|
|
if (array_key_exists('expireDate', $fd)) {
|
|
$dateModification = $fd['expireDate'];
|
|
if ($dateModification === 'null') {
|
|
$fd['expireDate'] = null;
|
|
} elseif (!empty($dateModification)) {
|
|
$fd['expireDate'] = date('Y-m-d', strtotime($dateModification));
|
|
} else {
|
|
$fd['expireDate'] = '';
|
|
}
|
|
}
|
|
$options['form_params'] = $fd;
|
|
}
|
|
|
|
try {
|
|
$this->response = $client->request('POST', $fullUrl, $options);
|
|
} catch (\GuzzleHttp\Exception\ClientException $ex) {
|
|
$this->response = $ex->getResponse();
|
|
}
|
|
|
|
$this->lastShareData = simplexml_load_string($this->response->getBody());
|
|
}
|
|
|
|
/**
|
|
* @When /^save the last share data as "([^"]*)"$/
|
|
*/
|
|
public function saveLastShareData($name) {
|
|
$this->storedShareData[$name] = $this->lastShareData;
|
|
}
|
|
|
|
/**
|
|
* @When /^restore the last share data from "([^"]*)"$/
|
|
*/
|
|
public function restoreLastShareData($name) {
|
|
$this->lastShareData = $this->storedShareData[$name];
|
|
}
|
|
|
|
/**
|
|
* @When /^creating a share with$/
|
|
* @param TableNode|null $body
|
|
*/
|
|
public function creatingShare($body) {
|
|
$this->asCreatingAShareWith($this->currentUser, $body);
|
|
}
|
|
|
|
/**
|
|
* @When /^accepting last share$/
|
|
*/
|
|
public function acceptingLastShare() {
|
|
$share_id = $this->lastShareData->data[0]->id;
|
|
$url = "/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/pending/$share_id";
|
|
$this->sendingToWith('POST', $url, null);
|
|
|
|
$this->theHTTPStatusCodeShouldBe('200');
|
|
}
|
|
|
|
/**
|
|
* @When /^user "([^"]*)" accepts last share$/
|
|
*
|
|
* @param string $user
|
|
*/
|
|
public function userAcceptsLastShare(string $user) {
|
|
// "As userXXX" and "user userXXX accepts last share" steps are not
|
|
// expected to be used in the same scenario, but restore the user just
|
|
// in case.
|
|
$previousUser = $this->currentUser;
|
|
|
|
$this->currentUser = $user;
|
|
|
|
$share_id = $this->lastShareData->data[0]->id;
|
|
$url = "/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/pending/$share_id";
|
|
$this->sendingToWith('POST', $url, null);
|
|
|
|
$this->currentUser = $previousUser;
|
|
|
|
$this->theHTTPStatusCodeShouldBe('200');
|
|
}
|
|
|
|
/**
|
|
* @Then /^last link share can be downloaded$/
|
|
*/
|
|
public function lastLinkShareCanBeDownloaded() {
|
|
if (count($this->lastShareData->data->element) > 0) {
|
|
$url = $this->lastShareData->data[0]->url;
|
|
} else {
|
|
$url = $this->lastShareData->data->url;
|
|
}
|
|
$fullUrl = $url . '/download';
|
|
$this->checkDownload($fullUrl, null, 'text/plain');
|
|
}
|
|
|
|
/**
|
|
* @Then /^last share can be downloaded$/
|
|
*/
|
|
public function lastShareCanBeDownloaded() {
|
|
if (count($this->lastShareData->data->element) > 0) {
|
|
$token = $this->lastShareData->data[0]->token;
|
|
} else {
|
|
$token = $this->lastShareData->data->token;
|
|
}
|
|
|
|
$fullUrl = substr($this->baseUrl, 0, -4) . 'index.php/s/' . $token . '/download';
|
|
$this->checkDownload($fullUrl, null, 'text/plain');
|
|
}
|
|
|
|
/**
|
|
* @Then /^last share with password "([^"]*)" can be downloaded$/
|
|
*/
|
|
public function lastShareWithPasswordCanBeDownloaded($password) {
|
|
if (count($this->lastShareData->data->element) > 0) {
|
|
$token = $this->lastShareData->data[0]->token;
|
|
} else {
|
|
$token = $this->lastShareData->data->token;
|
|
}
|
|
|
|
$fullUrl = substr($this->baseUrl, 0, -4) . "public.php/dav/files/$token/";
|
|
$this->checkDownload($fullUrl, ['', $password], 'text/plain');
|
|
}
|
|
|
|
private function checkDownload($url, $auth = null, $mimeType = null) {
|
|
if ($auth !== null) {
|
|
$options['auth'] = $auth;
|
|
}
|
|
$options['stream'] = true;
|
|
|
|
$client = new Client();
|
|
$this->response = $client->get($url, $options);
|
|
Assert::assertEquals(200, $this->response->getStatusCode());
|
|
|
|
$buf = '';
|
|
$body = $this->response->getBody();
|
|
while (!$body->eof()) {
|
|
// read everything
|
|
$buf .= $body->read(8192);
|
|
}
|
|
$body->close();
|
|
|
|
if ($mimeType !== null) {
|
|
$finfo = new finfo;
|
|
Assert::assertEquals($mimeType, $finfo->buffer($buf, FILEINFO_MIME_TYPE));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @When /^Adding expiration date to last share$/
|
|
*/
|
|
public function addingExpirationDate() {
|
|
$share_id = (string)$this->lastShareData->data[0]->id;
|
|
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/$share_id";
|
|
$client = new Client();
|
|
$options = [];
|
|
if ($this->currentUser === 'admin') {
|
|
$options['auth'] = $this->adminUser;
|
|
} else {
|
|
$options['auth'] = [$this->currentUser, $this->regularUser];
|
|
}
|
|
$date = date('Y-m-d', strtotime('+3 days'));
|
|
$options['form_params'] = ['expireDate' => $date];
|
|
$this->response = $this->response = $client->request('PUT', $fullUrl, $options);
|
|
Assert::assertEquals(200, $this->response->getStatusCode());
|
|
}
|
|
|
|
/**
|
|
* @When /^Updating last share with$/
|
|
* @param TableNode|null $body
|
|
*/
|
|
public function updatingLastShare($body) {
|
|
$share_id = (string)$this->lastShareData->data[0]->id;
|
|
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/$share_id";
|
|
$client = new Client();
|
|
$options = [
|
|
'headers' => [
|
|
'OCS-APIREQUEST' => 'true',
|
|
],
|
|
];
|
|
if ($this->currentUser === 'admin') {
|
|
$options['auth'] = $this->adminUser;
|
|
} else {
|
|
$options['auth'] = [$this->currentUser, $this->regularUser];
|
|
}
|
|
|
|
if ($body instanceof TableNode) {
|
|
$fd = $body->getRowsHash();
|
|
if (array_key_exists('expireDate', $fd)) {
|
|
$dateModification = $fd['expireDate'];
|
|
$fd['expireDate'] = date('Y-m-d', strtotime($dateModification));
|
|
}
|
|
$options['form_params'] = $fd;
|
|
}
|
|
|
|
try {
|
|
$this->response = $client->request('PUT', $fullUrl, $options);
|
|
} catch (\GuzzleHttp\Exception\ClientException $ex) {
|
|
$this->response = $ex->getResponse();
|
|
}
|
|
}
|
|
|
|
public function createShare($user,
|
|
$path = null,
|
|
$shareType = null,
|
|
$shareWith = null,
|
|
$publicUpload = null,
|
|
$password = null,
|
|
$permissions = null,
|
|
$viewOnly = false) {
|
|
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares";
|
|
$client = new Client();
|
|
$options = [
|
|
'headers' => [
|
|
'OCS-APIREQUEST' => 'true',
|
|
],
|
|
];
|
|
|
|
if ($user === 'admin') {
|
|
$options['auth'] = $this->adminUser;
|
|
} else {
|
|
$options['auth'] = [$user, $this->regularUser];
|
|
}
|
|
$body = [];
|
|
if (!is_null($path)) {
|
|
$body['path'] = $path;
|
|
}
|
|
if (!is_null($shareType)) {
|
|
$body['shareType'] = $shareType;
|
|
}
|
|
if (!is_null($shareWith)) {
|
|
$body['shareWith'] = $shareWith;
|
|
}
|
|
if (!is_null($publicUpload)) {
|
|
$body['publicUpload'] = $publicUpload;
|
|
}
|
|
if (!is_null($password)) {
|
|
$body['password'] = $password;
|
|
}
|
|
if (!is_null($permissions)) {
|
|
$body['permissions'] = $permissions;
|
|
}
|
|
|
|
if ($viewOnly === true) {
|
|
$body['attributes'] = json_encode([['scope' => 'permissions', 'key' => 'download', 'value' => false]]);
|
|
}
|
|
|
|
$options['form_params'] = $body;
|
|
|
|
try {
|
|
$this->response = $client->request('POST', $fullUrl, $options);
|
|
$this->lastShareData = simplexml_load_string($this->response->getBody());
|
|
} catch (\GuzzleHttp\Exception\ClientException $ex) {
|
|
$this->response = $ex->getResponse();
|
|
throw new \Exception($this->response->getBody());
|
|
}
|
|
}
|
|
|
|
public function isFieldInResponse($field, $contentExpected) {
|
|
$data = simplexml_load_string($this->response->getBody())->data[0];
|
|
if ((string)$field == 'expiration') {
|
|
if (!empty($contentExpected)) {
|
|
$contentExpected = date('Y-m-d', strtotime($contentExpected)) . ' 00:00:00';
|
|
}
|
|
}
|
|
if (count($data->element) > 0) {
|
|
foreach ($data as $element) {
|
|
if ($contentExpected == 'A_TOKEN') {
|
|
return (strlen((string)$element->$field) == 15);
|
|
} elseif ($contentExpected == 'A_NUMBER') {
|
|
return is_numeric((string)$element->$field);
|
|
} elseif ($contentExpected == 'AN_URL') {
|
|
return $this->isExpectedUrl((string)$element->$field, 'index.php/s/');
|
|
} elseif ((string)$element->$field == $contentExpected) {
|
|
return true;
|
|
} else {
|
|
print($element->$field);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
} else {
|
|
if ($contentExpected == 'A_TOKEN') {
|
|
return (strlen((string)$data->$field) == 15);
|
|
} elseif ($contentExpected == 'A_NUMBER') {
|
|
return is_numeric((string)$data->$field);
|
|
} elseif ($contentExpected == 'AN_URL') {
|
|
return $this->isExpectedUrl((string)$data->$field, 'index.php/s/');
|
|
} elseif ($contentExpected == $data->$field) {
|
|
return true;
|
|
} else {
|
|
print($data->$field);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @Then /^File "([^"]*)" should be included in the response$/
|
|
*
|
|
* @param string $filename
|
|
*/
|
|
public function checkSharedFileInResponse($filename) {
|
|
Assert::assertEquals(true, $this->isFieldInResponse('file_target', "/$filename"));
|
|
}
|
|
|
|
/**
|
|
* @Then /^File "([^"]*)" should not be included in the response$/
|
|
*
|
|
* @param string $filename
|
|
*/
|
|
public function checkSharedFileNotInResponse($filename) {
|
|
Assert::assertEquals(false, $this->isFieldInResponse('file_target', "/$filename"));
|
|
}
|
|
|
|
/**
|
|
* @Then /^User "([^"]*)" should be included in the response$/
|
|
*
|
|
* @param string $user
|
|
*/
|
|
public function checkSharedUserInResponse($user) {
|
|
Assert::assertEquals(true, $this->isFieldInResponse('share_with', "$user"));
|
|
}
|
|
|
|
/**
|
|
* @Then /^User "([^"]*)" should not be included in the response$/
|
|
*
|
|
* @param string $user
|
|
*/
|
|
public function checkSharedUserNotInResponse($user) {
|
|
Assert::assertEquals(false, $this->isFieldInResponse('share_with', "$user"));
|
|
}
|
|
|
|
public function isUserOrGroupInSharedData($userOrGroup, $permissions = null) {
|
|
$data = simplexml_load_string($this->response->getBody())->data[0];
|
|
foreach ($data as $element) {
|
|
if ($element->share_with == $userOrGroup && ($permissions === null || $permissions == $element->permissions)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @Given /^(file|folder|entry) "([^"]*)" of user "([^"]*)" is shared with user "([^"]*)"( with permissions ([\d]*))?( view-only)?$/
|
|
*
|
|
* @param string $filepath
|
|
* @param string $user1
|
|
* @param string $user2
|
|
*/
|
|
public function assureFileIsShared($entry, $filepath, $user1, $user2, $withPerms = null, $permissions = null, $viewOnly = null) {
|
|
// when view-only is set, permissions is empty string instead of null...
|
|
if ($permissions === '') {
|
|
$permissions = null;
|
|
}
|
|
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares" . "?path=$filepath";
|
|
$client = new Client();
|
|
$options = [];
|
|
if ($user1 === 'admin') {
|
|
$options['auth'] = $this->adminUser;
|
|
} else {
|
|
$options['auth'] = [$user1, $this->regularUser];
|
|
}
|
|
$options['headers'] = [
|
|
'OCS-APIREQUEST' => 'true',
|
|
];
|
|
$this->response = $client->get($fullUrl, $options);
|
|
if ($this->isUserOrGroupInSharedData($user2, $permissions)) {
|
|
return;
|
|
} else {
|
|
$this->createShare($user1, $filepath, 0, $user2, null, null, $permissions, $viewOnly !== null);
|
|
}
|
|
$this->response = $client->get($fullUrl, $options);
|
|
Assert::assertEquals(true, $this->isUserOrGroupInSharedData($user2, $permissions));
|
|
}
|
|
|
|
/**
|
|
* @Given /^(file|folder|entry) "([^"]*)" of user "([^"]*)" is shared with group "([^"]*)"( with permissions ([\d]*))?( view-only)?$/
|
|
*
|
|
* @param string $filepath
|
|
* @param string $user
|
|
* @param string $group
|
|
*/
|
|
public function assureFileIsSharedWithGroup($entry, $filepath, $user, $group, $withPerms = null, $permissions = null, $viewOnly = null) {
|
|
// when view-only is set, permissions is empty string instead of null...
|
|
if ($permissions === '') {
|
|
$permissions = null;
|
|
}
|
|
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares" . "?path=$filepath";
|
|
$client = new Client();
|
|
$options = [];
|
|
if ($user === 'admin') {
|
|
$options['auth'] = $this->adminUser;
|
|
} else {
|
|
$options['auth'] = [$user, $this->regularUser];
|
|
}
|
|
$options['headers'] = [
|
|
'OCS-APIREQUEST' => 'true',
|
|
];
|
|
$this->response = $client->get($fullUrl, $options);
|
|
if ($this->isUserOrGroupInSharedData($group, $permissions)) {
|
|
return;
|
|
} else {
|
|
$this->createShare($user, $filepath, 1, $group, null, null, $permissions, $viewOnly !== null);
|
|
}
|
|
$this->response = $client->get($fullUrl, $options);
|
|
Assert::assertEquals(true, $this->isUserOrGroupInSharedData($group, $permissions));
|
|
}
|
|
|
|
/**
|
|
* @When /^Deleting last share$/
|
|
*/
|
|
public function deletingLastShare() {
|
|
$share_id = $this->lastShareData->data[0]->id;
|
|
$url = "/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/$share_id";
|
|
$this->sendingToWith('DELETE', $url, null);
|
|
}
|
|
|
|
/**
|
|
* @When /^Getting info of last share$/
|
|
*/
|
|
public function gettingInfoOfLastShare() {
|
|
$share_id = $this->lastShareData->data[0]->id;
|
|
$url = "/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/$share_id";
|
|
$this->sendingToWith('GET', $url, null);
|
|
}
|
|
|
|
/**
|
|
* @Then /^last share_id is included in the answer$/
|
|
*/
|
|
public function checkingLastShareIDIsIncluded() {
|
|
$share_id = $this->lastShareData->data[0]->id;
|
|
if (!$this->isFieldInResponse('id', $share_id)) {
|
|
Assert::fail("Share id $share_id not found in response");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @Then /^last share_id is not included in the answer$/
|
|
*/
|
|
public function checkingLastShareIDIsNotIncluded() {
|
|
$share_id = $this->lastShareData->data[0]->id;
|
|
if ($this->isFieldInResponse('id', $share_id)) {
|
|
Assert::fail("Share id $share_id has been found in response");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @Then /^Share fields of last share match with$/
|
|
* @param TableNode|null $body
|
|
*/
|
|
public function checkShareFields($body) {
|
|
if ($body instanceof TableNode) {
|
|
$fd = $body->getRowsHash();
|
|
|
|
foreach ($fd as $field => $value) {
|
|
if (substr($field, 0, 10) === 'share_with') {
|
|
$value = str_replace('REMOTE', substr($this->remoteBaseUrl, 0, -5), $value);
|
|
$value = str_replace('LOCAL', substr($this->localBaseUrl, 0, -5), $value);
|
|
}
|
|
if (substr($field, 0, 6) === 'remote') {
|
|
$value = str_replace('REMOTE', substr($this->remoteBaseUrl, 0, -4), $value);
|
|
$value = str_replace('LOCAL', substr($this->localBaseUrl, 0, -4), $value);
|
|
}
|
|
if (!$this->isFieldInResponse($field, $value)) {
|
|
Assert::fail("$field" . " doesn't have value " . "$value");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @Then the list of returned shares has :count shares
|
|
*/
|
|
public function theListOfReturnedSharesHasShares(int $count) {
|
|
$this->theHTTPStatusCodeShouldBe('200');
|
|
$this->theOCSStatusCodeShouldBe('100');
|
|
|
|
$returnedShares = $this->getXmlResponse()->data[0];
|
|
|
|
Assert::assertEquals($count, count($returnedShares->element));
|
|
}
|
|
|
|
/**
|
|
* @Then share :count is returned with
|
|
*
|
|
* @param int $number
|
|
* @param TableNode $body
|
|
*/
|
|
public function shareXIsReturnedWith(int $number, TableNode $body) {
|
|
$this->theHTTPStatusCodeShouldBe('200');
|
|
$this->theOCSStatusCodeShouldBe('100');
|
|
|
|
if (!($body instanceof TableNode)) {
|
|
return;
|
|
}
|
|
|
|
$returnedShare = $this->getXmlResponse()->data[0];
|
|
if ($returnedShare->element) {
|
|
$returnedShare = $returnedShare->element[$number];
|
|
}
|
|
|
|
$defaultExpectedFields = [
|
|
'id' => 'A_NUMBER',
|
|
'permissions' => '19',
|
|
'stime' => 'A_NUMBER',
|
|
'parent' => '',
|
|
'expiration' => '',
|
|
'token' => '',
|
|
'storage' => 'A_NUMBER',
|
|
'item_source' => 'A_NUMBER',
|
|
'file_source' => 'A_NUMBER',
|
|
'file_parent' => 'A_NUMBER',
|
|
'mail_send' => '0'
|
|
];
|
|
$expectedFields = array_merge($defaultExpectedFields, $body->getRowsHash());
|
|
|
|
if (!array_key_exists('uid_file_owner', $expectedFields)
|
|
&& array_key_exists('uid_owner', $expectedFields)) {
|
|
$expectedFields['uid_file_owner'] = $expectedFields['uid_owner'];
|
|
}
|
|
if (!array_key_exists('displayname_file_owner', $expectedFields)
|
|
&& array_key_exists('displayname_owner', $expectedFields)) {
|
|
$expectedFields['displayname_file_owner'] = $expectedFields['displayname_owner'];
|
|
}
|
|
|
|
if (array_key_exists('share_type', $expectedFields)
|
|
&& $expectedFields['share_type'] == 10 /* IShare::TYPE_ROOM */
|
|
&& array_key_exists('share_with', $expectedFields)) {
|
|
if ($expectedFields['share_with'] === 'private_conversation') {
|
|
$expectedFields['share_with'] = 'REGEXP /^private_conversation_[0-9a-f]{6}$/';
|
|
} else {
|
|
$expectedFields['share_with'] = FeatureContext::getTokenForIdentifier($expectedFields['share_with']);
|
|
}
|
|
}
|
|
|
|
foreach ($expectedFields as $field => $value) {
|
|
$this->assertFieldIsInReturnedShare($field, $value, $returnedShare);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return SimpleXMLElement
|
|
*/
|
|
private function getXmlResponse(): \SimpleXMLElement {
|
|
return simplexml_load_string($this->response->getBody());
|
|
}
|
|
|
|
/**
|
|
* @param string $field
|
|
* @param string $contentExpected
|
|
* @param \SimpleXMLElement $returnedShare
|
|
*/
|
|
private function assertFieldIsInReturnedShare(string $field, string $contentExpected, \SimpleXMLElement $returnedShare) {
|
|
if ($contentExpected === 'IGNORE') {
|
|
return;
|
|
}
|
|
|
|
if (!property_exists($returnedShare, $field)) {
|
|
Assert::fail("$field was not found in response");
|
|
}
|
|
|
|
if ($field === 'expiration' && !empty($contentExpected)) {
|
|
$contentExpected = date('Y-m-d', strtotime($contentExpected)) . ' 00:00:00';
|
|
}
|
|
|
|
if ($contentExpected === 'A_NUMBER') {
|
|
Assert::assertTrue(is_numeric((string)$returnedShare->$field), "Field '$field' is not a number: " . $returnedShare->$field);
|
|
} elseif ($contentExpected === 'A_TOKEN') {
|
|
// A token is composed by 15 characters from
|
|
// ISecureRandom::CHAR_HUMAN_READABLE.
|
|
Assert::assertRegExp('/^[abcdefgijkmnopqrstwxyzABCDEFGHJKLMNPQRSTWXYZ23456789]{15}$/', (string)$returnedShare->$field, "Field '$field' is not a token");
|
|
} elseif (strpos($contentExpected, 'REGEXP ') === 0) {
|
|
Assert::assertRegExp(substr($contentExpected, strlen('REGEXP ')), (string)$returnedShare->$field, "Field '$field' does not match");
|
|
} else {
|
|
Assert::assertEquals($contentExpected, (string)$returnedShare->$field, "Field '$field' does not match");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @Then As :user remove all shares from the file named :fileName
|
|
*/
|
|
public function asRemoveAllSharesFromTheFileNamed($user, $fileName) {
|
|
$url = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares?format=json";
|
|
$client = new \GuzzleHttp\Client();
|
|
$res = $client->get(
|
|
$url,
|
|
[
|
|
'auth' => [
|
|
$user,
|
|
'123456',
|
|
],
|
|
'headers' => [
|
|
'Content-Type' => 'application/json',
|
|
'OCS-APIREQUEST' => 'true',
|
|
],
|
|
]
|
|
);
|
|
$json = json_decode($res->getBody()->getContents(), true);
|
|
$deleted = false;
|
|
foreach ($json['ocs']['data'] as $data) {
|
|
if (stripslashes($data['path']) === $fileName) {
|
|
$id = $data['id'];
|
|
$client->delete(
|
|
$this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/{$id}",
|
|
[
|
|
'auth' => [
|
|
$user,
|
|
'123456',
|
|
],
|
|
'headers' => [
|
|
'Content-Type' => 'application/json',
|
|
'OCS-APIREQUEST' => 'true',
|
|
],
|
|
]
|
|
);
|
|
$deleted = true;
|
|
}
|
|
}
|
|
|
|
if ($deleted === false) {
|
|
throw new \Exception("Could not delete file $fileName");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @When save last share id
|
|
*/
|
|
public function saveLastShareId() {
|
|
$this->savedShareId = ($this->lastShareData['data']['id'] ?? null);
|
|
}
|
|
|
|
/**
|
|
* @Then share ids should match
|
|
*/
|
|
public function shareIdsShouldMatch() {
|
|
if ($this->savedShareId !== ($this->lastShareData['data']['id'] ?? null)) {
|
|
throw new \Exception('Expected the same link share to be returned');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @When /^getting sharees for$/
|
|
* @param TableNode $body
|
|
*/
|
|
public function whenGettingShareesFor($body) {
|
|
$url = '/apps/files_sharing/api/v1/sharees';
|
|
if ($body instanceof TableNode) {
|
|
$parameters = [];
|
|
foreach ($body->getRowsHash() as $key => $value) {
|
|
$parameters[] = $key . '=' . $value;
|
|
}
|
|
if (!empty($parameters)) {
|
|
$url .= '?' . implode('&', $parameters);
|
|
}
|
|
}
|
|
|
|
$this->sendingTo('GET', $url);
|
|
}
|
|
|
|
/**
|
|
* @Then /^"([^"]*)" sharees returned (are|is empty)$/
|
|
* @param string $shareeType
|
|
* @param string $isEmpty
|
|
* @param TableNode|null $shareesList
|
|
*/
|
|
public function thenListOfSharees($shareeType, $isEmpty, $shareesList = null) {
|
|
if ($isEmpty !== 'is empty') {
|
|
$sharees = $shareesList->getRows();
|
|
$respondedArray = $this->getArrayOfShareesResponded($this->response, $shareeType);
|
|
Assert::assertEquals($sharees, $respondedArray);
|
|
} else {
|
|
$respondedArray = $this->getArrayOfShareesResponded($this->response, $shareeType);
|
|
Assert::assertEmpty($respondedArray);
|
|
}
|
|
}
|
|
|
|
public function getArrayOfShareesResponded(ResponseInterface $response, $shareeType) {
|
|
$elements = simplexml_load_string($response->getBody())->data;
|
|
$elements = json_decode(json_encode($elements), 1);
|
|
if (strpos($shareeType, 'exact ') === 0) {
|
|
$elements = $elements['exact'];
|
|
$shareeType = substr($shareeType, 6);
|
|
}
|
|
|
|
$sharees = [];
|
|
foreach ($elements[$shareeType] as $element) {
|
|
$sharees[] = [$element['label'], $element['value']['shareType'], $element['value']['shareWith']];
|
|
}
|
|
return $sharees;
|
|
}
|
|
}
|