fix(core): grant plugin media write access on storage-only backends (#1313)#1562
Open
marcusbellamyshaw-cell wants to merge 1 commit into
Open
Conversation
…mdash-cms#1313) ctx.media.upload() and ctx.media.delete() were gated behind getUploadUrl being set, but upload() only needs a storage backend. On the Cloudflare R2 Worker binding (which has no presigned-URL support) this stripped write access from media:write plugins entirely, forcing them to bypass the media API. Gate media write access on (getUploadUrl OR storage). getUploadUrl() now throws a clear "not supported" error when no presign provider is configured, instead of silently removing upload()/delete() from the context. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 83ae344 The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
|
Could not push formatting changes to this fork. The contributor may have "Allow edits by maintainers" disabled. Please run the formatter locally: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Fixes
ctx.media.upload()andctx.media.delete()being silently unavailable to in-process (native) plugins on storage backends that don't support presigned URLs — notably the Cloudflare R2 Worker binding.In
PluginContextFactory.createContext, media write access was gated onthis.getUploadUrlbeing truthy:But
upload()never usesgetUploadUrl— it only needsstorage. The R2 Worker binding intentionally providesstoragebut no presigned-URL support, sogetUploadUrlis never set and a plugin grantedmedia:writeloses all write access despite having a fully functional storage backend. The only workaround today is to bypass the media API and write to the bucket binding directly.This is the same gap the
@emdash-cms/cloudflaresandbox wrapper already papers over by settinggetUploadUrlto a stub that throws — confirming the intent is forupload()to work on the binding.The fix
(this.getUploadUrl || this.storage), so a plugin can write whenever it actually can — via a presign provider or a direct storage backend.getUploadUrlFnoptional increateMediaAccessWithWrite. When no presign provider is configured,media.getUploadUrl()now throws a clear "not supported — use media.upload() instead" error rather than silently strippingupload()/delete()from the context.getUploadUrlis configured.Closes #1313
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change) —packages/coreplugin suites: 706 passedpnpm formathas been runAI-generated code disclosure
Screenshots / test output
New tests in
packages/core/tests/integration/plugins/capabilities.test.ts(describe: "Media Access write gate (#1313)") cover:media:write+ storage (nogetUploadUrl) →upload()/delete()available (the regression)upload()round-trips bytes through the storage backendgetUploadUrl()rejects with a clear error when no presign provider existsgetUploadUrl-configured path still grants writemedia:readstays read-only;media:writewith neither storage nor presign nor read → no media access