@payloadcms/plugin-cloud-storage 3.90.1 → 3.90.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAa,aAAa,EAAE,MAAM,YAAY,CAAA;AAiB1D,eAAO,MAAM,kBAAkB,kBACb,aAAa,sBACZ,MAAM,KAAG,MA8LzB,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAa,aAAa,EAAE,MAAM,YAAY,CAAA;AAiB1D,eAAO,MAAM,kBAAkB,kBACb,aAAa,sBACZ,MAAM,KAAG,MA+LzB,CAAA"}
package/dist/plugin.js CHANGED
@@ -62,6 +62,7 @@ export const cloudStoragePlugin = (pluginOptions)=>(incomingConfig)=>{
62
62
  }
63
63
  const fields = getFields({
64
64
  adapter,
65
+ alwaysInsertFields,
65
66
  collection: existingCollection,
66
67
  disablePayloadAccessControl: options.disablePayloadAccessControl,
67
68
  generateFileURL: options.generateFileURL,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type { AllowList, PluginOptions } from './types.js'\n\nimport { getFields } from './fields/getFields.js'\nimport { getAfterChangeHook } from './hooks/afterChange.js'\nimport { getAfterDeleteHook } from './hooks/afterDelete.js'\nimport { getNormalizeUploadPrefixHook } from './hooks/normalizeUploadPrefix.js'\nimport { getPreserveFileDataHook } from './hooks/preserveFileData.js'\n\n// This plugin extends all targeted collections by offloading uploaded files\n// to cloud storage instead of solely storing files locally.\n\n// It is based on an adapter approach, where adapters can be written for any cloud provider.\n// Adapters are responsible for providing four actions that this plugin will use:\n// 1. handleUpload, 2. handleDelete, 3. generateURL, 4. staticHandler\n\n// Optionally, the adapter can specify any Webpack config overrides if they are necessary.\n\nexport const cloudStoragePlugin =\n (pluginOptions: PluginOptions) =>\n (incomingConfig: Config): Config => {\n const {\n alwaysInsertFields,\n collections: allCollectionOptions,\n enabled,\n useCompositePrefixes,\n } = pluginOptions\n const config = { ...incomingConfig }\n\n // If disabled but alwaysInsertFields is true, only insert fields without full plugin functionality\n if (enabled === false) {\n if (alwaysInsertFields) {\n return {\n ...config,\n collections: (config.collections || []).map((existingCollection) => {\n const options = allCollectionOptions[existingCollection.slug]\n\n if (options) {\n // If adapter is provided, use it to get fields\n const adapter = options.adapter\n ? options.adapter({\n collection: existingCollection,\n prefix: options.prefix,\n })\n : undefined\n\n const fields = getFields({\n adapter,\n alwaysInsertFields: true,\n collection: existingCollection,\n disablePayloadAccessControl: options.disablePayloadAccessControl,\n generateFileURL: options.generateFileURL,\n prefix: options.prefix,\n useCompositePrefixes,\n })\n\n return {\n ...existingCollection,\n fields,\n }\n }\n\n return existingCollection\n }),\n }\n }\n\n return config\n }\n\n const initFunctions: Array<() => Promise<void> | void> = []\n\n return {\n ...config,\n collections: (config.collections || []).map((existingCollection) => {\n const options = allCollectionOptions[existingCollection.slug]\n\n if (options?.adapter) {\n const adapter = options.adapter({\n collection: existingCollection,\n prefix: options.prefix,\n })\n\n if (adapter.onInit) {\n initFunctions.push(adapter.onInit)\n }\n\n const fields = getFields({\n adapter,\n collection: existingCollection,\n disablePayloadAccessControl: options.disablePayloadAccessControl,\n generateFileURL: options.generateFileURL,\n prefix: options.prefix,\n useCompositePrefixes,\n })\n\n const handlers = [\n ...(typeof existingCollection.upload === 'object' &&\n Array.isArray(existingCollection.upload.handlers)\n ? existingCollection.upload.handlers\n : []),\n ]\n\n if (!options.disablePayloadAccessControl) {\n handlers.push(adapter.staticHandler)\n // Else if disablePayloadAccessControl: true and clientUploads is used\n // Build the \"proxied\" handler that responses only when the file was requested by client upload in addDataAndFileToRequest\n } else if (adapter.clientUploads) {\n handlers.push((req, args) => {\n if ('clientUploadContext' in args.params) {\n return adapter.staticHandler(req, args)\n }\n })\n }\n\n const getSkipSafeFetchSetting = (): AllowList | boolean => {\n const isBooleanTrueSkipSafeFetch =\n typeof existingCollection.upload === 'object' &&\n existingCollection.upload.skipSafeFetch === true\n\n const isAllowListSkipSafeFetch =\n typeof existingCollection.upload === 'object' &&\n Array.isArray(existingCollection.upload.skipSafeFetch)\n\n if (isBooleanTrueSkipSafeFetch) {\n return true\n } else if (isAllowListSkipSafeFetch) {\n const existingSkipSafeFetch =\n typeof existingCollection.upload === 'object' &&\n Array.isArray(existingCollection.upload.skipSafeFetch)\n ? existingCollection.upload.skipSafeFetch\n : []\n\n const hasExactLocalhostMatch = existingSkipSafeFetch.some((entry) => {\n const entryKeys = Object.keys(entry)\n return entryKeys.length === 1 && entry.hostname === 'localhost'\n })\n\n const localhostEntry =\n process.env.NODE_ENV !== 'production' && !hasExactLocalhostMatch\n ? [{ hostname: 'localhost' }]\n : []\n\n return [...existingSkipSafeFetch, ...localhostEntry]\n }\n\n if (process.env.NODE_ENV !== 'production') {\n return [{ hostname: 'localhost' }]\n }\n\n return false\n }\n\n return {\n ...existingCollection,\n fields,\n hooks: {\n ...(existingCollection.hooks || {}),\n afterChange: [\n ...(existingCollection.hooks?.afterChange || []),\n getAfterChangeHook({\n adapter,\n collection: existingCollection,\n collectionPrefix: options.prefix,\n useCompositePrefixes,\n }),\n ],\n afterDelete: [\n ...(existingCollection.hooks?.afterDelete || []),\n getAfterDeleteHook({\n adapter,\n collection: existingCollection,\n collectionPrefix: options.prefix,\n useCompositePrefixes,\n }),\n ],\n beforeChange: [\n ...(existingCollection.hooks?.beforeChange || []),\n getNormalizeUploadPrefixHook({\n collectionPrefix: options.prefix,\n useCompositePrefixes,\n }),\n getPreserveFileDataHook(),\n ],\n },\n upload: {\n ...(typeof existingCollection.upload === 'object' ? existingCollection.upload : {}),\n adapter: adapter.name,\n disableLocalStorage:\n typeof options.disableLocalStorage === 'boolean'\n ? options.disableLocalStorage\n : true,\n handlers,\n requiresClientUploadReceipt: adapter.requiresClientUploadReceipt,\n skipSafeFetch: getSkipSafeFetchSetting(),\n },\n }\n }\n\n return existingCollection\n }),\n onInit: async (payload) => {\n // Await each init so a provisioning failure fails Payload startup\n // instead of becoming an unhandled rejection.\n await Promise.all(initFunctions.map((fn) => fn()))\n if (config.onInit) {\n await config.onInit(payload)\n }\n },\n }\n }\n"],"names":["getFields","getAfterChangeHook","getAfterDeleteHook","getNormalizeUploadPrefixHook","getPreserveFileDataHook","cloudStoragePlugin","pluginOptions","incomingConfig","alwaysInsertFields","collections","allCollectionOptions","enabled","useCompositePrefixes","config","map","existingCollection","options","slug","adapter","collection","prefix","undefined","fields","disablePayloadAccessControl","generateFileURL","initFunctions","onInit","push","handlers","upload","Array","isArray","staticHandler","clientUploads","req","args","params","getSkipSafeFetchSetting","isBooleanTrueSkipSafeFetch","skipSafeFetch","isAllowListSkipSafeFetch","existingSkipSafeFetch","hasExactLocalhostMatch","some","entry","entryKeys","Object","keys","length","hostname","localhostEntry","process","env","NODE_ENV","hooks","afterChange","collectionPrefix","afterDelete","beforeChange","name","disableLocalStorage","requiresClientUploadReceipt","payload","Promise","all","fn"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type { AllowList, PluginOptions } from './types.js'\n\nimport { getFields } from './fields/getFields.js'\nimport { getAfterChangeHook } from './hooks/afterChange.js'\nimport { getAfterDeleteHook } from './hooks/afterDelete.js'\nimport { getNormalizeUploadPrefixHook } from './hooks/normalizeUploadPrefix.js'\nimport { getPreserveFileDataHook } from './hooks/preserveFileData.js'\n\n// This plugin extends all targeted collections by offloading uploaded files\n// to cloud storage instead of solely storing files locally.\n\n// It is based on an adapter approach, where adapters can be written for any cloud provider.\n// Adapters are responsible for providing four actions that this plugin will use:\n// 1. handleUpload, 2. handleDelete, 3. generateURL, 4. staticHandler\n\n// Optionally, the adapter can specify any Webpack config overrides if they are necessary.\n\nexport const cloudStoragePlugin =\n (pluginOptions: PluginOptions) =>\n (incomingConfig: Config): Config => {\n const {\n alwaysInsertFields,\n collections: allCollectionOptions,\n enabled,\n useCompositePrefixes,\n } = pluginOptions\n const config = { ...incomingConfig }\n\n // If disabled but alwaysInsertFields is true, only insert fields without full plugin functionality\n if (enabled === false) {\n if (alwaysInsertFields) {\n return {\n ...config,\n collections: (config.collections || []).map((existingCollection) => {\n const options = allCollectionOptions[existingCollection.slug]\n\n if (options) {\n // If adapter is provided, use it to get fields\n const adapter = options.adapter\n ? options.adapter({\n collection: existingCollection,\n prefix: options.prefix,\n })\n : undefined\n\n const fields = getFields({\n adapter,\n alwaysInsertFields: true,\n collection: existingCollection,\n disablePayloadAccessControl: options.disablePayloadAccessControl,\n generateFileURL: options.generateFileURL,\n prefix: options.prefix,\n useCompositePrefixes,\n })\n\n return {\n ...existingCollection,\n fields,\n }\n }\n\n return existingCollection\n }),\n }\n }\n\n return config\n }\n\n const initFunctions: Array<() => Promise<void> | void> = []\n\n return {\n ...config,\n collections: (config.collections || []).map((existingCollection) => {\n const options = allCollectionOptions[existingCollection.slug]\n\n if (options?.adapter) {\n const adapter = options.adapter({\n collection: existingCollection,\n prefix: options.prefix,\n })\n\n if (adapter.onInit) {\n initFunctions.push(adapter.onInit)\n }\n\n const fields = getFields({\n adapter,\n alwaysInsertFields,\n collection: existingCollection,\n disablePayloadAccessControl: options.disablePayloadAccessControl,\n generateFileURL: options.generateFileURL,\n prefix: options.prefix,\n useCompositePrefixes,\n })\n\n const handlers = [\n ...(typeof existingCollection.upload === 'object' &&\n Array.isArray(existingCollection.upload.handlers)\n ? existingCollection.upload.handlers\n : []),\n ]\n\n if (!options.disablePayloadAccessControl) {\n handlers.push(adapter.staticHandler)\n // Else if disablePayloadAccessControl: true and clientUploads is used\n // Build the \"proxied\" handler that responses only when the file was requested by client upload in addDataAndFileToRequest\n } else if (adapter.clientUploads) {\n handlers.push((req, args) => {\n if ('clientUploadContext' in args.params) {\n return adapter.staticHandler(req, args)\n }\n })\n }\n\n const getSkipSafeFetchSetting = (): AllowList | boolean => {\n const isBooleanTrueSkipSafeFetch =\n typeof existingCollection.upload === 'object' &&\n existingCollection.upload.skipSafeFetch === true\n\n const isAllowListSkipSafeFetch =\n typeof existingCollection.upload === 'object' &&\n Array.isArray(existingCollection.upload.skipSafeFetch)\n\n if (isBooleanTrueSkipSafeFetch) {\n return true\n } else if (isAllowListSkipSafeFetch) {\n const existingSkipSafeFetch =\n typeof existingCollection.upload === 'object' &&\n Array.isArray(existingCollection.upload.skipSafeFetch)\n ? existingCollection.upload.skipSafeFetch\n : []\n\n const hasExactLocalhostMatch = existingSkipSafeFetch.some((entry) => {\n const entryKeys = Object.keys(entry)\n return entryKeys.length === 1 && entry.hostname === 'localhost'\n })\n\n const localhostEntry =\n process.env.NODE_ENV !== 'production' && !hasExactLocalhostMatch\n ? [{ hostname: 'localhost' }]\n : []\n\n return [...existingSkipSafeFetch, ...localhostEntry]\n }\n\n if (process.env.NODE_ENV !== 'production') {\n return [{ hostname: 'localhost' }]\n }\n\n return false\n }\n\n return {\n ...existingCollection,\n fields,\n hooks: {\n ...(existingCollection.hooks || {}),\n afterChange: [\n ...(existingCollection.hooks?.afterChange || []),\n getAfterChangeHook({\n adapter,\n collection: existingCollection,\n collectionPrefix: options.prefix,\n useCompositePrefixes,\n }),\n ],\n afterDelete: [\n ...(existingCollection.hooks?.afterDelete || []),\n getAfterDeleteHook({\n adapter,\n collection: existingCollection,\n collectionPrefix: options.prefix,\n useCompositePrefixes,\n }),\n ],\n beforeChange: [\n ...(existingCollection.hooks?.beforeChange || []),\n getNormalizeUploadPrefixHook({\n collectionPrefix: options.prefix,\n useCompositePrefixes,\n }),\n getPreserveFileDataHook(),\n ],\n },\n upload: {\n ...(typeof existingCollection.upload === 'object' ? existingCollection.upload : {}),\n adapter: adapter.name,\n disableLocalStorage:\n typeof options.disableLocalStorage === 'boolean'\n ? options.disableLocalStorage\n : true,\n handlers,\n requiresClientUploadReceipt: adapter.requiresClientUploadReceipt,\n skipSafeFetch: getSkipSafeFetchSetting(),\n },\n }\n }\n\n return existingCollection\n }),\n onInit: async (payload) => {\n // Await each init so a provisioning failure fails Payload startup\n // instead of becoming an unhandled rejection.\n await Promise.all(initFunctions.map((fn) => fn()))\n if (config.onInit) {\n await config.onInit(payload)\n }\n },\n }\n }\n"],"names":["getFields","getAfterChangeHook","getAfterDeleteHook","getNormalizeUploadPrefixHook","getPreserveFileDataHook","cloudStoragePlugin","pluginOptions","incomingConfig","alwaysInsertFields","collections","allCollectionOptions","enabled","useCompositePrefixes","config","map","existingCollection","options","slug","adapter","collection","prefix","undefined","fields","disablePayloadAccessControl","generateFileURL","initFunctions","onInit","push","handlers","upload","Array","isArray","staticHandler","clientUploads","req","args","params","getSkipSafeFetchSetting","isBooleanTrueSkipSafeFetch","skipSafeFetch","isAllowListSkipSafeFetch","existingSkipSafeFetch","hasExactLocalhostMatch","some","entry","entryKeys","Object","keys","length","hostname","localhostEntry","process","env","NODE_ENV","hooks","afterChange","collectionPrefix","afterDelete","beforeChange","name","disableLocalStorage","requiresClientUploadReceipt","payload","Promise","all","fn"],"mappings":"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"}
@@ -161,6 +161,26 @@ describe('cloudStoragePlugin', ()=>{
161
161
  }
162
162
  expect(data.prefix).toBe('tenant/acme');
163
163
  });
164
+ it('should insert the prefix field with alwaysInsertFields when the plugin is enabled', ()=>{
165
+ const config = cloudStoragePlugin({
166
+ alwaysInsertFields: true,
167
+ collections: {
168
+ media: {
169
+ adapter
170
+ }
171
+ }
172
+ })({
173
+ collections: [
174
+ {
175
+ fields: [],
176
+ slug: 'media',
177
+ upload: true
178
+ }
179
+ ]
180
+ });
181
+ const fields = config.collections?.[0]?.fields || [];
182
+ expect(fields.some((field)=>'name' in field && field.name === 'prefix')).toBe(true);
183
+ });
164
184
  });
165
185
 
166
186
  //# sourceMappingURL=plugin.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin.spec.ts"],"sourcesContent":["import type { AddressInfo } from 'node:net'\nimport type { Config, PayloadRequest, UploadConfig } from 'payload'\n\nimport { createServer } from 'node:http'\nimport { getExternalFile } from 'payload/internal'\nimport { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest'\n\nimport { cloudStoragePlugin } from './plugin.js'\n\nconst collectionSlug = 'media'\n\ndescribe('cloudStoragePlugin external file fetching', () => {\n const server = createServer((_req, res) => {\n res.writeHead(200, {\n 'Content-Length': '12',\n 'Content-Type': 'text/plain',\n })\n res.end('stored file\\n')\n })\n\n let port: number\n\n beforeAll(async () => {\n await new Promise<void>((resolve) => server.listen(0, resolve))\n port = (server.address() as AddressInfo).port\n })\n\n afterEach(() => {\n vi.unstubAllEnvs()\n })\n\n afterAll(async () => {\n await new Promise<void>((resolve, reject) => {\n server.close((error) => (error ? reject(error) : resolve()))\n })\n })\n\n it('should filter private URLs when Payload file access control is disabled', async () => {\n vi.stubEnv('NODE_ENV', 'production')\n const uploadConfig = buildUploadConfig()\n\n await expect(\n fetchExternalFile({ uploadConfig, url: `http://127.0.0.1:${port}/file.txt` }),\n ).rejects.toThrow('Blocked unsafe attempt to 127.0.0.1')\n })\n\n it('should allow private URLs when skipSafeFetch is explicitly true', async () => {\n vi.stubEnv('NODE_ENV', 'production')\n const uploadConfig = buildUploadConfig(true)\n\n const file = await fetchExternalFile({\n uploadConfig,\n url: `http://127.0.0.1:${port}/file.txt`,\n })\n\n expect(file.data.toString()).toBe('stored file\\n')\n })\n\n it('should allow private URLs that match an explicit skipSafeFetch allowlist', async () => {\n vi.stubEnv('NODE_ENV', 'production')\n const uploadConfig = buildUploadConfig([\n {\n hostname: '127.0.0.1',\n port: String(port),\n protocol: 'http',\n },\n ])\n\n const file = await fetchExternalFile({\n uploadConfig,\n url: `http://127.0.0.1:${port}/file.txt`,\n })\n\n expect(file.data.toString()).toBe('stored file\\n')\n })\n\n it('should allow localhost URLs outside production', async () => {\n vi.stubEnv('NODE_ENV', 'development')\n const uploadConfig = buildUploadConfig()\n\n const file = await fetchExternalFile({\n uploadConfig,\n url: `http://localhost:${port}/file.txt`,\n })\n\n expect(file.data.toString()).toBe('stored file\\n')\n })\n})\n\nfunction buildUploadConfig(skipSafeFetch?: UploadConfig['skipSafeFetch']): UploadConfig {\n const config = cloudStoragePlugin({\n collections: {\n [collectionSlug]: {\n adapter: () => ({\n handleDelete: async () => undefined,\n handleUpload: async () => undefined,\n name: 'test-adapter',\n staticHandler: async () => new Response(null, { status: 404 }),\n }),\n disablePayloadAccessControl: true,\n },\n },\n })({\n collections: [\n {\n fields: [],\n slug: collectionSlug,\n upload: typeof skipSafeFetch === 'undefined' ? true : { skipSafeFetch },\n },\n ],\n } as Config)\n\n const uploadConfig = config.collections?.[0]?.upload\n if (!uploadConfig || typeof uploadConfig !== 'object') {\n throw new Error('Expected an upload configuration')\n }\n\n return uploadConfig\n}\n\nasync function fetchExternalFile({\n uploadConfig,\n url,\n}: {\n uploadConfig: UploadConfig\n url: string\n}) {\n return getExternalFile({\n data: {\n filename: 'file.txt',\n url,\n },\n req: {\n headers: new Headers(),\n payload: {\n config: {\n cookiePrefix: 'payload',\n },\n },\n } as PayloadRequest,\n uploadConfig,\n })\n}\n\nconst adapter = () => ({\n handleDelete: () => undefined,\n handleUpload: () => undefined,\n name: 'test-adapter',\n staticHandler: () => new Response(),\n})\n\ndescribe('cloudStoragePlugin', () => {\n it('should normalize a stored prefix during a server-mediated upload', async () => {\n const config = cloudStoragePlugin({\n collections: {\n media: { adapter },\n },\n } as any)({\n collections: [{ fields: [], slug: 'media', upload: true }],\n } as any)\n const hooks = config.collections?.[0]?.hooks?.beforeChange || []\n const req = {\n context: {},\n file: { mimetype: 'image/png', name: 'photo.png', size: 42 },\n }\n let data = { filename: 'photo.png', prefix: '/tenant/../acme' }\n\n for (const hook of hooks) {\n const result = await hook({ data, operation: 'create', req } as any)\n data = result || data\n }\n\n expect(data.prefix).toBe('tenant/acme')\n })\n})\n"],"names":["createServer","getExternalFile","afterAll","afterEach","beforeAll","describe","expect","it","vi","cloudStoragePlugin","collectionSlug","server","_req","res","writeHead","end","port","Promise","resolve","listen","address","unstubAllEnvs","reject","close","error","stubEnv","uploadConfig","buildUploadConfig","fetchExternalFile","url","rejects","toThrow","file","data","toString","toBe","hostname","String","protocol","skipSafeFetch","config","collections","adapter","handleDelete","undefined","handleUpload","name","staticHandler","Response","status","disablePayloadAccessControl","fields","slug","upload","Error","filename","req","headers","Headers","payload","cookiePrefix","media","hooks","beforeChange","context","mimetype","size","prefix","hook","result","operation"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/plugin.spec.ts"],"sourcesContent":["import type { AddressInfo } from 'node:net'\nimport type { Config, PayloadRequest, UploadConfig } from 'payload'\n\nimport { createServer } from 'node:http'\nimport { getExternalFile } from 'payload/internal'\nimport { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest'\n\nimport { cloudStoragePlugin } from './plugin.js'\n\nconst collectionSlug = 'media'\n\ndescribe('cloudStoragePlugin external file fetching', () => {\n const server = createServer((_req, res) => {\n res.writeHead(200, {\n 'Content-Length': '12',\n 'Content-Type': 'text/plain',\n })\n res.end('stored file\\n')\n })\n\n let port: number\n\n beforeAll(async () => {\n await new Promise<void>((resolve) => server.listen(0, resolve))\n port = (server.address() as AddressInfo).port\n })\n\n afterEach(() => {\n vi.unstubAllEnvs()\n })\n\n afterAll(async () => {\n await new Promise<void>((resolve, reject) => {\n server.close((error) => (error ? reject(error) : resolve()))\n })\n })\n\n it('should filter private URLs when Payload file access control is disabled', async () => {\n vi.stubEnv('NODE_ENV', 'production')\n const uploadConfig = buildUploadConfig()\n\n await expect(\n fetchExternalFile({ uploadConfig, url: `http://127.0.0.1:${port}/file.txt` }),\n ).rejects.toThrow('Blocked unsafe attempt to 127.0.0.1')\n })\n\n it('should allow private URLs when skipSafeFetch is explicitly true', async () => {\n vi.stubEnv('NODE_ENV', 'production')\n const uploadConfig = buildUploadConfig(true)\n\n const file = await fetchExternalFile({\n uploadConfig,\n url: `http://127.0.0.1:${port}/file.txt`,\n })\n\n expect(file.data.toString()).toBe('stored file\\n')\n })\n\n it('should allow private URLs that match an explicit skipSafeFetch allowlist', async () => {\n vi.stubEnv('NODE_ENV', 'production')\n const uploadConfig = buildUploadConfig([\n {\n hostname: '127.0.0.1',\n port: String(port),\n protocol: 'http',\n },\n ])\n\n const file = await fetchExternalFile({\n uploadConfig,\n url: `http://127.0.0.1:${port}/file.txt`,\n })\n\n expect(file.data.toString()).toBe('stored file\\n')\n })\n\n it('should allow localhost URLs outside production', async () => {\n vi.stubEnv('NODE_ENV', 'development')\n const uploadConfig = buildUploadConfig()\n\n const file = await fetchExternalFile({\n uploadConfig,\n url: `http://localhost:${port}/file.txt`,\n })\n\n expect(file.data.toString()).toBe('stored file\\n')\n })\n})\n\nfunction buildUploadConfig(skipSafeFetch?: UploadConfig['skipSafeFetch']): UploadConfig {\n const config = cloudStoragePlugin({\n collections: {\n [collectionSlug]: {\n adapter: () => ({\n handleDelete: async () => undefined,\n handleUpload: async () => undefined,\n name: 'test-adapter',\n staticHandler: async () => new Response(null, { status: 404 }),\n }),\n disablePayloadAccessControl: true,\n },\n },\n })({\n collections: [\n {\n fields: [],\n slug: collectionSlug,\n upload: typeof skipSafeFetch === 'undefined' ? true : { skipSafeFetch },\n },\n ],\n } as Config)\n\n const uploadConfig = config.collections?.[0]?.upload\n if (!uploadConfig || typeof uploadConfig !== 'object') {\n throw new Error('Expected an upload configuration')\n }\n\n return uploadConfig\n}\n\nasync function fetchExternalFile({\n uploadConfig,\n url,\n}: {\n uploadConfig: UploadConfig\n url: string\n}) {\n return getExternalFile({\n data: {\n filename: 'file.txt',\n url,\n },\n req: {\n headers: new Headers(),\n payload: {\n config: {\n cookiePrefix: 'payload',\n },\n },\n } as PayloadRequest,\n uploadConfig,\n })\n}\n\nconst adapter = () => ({\n handleDelete: () => undefined,\n handleUpload: () => undefined,\n name: 'test-adapter',\n staticHandler: () => new Response(),\n})\n\ndescribe('cloudStoragePlugin', () => {\n it('should normalize a stored prefix during a server-mediated upload', async () => {\n const config = cloudStoragePlugin({\n collections: {\n media: { adapter },\n },\n } as any)({\n collections: [{ fields: [], slug: 'media', upload: true }],\n } as any)\n const hooks = config.collections?.[0]?.hooks?.beforeChange || []\n const req = {\n context: {},\n file: { mimetype: 'image/png', name: 'photo.png', size: 42 },\n }\n let data = { filename: 'photo.png', prefix: '/tenant/../acme' }\n\n for (const hook of hooks) {\n const result = await hook({ data, operation: 'create', req } as any)\n data = result || data\n }\n\n expect(data.prefix).toBe('tenant/acme')\n })\n\n it('should insert the prefix field with alwaysInsertFields when the plugin is enabled', () => {\n const config = cloudStoragePlugin({\n alwaysInsertFields: true,\n collections: {\n media: { adapter },\n },\n } as any)({\n collections: [{ fields: [], slug: 'media', upload: true }],\n } as any)\n const fields = config.collections?.[0]?.fields || []\n\n expect(fields.some((field) => 'name' in field && field.name === 'prefix')).toBe(true)\n })\n})\n"],"names":["createServer","getExternalFile","afterAll","afterEach","beforeAll","describe","expect","it","vi","cloudStoragePlugin","collectionSlug","server","_req","res","writeHead","end","port","Promise","resolve","listen","address","unstubAllEnvs","reject","close","error","stubEnv","uploadConfig","buildUploadConfig","fetchExternalFile","url","rejects","toThrow","file","data","toString","toBe","hostname","String","protocol","skipSafeFetch","config","collections","adapter","handleDelete","undefined","handleUpload","name","staticHandler","Response","status","disablePayloadAccessControl","fields","slug","upload","Error","filename","req","headers","Headers","payload","cookiePrefix","media","hooks","beforeChange","context","mimetype","size","prefix","hook","result","operation","alwaysInsertFields","some","field"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"initClientUploads.d.ts","sourceRoot":"","sources":["../../src/utilities/initClientUploads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAErD,eAAO,MAAM,iBAAiB,GAAI,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,+GAQ5E;IACD,sCAAsC;IACtC,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,gDAAgD;IAChD,uBAAuB,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,KAAK,UAAU,CAAA;IACvD,aAAa,EAAE,cAAc,CAAA;IAC7B,iBAAiB,EAAE,MAAM,CAAA;CAC1B,SA8EA,CAAA"}
1
+ {"version":3,"file":"initClientUploads.d.ts","sourceRoot":"","sources":["../../src/utilities/initClientUploads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAErD,eAAO,MAAM,iBAAiB,GAAI,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,+GAQ5E;IACD,sCAAsC;IACtC,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,gDAAgD;IAChD,uBAAuB,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,KAAK,UAAU,CAAA;IACvD,aAAa,EAAE,cAAc,CAAA;IAC7B,iBAAiB,EAAE,MAAM,CAAA;CAC1B,SAkFA,CAAA"}
@@ -35,6 +35,9 @@ export const initClientUploads = ({ clientHandler, collections, config, enabled,
35
35
  type: 'function',
36
36
  path: clientHandler
37
37
  };
38
+ if (!enabled) {
39
+ return;
40
+ }
38
41
  if (!config.admin.components) {
39
42
  config.admin.components = {};
40
43
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/initClientUploads.ts"],"sourcesContent":["import type { Config, PayloadHandler } from 'payload'\n\nexport const initClientUploads = <ExtraProps extends Record<string, unknown>, T>({\n clientHandler,\n collections,\n config,\n enabled,\n extraClientHandlerProps,\n serverHandler,\n serverHandlerPath,\n}: {\n /** Path to clientHandler component */\n clientHandler: string\n collections: Record<string, T>\n config: Config\n enabled: boolean\n /** extra props to pass to the client handler */\n extraClientHandlerProps?: (collection: T) => ExtraProps\n serverHandler: PayloadHandler\n serverHandlerPath: string\n}) => {\n if (enabled) {\n if (!config.endpoints) {\n config.endpoints = []\n }\n\n /**\n * Tracks how many times the same handler was already applied.\n * This allows to apply the same plugin multiple times, for example\n * to use different buckets for different collections.\n */\n let handlerCount = 0\n\n for (const endpoint of config.endpoints) {\n // We want to match on 'path', 'path-1', 'path-2', etc.\n if (endpoint.path?.startsWith(serverHandlerPath)) {\n handlerCount++\n }\n }\n\n if (handlerCount) {\n serverHandlerPath = `${serverHandlerPath}-${handlerCount}`\n }\n\n config.endpoints.push({\n handler: serverHandler,\n method: 'post',\n path: serverHandlerPath,\n })\n }\n\n if (!config.admin) {\n config.admin = {}\n }\n\n if (!config.admin.dependencies) {\n config.admin.dependencies = {}\n }\n // Ensure client handler is always part of the import map, to avoid\n // import map discrepancies between dev and prod\n config.admin.dependencies[clientHandler] = {\n type: 'function',\n path: clientHandler,\n }\n\n if (!config.admin.components) {\n config.admin.components = {}\n }\n\n if (!config.admin.components.providers) {\n config.admin.components.providers = []\n }\n\n for (const collectionSlug in collections) {\n const collection = collections[collectionSlug]\n\n let collectionPrefix: string | undefined\n\n if (\n collection &&\n typeof collection === 'object' &&\n 'prefix' in collection &&\n typeof collection.prefix === 'string'\n ) {\n collectionPrefix = collection.prefix\n }\n\n config.admin.components.providers.push({\n clientProps: {\n collectionSlug,\n enabled,\n extra: extraClientHandlerProps ? extraClientHandlerProps(collection!) : undefined,\n prefix: collectionPrefix,\n serverHandlerPath,\n },\n path: clientHandler,\n })\n }\n}\n"],"names":["initClientUploads","clientHandler","collections","config","enabled","extraClientHandlerProps","serverHandler","serverHandlerPath","endpoints","handlerCount","endpoint","path","startsWith","push","handler","method","admin","dependencies","type","components","providers","collectionSlug","collection","collectionPrefix","prefix","clientProps","extra","undefined"],"mappings":"AAEA,OAAO,MAAMA,oBAAoB,CAAgD,EAC/EC,aAAa,EACbC,WAAW,EACXC,MAAM,EACNC,OAAO,EACPC,uBAAuB,EACvBC,aAAa,EACbC,iBAAiB,EAWlB;IACC,IAAIH,SAAS;QACX,IAAI,CAACD,OAAOK,SAAS,EAAE;YACrBL,OAAOK,SAAS,GAAG,EAAE;QACvB;QAEA;;;;KAIC,GACD,IAAIC,eAAe;QAEnB,KAAK,MAAMC,YAAYP,OAAOK,SAAS,CAAE;YACvC,uDAAuD;YACvD,IAAIE,SAASC,IAAI,EAAEC,WAAWL,oBAAoB;gBAChDE;YACF;QACF;QAEA,IAAIA,cAAc;YAChBF,oBAAoB,GAAGA,kBAAkB,CAAC,EAAEE,cAAc;QAC5D;QAEAN,OAAOK,SAAS,CAACK,IAAI,CAAC;YACpBC,SAASR;YACTS,QAAQ;YACRJ,MAAMJ;QACR;IACF;IAEA,IAAI,CAACJ,OAAOa,KAAK,EAAE;QACjBb,OAAOa,KAAK,GAAG,CAAC;IAClB;IAEA,IAAI,CAACb,OAAOa,KAAK,CAACC,YAAY,EAAE;QAC9Bd,OAAOa,KAAK,CAACC,YAAY,GAAG,CAAC;IAC/B;IACA,mEAAmE;IACnE,gDAAgD;IAChDd,OAAOa,KAAK,CAACC,YAAY,CAAChB,cAAc,GAAG;QACzCiB,MAAM;QACNP,MAAMV;IACR;IAEA,IAAI,CAACE,OAAOa,KAAK,CAACG,UAAU,EAAE;QAC5BhB,OAAOa,KAAK,CAACG,UAAU,GAAG,CAAC;IAC7B;IAEA,IAAI,CAAChB,OAAOa,KAAK,CAACG,UAAU,CAACC,SAAS,EAAE;QACtCjB,OAAOa,KAAK,CAACG,UAAU,CAACC,SAAS,GAAG,EAAE;IACxC;IAEA,IAAK,MAAMC,kBAAkBnB,YAAa;QACxC,MAAMoB,aAAapB,WAAW,CAACmB,eAAe;QAE9C,IAAIE;QAEJ,IACED,cACA,OAAOA,eAAe,YACtB,YAAYA,cACZ,OAAOA,WAAWE,MAAM,KAAK,UAC7B;YACAD,mBAAmBD,WAAWE,MAAM;QACtC;QAEArB,OAAOa,KAAK,CAACG,UAAU,CAACC,SAAS,CAACP,IAAI,CAAC;YACrCY,aAAa;gBACXJ;gBACAjB;gBACAsB,OAAOrB,0BAA0BA,wBAAwBiB,cAAeK;gBACxEH,QAAQD;gBACRhB;YACF;YACAI,MAAMV;QACR;IACF;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/utilities/initClientUploads.ts"],"sourcesContent":["import type { Config, PayloadHandler } from 'payload'\n\nexport const initClientUploads = <ExtraProps extends Record<string, unknown>, T>({\n clientHandler,\n collections,\n config,\n enabled,\n extraClientHandlerProps,\n serverHandler,\n serverHandlerPath,\n}: {\n /** Path to clientHandler component */\n clientHandler: string\n collections: Record<string, T>\n config: Config\n enabled: boolean\n /** extra props to pass to the client handler */\n extraClientHandlerProps?: (collection: T) => ExtraProps\n serverHandler: PayloadHandler\n serverHandlerPath: string\n}) => {\n if (enabled) {\n if (!config.endpoints) {\n config.endpoints = []\n }\n\n /**\n * Tracks how many times the same handler was already applied.\n * This allows to apply the same plugin multiple times, for example\n * to use different buckets for different collections.\n */\n let handlerCount = 0\n\n for (const endpoint of config.endpoints) {\n // We want to match on 'path', 'path-1', 'path-2', etc.\n if (endpoint.path?.startsWith(serverHandlerPath)) {\n handlerCount++\n }\n }\n\n if (handlerCount) {\n serverHandlerPath = `${serverHandlerPath}-${handlerCount}`\n }\n\n config.endpoints.push({\n handler: serverHandler,\n method: 'post',\n path: serverHandlerPath,\n })\n }\n\n if (!config.admin) {\n config.admin = {}\n }\n\n if (!config.admin.dependencies) {\n config.admin.dependencies = {}\n }\n // Ensure client handler is always part of the import map, to avoid\n // import map discrepancies between dev and prod\n config.admin.dependencies[clientHandler] = {\n type: 'function',\n path: clientHandler,\n }\n\n if (!enabled) {\n return\n }\n\n if (!config.admin.components) {\n config.admin.components = {}\n }\n\n if (!config.admin.components.providers) {\n config.admin.components.providers = []\n }\n\n for (const collectionSlug in collections) {\n const collection = collections[collectionSlug]\n\n let collectionPrefix: string | undefined\n\n if (\n collection &&\n typeof collection === 'object' &&\n 'prefix' in collection &&\n typeof collection.prefix === 'string'\n ) {\n collectionPrefix = collection.prefix\n }\n\n config.admin.components.providers.push({\n clientProps: {\n collectionSlug,\n enabled,\n extra: extraClientHandlerProps ? extraClientHandlerProps(collection!) : undefined,\n prefix: collectionPrefix,\n serverHandlerPath,\n },\n path: clientHandler,\n })\n }\n}\n"],"names":["initClientUploads","clientHandler","collections","config","enabled","extraClientHandlerProps","serverHandler","serverHandlerPath","endpoints","handlerCount","endpoint","path","startsWith","push","handler","method","admin","dependencies","type","components","providers","collectionSlug","collection","collectionPrefix","prefix","clientProps","extra","undefined"],"mappings":"AAEA,OAAO,MAAMA,oBAAoB,CAAgD,EAC/EC,aAAa,EACbC,WAAW,EACXC,MAAM,EACNC,OAAO,EACPC,uBAAuB,EACvBC,aAAa,EACbC,iBAAiB,EAWlB;IACC,IAAIH,SAAS;QACX,IAAI,CAACD,OAAOK,SAAS,EAAE;YACrBL,OAAOK,SAAS,GAAG,EAAE;QACvB;QAEA;;;;KAIC,GACD,IAAIC,eAAe;QAEnB,KAAK,MAAMC,YAAYP,OAAOK,SAAS,CAAE;YACvC,uDAAuD;YACvD,IAAIE,SAASC,IAAI,EAAEC,WAAWL,oBAAoB;gBAChDE;YACF;QACF;QAEA,IAAIA,cAAc;YAChBF,oBAAoB,GAAGA,kBAAkB,CAAC,EAAEE,cAAc;QAC5D;QAEAN,OAAOK,SAAS,CAACK,IAAI,CAAC;YACpBC,SAASR;YACTS,QAAQ;YACRJ,MAAMJ;QACR;IACF;IAEA,IAAI,CAACJ,OAAOa,KAAK,EAAE;QACjBb,OAAOa,KAAK,GAAG,CAAC;IAClB;IAEA,IAAI,CAACb,OAAOa,KAAK,CAACC,YAAY,EAAE;QAC9Bd,OAAOa,KAAK,CAACC,YAAY,GAAG,CAAC;IAC/B;IACA,mEAAmE;IACnE,gDAAgD;IAChDd,OAAOa,KAAK,CAACC,YAAY,CAAChB,cAAc,GAAG;QACzCiB,MAAM;QACNP,MAAMV;IACR;IAEA,IAAI,CAACG,SAAS;QACZ;IACF;IAEA,IAAI,CAACD,OAAOa,KAAK,CAACG,UAAU,EAAE;QAC5BhB,OAAOa,KAAK,CAACG,UAAU,GAAG,CAAC;IAC7B;IAEA,IAAI,CAAChB,OAAOa,KAAK,CAACG,UAAU,CAACC,SAAS,EAAE;QACtCjB,OAAOa,KAAK,CAACG,UAAU,CAACC,SAAS,GAAG,EAAE;IACxC;IAEA,IAAK,MAAMC,kBAAkBnB,YAAa;QACxC,MAAMoB,aAAapB,WAAW,CAACmB,eAAe;QAE9C,IAAIE;QAEJ,IACED,cACA,OAAOA,eAAe,YACtB,YAAYA,cACZ,OAAOA,WAAWE,MAAM,KAAK,UAC7B;YACAD,mBAAmBD,WAAWE,MAAM;QACtC;QAEArB,OAAOa,KAAK,CAACG,UAAU,CAACC,SAAS,CAACP,IAAI,CAAC;YACrCY,aAAa;gBACXJ;gBACAjB;gBACAsB,OAAOrB,0BAA0BA,wBAAwBiB,cAAeK;gBACxEH,QAAQD;gBACRhB;YACF;YACAI,MAAMV;QACR;IACF;AACF,EAAC"}
@@ -0,0 +1,31 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { initClientUploads } from './initClientUploads.js';
3
+ describe('initClientUploads', ()=>{
4
+ it('does not add Admin providers when client uploads are disabled', ()=>{
5
+ const clientHandler = '@payloadcms/storage-s3/client#S3ClientUploadHandler';
6
+ const collections = Object.fromEntries(Array.from({
7
+ length: 50
8
+ }, (_, index)=>[
9
+ `upload-${index}`,
10
+ true
11
+ ]));
12
+ const config = {};
13
+ initClientUploads({
14
+ clientHandler,
15
+ collections,
16
+ config,
17
+ enabled: false,
18
+ serverHandler: vi.fn(),
19
+ serverHandlerPath: '/storage-s3-generate-signed-url'
20
+ });
21
+ expect(config.admin?.dependencies).toEqual({
22
+ [clientHandler]: {
23
+ path: clientHandler,
24
+ type: 'function'
25
+ }
26
+ });
27
+ expect(config.admin?.components?.providers).toBeUndefined();
28
+ });
29
+ });
30
+
31
+ //# sourceMappingURL=initClientUploads.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/initClientUploads.spec.ts"],"sourcesContent":["import type { Config, PayloadHandler } from 'payload'\n\nimport { describe, expect, it, vi } from 'vitest'\n\nimport { initClientUploads } from './initClientUploads.js'\n\ndescribe('initClientUploads', () => {\n it('does not add Admin providers when client uploads are disabled', () => {\n const clientHandler = '@payloadcms/storage-s3/client#S3ClientUploadHandler'\n const collections = Object.fromEntries(\n Array.from({ length: 50 }, (_, index) => [`upload-${index}`, true] as const),\n )\n const config = {} as Config\n\n initClientUploads({\n clientHandler,\n collections,\n config,\n enabled: false,\n serverHandler: vi.fn() as PayloadHandler,\n serverHandlerPath: '/storage-s3-generate-signed-url',\n })\n\n expect(config.admin?.dependencies).toEqual({\n [clientHandler]: {\n path: clientHandler,\n type: 'function',\n },\n })\n expect(config.admin?.components?.providers).toBeUndefined()\n })\n})\n"],"names":["describe","expect","it","vi","initClientUploads","clientHandler","collections","Object","fromEntries","Array","from","length","_","index","config","enabled","serverHandler","fn","serverHandlerPath","admin","dependencies","toEqual","path","type","components","providers","toBeUndefined"],"mappings":"AAEA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAQ;AAEjD,SAASC,iBAAiB,QAAQ,yBAAwB;AAE1DJ,SAAS,qBAAqB;IAC5BE,GAAG,iEAAiE;QAClE,MAAMG,gBAAgB;QACtB,MAAMC,cAAcC,OAAOC,WAAW,CACpCC,MAAMC,IAAI,CAAC;YAAEC,QAAQ;QAAG,GAAG,CAACC,GAAGC,QAAU;gBAAC,CAAC,OAAO,EAAEA,OAAO;gBAAE;aAAK;QAEpE,MAAMC,SAAS,CAAC;QAEhBV,kBAAkB;YAChBC;YACAC;YACAQ;YACAC,SAAS;YACTC,eAAeb,GAAGc,EAAE;YACpBC,mBAAmB;QACrB;QAEAjB,OAAOa,OAAOK,KAAK,EAAEC,cAAcC,OAAO,CAAC;YACzC,CAAChB,cAAc,EAAE;gBACfiB,MAAMjB;gBACNkB,MAAM;YACR;QACF;QACAtB,OAAOa,OAAOK,KAAK,EAAEK,YAAYC,WAAWC,aAAa;IAC3D;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/plugin-cloud-storage",
3
- "version": "3.90.1",
3
+ "version": "3.90.2",
4
4
  "description": "The official cloud storage plugin for Payload CMS",
5
5
  "homepage": "https://payloadcms.com",
6
6
  "repository": {
@@ -51,18 +51,18 @@
51
51
  "dependencies": {
52
52
  "find-node-modules": "^2.1.3",
53
53
  "range-parser": "^1.2.1",
54
- "@payloadcms/ui": "3.90.1"
54
+ "@payloadcms/ui": "3.90.2"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/find-node-modules": "^2.1.2",
58
58
  "@types/react": "19.2.14",
59
59
  "@types/react-dom": "19.2.3",
60
- "payload": "3.90.1"
60
+ "payload": "3.90.2"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "react": "^19.0.1 || ^19.1.2 || ^19.2.1",
64
64
  "react-dom": "^19.0.1 || ^19.1.2 || ^19.2.1",
65
- "payload": "3.90.1"
65
+ "payload": "3.90.2"
66
66
  },
67
67
  "publishConfig": {
68
68
  "registry": "https://registry.npmjs.org/"