Skip to content

feat: Add @microsoft.graph.downloadUrl annotation and /content endpoi…#38

Merged
micbar merged 4 commits intomainfrom
feat/download-url
Apr 21, 2026
Merged

feat: Add @microsoft.graph.downloadUrl annotation and /content endpoi…#38
micbar merged 4 commits intomainfrom
feat/download-url

Conversation

@dschmidt
Copy link
Copy Markdown
Contributor

@dschmidt dschmidt commented Apr 17, 2026

Problem

The libre-graph-api spec currently provides no way to create signed links for a driveItem. Clients that need file content and can't send auth headers for the download have to leave Graph and fall back to:

This forces every Graph-consuming client that ever needs to generate a signed url for a file to switch protocol to WebDAV.

Proposal

Mirror the Microsoft Graph API's two-pronged approach:

  1. @microsoft.graph.downloadUrl instance annotation on driveItem, opt-in via $select, for clients that want to obtain the URL without following a redirect (useful for prefetching, scheduling, or inspecting the URL).

  2. GET /v1beta1/drives/{drive-id}/items/{item-id}/content returning 302 Found redirecting to the same pre-authenticated URL, for clients that just want to download and are happy to follow redirects.

Both mechanisms return the same short-lived URL. The annotation is opt-in because computing the URL requires a signing operation; clients shouldn't pay that cost when they only wanted metadata.

We can use the regular dav endpoint as content for downloadUrl and as redirect target for /content.

What's in this PR

Three additions to api/openapi-spec/v1.0.yaml:

  1. Schema: Adds @microsoft.graph.downloadUrl as an optional string property on the driveItem schema, alongside the existing @client.synchronize and @UI.Hidden annotations.

  2. Parameter component: Adds a new driveItemSelect component (following the drivesSelect / permissionsSelect pattern) with an enum listing @microsoft.graph.downloadUrl.

  3. Endpoints:

    • Attaches $select to the existing GetDriveItem operation.
    • Adds a new GetDriveItemContent operation at /v1beta1/drives/{drive-id}/items/{item-id}/content returning 302.
    • Should be added to /children endpoints, but they are missing from spec. Different scope

Design decisions (happy to revisit)

Name: @microsoft.graph.downloadUrl, matching MS Graph exactly. Alternative would be @libre.graph.downloadUrl, which would be more consistent with existing project-specific annotations like @libre.graph.hasTrashedItems and @libre.graph.quickLink. I went with the MS-compatible name. Happy to switch to @libre.graph.downloadUrl if you take a different stance on this.

Opt-in via $select: Mirrors the WebDAV PROPFIND pattern, where oc:downloadURL is only returned when explicitly requested. Signing is cheap but non-zero, and the resulting URL is short-lived garbage if unused.

302 redirect on /content: Matches MS Graph. We can just use the existing endpoint in WebDAV.

Open questions for the implementation side (not in this PR)

These are for the corresponding opencloud implementation, but worth flagging here since they affect the contract:

  1. TTL. WebDAV PROPFIND's downloadURL hardcodes 30 minutes in Reva ([propfind.go:1770](https://github.com/opencloud-eu/reva/blob/main/internal/http/services/owncloud/ocdav/propfind/propfind.go#L1770)). MS Graph documents its equivalent as "a few minutes to 1 hour". The implementation should probably share a constant (or config) across both code paths for predictable behavior.

  2. Public shares. WebDAV's downloadURL has a separate signing path for public-share contexts (PublicShare.Signature).

I'm willing to take care of the implementation.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Libre Graph OpenAPI spec to support generating short-lived, pre-authenticated download URLs for driveItem content—mirroring Microsoft Graph’s @microsoft.graph.downloadUrl annotation and /content redirect pattern.

Changes:

  • Adds optional @microsoft.graph.downloadUrl instance annotation to the driveItem schema (opt-in via $select).
  • Introduces a new driveItemSelect $select parameter component to request the annotation.
  • Adds GET /v1beta1/drives/{drive-id}/items/{item-id}/content returning 302 with a Location header, and wires $select into GetDriveItem.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread api/openapi-spec/v1.0.yaml Outdated
Comment thread api/openapi-spec/v1.0.yaml Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread api/openapi-spec/v1.0.yaml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Member

@butonic butonic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the @microsoft.graph.downloadUrl as we can implement it cleanly. I like this!

@dschmidt
Copy link
Copy Markdown
Contributor Author

Ok, who merges it when?

For some reason I seem to be allowed to merge, but I'm not sure whether one approving review is enough and/or who should click merge.

@micbar micbar merged commit 7fb96d4 into main Apr 21, 2026
@micbar micbar deleted the feat/download-url branch April 21, 2026 19:56
dschmidt added a commit that referenced this pull request Apr 21, 2026
Adds an optional, `$select`-gated instance annotation on `driveItem` that
carries the list of libre.graph actions the caller is allowed to perform on
the item. Mirrors the annotation of the same name on the `/permissions`
endpoint so clients (e.g. a sharing dialog in a search/listing UI) can get
the effective-actions view inline without a separate round-trip per item.

- Adds `@libre.graph.permissions.actions.allowedValues` to the `driveItem`
  schema, marked read-only and documented as only populated when requested.
- Adds a reusable `driveItemSelect` component parameter with a narrow enum,
  following the same pattern as PR #38 (feat/download-url). When both land,
  the enum values merge.
- Wires the new parameter to `GetDriveItem`.

Rationale discussed in #34.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants