feat(graph): expose the sharer as the owner of a public link drive

The public share mountpoint carries no space owner, so GET /drives/{pub}
came back without one and the drop page had no name to show. The request
runs as the share creator (publicshares auth), so the context user is who
shared the link; fill drive.Owner from it, id and display name, the same
source webdav fills oc:owner-display-name from. Deliberate disclosure to the
anonymous visitor, matching webdav and MS Graph's sharedDriveItem.owner.
This commit is contained in:
Dominik Schmidt committed 2026-09-08 11:21:02 +02:00
1 parent b392f43662
commit 359dd2f267
3 files changed
+63

No files matched your search

+13
View File
@@ -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)
@@ -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.
@@ -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" }
}
}
}
}
}
}
"""