diff --git a/services/graph/pkg/service/v0/drives.go b/services/graph/pkg/service/v0/drives.go index 954cd0791d..114f59d3e0 100644 --- a/services/graph/pkg/service/v0/drives.go +++ b/services/graph/pkg/service/v0/drives.go @@ -881,6 +881,19 @@ func (g Graph) cs3StorageSpaceToDrive(ctx context.Context, baseURL *url.URL, spa // DisplayName: , TODO read and cache from users provider }, } + } else if space.GetRoot().GetStorageId() == utils.PublicStorageProviderID { + // a public share mountpoint carries no space owner; the request runs as + // the share creator (publicshares auth), so the context user is who + // shared it, the same source webdav fills oc:owner-display-name from. + if u, ok := revactx.ContextGetUser(ctx); ok && u.GetId().GetOpaqueId() != "" { + id := u.GetId().GetOpaqueId() + drive.Owner = &libregraph.IdentitySet{ + User: &libregraph.Identity{ + Id: &id, + DisplayName: u.GetDisplayName(), + }, + } + } } if space.Mtime != nil { lastModified := cs3TimestampToTime(space.Mtime) diff --git a/tests/acceptance/bootstrap/GraphContext.php b/tests/acceptance/bootstrap/GraphContext.php index 64569d397e..ec5cd33e11 100644 --- a/tests/acceptance/bootstrap/GraphContext.php +++ b/tests/acceptance/bootstrap/GraphContext.php @@ -3758,6 +3758,28 @@ class GraphContext implements Context { $this->featureContext->setResponse($response); } + /** + * The public link drive endpoint rejects the token as a query parameter, + * so it rides in the header here. + * + * @param string|null $password + * + * @return void + */ + #[When('the public gets the drive of the last created public link with password :password using the Graph API')] + public function thePublicGetsTheDriveOfTheLastCreatedPublicLink(?string $password = null): void { + $token = $this->featureContext->shareNgGetLastCreatedLinkShareToken(); + $driveId = $this->publicLinkDriveId($token); + $response = HttpRequestHelper::get( + $this->featureContext->getBaseUrl() . "/graph/v1.0/drives/$driveId", + $this->featureContext->getStepLineRef(), + $password === null ? null : "public", + $this->featureContext->getActualPassword($password), + ["public-token" => $token] + ); + $this->featureContext->setResponse($response); + } + /** * Item anchored colon path: the anchor id is resolved through the public * children listing, so the step stays within the public API. diff --git a/tests/acceptance/features/apiGraph/publicLinkDriveItemListing.feature b/tests/acceptance/features/apiGraph/publicLinkDriveItemListing.feature index 4ee12b868d..db605dbd50 100644 --- a/tests/acceptance/features/apiGraph/publicLinkDriveItemListing.feature +++ b/tests/acceptance/features/apiGraph/publicLinkDriveItemListing.feature @@ -335,3 +335,31 @@ Feature: listing the content of a public link via the Graph API | delete | 400 | | rename | 400 | | list the permissions of | 404 | + + + Scenario: the public sees who shared the link on the drive + When the public gets the 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": ["driveType", "owner"], + "properties": { + "driveType": { "const": "mountpoint" }, + "owner": { + "type": "object", + "required": ["user"], + "properties": { + "user": { + "type": "object", + "required": ["id", "displayName"], + "properties": { + "displayName": { "const": "Alice Hansen" } + } + } + } + } + } + } + """