diff --git a/tests/TestHelpers/GraphHelper.php b/tests/TestHelpers/GraphHelper.php index a96d5f32453..6bc12b86ed3 100644 --- a/tests/TestHelpers/GraphHelper.php +++ b/tests/TestHelpers/GraphHelper.php @@ -1666,4 +1666,39 @@ public static function createLinkShare( $body ); } + + /** + * @param string $baseUrl + * @param string $xRequestId + * @param string $user + * @param string $password + * @param string $spaceId + * @param string $itemId + * @param mixed $body + * @param string $shareId + * + * @return ResponseInterface + * @throws GuzzleException + */ + public static function updateLinkShare( + string $baseUrl, + string $xRequestId, + string $user, + string $password, + string $spaceId, + string $itemId, + $body, + string $shareId + ): ResponseInterface { + $url = self::getBetaFullUrl($baseUrl, "drives/$spaceId/items/$itemId/permissions/$shareId"); + return HttpRequestHelper::sendRequestOnce( + $url, + $xRequestId, + 'PATCH', + $user, + $password, + self::getRequestHeaders(), + $body + ); + } } diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index eb3f8aafcef..6bce9415bac 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -256,11 +256,14 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiLocks/lockFiles.feature:457](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiLocks/lockFiles.feature#L457) ### [blocksDownload link type is not implemented yet (sharing-ng)](https://github.com/owncloud/ocis/issues/7879) -- [apiSharingNg/createLink.feature:78](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/createLink.feature#L78) -- [apiSharingNg/createLink.feature:147](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/createLink.feature#L147) -- [apiSharingNg/createLink.feature:225](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/createLink.feature#L225) -- [apiSharingNg/createLink.feature:301](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/createLink.feature#L301) -- [apiSharingNg/createLink.feature:372](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/createLink.feature#L372) - +- [apiSharingNg/linkShare.feature:78](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L78) +- [apiSharingNg/linkShare.feature:147](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L147) +- [apiSharingNg/linkShare.feature:225](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L225) +- [apiSharingNg/linkShare.feature:301](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L301) +- [apiSharingNg/linkShare.feature:372](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L372) +- [apiSharingNg/linkShare.feature:445](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L445) +- [apiSharingNg/linkShare.feature:447](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L447) +- [apiSharingNg/linkShare.feature:448](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L448) +- [apiSharingNg/linkShare.feature:449](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L449) - Note: always have an empty line at the end of this file. The bash script that processes this file requires that the last line has a newline on the end. diff --git a/tests/acceptance/features/apiSharingNg/createLink.feature b/tests/acceptance/features/apiSharingNg/linkShare.feature similarity index 69% rename from tests/acceptance/features/apiSharingNg/createLink.feature rename to tests/acceptance/features/apiSharingNg/linkShare.feature index e9644bc3fac..83087931bcd 100644 --- a/tests/acceptance/features/apiSharingNg/createLink.feature +++ b/tests/acceptance/features/apiSharingNg/linkShare.feature @@ -300,7 +300,7 @@ Feature: Create a share link for a resource | edit | | blocksDownload | - @env-config + @env-config @issue-7879 Scenario Outline: create a link share of a file without password Given the following configs have been set: | config | value | @@ -370,3 +370,151 @@ Feature: Create a share link for a resource | view | | edit | | blocksDownload | + + @issue-7879 + Scenario Outline: update role of a file's link share + Given user "Alice" has uploaded file with content "other data" to "textfile1.txt" + And user "Alice" has created the following link share: + | resourceType | file | + | resource | textfile1.txt | + | space | Personal | + | role | | + | password | %public% | + When user "Alice" updates the last public link share using the Graph API with + | resourceType | file | + | resource | textfile1.txt | + | space | Personal | + | role | | + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "hasPassword", + "id", + "link" + ], + "properties": { + "hasPassword": { + "type": "boolean", + "enum": [true] + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z]{15}$" + }, + "link": { + "type": "object", + "required": [ + "@libre.graph.displayName", + "@libre.graph.quickLink", + "preventsDownload", + "type", + "webUrl" + ], + "properties": { + "@libre.graph.displayName": { + "type": "string", + "enum": [""] + }, + "@libre.graph.quickLink": { + "type": "boolean", + "enum": [false] + }, + "preventsDownload": { + "type": "boolean", + "enum": [false] + }, + "type": { + "type": "string", + "enum": [""] + }, + "webUrl": { + "type": "string", + "pattern": "^%base_url%\/s\/[a-zA-Z]{15}$" + } + } + } + } + } + """ + Examples: + | previousRole | newRole | + | view | edit | + | view | blocksDownload | + | edit | view | + | edit | blocksDownload | + | blocksDownload | edit | + | blocksDownload | blocksDownload | + + + Scenario: update expiration date of a file's link share + Given user "Alice" has uploaded file with content "other data" to "textfile1.txt" + And user "Alice" has created the following link share: + | resourceType | file | + | resource | textfile1.txt | + | space | Personal | + | role | view | + | password | %public% | + | expirationDateTime | 2200-07-15T14:00:00.000Z | + When user "Alice" updates the last public link share using the Graph API with + | resourceType | file | + | resource | textfile1.txt | + | space | Personal | + | expirationDateTime | 2201-07-15T14:00:00.000Z | + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "hasPassword", + "id", + "link", + "expirationDateTime" + ], + "properties": { + "hasPassword": { + "type": "boolean", + "enum": [true] + }, + "id": { + "type": "string", + "pattern": "^[a-zA-Z]{15}$" + }, + "expirationDateTime": { + "type": "string", + "enum": ["2201-07-15T23:59:59Z"] + }, + "link": { + "type": "object", + "required": [ + "@libre.graph.displayName", + "@libre.graph.quickLink", + "preventsDownload", + "type", + "webUrl" + ], + "properties": { + "@libre.graph.quickLink": { + "type": "boolean", + "enum": [false] + }, + "preventsDownload": { + "type": "boolean", + "enum": [false] + }, + "type": { + "type": "string", + "enum": ["view"] + }, + "webUrl": { + "type": "string", + "pattern": "^%base_url%\/s\/[a-zA-Z]{15}$" + } + } + } + } + } + """ diff --git a/tests/acceptance/features/bootstrap/Sharing.php b/tests/acceptance/features/bootstrap/Sharing.php index d40b2976095..1b79c77bb8a 100755 --- a/tests/acceptance/features/bootstrap/Sharing.php +++ b/tests/acceptance/features/bootstrap/Sharing.php @@ -75,6 +75,11 @@ trait Sharing { */ private array $createdPublicShares = []; + /** + * @var array + */ + private array $shareNgCreatedLinkShares = []; + /** * @return string */ @@ -98,6 +103,22 @@ public function addToCreatedPublicShares(SimpleXMLElement $shareData): void { $this->createdPublicShares[] = $shareData; } + /** + * @param ResponseInterface $response + * + * @return void + */ + public function shareNgAddToCreatedLinkShares(ResponseInterface $response): void { + $this->shareNgCreatedLinkShares[] = $response; + } + + /** + * @return ResponseInterface|null + */ + public function shareNgGetLastCreatedLinkShare():?ResponseInterface { + return \end($this->shareNgCreatedLinkShares); + } + /** * @param string $sharer * @param SimpleXMLElement $shareData @@ -152,6 +173,17 @@ public function getSharesEndpointPath(?string $postfix = ''):string { return "/apps/files_sharing/api/v$this->sharingApiVersion/shares$postfix"; } + /** + * @return string + */ + public function shareNgGetLastCreatedLinkShareID(): string { + $lastResponse = $this->shareNgGetLastCreatedLinkShare(); + if (!isset($this->getJsonDecodedResponse($lastResponse)['id'])) { + throw new Error('Response did not contain share id ' . $this->getJsonDecodedResponse($lastResponse)['id'] . ' for the created public link'); + } + return $this->getJsonDecodedResponse($lastResponse)['id']; + } + /** * Split given permissions string each separated with "," into array of strings * diff --git a/tests/acceptance/features/bootstrap/SharingNgContext.php b/tests/acceptance/features/bootstrap/SharingNgContext.php index 9a37d1cdebc..dc508ffc7eb 100644 --- a/tests/acceptance/features/bootstrap/SharingNgContext.php +++ b/tests/acceptance/features/bootstrap/SharingNgContext.php @@ -22,6 +22,7 @@ use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use PHPUnit\Framework\Assert; +use Psr\Http\Message\ResponseInterface; use TestHelpers\GraphHelper; use Behat\Gherkin\Node\TableNode; @@ -52,6 +53,48 @@ public function before(BeforeScenarioScope $scope): void { $this->spacesContext = $environment->getContext('SpacesContext'); } + /** + * @param string $user + * @param TableNode|null $body + * + * @return ResponseInterface + * @throws Exception + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function createLinkShare(string $user, TableNode $body): ResponseInterface { + $bodyRows = $body->getRowsHash(); + $space = $bodyRows['space']; + $resourceType = $bodyRows['resourceType']; + $resource = $bodyRows['resource']; + + $spaceId = ($this->spacesContext->getSpaceByName($user, $space))["id"]; + if ($resourceType === 'folder') { + $itemId = $this->spacesContext->getResourceId($user, $space, $resource); + } else { + $itemId = $this->spacesContext->getFileId($user, $space, $resource); + } + + $bodyRows['displayName'] = $bodyRows['displayName'] ?? null; + $bodyRows['expirationDateTime'] = $bodyRows['expirationDateTime'] ?? null; + $bodyRows['password'] = $bodyRows['password'] ?? null; + $body = [ + 'type' => $bodyRows['role'], + 'displayName' => $bodyRows['displayName'], + 'expirationDateTime' => $bodyRows['expirationDateTime'], + 'password' => $this->featureContext->getActualPassword($bodyRows['password']) + ]; + + return GraphHelper::createLinkShare( + $this->featureContext->getBaseUrl(), + $this->featureContext->getStepLineRef(), + $user, + $this->featureContext->getPasswordForUser($user), + $spaceId, + $itemId, + \json_encode($body) + ); + } + /** * @When /^user "([^"]*)" gets permissions list for (folder|file) "([^"]*)" of the space "([^"]*)" using the Graph API$/ * @@ -132,14 +175,42 @@ public function userSendsTheFollowingShareInvitationUsingTheGraphApi(string $use * @param TableNode|null $body * * @return void - * @throws Exception + * @throws \GuzzleHttp\Exception\GuzzleException */ public function userCreatesAPublicLinkShareWithSettings(string $user, TableNode $body):void { + $response = $this->createLinkShare($user, $body); + $this->featureContext->setResponse($response); + } + + /** + * @Given /^user "([^"]*)" has created the following link share:$/ + * + * @param string $user + * @param TableNode|null $body + * + * @return void + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function userHasCreatedTheFollowingLinkShare(string $user, TableNode $body): void { + $response = $this->createLinkShare($user, $body); + $this->featureContext->theHTTPStatusCodeShouldBe(200, "Failed while creating public share link!", $response); + $this->featureContext->shareNgAddToCreatedLinkShares($response); + } + + /** + * @When /^user "([^"]*)" updates the last public link share using the Graph API with$/ + * + * @param string $user + * @param TableNode|null $body + * + * @return void + * @throws Exception + */ + public function userUpdatesLastPublicLinkShareUsingTheGraphApiWith(string $user, TableNode $body):void { $bodyRows = $body->getRowsHash(); $space = $bodyRows['space']; $resourceType = $bodyRows['resourceType']; $resource = $bodyRows['resource']; - $spaceId = ($this->spacesContext->getSpaceByName($user, $space))["id"]; if ($resourceType === 'folder') { $itemId = $this->spacesContext->getResourceId($user, $space, $resource); @@ -147,25 +218,37 @@ public function userCreatesAPublicLinkShareWithSettings(string $user, TableNode $itemId = $this->spacesContext->getFileId($user, $space, $resource); } - $bodyRows['displayName'] = $bodyRows['displayName'] ?? null; - $bodyRows['expirationDateTime'] = $bodyRows['expirationDateTime'] ?? null; - $bodyRows['password'] = $bodyRows['password'] ?? null; - $body = [ - 'type' => $bodyRows['role'], - 'displayName' => $bodyRows['displayName'], - 'expirationDateTime' => $bodyRows['expirationDateTime'], - 'password' => $this->featureContext->getActualPassword($bodyRows['password']) - ]; + if (\array_key_exists('role', $bodyRows) && \array_key_exists('expirationDateTime', $bodyRows)) { + $body = [ + "expirationDateTime" => $bodyRows['expirationDateTime'], + "link" => [ + "type" => $bodyRows['role'] + ] + ]; + } elseif (\array_key_exists('role', $bodyRows)) { + $body = [ + "link" => [ + "type" => $bodyRows['role'] + ] + ]; + } elseif (\array_key_exists('expirationDateTime', $bodyRows)) { + $body = [ + "expirationDateTime" => $bodyRows['expirationDateTime'] + ]; + } else { + throw new Error('Expiration date or role is missing to update for share link!'); + } $this->featureContext->setResponse( - GraphHelper::createLinkShare( + GraphHelper::updateLinkShare( $this->featureContext->getBaseUrl(), $this->featureContext->getStepLineRef(), $user, $this->featureContext->getPasswordForUser($user), $spaceId, $itemId, - \json_encode($body) + \json_encode($body), + $this->featureContext->shareNgGetLastCreatedLinkShareID() ) ); }