diff --git a/tests/acceptance/bootstrap/GraphContext.php b/tests/acceptance/bootstrap/GraphContext.php index ea98fd5bf8..f015f5dadb 100644 --- a/tests/acceptance/bootstrap/GraphContext.php +++ b/tests/acceptance/bootstrap/GraphContext.php @@ -3763,7 +3763,7 @@ class GraphContext implements Context { * * @return void */ - #[When('the public tries to get the child :child of the last created public link through its real drive id with password :password using the Graph API')] + #[When('the public gets the child :child of the last created public link through its real drive id with password :password using the Graph API')] public function thePublicTriesToGetTheChildThroughItsRealDriveId(string $child, ?string $password = null): void { $childId = $this->publicLinkChildId($child, $password); $realDriveId = \explode("!", $childId)[0]; @@ -3937,4 +3937,73 @@ class GraphContext implements Context { ): void { $this->publicSendsGraphDriveRequest("/root:/$path:", $password); } + + /** + * @param string $user + * @param string $path + * + * @return array [real drive id, resource id] + */ + private function realDriveOfResource(string $user, string $path): array { + $resourceId = $this->featureContext->getFileIdForPath($this->featureContext->getActualUsername($user), $path); + return [\explode("!", $resourceId)[0], $resourceId]; + } + + /** + * @param string $path + * @param string $user + * @param string $password + * + * @return void + */ + #[When('the public lists the children of resource :path of user :user through the real drive of the last created public link with password :password using the Graph API')] + public function thePublicListsTheChildrenOfResourceThroughTheRealDrive(string $path, string $user, string $password): void { + [$driveId, $resourceId] = $this->realDriveOfResource($user, $path); + $this->publicSendsRawGraphRequest("/drives/$driveId/items/$resourceId/children", $password); + } + + /** + * @param string $path + * @param string $user + * @param string $password + * + * @return void + */ + #[When('the public tries to get the resource :path of user :user through the real drive of the last created public link with password :password using the Graph API')] + public function thePublicTriesToGetTheResourceThroughTheRealDrive(string $path, string $user, string $password): void { + [$driveId, $resourceId] = $this->realDriveOfResource($user, $path); + $this->publicSendsRawGraphRequest("/drives/$driveId/items/$resourceId", $password); + } + + /** + * @param string $path + * @param string $user + * @param string $password + * + * @return void + */ + #[When('the public tries to get the drive of resource :path of user :user through the last created public link with password :password using the Graph API')] + public function thePublicTriesToGetTheDriveOfResource(string $path, string $user, string $password): void { + [$driveId] = $this->realDriveOfResource($user, $path); + $this->publicSendsRawGraphRequest("/drives/$driveId", $password); + } + + /** + * @param string $relativePath + * @param string $path + * @param string $user + * @param string $password + * + * @return void + */ + #[When('the public tries to get the path :relativePath from the real drive root of resource :path of user :user through the last created public link with password :password using the Graph API')] + public function thePublicTriesToGetThePathFromTheRealDriveRoot( + string $relativePath, + string $path, + string $user, + string $password + ): void { + [$driveId] = $this->realDriveOfResource($user, $path); + $this->publicSendsRawGraphRequest("/drives/$driveId/root:/$relativePath:", $password); + } } diff --git a/tests/acceptance/features/apiGraph/publicLinkDriveItemListing.feature b/tests/acceptance/features/apiGraph/publicLinkDriveItemListing.feature index cf7187cfe0..4d90d480df 100644 --- a/tests/acceptance/features/apiGraph/publicLinkDriveItemListing.feature +++ b/tests/acceptance/features/apiGraph/publicLinkDriveItemListing.feature @@ -161,7 +161,7 @@ Feature: listing the content of a public link via the Graph API "required": ["path", "driveId"], "properties": { "path": { "const": "/" }, - "driveId": { "pattern": "^7993447f-687f-490d-875c-ac95e89a62a4\\$7993447f-687f-490d-875c-ac95e89a62a4!" } + "driveId": { "not": { "pattern": "^7993447f-687f-490d-875c-ac95e89a62a4" } } } } } @@ -281,11 +281,70 @@ Feature: listing the content of a public link via the Graph API Then the HTTP status code should be "401" - Scenario: an in-share item is not addressable through its real drive id - When the public tries to get the child "sub" of the last created public link through its real drive id with password "%public%" using the Graph API + Scenario: an in-share item is addressable through its real drive id + When the public gets the child "sub" of the last created public link through its real drive id with password "%public%" using the Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": ["name"], + "properties": { + "name": { "const": "sub" } + } + } + """ + + + Scenario: the public lists a subfolder through the real drive + When the public lists the children of resource "publicfolder/sub" of user "Alice" through the real drive of the last created public link with password "%public%" using the Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": ["value"], + "properties": { + "value": { + "type": "array", + "minItems": 1, + "maxItems": 1, + "uniqueItems": true, + "items": { + "type": "object", + "required": ["name", "parentReference"], + "properties": { + "name": { "const": "b.txt" }, + "parentReference": { + "type": "object", + "required": ["path"], + "properties": { + "path": { "const": "/sub" } + } + } + } + } + } + } + } + """ + + + Scenario: the real drive itself stays closed to a public token + When the public tries to get the drive of resource "publicfolder" of user "Alice" through the last created public link with password "%public%" using the Graph API Then the HTTP status code should be "401" + Scenario: the root of the real drive stays closed to a public token + When the public tries to get the path "private.txt" from the real drive root of resource "publicfolder" of user "Alice" through the last created public link with password "%public%" using the Graph API + Then the HTTP status code should be "401" + + + Scenario: a resource outside the public link is not readable through the real drive + When the public tries to get the resource "private.txt" of user "Alice" through the real drive of the last created public link with password "%public%" using the Graph API + Then the HTTP status code should be "404" + + Scenario: a token does not open another link's drive When the public tries to list the children of a foreign public link drive using the last created token with password "%public%" using the Graph API Then the HTTP status code should be "401" @@ -416,6 +475,16 @@ Feature: listing the content of a public link via the Graph API Then the HTTP status code should be "200" + Scenario: a file drop link does not list its folder through the real drive + Given user "Alice" has created the following resource link share: + | resource | publicfolder | + | space | Personal | + | permissionsRole | createOnly | + | password | %public% | + When the public lists the children of resource "publicfolder" of user "Alice" through the real drive of the last created public link with password "%public%" using the Graph API + Then the HTTP status code should be "403" + + Scenario: an internal link does not list its folder through the real id Given user "Alice" has created the following resource link share: | resource | publicfolder | @@ -493,9 +562,29 @@ Feature: listing the content of a public link via the Graph API """ { "type": "object", - "required": ["driveType", "owner"], + "required": ["driveType", "owner", "root"], "properties": { "driveType": { "const": "mountpoint" }, + "root": { + "type": "object", + "required": ["remoteItem"], + "properties": { + "remoteItem": { + "type": "object", + "required": ["id", "name"], + "properties": { + "name": { "const": "publicfolder" } + }, + "not": { + "anyOf": [ + { "required": ["path"] }, + { "required": ["driveAlias"] }, + { "required": ["size"] } + ] + } + } + } + }, "owner": { "type": "object", "required": ["user"],