diff options
Diffstat (limited to 'build/integration/features/bootstrap')
-rw-r--r-- | build/integration/features/bootstrap/BasicStructure.php | 312 | ||||
-rw-r--r-- | build/integration/features/bootstrap/FeatureContext.php | 244 | ||||
-rw-r--r-- | build/integration/features/bootstrap/FederationContext.php | 54 | ||||
-rw-r--r-- | build/integration/features/bootstrap/Provisioning.php | 656 | ||||
-rw-r--r-- | build/integration/features/bootstrap/Sharing.php | 498 | ||||
-rw-r--r-- | build/integration/features/bootstrap/WebDav.php | 508 |
6 files changed, 2033 insertions, 239 deletions
diff --git a/build/integration/features/bootstrap/BasicStructure.php b/build/integration/features/bootstrap/BasicStructure.php new file mode 100644 index 00000000000..f693a242e17 --- /dev/null +++ b/build/integration/features/bootstrap/BasicStructure.php @@ -0,0 +1,312 @@ +<?php + +use GuzzleHttp\Client; +use GuzzleHttp\Message\ResponseInterface; + +require __DIR__ . '/../../vendor/autoload.php'; + +trait BasicStructure { + + /** @var string */ + private $currentUser = ''; + + /** @var string */ + private $currentServer = ''; + + /** @var string */ + private $baseUrl = ''; + + /** @var int */ + private $apiVersion = 1; + + /** @var ResponseInterface */ + private $response = null; + + /** @var \GuzzleHttp\Cookie\CookieJar */ + private $cookieJar; + + /** @var string */ + private $requestToken; + + public function __construct($baseUrl, $admin, $regular_user_password) { + + // Initialize your context here + $this->baseUrl = $baseUrl; + $this->adminUser = $admin; + $this->regularUser = $regular_user_password; + $this->localBaseUrl = $this->baseUrl; + $this->remoteBaseUrl = $this->baseUrl; + $this->currentServer = 'LOCAL'; + $this->cookieJar = new \GuzzleHttp\Cookie\CookieJar(); + + // in case of ci deployment we take the server url from the environment + $testServerUrl = getenv('TEST_SERVER_URL'); + if ($testServerUrl !== false) { + $this->baseUrl = $testServerUrl; + $this->localBaseUrl = $testServerUrl; + } + + // federated server url from the environment + $testRemoteServerUrl = getenv('TEST_SERVER_FED_URL'); + if ($testRemoteServerUrl !== false) { + $this->remoteBaseUrl = $testRemoteServerUrl; + } + } + + /** + * @Given /^using api version "([^"]*)"$/ + * @param string $version + */ + public function usingApiVersion($version) { + $this->apiVersion = $version; + } + + /** + * @Given /^As an "([^"]*)"$/ + * @param string $user + */ + public function asAn($user) { + $this->currentUser = $user; + } + + /** + * @Given /^Using server "(LOCAL|REMOTE)"$/ + * @param string $server + * @return string Previous used server + */ + public function usingServer($server) { + $previousServer = $this->currentServer; + if ($server === 'LOCAL'){ + $this->baseUrl = $this->localBaseUrl; + $this->currentServer = 'LOCAL'; + return $previousServer; + } else { + $this->baseUrl = $this->remoteBaseUrl; + $this->currentServer = 'REMOTE'; + return $previousServer; + } + } + + /** + * @When /^sending "([^"]*)" to "([^"]*)"$/ + * @param string $verb + * @param string $url + */ + public function sendingTo($verb, $url) { + $this->sendingToWith($verb, $url, null); + } + + /** + * Parses the xml answer to get ocs response which doesn't match with + * http one in v1 of the api. + * @param ResponseInterface $response + * @return string + */ + public function getOCSResponse($response) { + return $response->xml()->meta[0]->statuscode; + } + + /** + * This function is needed to use a vertical fashion in the gherkin tables. + * @param array $arrayOfArrays + * @return array + */ + public function simplifyArray($arrayOfArrays){ + $a = array_map(function($subArray) { return $subArray[0]; }, $arrayOfArrays); + return $a; + } + + /** + * @When /^sending "([^"]*)" to "([^"]*)" with$/ + * @param string $verb + * @param string $url + * @param \Behat\Gherkin\Node\TableNode $body + */ + public function sendingToWith($verb, $url, $body) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php" . $url; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$this->currentUser, $this->regularUser]; + } + if ($body instanceof \Behat\Gherkin\Node\TableNode) { + $fd = $body->getRowsHash(); + $options['body'] = $fd; + } + + try { + $this->response = $client->send($client->createRequest($verb, $fullUrl, $options)); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + } + } + + public function isExpectedUrl($possibleUrl, $finalPart){ + $baseUrlChopped = substr($this->baseUrl, 0, -4); + $endCharacter = strlen($baseUrlChopped) + strlen($finalPart); + return (substr($possibleUrl,0,$endCharacter) == "$baseUrlChopped" . "$finalPart"); + } + + /** + * @Then /^the OCS status code should be "([^"]*)"$/ + * @param int $statusCode + */ + public function theOCSStatusCodeShouldBe($statusCode) { + PHPUnit_Framework_Assert::assertEquals($statusCode, $this->getOCSResponse($this->response)); + } + + /** + * @Then /^the HTTP status code should be "([^"]*)"$/ + * @param int $statusCode + */ + public function theHTTPStatusCodeShouldBe($statusCode) { + PHPUnit_Framework_Assert::assertEquals($statusCode, $this->response->getStatusCode()); + } + + /** + * @param ResponseInterface $response + */ + private function extracRequestTokenFromResponse(ResponseInterface $response) { + $this->requestToken = substr(preg_replace('/(.*)data-requesttoken="(.*)">(.*)/sm', '\2', $response->getBody()->getContents()), 0, 89); + } + + /** + * @Given Logging in using web as :user + * @param string $user + */ + public function loggingInUsingWebAs($user) { + $loginUrl = substr($this->baseUrl, 0, -5) . '/login'; + // Request a new session and extract CSRF token + $client = new Client(); + $response = $client->get( + $loginUrl, + [ + 'cookies' => $this->cookieJar, + ] + ); + $this->extracRequestTokenFromResponse($response); + + // Login and extract new token + $password = ($user === 'admin') ? 'admin' : '123456'; + $client = new Client(); + $response = $client->post( + $loginUrl, + [ + 'body' => [ + 'user' => $user, + 'password' => $password, + 'requesttoken' => $this->requestToken, + ], + 'cookies' => $this->cookieJar, + ] + ); + $this->extracRequestTokenFromResponse($response); + } + + /** + * @When Sending a :method to :url with requesttoken + * @param string $method + * @param string $url + */ + public function sendingAToWithRequesttoken($method, $url) { + $baseUrl = substr($this->baseUrl, 0, -5); + + $client = new Client(); + $request = $client->createRequest( + $method, + $baseUrl . $url, + [ + 'cookies' => $this->cookieJar, + ] + ); + $request->addHeader('requesttoken', $this->requestToken); + try { + $this->response = $client->send($request); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @When Sending a :method to :url without requesttoken + * @param string $method + * @param string $url + */ + public function sendingAToWithoutRequesttoken($method, $url) { + $baseUrl = substr($this->baseUrl, 0, -5); + + $client = new Client(); + $request = $client->createRequest( + $method, + $baseUrl . $url, + [ + 'cookies' => $this->cookieJar, + ] + ); + try { + $this->response = $client->send($request); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + public static function removeFile($path, $filename){ + if (file_exists("$path" . "$filename")) { + unlink("$path" . "$filename"); + } + } + + /** + * @Given User :user modifies text of :filename with text :text + * @param string $user + * @param string $filename + * @param string $text + */ + public function modifyTextOfFile($user, $filename, $text) { + self::removeFile("../../data/$user/files", "$filename"); + file_put_contents("../../data/$user/files" . "$filename", "$text"); + } + + /** + * @BeforeSuite + */ + public static function addFilesToSkeleton(){ + for ($i=0; $i<5; $i++){ + file_put_contents("../../core/skeleton/" . "textfile" . "$i" . ".txt", "ownCloud test text file\n"); + } + if (!file_exists("../../core/skeleton/FOLDER")) { + mkdir("../../core/skeleton/FOLDER", 0777, true); + } + if (!file_exists("../../core/skeleton/PARENT")) { + mkdir("../../core/skeleton/PARENT", 0777, true); + } + file_put_contents("../../core/skeleton/PARENT/" . "parent.txt", "ownCloud test text file\n"); + if (!file_exists("../../core/skeleton/PARENT/CHILD")) { + mkdir("../../core/skeleton/PARENT/CHILD", 0777, true); + } + file_put_contents("../../core/skeleton/PARENT/CHILD/" . "child.txt", "ownCloud test text file\n"); + } + + /** + * @AfterSuite + */ + public static function removeFilesFromSkeleton(){ + for ($i=0; $i<5; $i++){ + self::removeFile("../../core/skeleton/", "textfile" . "$i" . ".txt"); + } + if (is_dir("../../core/skeleton/FOLDER")) { + rmdir("../../core/skeleton/FOLDER"); + } + self::removeFile("../../core/skeleton/PARENT/CHILD/", "child.txt"); + if (is_dir("../../core/skeleton/PARENT/CHILD")) { + rmdir("../../core/skeleton/PARENT/CHILD"); + } + self::removeFile("../../core/skeleton/PARENT/", "parent.txt"); + if (is_dir("../../core/skeleton/PARENT")) { + rmdir("../../core/skeleton/PARENT"); + } + } +} + diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index caff517a16d..21ca8d87295 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -1,248 +1,14 @@ <?php -use Behat\Behat\Context\BehatContext; -use GuzzleHttp\Client; -use GuzzleHttp\Message\ResponseInterface; +use Behat\Behat\Context\Context; +use Behat\Behat\Context\SnippetAcceptingContext; require __DIR__ . '/../../vendor/autoload.php'; + /** * Features context. */ -class FeatureContext extends BehatContext { - - /** @var string */ - private $baseUrl = ''; - - /** @var ResponseInterface */ - private $response = null; - - /** @var string */ - private $currentUser = ''; - - /** @var int */ - private $apiVersion = 1; - - /** - * Initializes context. - * Every scenario gets it's own context object. - * - * @param array $parameters context parameters (set them up through behat.yml) - */ - public function __construct(array $parameters) { - - // Initialize your context here - $this->baseUrl = $parameters['baseUrl']; - $this->adminUser = $parameters['admin']; - - // in case of ci deployment we take the server url from the environment - $testServerUrl = getenv('TEST_SERVER_URL'); - if ($testServerUrl !== false) { - $this->baseUrl = $testServerUrl; - } - } - - /** - * @When /^sending "([^"]*)" to "([^"]*)"$/ - */ - public function sendingTo($verb, $url) { - $this->sendingToWith($verb, $url, null); - } - - /** - * Parses the xml answer to get ocs response which doesn't match with - * http one in v1 of the api. - */ - public function getOCSResponse($response) { - return $response->xml()->meta[0]->statuscode; - } - - /** - * Parses the xml answer to get the array of users returned. - */ - public function getArrayOfUsersResponded($resp) { - $listCheckedElements = $resp->xml()->data[0]->users[0]->element; - $extractedElementsArray = json_decode(json_encode($listCheckedElements), 1); - return $extractedElementsArray; - } - - /** - * Parses the xml answer to get the array of groups returned. - */ - public function getArrayOfGroupsResponded($resp) { - $listCheckedElements = $resp->xml()->data[0]->groups[0]->element; - $extractedElementsArray = json_decode(json_encode($listCheckedElements), 1); - return $extractedElementsArray; - } - - /** - * @Then /^users returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData - */ - public function theUsersShouldBe($usersList) { - if ($usersList instanceof \Behat\Gherkin\Node\TableNode) { - $users = $usersList->getRows()[0]; - $respondedArray = $this->getArrayOfUsersResponded($this->response); - PHPUnit_Framework_Assert::assertEquals(asort($users), asort($respondedArray)); - } - - } - - /** - * @Then /^groups returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData - */ - public function theGroupsShouldBe($groupsList) { - if ($groupsList instanceof \Behat\Gherkin\Node\TableNode) { - $groups = $groupsList->getRows()[0]; - $respondedArray = $this->getArrayOfGroupsResponded($this->response); - PHPUnit_Framework_Assert::assertEquals(asort($groups), asort($respondedArray)); - } - - } - - /** - * @Then /^the OCS status code should be "([^"]*)"$/ - */ - public function theOCSStatusCodeShouldBe($statusCode) { - PHPUnit_Framework_Assert::assertEquals($statusCode, $this->getOCSResponse($this->response)); - } - - /** - * @Then /^the HTTP status code should be "([^"]*)"$/ - */ - public function theHTTPStatusCodeShouldBe($statusCode) { - PHPUnit_Framework_Assert::assertEquals($statusCode, $this->response->getStatusCode()); - } - - /** - * @Given /^As an "([^"]*)"$/ - */ - public function asAn($user) { - $this->currentUser = $user; - } - - /** - * @Given /^using api version "([^"]*)"$/ - */ - public function usingApiVersion($version) { - $this->apiVersion = $version; - } - - /** - * @Given /^user "([^"]*)" exists$/ - */ - public function userExists($user) { - $fullUrl = $this->baseUrl . "v2.php/cloud/users/$user"; - $client = new Client(); - $options = []; - if ($this->currentUser === 'admin') { - $options['auth'] = $this->adminUser; - } - - $this->response = $client->get($fullUrl, $options); - PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); - } - - /** - * @Given /^user "([^"]*)" does not exist$/ - */ - public function userDoesNotExist($user) { - try { - $this->userExists($user); - PHPUnit_Framework_Assert::fail('The user "' . $user . '" exists'); - } catch (\GuzzleHttp\Exception\ClientException $ex) { - $this->response = $ex->getResponse(); - PHPUnit_Framework_Assert::assertEquals(404, $ex->getResponse()->getStatusCode()); - } - } - - /** - * @When /^creating the user "([^"]*)r"$/ - */ - public function creatingTheUser($user) { - $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/$user"; - $client = new Client(); - $options = []; - if ($this->currentUser === 'admin') { - $options['auth'] = $this->adminUser; - } - - $this->response = $client->post($fullUrl, [ - 'form_params' => [ - 'userid' => $user, - 'password' => '123456' - ] - ]); - - } - - /** - * @When /^creating the group "([^"]*)r"$/ - */ - public function creatingTheGroup($group) { - $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/groups/addgroup"; - $client = new Client(); - $options = []; - if ($this->currentUser === 'admin') { - $options['auth'] = $this->adminUser; - } - - $this->response = $client->post($fullUrl, [ - 'form_params' => [ - 'groupid' => $user - ] - ]); - } - - /** - * @Given /^group "([^"]*)" exists$/ - */ - public function groupExists($group) { - $fullUrl = $this->baseUrl . "v2.php/cloud/groups/$group"; - $client = new Client(); - $options = []; - if ($this->currentUser === 'admin') { - $options['auth'] = $this->adminUser; - } - - $this->response = $client->get($fullUrl, $options); - PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); - } - - /** - * @Given /^group "([^"]*)" does not exist$/ - */ - public function groupDoesNotExist($group) { - try { - $this->groupExists($group); - PHPUnit_Framework_Assert::fail('The group "' . $group . '" exists'); - } catch (\GuzzleHttp\Exception\ClientException $ex) { - $this->response = $ex->getResponse(); - PHPUnit_Framework_Assert::assertEquals(404, $ex->getResponse()->getStatusCode()); - } - } - - /** - * @When /^sending "([^"]*)" to "([^"]*)" with$/ - * @param \Behat\Gherkin\Node\TableNode|null $formData - */ - public function sendingToWith($verb, $url, $body) { - $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php" . $url; - $client = new Client(); - $options = []; - if ($this->currentUser === 'admin') { - $options['auth'] = $this->adminUser; - } - if ($body instanceof \Behat\Gherkin\Node\TableNode) { - $fd = $body->getRowsHash(); - $options['body'] = $fd; - } - - try { - $this->response = $client->send($client->createRequest($verb, $fullUrl, $options)); - } catch (\GuzzleHttp\Exception\ClientException $ex) { - $this->response = $ex->getResponse(); - } - } +class FeatureContext implements Context, SnippetAcceptingContext { + use WebDav; } diff --git a/build/integration/features/bootstrap/FederationContext.php b/build/integration/features/bootstrap/FederationContext.php new file mode 100644 index 00000000000..55f3a55da0d --- /dev/null +++ b/build/integration/features/bootstrap/FederationContext.php @@ -0,0 +1,54 @@ +<?php + +use Behat\Behat\Context\Context; +use Behat\Behat\Context\SnippetAcceptingContext; +use GuzzleHttp\Client; +use GuzzleHttp\Message\ResponseInterface; + +require __DIR__ . '/../../vendor/autoload.php'; + +/** + * Federation context. + */ +class FederationContext implements Context, SnippetAcceptingContext { + + use WebDav; + + /** + * @Given /^User "([^"]*)" from server "(LOCAL|REMOTE)" shares "([^"]*)" with user "([^"]*)" from server "(LOCAL|REMOTE)"$/ + * + * @param string $sharerUser + * @param string $sharerServer "LOCAL" or "REMOTE" + * @param string $sharerPath + * @param string $shareeUser + * @param string $shareeServer "LOCAL" or "REMOTE" + */ + public function federateSharing($sharerUser, $sharerServer, $sharerPath, $shareeUser, $shareeServer){ + if ($shareeServer == "REMOTE"){ + $shareWith = "$shareeUser@" . substr($this->remoteBaseUrl, 0, -4); + } else { + $shareWith = "$shareeUser@" . substr($this->localBaseUrl, 0, -4); + } + $previous = $this->usingServer($sharerServer); + $this->createShare($sharerUser, $sharerPath, 6, $shareWith, null, null, null); + $this->usingServer($previous); + } + + /** + * @When /^User "([^"]*)" from server "(LOCAL|REMOTE)" accepts last pending share$/ + * @param string $user + * @param string $server + */ + public function acceptLastPendingShare($user, $server){ + $previous = $this->usingServer($server); + $this->asAn($user); + $this->sendingToWith('GET', "/apps/files_sharing/api/v1/remote_shares/pending", null); + $this->theHTTPStatusCodeShouldBe('200'); + $this->theOCSStatusCodeShouldBe('100'); + $share_id = $this->response->xml()->data[0]->element[0]->id; + $this->sendingToWith('POST', "/apps/files_sharing/api/v1/remote_shares/pending/{$share_id}", null); + $this->theHTTPStatusCodeShouldBe('200'); + $this->theOCSStatusCodeShouldBe('100'); + $this->usingServer($previous); + } +} diff --git a/build/integration/features/bootstrap/Provisioning.php b/build/integration/features/bootstrap/Provisioning.php new file mode 100644 index 00000000000..6cf57514483 --- /dev/null +++ b/build/integration/features/bootstrap/Provisioning.php @@ -0,0 +1,656 @@ +<?php + +use GuzzleHttp\Client; +use GuzzleHttp\Message\ResponseInterface; + +require __DIR__ . '/../../vendor/autoload.php'; + +trait Provisioning { + use BasicStructure; + + /** @var array */ + private $createdUsers = []; + + /** @var array */ + private $createdRemoteUsers = []; + + /** @var array */ + private $createdRemoteGroups = []; + + /** @var array */ + private $createdGroups = []; + + /** + * @Given /^user "([^"]*)" exists$/ + * @param string $user + */ + public function assureUserExists($user) { + try { + $this->userExists($user); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + $this->creatingTheUser($user); + $this->currentUser = $previous_user; + } + $this->userExists($user); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** + * @Given /^user "([^"]*)" does not exist$/ + * @param string $user + */ + public function userDoesNotExist($user) { + try { + $this->userExists($user); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + PHPUnit_Framework_Assert::assertEquals(404, $ex->getResponse()->getStatusCode()); + return; + } + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + $this->deletingTheUser($user); + $this->currentUser = $previous_user; + try { + $this->userExists($user); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + PHPUnit_Framework_Assert::assertEquals(404, $ex->getResponse()->getStatusCode()); + } + } + + public function creatingTheUser($user) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $options['body'] = [ + 'userid' => $user, + 'password' => '123456' + ]; + + $this->response = $client->send($client->createRequest("POST", $fullUrl, $options)); + if ($this->currentServer === 'LOCAL'){ + $this->createdUsers[$user] = $user; + } elseif ($this->currentServer === 'REMOTE') { + $this->createdRemoteUsers[$user] = $user; + } + + //Quick hack to login once with the current user + $options2 = [ + 'auth' => [$user, '123456'], + ]; + $url = $fullUrl.'/'.$user; + $client->send($client->createRequest('GET', $url, $options2)); + } + + public function createUser($user) { + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + $this->creatingTheUser($user); + $this->userExists($user); + $this->currentUser = $previous_user; + } + + public function deleteUser($user) { + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + $this->deletingTheUser($user); + $this->userDoesNotExist($user); + $this->currentUser = $previous_user; + } + + public function createGroup($group) { + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + $this->creatingTheGroup($group); + $this->groupExists($group); + $this->currentUser = $previous_user; + } + + public function deleteGroup($group) { + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + $this->deletingTheGroup($group); + $this->groupDoesNotExist($group); + $this->currentUser = $previous_user; + } + + public function userExists($user){ + $fullUrl = $this->baseUrl . "v2.php/cloud/users/$user"; + $client = new Client(); + $options = []; + $options['auth'] = $this->adminUser; + + $this->response = $client->get($fullUrl, $options); + } + + /** + * @Then /^check that user "([^"]*)" belongs to group "([^"]*)"$/ + * @param string $user + * @param string $group + */ + public function checkThatUserBelongsToGroup($user, $group) { + $fullUrl = $this->baseUrl . "v2.php/cloud/users/$user/groups"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + $respondedArray = $this->getArrayOfGroupsResponded($this->response); + sort($respondedArray); + PHPUnit_Framework_Assert::assertContains($group, $respondedArray); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + public function userBelongsToGroup($user, $group) { + $fullUrl = $this->baseUrl . "v2.php/cloud/users/$user/groups"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + $respondedArray = $this->getArrayOfGroupsResponded($this->response); + + if (array_key_exists($group, $respondedArray)) { + return True; + } else{ + return False; + } + } + + /** + * @Given /^user "([^"]*)" belongs to group "([^"]*)"$/ + * @param string $user + * @param string $group + */ + public function assureUserBelongsToGroup($user, $group){ + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + + if (!$this->userBelongsToGroup($user, $group)){ + $this->addingUserToGroup($user, $group); + } + + $this->checkThatUserBelongsToGroup($user, $group); + $this->currentUser = $previous_user; + } + + /** + * @Given /^user "([^"]*)" does not belong to group "([^"]*)"$/ + * @param string $user + * @param string $group + */ + public function userDoesNotBelongToGroup($user, $group) { + $fullUrl = $this->baseUrl . "v2.php/cloud/users/$user/groups"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + $groups = array($group); + $respondedArray = $this->getArrayOfGroupsResponded($this->response); + PHPUnit_Framework_Assert::assertNotEquals($groups, $respondedArray, "", 0.0, 10, true); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** + * @When /^creating the group "([^"]*)"$/ + * @param string $group + */ + public function creatingTheGroup($group) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/groups"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $options['body'] = [ + 'groupid' => $group, + ]; + + $this->response = $client->send($client->createRequest("POST", $fullUrl, $options)); + if ($this->currentServer === 'LOCAL'){ + $this->createdGroups[$group] = $group; + } elseif ($this->currentServer === 'REMOTE') { + $this->createdRemoteGroups[$group] = $group; + } + } + + /** + * @When /^assure user "([^"]*)" is disabled$/ + */ + public function assureUserIsDisabled($user) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/$user/disable"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->send($client->createRequest("PUT", $fullUrl, $options)); + } + + /** + * @When /^Deleting the user "([^"]*)"$/ + * @param string $user + */ + public function deletingTheUser($user) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/$user"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->send($client->createRequest("DELETE", $fullUrl, $options)); + } + + /** + * @When /^Deleting the group "([^"]*)"$/ + * @param string $group + */ + public function deletingTheGroup($group) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/groups/$group"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->send($client->createRequest("DELETE", $fullUrl, $options)); + } + + /** + * @Given /^Add user "([^"]*)" to the group "([^"]*)"$/ + * @param string $user + * @param string $group + */ + public function addUserToGroup($user, $group) { + $this->userExists($user); + $this->groupExists($group); + $this->addingUserToGroup($user, $group); + + } + + /** + * @When /^User "([^"]*)" is added to the group "([^"]*)"$/ + * @param string $user + * @param string $group + */ + public function addingUserToGroup($user, $group) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/$user/groups"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $options['body'] = [ + 'groupid' => $group, + ]; + + $this->response = $client->send($client->createRequest("POST", $fullUrl, $options)); + } + + + public function groupExists($group) { + $fullUrl = $this->baseUrl . "v2.php/cloud/groups/$group"; + $client = new Client(); + $options = []; + $options['auth'] = $this->adminUser; + + $this->response = $client->get($fullUrl, $options); + } + + /** + * @Given /^group "([^"]*)" exists$/ + * @param string $group + */ + public function assureGroupExists($group) { + try { + $this->groupExists($group); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + $this->creatingTheGroup($group); + $this->currentUser = $previous_user; + } + $this->groupExists($group); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** + * @Given /^group "([^"]*)" does not exist$/ + * @param string $group + */ + public function groupDoesNotExist($group) { + try { + $this->groupExists($group); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + PHPUnit_Framework_Assert::assertEquals(404, $ex->getResponse()->getStatusCode()); + return; + } + $previous_user = $this->currentUser; + $this->currentUser = "admin"; + $this->deletingTheGroup($group); + $this->currentUser = $previous_user; + try { + $this->groupExists($group); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + PHPUnit_Framework_Assert::assertEquals(404, $ex->getResponse()->getStatusCode()); + } + } + + /** + * @Given /^user "([^"]*)" is subadmin of group "([^"]*)"$/ + * @param string $user + * @param string $group + */ + public function userIsSubadminOfGroup($user, $group) { + $fullUrl = $this->baseUrl . "v2.php/cloud/groups/$group/subadmins"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + $respondedArray = $this->getArrayOfSubadminsResponded($this->response); + sort($respondedArray); + PHPUnit_Framework_Assert::assertContains($user, $respondedArray); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** + * @Given /^Assure user "([^"]*)" is subadmin of group "([^"]*)"$/ + * @param string $user + * @param string $group + */ + public function assureUserIsSubadminOfGroup($user, $group) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/$user/subadmins"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + $options['body'] = [ + 'groupid' => $group + ]; + $this->response = $client->send($client->createRequest("POST", $fullUrl, $options)); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** + * @Given /^user "([^"]*)" is not a subadmin of group "([^"]*)"$/ + * @param string $user + * @param string $group + */ + public function userIsNotSubadminOfGroup($user, $group) { + $fullUrl = $this->baseUrl . "v2.php/cloud/groups/$group/subadmins"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + $respondedArray = $this->getArrayOfSubadminsResponded($this->response); + sort($respondedArray); + PHPUnit_Framework_Assert::assertNotContains($user, $respondedArray); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** + * @Then /^users returned are$/ + * @param \Behat\Gherkin\Node\TableNode|null $usersList + */ + public function theUsersShouldBe($usersList) { + if ($usersList instanceof \Behat\Gherkin\Node\TableNode) { + $users = $usersList->getRows(); + $usersSimplified = $this->simplifyArray($users); + $respondedArray = $this->getArrayOfUsersResponded($this->response); + PHPUnit_Framework_Assert::assertEquals($usersSimplified, $respondedArray, "", 0.0, 10, true); + } + + } + + /** + * @Then /^groups returned are$/ + * @param \Behat\Gherkin\Node\TableNode|null $groupsList + */ + public function theGroupsShouldBe($groupsList) { + if ($groupsList instanceof \Behat\Gherkin\Node\TableNode) { + $groups = $groupsList->getRows(); + $groupsSimplified = $this->simplifyArray($groups); + $respondedArray = $this->getArrayOfGroupsResponded($this->response); + PHPUnit_Framework_Assert::assertEquals($groupsSimplified, $respondedArray, "", 0.0, 10, true); + } + + } + + /** + * @Then /^subadmin groups returned are$/ + * @param \Behat\Gherkin\Node\TableNode|null $groupsList + */ + public function theSubadminGroupsShouldBe($groupsList) { + if ($groupsList instanceof \Behat\Gherkin\Node\TableNode) { + $groups = $groupsList->getRows(); + $groupsSimplified = $this->simplifyArray($groups); + $respondedArray = $this->getArrayOfSubadminsResponded($this->response); + PHPUnit_Framework_Assert::assertEquals($groupsSimplified, $respondedArray, "", 0.0, 10, true); + } + + } + + /** + * @Then /^apps returned are$/ + * @param \Behat\Gherkin\Node\TableNode|null $appList + */ + public function theAppsShouldBe($appList) { + if ($appList instanceof \Behat\Gherkin\Node\TableNode) { + $apps = $appList->getRows(); + $appsSimplified = $this->simplifyArray($apps); + $respondedArray = $this->getArrayOfAppsResponded($this->response); + PHPUnit_Framework_Assert::assertEquals($appsSimplified, $respondedArray, "", 0.0, 10, true); + } + + } + + /** + * @Then /^subadmin users returned are$/ + * @param \Behat\Gherkin\Node\TableNode|null $groupsList + */ + public function theSubadminUsersShouldBe($groupsList) { + $this->theSubadminGroupsShouldBe($groupsList); + } + + /** + * Parses the xml answer to get the array of users returned. + * @param ResponseInterface $resp + * @return array + */ + public function getArrayOfUsersResponded($resp) { + $listCheckedElements = $resp->xml()->data[0]->users[0]->element; + $extractedElementsArray = json_decode(json_encode($listCheckedElements), 1); + return $extractedElementsArray; + } + + /** + * Parses the xml answer to get the array of groups returned. + * @param ResponseInterface $resp + * @return array + */ + public function getArrayOfGroupsResponded($resp) { + $listCheckedElements = $resp->xml()->data[0]->groups[0]->element; + $extractedElementsArray = json_decode(json_encode($listCheckedElements), 1); + return $extractedElementsArray; + } + + /** + * Parses the xml answer to get the array of apps returned. + * @param ResponseInterface $resp + * @return array + */ + public function getArrayOfAppsResponded($resp) { + $listCheckedElements = $resp->xml()->data[0]->apps[0]->element; + $extractedElementsArray = json_decode(json_encode($listCheckedElements), 1); + return $extractedElementsArray; + } + + /** + * Parses the xml answer to get the array of subadmins returned. + * @param ResponseInterface $resp + * @return array + */ + public function getArrayOfSubadminsResponded($resp) { + $listCheckedElements = $resp->xml()->data[0]->element; + $extractedElementsArray = json_decode(json_encode($listCheckedElements), 1); + return $extractedElementsArray; + } + + + /** + * @Given /^app "([^"]*)" is disabled$/ + * @param string $app + */ + public function appIsDisabled($app) { + $fullUrl = $this->baseUrl . "v2.php/cloud/apps?filter=disabled"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + $respondedArray = $this->getArrayOfAppsResponded($this->response); + PHPUnit_Framework_Assert::assertContains($app, $respondedArray); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** + * @Given /^app "([^"]*)" is enabled$/ + * @param string $app + */ + public function appIsEnabled($app) { + $fullUrl = $this->baseUrl . "v2.php/cloud/apps?filter=enabled"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + $respondedArray = $this->getArrayOfAppsResponded($this->response); + PHPUnit_Framework_Assert::assertContains($app, $respondedArray); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** + * @Then /^user "([^"]*)" is disabled$/ + * @param string $user + */ + public function userIsDisabled($user) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/$user"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + PHPUnit_Framework_Assert::assertEquals("false", $this->response->xml()->data[0]->enabled); + } + + /** + * @Then /^user "([^"]*)" is enabled$/ + * @param string $user + */ + public function userIsEnabled($user) { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/$user"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } + + $this->response = $client->get($fullUrl, $options); + PHPUnit_Framework_Assert::assertEquals("true", $this->response->xml()->data[0]->enabled); + } + + /** + * @Given user :user has a quota of :quota + * @param string $user + * @param string $quota + */ + public function userHasAQuotaOf($user, $quota) + { + $body = new \Behat\Gherkin\Node\TableNode([ + 0 => ['key', 'quota'], + 1 => ['value', $quota], + ]); + + // method used from BasicStructure trait + $this->sendingToWith("PUT", "/cloud/users/" . $user, $body); + } + + /** + * @Given user :user has unlimited quota + * @param string $user + */ + public function userHasUnlimitedQuota($user) + { + $this->userHasAQuotaOf($user, 'none'); + } + + /** + * @BeforeScenario + * @AfterScenario + */ + public function cleanupUsers() + { + $previousServer = $this->currentServer; + $this->usingServer('LOCAL'); + foreach($this->createdUsers as $user) { + $this->deleteUser($user); + } + $this->usingServer('REMOTE'); + foreach($this->createdRemoteUsers as $remoteUser) { + $this->deleteUser($remoteUser); + } + $this->usingServer($previousServer); + } + + /** + * @BeforeScenario + * @AfterScenario + */ + public function cleanupGroups() + { + $previousServer = $this->currentServer; + $this->usingServer('LOCAL'); + foreach($this->createdGroups as $group) { + $this->deleteGroup($group); + } + $this->usingServer('REMOTE'); + foreach($this->createdRemoteGroups as $remoteGroup) { + $this->deleteUser($remoteGroup); + } + $this->usingServer($previousServer); + } + +} diff --git a/build/integration/features/bootstrap/Sharing.php b/build/integration/features/bootstrap/Sharing.php new file mode 100644 index 00000000000..39ec4397bab --- /dev/null +++ b/build/integration/features/bootstrap/Sharing.php @@ -0,0 +1,498 @@ +<?php + +use GuzzleHttp\Client; +use GuzzleHttp\Message\ResponseInterface; + +require __DIR__ . '/../../vendor/autoload.php'; + + + +trait Sharing { + use Provisioning; + + /** @var int */ + private $sharingApiVersion = 1; + + /** @var SimpleXMLElement */ + private $lastShareData = null; + + /** @var int */ + private $savedShareId = null; + + /** + * @Given /^as "([^"]*)" creating a share with$/ + * @param string $user + * @param \Behat\Gherkin\Node\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 = []; + if ($user === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$user, $this->regularUser]; + } + + if ($body instanceof \Behat\Gherkin\Node\TableNode) { + $fd = $body->getRowsHash(); + if (array_key_exists('expireDate', $fd)){ + $dateModification = $fd['expireDate']; + $fd['expireDate'] = date('Y-m-d', strtotime($dateModification)); + } + $options['body'] = $fd; + } + + try { + $this->response = $client->send($client->createRequest("POST", $fullUrl, $options)); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + } + + $this->lastShareData = $this->response->xml(); + } + + /** + * @When /^creating a share with$/ + * @param \Behat\Gherkin\Node\TableNode|null $body + */ + public function creatingShare($body) { + $this->asCreatingAShareWith($this->currentUser, $body); + } + + /** + * @Then /^Public shared file "([^"]*)" can be downloaded$/ + */ + public function checkPublicSharedFile($filename) { + $client = new Client(); + $options = []; + if (count($this->lastShareData->data->element) > 0){ + $url = $this->lastShareData->data[0]->url; + } + else{ + $url = $this->lastShareData->data->url; + } + $fullUrl = $url . "/download"; + $options['save_to'] = "./$filename"; + $this->response = $client->get($fullUrl, $options); + $finfo = new finfo; + $fileinfo = $finfo->file("./$filename", FILEINFO_MIME_TYPE); + PHPUnit_Framework_Assert::assertEquals($fileinfo, "text/plain"); + if (file_exists("./$filename")) { + unlink("./$filename"); + } + } + + /** + * @Then /^Public shared file "([^"]*)" with password "([^"]*)" can be downloaded$/ + */ + public function checkPublicSharedFileWithPassword($filename, $password) { + $client = new Client(); + $options = []; + 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/webdav"; + $options['auth'] = [$token, $password]; + $options['save_to'] = "./$filename"; + $this->response = $client->get($fullUrl, $options); + $finfo = new finfo; + $fileinfo = $finfo->file("./$filename", FILEINFO_MIME_TYPE); + PHPUnit_Framework_Assert::assertEquals($fileinfo, "text/plain"); + if (file_exists("./$filename")) { + unlink("./$filename"); + } + } + + /** + * @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['body'] = ['expireDate' => $date]; + $this->response = $client->send($client->createRequest("PUT", $fullUrl, $options)); + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + /** + * @When /^Updating last share with$/ + * @param \Behat\Gherkin\Node\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 = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$this->currentUser, $this->regularUser]; + } + + if ($body instanceof \Behat\Gherkin\Node\TableNode) { + $fd = $body->getRowsHash(); + if (array_key_exists('expireDate', $fd)){ + $dateModification = $fd['expireDate']; + $fd['expireDate'] = date('Y-m-d', strtotime($dateModification)); + } + $options['body'] = $fd; + } + + try { + $this->response = $client->send($client->createRequest("PUT", $fullUrl, $options)); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + } + + PHPUnit_Framework_Assert::assertEquals(200, $this->response->getStatusCode()); + } + + public function createShare($user, + $path = null, + $shareType = null, + $shareWith = null, + $publicUpload = null, + $password = null, + $permissions = null){ + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares"; + $client = new Client(); + $options = []; + + if ($user === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$user, $this->regularUser]; + } + $fd = []; + if (!is_null($path)){ + $fd['path'] = $path; + } + if (!is_null($shareType)){ + $fd['shareType'] = $shareType; + } + if (!is_null($shareWith)){ + $fd['shareWith'] = $shareWith; + } + if (!is_null($publicUpload)){ + $fd['publicUpload'] = $publicUpload; + } + if (!is_null($password)){ + $fd['password'] = $password; + } + if (!is_null($permissions)){ + $fd['permissions'] = $permissions; + } + + $options['body'] = $fd; + + try { + $this->response = $client->send($client->createRequest("POST", $fullUrl, $options)); + $this->lastShareData = $this->response->xml(); + } catch (\GuzzleHttp\Exception\ClientException $ex) { + $this->response = $ex->getResponse(); + } + } + + public function isFieldInResponse($field, $contentExpected){ + $data = $this->response->xml()->data[0]; + if ((string)$field == 'expiration'){ + $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 ($data->$field == $contentExpected){ + return True; + } + return False; + } + } + + /** + * @Then /^File "([^"]*)" should be included in the response$/ + * + * @param string $filename + */ + public function checkSharedFileInResponse($filename){ + PHPUnit_Framework_Assert::assertEquals(True, $this->isFieldInResponse('file_target', "/$filename")); + } + + /** + * @Then /^File "([^"]*)" should not be included in the response$/ + * + * @param string $filename + */ + public function checkSharedFileNotInResponse($filename){ + PHPUnit_Framework_Assert::assertEquals(False, $this->isFieldInResponse('file_target', "/$filename")); + } + + /** + * @Then /^User "([^"]*)" should be included in the response$/ + * + * @param string $user + */ + public function checkSharedUserInResponse($user){ + PHPUnit_Framework_Assert::assertEquals(True, $this->isFieldInResponse('share_with', "$user")); + } + + /** + * @Then /^User "([^"]*)" should not be included in the response$/ + * + * @param string $user + */ + public function checkSharedUserNotInResponse($user){ + PHPUnit_Framework_Assert::assertEquals(False, $this->isFieldInResponse('share_with', "$user")); + } + + public function isUserOrGroupInSharedData($userOrGroup){ + $data = $this->response->xml()->data[0]; + foreach($data as $element) { + if ($element->share_with == $userOrGroup){ + return True; + } + } + return False; + } + + /** + * @Given /^file "([^"]*)" of user "([^"]*)" is shared with user "([^"]*)"$/ + * + * @param string $filepath + * @param string $user1 + * @param string $user2 + */ + public function assureFileIsShared($filepath, $user1, $user2){ + $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]; + } + $this->response = $client->get($fullUrl, $options); + if ($this->isUserOrGroupInSharedData($user2)){ + return; + } else { + $this->createShare($user1, $filepath, 0, $user2, null, null, null); + } + $this->response = $client->get($fullUrl, $options); + PHPUnit_Framework_Assert::assertEquals(True, $this->isUserOrGroupInSharedData($user2)); + } + + /** + * @Given /^file "([^"]*)" of user "([^"]*)" is shared with group "([^"]*)"$/ + * + * @param string $filepath + * @param string $user + * @param string $group + */ + public function assureFileIsSharedWithGroup($filepath, $user, $group){ + $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]; + } + $this->response = $client->get($fullUrl, $options); + if ($this->isUserOrGroupInSharedData($group)){ + return; + } else { + $this->createShare($user, $filepath, 1, $group, null, null, null); + } + $this->response = $client->get($fullUrl, $options); + PHPUnit_Framework_Assert::assertEquals(True, $this->isUserOrGroupInSharedData($group)); + } + + /** + * @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)){ + PHPUnit_Framework_Assert::fail("Share id $share_id not found in response"); + } + } + + /** + * @Then /^last share_id is included in the answer as parent$/ + */ + public function checkingLastShareIDIsIncludedAsParent(){ + $share_id = $this->lastShareData->data[0]->id; + //This is a problem before 9.0, setupFS is called with every api call so a new share id is created + //we just need to check the parent id to match with the returned id. + if (!$this->isFieldInResponse('parent', $share_id)){ + PHPUnit_Framework_Assert::fail("Share id $share_id not found in response as parent"); + } + } + + /** + * @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)){ + PHPUnit_Framework_Assert::fail("Share id $share_id has been found in response"); + } + } + + /** + * @Then /^last share_id is not included in the answer as parent$/ + */ + public function checkingLastShareIDIsNotIncludedAsParent(){ + $share_id = $this->lastShareData->data[0]->id; + //This is a problem before 9.0, setupFS is called with every api call so a new share id is created + //we just need to check the parent id to match with the returned id. + if ($this->isFieldInResponse('parent', $share_id)){ + PHPUnit_Framework_Assert::fail("Share id $share_id has been found in response as parent"); + } + } + + /** + * @Then /^Share fields of last share match with$/ + * @param \Behat\Gherkin\Node\TableNode|null $body + */ + public function checkShareFields($body){ + if ($body instanceof \Behat\Gherkin\Node\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)){ + PHPUnit_Framework_Assert::fail("$field" . " doesn't have value " . "$value"); + } + } + } + } + + /** + * @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', + ], + ] + ); + $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', + ], + ] + ); + $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']; + } + + /** + * @Then share ids should match + */ + public function shareIdsShouldMatch() + { + if ($this->savedShareId !== $this->lastShareData['data']['id']) { + throw new \Exception('Expected the same link share to be returned'); + } + } +} + diff --git a/build/integration/features/bootstrap/WebDav.php b/build/integration/features/bootstrap/WebDav.php new file mode 100644 index 00000000000..3df37db72bb --- /dev/null +++ b/build/integration/features/bootstrap/WebDav.php @@ -0,0 +1,508 @@ +<?php + +use GuzzleHttp\Client as GClient; +use GuzzleHttp\Message\ResponseInterface; +use Sabre\DAV\Client as SClient; + +require __DIR__ . '/../../vendor/autoload.php'; + + +trait WebDav { + use Sharing; + + /** @var string*/ + private $davPath = "remote.php/webdav"; + /** @var ResponseInterface */ + private $response; + + /** + * @Given /^using dav path "([^"]*)"$/ + */ + public function usingDavPath($davPath) { + $this->davPath = $davPath; + } + + public function makeDavRequest($user, $method, $path, $headers, $body = null){ + $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath . "$path"; + $client = new GClient(); + $options = []; + if ($user === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$user, $this->regularUser]; + } + $request = $client->createRequest($method, $fullUrl, $options); + if (!is_null($headers)){ + foreach ($headers as $key => $value) { + $request->addHeader($key, $value); + } + } + + if (!is_null($body)) { + $request->setBody($body); + } + + return $client->send($request); + } + + /** + * @Given /^User "([^"]*)" moved file "([^"]*)" to "([^"]*)"$/ + * @param string $user + * @param string $fileSource + * @param string $fileDestination + */ + public function userMovedFile($user, $fileSource, $fileDestination){ + $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath; + $headers['Destination'] = $fullUrl . $fileDestination; + $this->response = $this->makeDavRequest($user, "MOVE", $fileSource, $headers); + PHPUnit_Framework_Assert::assertEquals(201, $this->response->getStatusCode()); + } + + /** + * @When /^User "([^"]*)" moves file "([^"]*)" to "([^"]*)"$/ + * @param string $user + * @param string $fileSource + * @param string $fileDestination + */ + public function userMovesFile($user, $fileSource, $fileDestination){ + $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath; + $headers['Destination'] = $fullUrl . $fileDestination; + try { + $this->response = $this->makeDavRequest($user, "MOVE", $fileSource, $headers); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @When /^User "([^"]*)" copies file "([^"]*)" to "([^"]*)"$/ + * @param string $user + * @param string $fileSource + * @param string $fileDestination + */ + public function userCopiesFile($user, $fileSource, $fileDestination){ + $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath; + $headers['Destination'] = $fullUrl . $fileDestination; + try { + $this->response = $this->makeDavRequest($user, "COPY", $fileSource, $headers); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @When /^Downloading file "([^"]*)" with range "([^"]*)"$/ + * @param string $fileSource + * @param string $range + */ + public function downloadFileWithRange($fileSource, $range){ + $headers['Range'] = $range; + $this->response = $this->makeDavRequest($this->currentUser, "GET", $fileSource, $headers); + } + + /** + * @When /^Downloading last public shared file with range "([^"]*)"$/ + * @param string $range + */ + public function downloadPublicFileWithRange($range){ + $token = $this->lastShareData->data->token; + $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/webdav"; + $headers['Range'] = $range; + + $client = new GClient(); + $options = []; + $options['auth'] = [$token, ""]; + + $request = $client->createRequest("GET", $fullUrl, $options); + $request->addHeader('Range', $range); + + $this->response = $client->send($request); + } + + /** + * @When /^Downloading last public shared file inside a folder "([^"]*)" with range "([^"]*)"$/ + * @param string $range + */ + public function downloadPublicFileInsideAFolderWithRange($path, $range){ + $token = $this->lastShareData->data->token; + $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/webdav" . "$path"; + $headers['Range'] = $range; + + $client = new GClient(); + $options = []; + $options['auth'] = [$token, ""]; + + $request = $client->createRequest("GET", $fullUrl, $options); + $request->addHeader('Range', $range); + + $this->response = $client->send($request); + } + + /** + * @Then /^Downloaded content should be "([^"]*)"$/ + * @param string $content + */ + public function downloadedContentShouldBe($content){ + PHPUnit_Framework_Assert::assertEquals($content, (string)$this->response->getBody()); + } + + /** + * @Then /^Downloaded content when downloading file "([^"]*)" with range "([^"]*)" should be "([^"]*)"$/ + * @param string $fileSource + * @param string $range + * @param string $content + */ + public function downloadedContentWhenDownloadindShouldBe($fileSource, $range, $content){ + $this->downloadFileWithRange($fileSource, $range); + $this->downloadedContentShouldBe($content); + } + + /** + * @When Downloading file :fileName + * @param string $fileName + */ + public function downloadingFile($fileName) { + try { + $this->response = $this->makeDavRequest($this->currentUser, 'GET', $fileName, []); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @Then The following headers should be set + * @param \Behat\Gherkin\Node\TableNode $table + * @throws \Exception + */ + public function theFollowingHeadersShouldBeSet(\Behat\Gherkin\Node\TableNode $table) { + foreach($table->getTable() as $header) { + $headerName = $header[0]; + $expectedHeaderValue = $header[1]; + $returnedHeader = $this->response->getHeader($headerName); + if($returnedHeader !== $expectedHeaderValue) { + throw new \Exception( + sprintf( + "Expected value '%s' for header '%s', got '%s'", + $expectedHeaderValue, + $headerName, + $returnedHeader + ) + ); + } + } + } + + /** + * @Then Downloaded content should start with :start + * @param int $start + * @throws \Exception + */ + public function downloadedContentShouldStartWith($start) { + if(strpos($this->response->getBody()->getContents(), $start) !== 0) { + throw new \Exception( + sprintf( + "Expected '%s', got '%s'", + $start, + $this->response->getBody()->getContents() + ) + ); + } + } + + /** + * @Then /^as "([^"]*)" gets properties of folder "([^"]*)" with$/ + * @param string $user + * @param string $path + * @param \Behat\Gherkin\Node\TableNode|null $propertiesTable + */ + public function asGetsPropertiesOfFolderWith($user, $path, $propertiesTable) { + $properties = null; + if ($propertiesTable instanceof \Behat\Gherkin\Node\TableNode) { + foreach ($propertiesTable->getRows() as $row) { + $properties[] = $row[0]; + } + } + $this->response = $this->listFolder($user, $path, 0, $properties); + } + + /** + * @Then the single response should contain a property :key with value :value + * @param string $key + * @param string $expectedValue + * @throws \Exception + */ + public function theSingleResponseShouldContainAPropertyWithValue($key, $expectedValue) { + $keys = $this->response; + if (!array_key_exists($key, $keys)) { + throw new \Exception("Cannot find property \"$key\" with \"$expectedValue\""); + } + + $value = $keys[$key]; + if ($value != $expectedValue) { + throw new \Exception("Property \"$key\" found with value \"$value\", expected \"$expectedValue\""); + } + } + + /** + * @Then the response should contain a share-types property with + */ + public function theResponseShouldContainAShareTypesPropertyWith($table) + { + $keys = $this->response; + if (!array_key_exists('{http://owncloud.org/ns}share-types', $keys)) { + throw new \Exception("Cannot find property \"{http://owncloud.org/ns}share-types\""); + } + + $foundTypes = []; + $data = $keys['{http://owncloud.org/ns}share-types']; + foreach ($data as $item) { + if ($item['name'] !== '{http://owncloud.org/ns}share-type') { + throw new \Exception('Invalid property found: "' . $item['name'] . '"'); + } + + $foundTypes[] = $item['value']; + } + + foreach ($table->getRows() as $row) { + $key = array_search($row[0], $foundTypes); + if ($key === false) { + throw new \Exception('Expected type ' . $row[0] . ' not found'); + } + + unset($foundTypes[$key]); + } + + if ($foundTypes !== []) { + throw new \Exception('Found more share types then specified: ' . $foundTypes); + } + } + + /** + * @Then the response should contain an empty property :property + * @param string $property + * @throws \Exception + */ + public function theResponseShouldContainAnEmptyProperty($property) { + $properties = $this->response; + if (!array_key_exists($property, $properties)) { + throw new \Exception("Cannot find property \"$property\""); + } + + if ($properties[$property] !== null) { + throw new \Exception("Property \"$property\" is not empty"); + } + } + + + /*Returns the elements of a propfind, $folderDepth requires 1 to see elements without children*/ + public function listFolder($user, $path, $folderDepth, $properties = null){ + $fullUrl = substr($this->baseUrl, 0, -4); + + $settings = array( + 'baseUri' => $fullUrl, + 'userName' => $user, + ); + + if ($user === 'admin') { + $settings['password'] = $this->adminUser[1]; + } else { + $settings['password'] = $this->regularUser; + } + + $client = new SClient($settings); + + if (!$properties) { + $properties = [ + '{DAV:}getetag' + ]; + } + + $response = $client->propfind($this->davPath . '/' . ltrim($path, '/'), $properties, $folderDepth); + + return $response; + } + + /** + * @Then /^user "([^"]*)" should see following elements$/ + * @param string $user + * @param \Behat\Gherkin\Node\TableNode|null $expectedElements + */ + public function checkElementList($user, $expectedElements){ + $elementList = $this->listFolder($user, '/', 3); + if ($expectedElements instanceof \Behat\Gherkin\Node\TableNode) { + $elementRows = $expectedElements->getRows(); + $elementsSimplified = $this->simplifyArray($elementRows); + foreach($elementsSimplified as $expectedElement) { + $webdavPath = "/" . $this->davPath . $expectedElement; + if (!array_key_exists($webdavPath,$elementList)){ + PHPUnit_Framework_Assert::fail("$webdavPath" . " is not in propfind answer"); + } + } + } + } + + /** + * @When User :user uploads file :source to :destination + * @param string $user + * @param string $source + * @param string $destination + */ + public function userUploadsAFileTo($user, $source, $destination) + { + $file = \GuzzleHttp\Stream\Stream::factory(fopen($source, 'r')); + try { + $this->response = $this->makeDavRequest($user, "PUT", $destination, [], $file); + } catch (\GuzzleHttp\Exception\ServerException $e) { + // 4xx and 5xx responses cause an exception + $this->response = $e->getResponse(); + } + } + + /** + * @When User :user uploads file with content :content to :destination + */ + public function userUploadsAFileWithContentTo($user, $content, $destination) + { + $file = \GuzzleHttp\Stream\Stream::factory($content); + try { + $this->response = $this->makeDavRequest($user, "PUT", $destination, [], $file); + } catch (\GuzzleHttp\Exception\ServerException $e) { + // 4xx and 5xx responses cause an exception + $this->response = $e->getResponse(); + } + } + + /** + * @When User :user deletes file :file + * @param string $user + * @param string $file + */ + public function userDeletesFile($user, $file) { + try { + $this->response = $this->makeDavRequest($user, 'DELETE', $file, []); + } catch (\GuzzleHttp\Exception\ServerException $e) { + // 4xx and 5xx responses cause an exception + $this->response = $e->getResponse(); + } + } + + /** + * @Given User :user created a folder :destination + * @param string $user + * @param string $destination + */ + public function userCreatedAFolder($user, $destination){ + try { + $this->response = $this->makeDavRequest($user, "MKCOL", $destination, []); + } catch (\GuzzleHttp\Exception\ServerException $e) { + // 4xx and 5xx responses cause an exception + $this->response = $e->getResponse(); + } + } + + /** + * @Given user :user uploads chunk file :num of :total with :data to :destination + * @param string $user + * @param int $num + * @param int $total + * @param string $data + * @param string $destination + */ + public function userUploadsChunkFileOfWithToWithChecksum($user, $num, $total, $data, $destination) + { + $num -= 1; + $data = \GuzzleHttp\Stream\Stream::factory($data); + $file = $destination . '-chunking-42-'.$total.'-'.$num; + $this->makeDavRequest($user, 'PUT', $file, ['OC-Chunked' => '1'], $data); + } + + /** + * @Given user :user creates a new chunking upload with id :id + */ + public function userCreatesANewChunkingUploadWithId($user, $id) + { + $destination = '/uploads/'.$user.'/'.$id; + $this->makeDavRequest($user, 'MKCOL', $destination, []); + } + + /** + * @Given user :user uploads new chunk file :num with :data to id :id + */ + public function userUploadsNewChunkFileOfWithToId($user, $num, $data, $id) + { + $data = \GuzzleHttp\Stream\Stream::factory($data); + $destination = '/uploads/'.$user.'/'.$id.'/'.$num; + $this->makeDavRequest($user, 'PUT', $destination, [], $data); + } + + /** + * @Given user :user moves new chunk file with id :id to :dest + */ + public function userMovesNewChunkFileWithIdToMychunkedfile($user, $id, $dest) + { + $source = '/uploads/'.$user.'/'.$id.'/.file'; + $destination = substr($this->baseUrl, 0, -4) . $this->davPath . '/files/'.$user.$dest; + $this->makeDavRequest($user, 'MOVE', $source, [ + 'Destination' => $destination + ]); + } + + + /** + * @Given /^Downloading file "([^"]*)" as "([^"]*)"$/ + */ + public function downloadingFileAs($fileName, $user) { + try { + $this->response = $this->makeDavRequest($user, 'GET', $fileName, []); + } catch (\GuzzleHttp\Exception\ServerException $ex) { + $this->response = $ex->getResponse(); + } + } + + /** + * @When user :user favorites element :path + */ + public function userFavoritesElement($user, $path){ + $this->response = $this->changeFavStateOfAnElement($user, $path, 1, 0, null); + } + + /** + * @When user :user unfavorites element :path + */ + public function userUnfavoritesElement($user, $path){ + $this->response = $this->changeFavStateOfAnElement($user, $path, 0, 0, null); + } + + /*Set the elements of a proppatch, $folderDepth requires 1 to see elements without children*/ + public function changeFavStateOfAnElement($user, $path, $favOrUnfav, $folderDepth, $properties = null){ + $fullUrl = substr($this->baseUrl, 0, -4); + $settings = array( + 'baseUri' => $fullUrl, + 'userName' => $user, + ); + if ($user === 'admin') { + $settings['password'] = $this->adminUser[1]; + } else { + $settings['password'] = $this->regularUser; + } + $client = new SClient($settings); + if (!$properties) { + $properties = [ + '{http://owncloud.org/ns}favorite' => $favOrUnfav + ]; + } + + $response = $client->proppatch($this->davPath . '/' . ltrim($path, '/'), $properties, $folderDepth); + return $response; + } + + /** + * @Then /^as "([^"]*)" gets properties of file "([^"]*)" with$/ + * @param string $user + * @param string $path + * @param \Behat\Gherkin\Node\TableNode|null $propertiesTable + */ + public function asGetsPropertiesOfFileWith($user, $path, $propertiesTable) { + $this->asGetsPropertiesOfFolderWith($user, $path, $propertiesTable); + } +} |