diff --git a/build/integration/config/behat.yml b/build/integration/config/behat.yml index a87d4fe44c..a1f9d610c6 100644 --- a/build/integration/config/behat.yml +++ b/build/integration/config/behat.yml @@ -14,6 +14,8 @@ default: regular_user_password: 123456 - CommentsContext: baseUrl: http://localhost:8080 + - TagsContext: + baseUrl: http://localhost:8080 federation: paths: - %paths.base%/../federation_features diff --git a/build/integration/features/bootstrap/TagsContext.php b/build/integration/features/bootstrap/TagsContext.php new file mode 100644 index 0000000000..5e1f62ba83 --- /dev/null +++ b/build/integration/features/bootstrap/TagsContext.php @@ -0,0 +1,482 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +require __DIR__ . '/../../vendor/autoload.php'; + +use Behat\Gherkin\Node\TableNode; +use GuzzleHttp\Client; +use GuzzleHttp\Message\ResponseInterface; + +class TagsContext implements \Behat\Behat\Context\Context { + /** @var string */ + private $baseUrl; + /** @var Client */ + private $client; + /** @var ResponseInterface */ + private $response; + + /** + * @param string $baseUrl + */ + public function __construct($baseUrl) { + $this->baseUrl = $baseUrl; + + // in case of ci deployment we take the server url from the environment + $testServerUrl = getenv('TEST_SERVER_URL'); + if ($testServerUrl !== false) { + $this->baseUrl = substr($testServerUrl, 0, -5); + } + } + + /** @BeforeScenario */ + public function tearUpScenario() { + $this->client = new Client(); + } + + /** @AfterScenario */ + public function tearDownScenario() { + $user = 'admin'; + $tags = $this->requestTagsForUser($user); + foreach($tags as $tagId => $tag) { + $this->response = $this->client->delete( + $this->baseUrl . '/remote.php/dav/systemtags/'.$tagId, + [ + 'auth' => [ + $user, + $this->getPasswordForUser($user), + ], + 'headers' => [ + 'Content-Type' => 'application/json', + ], + ] + ); + } + try { + $this->client->delete( + $this->baseUrl . '/remote.php/webdav/myFileToTag.txt', + [ + 'auth' => [ + 'user0', + '123456', + ], + 'headers' => [ + 'Content-Type' => 'application/json', + ], + ] + ); + } catch (\GuzzleHttp\Exception\ClientException $e) {} + } + + /** + * @param string $userName + * @return string + */ + private function getPasswordForUser($userName) { + if($userName === 'admin') { + return 'admin'; + } + return '123456'; + } + + /** + * @When :user creates a :type tag with name :name + */ + public function createsATagWithName($user, $type, $name) { + $userVisible = 'true'; + $userAssignable = 'true'; + switch ($type) { + case 'normal': + break; + case 'not user-assignable': + $userAssignable = 'false'; + break; + case 'not user-visible': + $userVisible = 'false'; + break; + default: + throw new \Exception('Unsupported type'); + } + + try { + $this->response = $this->client->post( + $this->baseUrl . '/remote.php/dav/systemtags/', + [ + 'auth' => [ + $user, + $this->getPasswordForUser($user), + ], + 'headers' => [ + 'Content-Type' => 'application/json', + ], + 'body' => '{"name":"'.$name.'","userVisible":'.$userVisible.',"userAssignable":'.$userAssignable.'}', + ] + ); + } catch (\GuzzleHttp\Exception\ClientException $e){ + $this->response = $e->getResponse(); + } + } + + /** + * @Then The response should have a status code :statusCode + */ + public function theResponseShouldHaveAStatusCode($statusCode) { + if((int)$statusCode !== $this->response->getStatusCode()) { + throw new \Exception("Expected $statusCode, got ".$this->response->getStatusCode()); + } + } + + /** + * Returns all tags for a given user + * + * @param string $user + * @return array + */ + private function requestTagsForUser($user) { + try { + $request = $this->client->createRequest( + 'PROPFIND', + $this->baseUrl . '/remote.php/dav/systemtags/', + [ + 'body' => ' + + + + + + + +', + 'auth' => [ + $user, + $this->getPasswordForUser($user), + ], + 'headers' => [ + 'Content-Type' => 'application/json', + ], + ] + ); + $this->response = $this->client->send($request); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + + $tags = []; + $service = new Sabre\Xml\Service(); + $parsed = $service->parse($this->response->getBody()->getContents()); + foreach($parsed as $entry) { + $singleEntry = $entry['value'][1]['value'][0]['value']; + if(empty($singleEntry[0]['value'])) { + continue; + } + + $tags[$singleEntry[0]['value']] = [ + 'display-name' => $singleEntry[1]['value'], + 'user-visible' => $singleEntry[2]['value'], + 'user-assignable' => $singleEntry[3]['value'], + ]; + } + + return $tags; + } + + /** + * @Then The following tags should exist for :user + */ + public function theFollowingTagsShouldExistFor($user, TableNode $table) { + $tags = $this->requestTagsForUser($user); + + if(count($table->getRows()) !== count($tags)) { + throw new \Exception( + sprintf( + "Expected %s tags, got %s.", + count($table->getRows()), + count($tags) + ) + ); + } + + foreach($table->getRowsHash() as $rowDisplayName => $row) { + foreach($tags as $key => $tag) { + if( + $tag['display-name'] === $rowDisplayName && + $tag['user-visible'] === $row[0] && + $tag['user-assignable'] === $row[1] + ) { + unset($tags[$key]); + } + } + } + if(count($tags) !== 0) { + throw new \Exception('Not expected response'); + } + } + + /** + * @Then :count tags should exist for :user + */ + public function tagsShouldExistFor($count, $user) { + if((int)$count !== count($this->requestTagsForUser($user))) { + throw new \Exception("Expected $count tags, got ".count($this->requestTagsForUser($user))); + } + } + + /** + * @param string $name + * @return int + */ + private function findTagIdByName($name) { + $tags = $this->requestTagsForUser('admin'); + $tagId = 0; + foreach($tags as $id => $tag) { + if($tag['display-name'] === $name) { + $tagId = $id; + break; + } + } + return (int)$tagId; + } + + /** + * @When :user edits the tag with name :oldNmae and sets its name to :newName + */ + public function editsTheTagWithNameAndSetsItsNameTo($user, $oldName, $newName) { + $tagId = $this->findTagIdByName($oldName); + if($tagId === 0) { + throw new \Exception('Could not find tag to rename'); + } + + try { + $request = $this->client->createRequest( + 'PROPPATCH', + $this->baseUrl . '/remote.php/dav/systemtags/' . $tagId, + [ + 'body' => ' + + + + ' . $newName . ' + + +', + 'auth' => [ + $user, + $this->getPasswordForUser($user), + ], + ] + ); + $this->response = $this->client->send($request); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @When :user deletes the tag with name :name + */ + public function deletesTheTagWithName($user, $name) { + $tagId = $this->findTagIdByName($name); + try { + $this->response = $this->client->delete( + $this->baseUrl . '/remote.php/dav/systemtags/' . $tagId, + [ + 'auth' => [ + $user, + $this->getPasswordForUser($user), + ], + 'headers' => [ + 'Content-Type' => 'application/json', + ], + ] + ); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @param string $path + * @param string $user + * @return int + */ + private function getFileIdForPath($path, $user) { + $url = $this->baseUrl.'/remote.php/webdav/'.$path; + $credentials = base64_encode($user .':'.$this->getPasswordForUser($user)); + $context = stream_context_create(array( + 'http' => array( + 'method' => 'PROPFIND', + 'header' => "Authorization: Basic $credentials\r\nContent-Type: application/x-www-form-urlencoded", + 'content' => ' + + + + +' + ) + )); + $response = file_get_contents($url, false, $context); + preg_match_all('/\(.*)\<\/oc:fileid\>/', $response, $matches); + return (int)$matches[1][0]; + } + + /** + * @When :taggingUser adds the tag :tagName to :fileName shared by :sharingUser + */ + public function addsTheTagToSharedBy($taggingUser, $tagName, $fileName, $sharingUser) { + $fileId = $this->getFileIdForPath($fileName, $sharingUser); + $tagId = $this->findTagIdByName($tagName); + + try { + $this->response = $this->client->put( + $this->baseUrl.'/remote.php/dav/systemtags-relations/files/'.$fileId.'/'.$tagId, + [ + 'auth' => [ + $taggingUser, + $this->getPasswordForUser($taggingUser), + ] + ] + ); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @Then :fileName shared by :sharingUser has the following tags + */ + public function sharedByHasTheFollowingTags($fileName, $sharingUser, TableNode $table) { + $loadedExpectedTags = $table->getTable(); + $expectedTags = []; + foreach($loadedExpectedTags as $expected) { + $expectedTags[] = $expected[0]; + } + + // Get the real tags + $request = $this->client->createRequest( + 'PROPFIND', + $this->baseUrl.'/remote.php/dav/systemtags-relations/files/'.$this->getFileIdForPath($fileName, $sharingUser), + [ + 'auth' => [ + $sharingUser, + $this->getPasswordForUser($sharingUser), + ], + 'body' => ' + + + + + + + +', + ] + ); + $response = $this->client->send($request)->getBody()->getContents(); + preg_match_all('/\(.*)\<\/oc:display-name\>/', $response, $realTags); + + foreach($expectedTags as $key => $row) { + foreach($realTags as $tag) { + if($tag[0] === $row) { + unset($expectedTags[$key]); + } + } + } + + if(count($expectedTags) !== 0) { + throw new \Exception('Not all tags found.'); + } + } + + /** + * @Then :fileName shared by :sharingUser has the following tags for :user + */ + public function sharedByHasTheFollowingTagsFor($fileName, $sharingUser, $user, TableNode $table) { + $loadedExpectedTags = $table->getTable(); + $expectedTags = []; + foreach($loadedExpectedTags as $expected) { + $expectedTags[] = $expected[0]; + } + + // Get the real tags + try { + $request = $this->client->createRequest( + 'PROPFIND', + $this->baseUrl . '/remote.php/dav/systemtags-relations/files/' . $this->getFileIdForPath($fileName, $sharingUser), + [ + 'auth' => [ + $user, + $this->getPasswordForUser($user), + ], + 'body' => ' + + + + + + + +', + ] + ); + $this->response = $this->client->send($request)->getBody()->getContents(); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + preg_match_all('/\(.*)\<\/oc:display-name\>/', $this->response, $realTags); + $realTags = array_filter($realTags); + $expectedTags = array_filter($expectedTags); + + foreach($expectedTags as $key => $row) { + foreach($realTags as $tag) { + foreach($tag as $index => $foo) { + if($tag[$index] === $row) { + unset($expectedTags[$key]); + } + } + } + } + + if(count($expectedTags) !== 0) { + throw new \Exception('Not all tags found.'); + } + } + + /** + * @When :user removes the tag :tagName from :fileName shared by :shareUser + */ + public function removesTheTagFromSharedBy($user, $tagName, $fileName, $shareUser) { + $tagId = $this->findTagIdByName($tagName); + $fileId = $this->getFileIdForPath($fileName, $shareUser); + + try { + $this->response = $this->client->delete( + $this->baseUrl.'/remote.php/dav/systemtags-relations/files/'.$fileId.'/'.$tagId, + [ + 'auth' => [ + $user, + $this->getPasswordForUser($user), + ], + ] + ); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } +} diff --git a/build/integration/features/tags.feature b/build/integration/features/tags.feature new file mode 100644 index 0000000000..286fb62bf4 --- /dev/null +++ b/build/integration/features/tags.feature @@ -0,0 +1,370 @@ +Feature: tags + + Scenario: Creating a normal tag as regular user should work + Given user "user0" exists + When "user0" creates a "normal" tag with name "MySuperAwesomeTagName" + Then The response should have a status code "201" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|true|true| + And The following tags should exist for "user0" + |MySuperAwesomeTagName|true|true| + + Scenario: Creating a not user-assignable tag as regular user should fail + Given user "user0" exists + When "user0" creates a "not user-assignable" tag with name "MySuperAwesomeTagName" + Then The response should have a status code "400" + And "0" tags should exist for "admin" + + Scenario: Creating a not user-visible tag as regular user should fail + Given user "user0" exists + When "user0" creates a "not user-visible" tag with name "MySuperAwesomeTagName" + Then The response should have a status code "400" + And "0" tags should exist for "admin" + + Scenario: Renaming a normal tag as regular user should work + Given user "user0" exists + Given "admin" creates a "normal" tag with name "MySuperAwesomeTagName" + When "user0" edits the tag with name "MySuperAwesomeTagName" and sets its name to "AnotherTagName" + Then The response should have a status code "207" + And The following tags should exist for "admin" + |AnotherTagName|true|true| + + Scenario: Renaming a not user-assignable tag as regular user should fail + Given user "user0" exists + Given "admin" creates a "not user-assignable" tag with name "MySuperAwesomeTagName" + When "user0" edits the tag with name "MySuperAwesomeTagName" and sets its name to "AnotherTagName" + Then The response should have a status code "403" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|true|false| + + Scenario: Renaming a not user-visible tag as regular user should fail + Given user "user0" exists + Given "admin" creates a "not user-visible" tag with name "MySuperAwesomeTagName" + When "user0" edits the tag with name "MySuperAwesomeTagName" and sets its name to "AnotherTagName" + Then The response should have a status code "404" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|false|true| + + Scenario: Deleting a normal tag as regular user should work + Given user "user0" exists + Given "admin" creates a "normal" tag with name "MySuperAwesomeTagName" + When "user0" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "204" + And "0" tags should exist for "admin" + + Scenario: Deleting a not user-assignable tag as regular user should fail + Given user "user0" exists + Given "admin" creates a "not user-assignable" tag with name "MySuperAwesomeTagName" + When "user0" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "403" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|true|false| + + Scenario: Deleting a not user-visible tag as regular user should fail + Given user "user0" exists + Given "admin" creates a "not user-visible" tag with name "MySuperAwesomeTagName" + When "user0" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "404" + And The following tags should exist for "admin" + |MySuperAwesomeTagName|false|true| + + Scenario: Deleting a not user-assignable tag as admin should work + Given "admin" creates a "not user-assignable" tag with name "MySuperAwesomeTagName" + When "admin" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "204" + And "0" tags should exist for "admin" + + Scenario: Deleting a not user-visible tag as admin should work + Given "admin" creates a "not user-visible" tag with name "MySuperAwesomeTagName" + When "admin" deletes the tag with name "MySuperAwesomeTagName" + Then The response should have a status code "204" + And "0" tags should exist for "admin" + + Scenario: Assigning a normal tag to a file shared by someone else as regular user should work + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MySuperAwesomeTagName" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + When "user1" adds the tag "MySuperAwesomeTagName" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "201" + And "/myFileToTag.txt" shared by "user0" has the following tags + |MySuperAwesomeTagName| + + Scenario: Assigning a normal tag to a file belonging to someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "user1" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + And "/myFileToTag.txt" shared by "user0" has the following tags + |MyFirstTag| + + Scenario: Assigning a not user-assignable tag to a file shared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "not user-assignable" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "user1" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "403" + And "/myFileToTag.txt" shared by "user0" has the following tags + |MyFirstTag| + + Scenario: Assigning a not user-visible tag to a file shared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "not user-visible" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "user1" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "412" + And "/myFileToTag.txt" shared by "user0" has the following tags + |MyFirstTag| + + Scenario: Assigning a not user-visible tag to a file shared by someone else as admin user should work + Given user "user0" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "not user-visible" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "admin" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "201" + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MyFirstTag| + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + + Scenario: Assigning a not user-assignable tag to a file shared by someone else as admin user should worj + Given user "user0" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "not user-assignable" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + When "admin" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "201" + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MyFirstTag| + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + |MySecondTag| + + Scenario: Unassigning a normal tag from a file shared by someone else as regular user should work + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "user1" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "204" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MySecondTag| + + Scenario: Unassigning a normal tag from a file unshared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "user1" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + |MySecondTag| + + Scenario: Unassigning a not user-visible tag from a file shared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-visible" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "user1" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MyFirstTag| + |MySecondTag| + + Scenario: Unassigning a not user-visible tag from a file shared by someone else as admin should work + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-visible" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "admin" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "204" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MySecondTag| + + Scenario: Unassigning a not user-visible tag from a file unshared by someone else should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-visible" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Given As "user0" remove all shares from the file named "/myFileToTag.txt" + When "admin" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + + Scenario: Unassigning a not user-assignable tag from a file shared by someone else as regular user should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-assignable" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "user1" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "403" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MyFirstTag| + |MySecondTag| + + Scenario: Unassigning a not user-assignable tag from a file shared by someone else as admin should work + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-assignable" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + When "admin" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "204" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MySecondTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "admin" + |MySecondTag| + + Scenario: Unassigning a not user-assignable tag from a file unshared by someone else should fail + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "not user-assignable" tag with name "MyFirstTag" + Given "admin" creates a "normal" tag with name "MySecondTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | user1 | + | shareType | 0 | + Given As "user0" sending "POST" to "/apps/files_sharing/api/v1/shares" with + | path | myFileToTag.txt | + | shareWith | admin | + | shareType | 0 | + Given "admin" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + Given "user0" adds the tag "MySecondTag" to "/myFileToTag.txt" shared by "user0" + Given As "user0" remove all shares from the file named "/myFileToTag.txt" + When "admin" removes the tag "MyFirstTag" from "/myFileToTag.txt" shared by "user0" + Then The response should have a status code "404" + + Scenario: Overwriting existing normal tags should fail + Given user "user0" exists + Given "user0" creates a "normal" tag with name "MyFirstTag" + When "user0" creates a "normal" tag with name "MyFirstTag" + Then The response should have a status code "409" + + Scenario: Overwriting existing not user-assignable tags should fail + Given "admin" creates a "not user-assignable" tag with name "MyFirstTag" + When "admin" creates a "not user-assignable" tag with name "MyFirstTag" + Then The response should have a status code "409" + + Scenario: Overwriting existing not user-visible tags should fail + Given "admin" creates a "not user-visible" tag with name "MyFirstTag" + When "admin" creates a "not user-visible" tag with name "MyFirstTag" + Then The response should have a status code "409" + + Scenario: Getting tags only works with access to the file + Given user "user0" exists + Given user "user1" exists + Given "admin" creates a "normal" tag with name "MyFirstTag" + Given user "user0" uploads file "data/textfile.txt" to "/myFileToTag.txt" + When "user0" adds the tag "MyFirstTag" to "/myFileToTag.txt" shared by "user0" + And "/myFileToTag.txt" shared by "user0" has the following tags for "user0" + |MyFirstTag| + And "/myFileToTag.txt" shared by "user0" has the following tags for "user1" + || + And The response should have a status code "404"