@payloadcms/storage-vercel-blob 4.0.0-canary.33 → 4.0.0-canary.34

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.
Files changed (41) hide show
  1. package/dist/adapter.d.ts +3 -1
  2. package/dist/adapter.d.ts.map +1 -1
  3. package/dist/adapter.js +54 -24
  4. package/dist/adapter.js.map +1 -1
  5. package/dist/adapter.spec.js +124 -0
  6. package/dist/adapter.spec.js.map +1 -0
  7. package/dist/authorizeFileOverwrite.d.ts +16 -0
  8. package/dist/authorizeFileOverwrite.d.ts.map +1 -0
  9. package/dist/authorizeFileOverwrite.js +117 -0
  10. package/dist/authorizeFileOverwrite.js.map +1 -0
  11. package/dist/authorizeFileOverwrite.spec.js +92 -0
  12. package/dist/authorizeFileOverwrite.spec.js.map +1 -0
  13. package/dist/deleteFile.d.ts +2 -5
  14. package/dist/deleteFile.d.ts.map +1 -1
  15. package/dist/deleteFile.js +3 -10
  16. package/dist/deleteFile.js.map +1 -1
  17. package/dist/generateURL.d.ts +1 -0
  18. package/dist/generateURL.d.ts.map +1 -1
  19. package/dist/generateURL.js +13 -9
  20. package/dist/generateURL.js.map +1 -1
  21. package/dist/getCollectionSources.d.ts +20 -0
  22. package/dist/getCollectionSources.d.ts.map +1 -0
  23. package/dist/getCollectionSources.js +27 -0
  24. package/dist/getCollectionSources.js.map +1 -0
  25. package/dist/getCollectionSources.spec.js +67 -0
  26. package/dist/getCollectionSources.spec.js.map +1 -0
  27. package/dist/getFile.d.ts +3 -3
  28. package/dist/getFile.d.ts.map +1 -1
  29. package/dist/getFile.js +9 -7
  30. package/dist/getFile.js.map +1 -1
  31. package/dist/index.d.ts +8 -7
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +18 -5
  34. package/dist/index.js.map +1 -1
  35. package/dist/staticHandler.spec.js +71 -0
  36. package/dist/staticHandler.spec.js.map +1 -0
  37. package/dist/uploadFile.d.ts +2 -5
  38. package/dist/uploadFile.d.ts.map +1 -1
  39. package/dist/uploadFile.js +2 -9
  40. package/dist/uploadFile.js.map +1 -1
  41. package/package.json +4 -4
package/dist/adapter.d.ts CHANGED
@@ -1,13 +1,15 @@
1
1
  import type { Adapter, ClientUploadsConfig } from '@payloadcms/plugin-cloud-storage/types';
2
+ import type { VercelBlobCollectionSource } from './authorizeFileOverwrite.js';
2
3
  interface CreateVercelBlobAdapterArgs {
3
4
  access: 'public';
4
5
  addRandomSuffix?: boolean;
5
6
  baseUrl: string;
6
7
  cacheControlMaxAge: number;
7
8
  clientUploads?: ClientUploadsConfig;
9
+ collectionSources: VercelBlobCollectionSource[];
8
10
  token: string;
9
11
  useCompositePrefixes?: boolean;
10
12
  }
11
- export declare function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, clientUploads, token, useCompositePrefixes, }: CreateVercelBlobAdapterArgs): Adapter;
13
+ export declare function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, clientUploads, collectionSources, token, useCompositePrefixes, }: CreateVercelBlobAdapterArgs): Adapter;
12
14
  export {};
13
15
  //# sourceMappingURL=adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,mBAAmB,EAEpB,MAAM,wCAAwC,CAAA;AAW/C,UAAU,2BAA2B;IACnC,MAAM,EAAE,QAAQ,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,eAAe,EACf,OAAO,EACP,kBAAkB,EAClB,aAAa,EACb,KAAK,EACL,oBAA4B,GAC7B,EAAE,2BAA2B,GAAG,OAAO,CAwHvC"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,mBAAmB,EAEpB,MAAM,wCAAwC,CAAA;AAU/C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AAQ7E,UAAU,2BAA2B;IACnC,MAAM,EAAE,QAAQ,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,iBAAiB,EAAE,0BAA0B,EAAE,CAAA;IAC/C,KAAK,EAAE,MAAM,CAAA;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,eAAe,EACf,OAAO,EACP,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,KAAK,EACL,oBAA4B,GAC7B,EAAE,2BAA2B,GAAG,OAAO,CAgJvC"}
package/dist/adapter.js CHANGED
@@ -1,11 +1,13 @@
1
- import { resolveSignedURLKey } from '@payloadcms/plugin-cloud-storage/utilities';
1
+ import { buildUploadStoragePathData, resolveSignedURLKey } from '@payloadcms/plugin-cloud-storage/utilities';
2
2
  import { generateClientTokenFromReadWriteToken } from '@vercel/blob/client';
3
3
  import { Forbidden } from 'payload';
4
+ import { assertClientUploadAllowed, createClientUploadReceipt } from 'payload/internal';
5
+ import { authorizeClientOverwrite } from './authorizeFileOverwrite.js';
4
6
  import { deleteFile } from './deleteFile.js';
5
7
  import { generateURL } from './generateURL.js';
6
8
  import { getFile } from './getFile.js';
7
9
  import { uploadFile } from './uploadFile.js';
8
- export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, clientUploads, token, useCompositePrefixes = false }) {
10
+ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, clientUploads, collectionSources, token, useCompositePrefixes = false }) {
9
11
  const clientUploadsAccess = typeof clientUploads === 'object' ? clientUploads.access : undefined;
10
12
  return ({ collection, prefix = '' })=>({
11
13
  name: 'vercel-blob',
@@ -21,7 +23,40 @@ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cach
21
23
  }) : !req.user)) {
22
24
  throw new Forbidden(req.t);
23
25
  }
24
- const resolved = await resolveSignedURLKey({
26
+ assertClientUploadAllowed({
27
+ collection,
28
+ filename,
29
+ mimeType
30
+ });
31
+ const requested = buildUploadStoragePathData({
32
+ collectionPrefix: prefix,
33
+ docPrefix,
34
+ filename,
35
+ useCompositePrefixes
36
+ });
37
+ const allowOverwrite = await authorizeClientOverwrite({
38
+ collectionPrefix: prefix,
39
+ collectionSources,
40
+ overrideAccess,
41
+ req,
42
+ requestedCollectionSlug: collectionSlug,
43
+ requestedFilename: requested.sanitizedFilename,
44
+ requestedStorageFilePath: requested.storageFilePath
45
+ });
46
+ const resolved = allowOverwrite ? {
47
+ ...requested,
48
+ uploadReference: {
49
+ prefix: requested.sanitizedDocPrefix,
50
+ signedReceipt: createClientUploadReceipt({
51
+ allowOverwrite: true,
52
+ collectionSlug,
53
+ filename: requested.sanitizedFilename,
54
+ filePrefix: requested.sanitizedDocPrefix,
55
+ req,
56
+ storageFilePath: requested.storageFilePath
57
+ })
58
+ }
59
+ } : await resolveSignedURLKey({
25
60
  collectionPrefix: prefix,
26
61
  collectionSlug,
27
62
  docPrefix,
@@ -33,16 +68,18 @@ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cach
33
68
  name: 'uploadToVercelBlob',
34
69
  type: 'dispatch',
35
70
  data: {
36
- pathname: resolved.fileKey,
71
+ pathname: resolved.storageFilePath,
37
72
  token: await generateClientTokenFromReadWriteToken({
38
- addRandomSuffix,
73
+ addRandomSuffix: false,
39
74
  allowedContentTypes: mimeType ? [
40
75
  mimeType
41
76
  ] : undefined,
42
- allowOverwrite: true,
77
+ ...allowOverwrite && {
78
+ allowOverwrite: true
79
+ },
43
80
  cacheControlMaxAge,
44
81
  maximumSizeInBytes: filesize,
45
- pathname: resolved.fileKey,
82
+ pathname: resolved.storageFilePath,
46
83
  token
47
84
  })
48
85
  },
@@ -50,12 +87,11 @@ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cach
50
87
  filename: resolved.sanitizedFilename,
51
88
  mimeType,
52
89
  size: filesize,
53
- uploadReference: {
54
- prefix: resolved.sanitizedDocPrefix
55
- }
90
+ uploadReference: resolved.uploadReference
56
91
  }
57
92
  };
58
93
  },
94
+ requiresUploadReceipt: true,
59
95
  useInAdmin: true
60
96
  },
61
97
  generateURL: ({ filename, prefix: urlPrefix = '' })=>generateURL({
@@ -65,40 +101,34 @@ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cach
65
101
  prefix: urlPrefix,
66
102
  useCompositePrefixes
67
103
  }),
68
- handleDelete: ({ doc: { prefix: docPrefix = '' }, filename })=>deleteFile({
104
+ handleDelete: ({ storageFilePath })=>deleteFile({
69
105
  baseUrl,
70
- collectionPrefix: prefix,
71
- docPrefix,
72
- filename,
73
- token,
74
- useCompositePrefixes
106
+ storageFilePath,
107
+ token
75
108
  }),
76
- handleUpload: async ({ data, file: { buffer, filename, mimeType } })=>{
109
+ handleUpload: async ({ data, file: { buffer, mimeType }, storageFilePath })=>{
77
110
  const result = await uploadFile({
78
111
  access,
79
112
  addRandomSuffix,
80
113
  buffer,
81
114
  cacheControlMaxAge,
82
- collectionPrefix: prefix,
83
- docPrefix: data.prefix,
84
- filename,
85
115
  mimeType,
86
- token,
87
- useCompositePrefixes
116
+ storageFilePath,
117
+ token
88
118
  });
89
119
  if (result.filename) {
90
120
  data.filename = result.filename;
91
121
  }
92
122
  return data;
93
123
  },
94
- staticHandler: (req, { headers, params: { filename, prefix: prefixQueryParam, uploadReference } })=>getFile({
124
+ staticHandler: (req, { doc, headers, params: { filename, uploadReference } })=>getFile({
95
125
  baseUrl,
96
126
  cacheControlMaxAge,
97
127
  collection,
98
128
  collectionPrefix: prefix,
129
+ doc,
99
130
  filename,
100
131
  incomingHeaders: headers,
101
- prefixQueryParam,
102
132
  req,
103
133
  token,
104
134
  uploadReference,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapter.ts"],"sourcesContent":["import type {\n Adapter,\n ClientUploadsConfig,\n GeneratedAdapter,\n} from '@payloadcms/plugin-cloud-storage/types'\n\nimport { resolveSignedURLKey } from '@payloadcms/plugin-cloud-storage/utilities'\nimport { generateClientTokenFromReadWriteToken } from '@vercel/blob/client'\nimport { Forbidden } from 'payload'\n\nimport { deleteFile } from './deleteFile.js'\nimport { generateURL } from './generateURL.js'\nimport { getFile } from './getFile.js'\nimport { uploadFile } from './uploadFile.js'\n\ninterface CreateVercelBlobAdapterArgs {\n access: 'public'\n addRandomSuffix?: boolean\n baseUrl: string\n cacheControlMaxAge: number\n clientUploads?: ClientUploadsConfig\n token: string\n useCompositePrefixes?: boolean\n}\n\nexport function createVercelBlobAdapter({\n access,\n addRandomSuffix,\n baseUrl,\n cacheControlMaxAge,\n clientUploads,\n token,\n useCompositePrefixes = false,\n}: CreateVercelBlobAdapterArgs): Adapter {\n const clientUploadsAccess = typeof clientUploads === 'object' ? clientUploads.access : undefined\n\n return ({ collection, prefix = '' }): GeneratedAdapter => ({\n name: 'vercel-blob',\n\n uploadInstructions: {\n adminHandler: {\n path: '@payloadcms/storage-vercel-blob/client#VercelBlobClientUploadHandler',\n },\n enabled: Boolean(clientUploads),\n generate: async ({\n collectionSlug,\n docPrefix,\n filename,\n filesize,\n mimeType,\n overrideAccess,\n req,\n }) => {\n if (\n !overrideAccess &&\n (clientUploadsAccess ? !(await clientUploadsAccess({ collectionSlug, req })) : !req.user)\n ) {\n throw new Forbidden(req.t)\n }\n\n const resolved = await resolveSignedURLKey({\n collectionPrefix: prefix,\n collectionSlug,\n docPrefix,\n filename,\n req,\n useCompositePrefixes,\n })\n\n return {\n name: 'uploadToVercelBlob',\n type: 'dispatch',\n data: {\n pathname: resolved.fileKey,\n token: await generateClientTokenFromReadWriteToken({\n addRandomSuffix,\n allowedContentTypes: mimeType ? [mimeType] : undefined,\n allowOverwrite: true,\n cacheControlMaxAge,\n maximumSizeInBytes: filesize,\n pathname: resolved.fileKey,\n token,\n }),\n },\n file: {\n filename: resolved.sanitizedFilename,\n mimeType,\n size: filesize,\n uploadReference: { prefix: resolved.sanitizedDocPrefix },\n },\n }\n },\n useInAdmin: true,\n },\n\n generateURL: ({ filename, prefix: urlPrefix = '' }) =>\n generateURL({\n baseUrl,\n collectionPrefix: prefix,\n filename,\n prefix: urlPrefix,\n useCompositePrefixes,\n }),\n\n handleDelete: ({ doc: { prefix: docPrefix = '' }, filename }) =>\n deleteFile({\n baseUrl,\n collectionPrefix: prefix,\n docPrefix,\n filename,\n token,\n useCompositePrefixes,\n }),\n\n handleUpload: async ({ data, file: { buffer, filename, mimeType } }) => {\n const result = await uploadFile({\n access,\n addRandomSuffix,\n buffer,\n cacheControlMaxAge,\n collectionPrefix: prefix,\n docPrefix: data.prefix,\n filename,\n mimeType,\n token,\n useCompositePrefixes,\n })\n\n if (result.filename) {\n data.filename = result.filename\n }\n\n return data\n },\n\n staticHandler: (\n req,\n { headers, params: { filename, prefix: prefixQueryParam, uploadReference } },\n ) =>\n getFile({\n baseUrl,\n cacheControlMaxAge,\n collection,\n collectionPrefix: prefix,\n filename,\n incomingHeaders: headers,\n prefixQueryParam,\n req,\n token,\n uploadReference,\n useCompositePrefixes,\n }),\n })\n}\n"],"names":["resolveSignedURLKey","generateClientTokenFromReadWriteToken","Forbidden","deleteFile","generateURL","getFile","uploadFile","createVercelBlobAdapter","access","addRandomSuffix","baseUrl","cacheControlMaxAge","clientUploads","token","useCompositePrefixes","clientUploadsAccess","undefined","collection","prefix","name","uploadInstructions","adminHandler","path","enabled","Boolean","generate","collectionSlug","docPrefix","filename","filesize","mimeType","overrideAccess","req","user","t","resolved","collectionPrefix","type","data","pathname","fileKey","allowedContentTypes","allowOverwrite","maximumSizeInBytes","file","sanitizedFilename","size","uploadReference","sanitizedDocPrefix","useInAdmin","urlPrefix","handleDelete","doc","handleUpload","buffer","result","staticHandler","headers","params","prefixQueryParam","incomingHeaders"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/adapter.ts"],"sourcesContent":["import type {\n Adapter,\n ClientUploadsConfig,\n GeneratedAdapter,\n} from '@payloadcms/plugin-cloud-storage/types'\n\nimport {\n buildUploadStoragePathData,\n resolveSignedURLKey,\n} from '@payloadcms/plugin-cloud-storage/utilities'\nimport { generateClientTokenFromReadWriteToken } from '@vercel/blob/client'\nimport { Forbidden } from 'payload'\nimport { assertClientUploadAllowed, createClientUploadReceipt } from 'payload/internal'\n\nimport type { VercelBlobCollectionSource } from './authorizeFileOverwrite.js'\n\nimport { authorizeClientOverwrite } from './authorizeFileOverwrite.js'\nimport { deleteFile } from './deleteFile.js'\nimport { generateURL } from './generateURL.js'\nimport { getFile } from './getFile.js'\nimport { uploadFile } from './uploadFile.js'\n\ninterface CreateVercelBlobAdapterArgs {\n access: 'public'\n addRandomSuffix?: boolean\n baseUrl: string\n cacheControlMaxAge: number\n clientUploads?: ClientUploadsConfig\n collectionSources: VercelBlobCollectionSource[]\n token: string\n useCompositePrefixes?: boolean\n}\n\nexport function createVercelBlobAdapter({\n access,\n addRandomSuffix,\n baseUrl,\n cacheControlMaxAge,\n clientUploads,\n collectionSources,\n token,\n useCompositePrefixes = false,\n}: CreateVercelBlobAdapterArgs): Adapter {\n const clientUploadsAccess = typeof clientUploads === 'object' ? clientUploads.access : undefined\n\n return ({ collection, prefix = '' }): GeneratedAdapter => ({\n name: 'vercel-blob',\n\n uploadInstructions: {\n adminHandler: {\n path: '@payloadcms/storage-vercel-blob/client#VercelBlobClientUploadHandler',\n },\n enabled: Boolean(clientUploads),\n generate: async ({\n collectionSlug,\n docPrefix,\n filename,\n filesize,\n mimeType,\n overrideAccess,\n req,\n }) => {\n if (\n !overrideAccess &&\n (clientUploadsAccess ? !(await clientUploadsAccess({ collectionSlug, req })) : !req.user)\n ) {\n throw new Forbidden(req.t)\n }\n\n assertClientUploadAllowed({ collection, filename, mimeType })\n\n const requested = buildUploadStoragePathData({\n collectionPrefix: prefix,\n docPrefix,\n filename,\n useCompositePrefixes,\n })\n const allowOverwrite = await authorizeClientOverwrite({\n collectionPrefix: prefix,\n collectionSources,\n overrideAccess,\n req,\n requestedCollectionSlug: collectionSlug,\n requestedFilename: requested.sanitizedFilename,\n requestedStorageFilePath: requested.storageFilePath,\n })\n const resolved = allowOverwrite\n ? {\n ...requested,\n uploadReference: {\n prefix: requested.sanitizedDocPrefix,\n signedReceipt: createClientUploadReceipt({\n allowOverwrite: true,\n collectionSlug,\n filename: requested.sanitizedFilename,\n filePrefix: requested.sanitizedDocPrefix,\n req,\n storageFilePath: requested.storageFilePath,\n }),\n },\n }\n : await resolveSignedURLKey({\n collectionPrefix: prefix,\n collectionSlug,\n docPrefix,\n filename,\n req,\n useCompositePrefixes,\n })\n\n return {\n name: 'uploadToVercelBlob',\n type: 'dispatch',\n data: {\n pathname: resolved.storageFilePath,\n token: await generateClientTokenFromReadWriteToken({\n addRandomSuffix: false,\n allowedContentTypes: mimeType ? [mimeType] : undefined,\n ...(allowOverwrite && { allowOverwrite: true }),\n cacheControlMaxAge,\n maximumSizeInBytes: filesize,\n pathname: resolved.storageFilePath,\n token,\n }),\n },\n file: {\n filename: resolved.sanitizedFilename,\n mimeType,\n size: filesize,\n uploadReference: resolved.uploadReference,\n },\n }\n },\n requiresUploadReceipt: true,\n useInAdmin: true,\n },\n\n generateURL: ({ filename, prefix: urlPrefix = '' }) =>\n generateURL({\n baseUrl,\n collectionPrefix: prefix,\n filename,\n prefix: urlPrefix,\n useCompositePrefixes,\n }),\n\n handleDelete: ({ storageFilePath }) =>\n deleteFile({\n baseUrl,\n storageFilePath,\n token,\n }),\n\n handleUpload: async ({ data, file: { buffer, mimeType }, storageFilePath }) => {\n const result = await uploadFile({\n access,\n addRandomSuffix,\n buffer,\n cacheControlMaxAge,\n mimeType,\n storageFilePath,\n token,\n })\n\n if (result.filename) {\n data.filename = result.filename\n }\n\n return data\n },\n\n staticHandler: (req, { doc, headers, params: { filename, uploadReference } }) =>\n getFile({\n baseUrl,\n cacheControlMaxAge,\n collection,\n collectionPrefix: prefix,\n doc,\n filename,\n incomingHeaders: headers,\n req,\n token,\n uploadReference,\n useCompositePrefixes,\n }),\n })\n}\n"],"names":["buildUploadStoragePathData","resolveSignedURLKey","generateClientTokenFromReadWriteToken","Forbidden","assertClientUploadAllowed","createClientUploadReceipt","authorizeClientOverwrite","deleteFile","generateURL","getFile","uploadFile","createVercelBlobAdapter","access","addRandomSuffix","baseUrl","cacheControlMaxAge","clientUploads","collectionSources","token","useCompositePrefixes","clientUploadsAccess","undefined","collection","prefix","name","uploadInstructions","adminHandler","path","enabled","Boolean","generate","collectionSlug","docPrefix","filename","filesize","mimeType","overrideAccess","req","user","t","requested","collectionPrefix","allowOverwrite","requestedCollectionSlug","requestedFilename","sanitizedFilename","requestedStorageFilePath","storageFilePath","resolved","uploadReference","sanitizedDocPrefix","signedReceipt","filePrefix","type","data","pathname","allowedContentTypes","maximumSizeInBytes","file","size","requiresUploadReceipt","useInAdmin","urlPrefix","handleDelete","handleUpload","buffer","result","staticHandler","doc","headers","params","incomingHeaders"],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ const mocks = vi.hoisted(()=>({
3
+ generateClientToken: vi.fn(async ()=>'client-token'),
4
+ // Resolves the stored location of an owning document, so it matches the requested key.
5
+ buildStoragePathData: vi.fn(()=>({
6
+ storageFilePath: 'reference.png',
7
+ sanitizedCollectionPrefix: '',
8
+ sanitizedDocPrefix: '',
9
+ sanitizedFilename: 'reference.png'
10
+ })),
11
+ buildUploadStoragePathData: vi.fn(()=>({
12
+ storageFilePath: 'reference.png',
13
+ sanitizedCollectionPrefix: '',
14
+ sanitizedDocPrefix: '',
15
+ sanitizedFilename: 'reference.png'
16
+ })),
17
+ isStoragePathWithinCollectionPrefix: vi.fn(()=>true),
18
+ resolveSignedURLKey: vi.fn(async ()=>({
19
+ storageFilePath: 'reference-1.png',
20
+ sanitizedDocPrefix: '',
21
+ sanitizedFilename: 'reference-1.png',
22
+ uploadReference: {
23
+ prefix: '',
24
+ signedReceipt: 'upload-receipt'
25
+ }
26
+ }))
27
+ }));
28
+ vi.mock('@payloadcms/plugin-cloud-storage/utilities', ()=>({
29
+ buildStoragePathData: mocks.buildStoragePathData,
30
+ buildUploadStoragePathData: mocks.buildUploadStoragePathData,
31
+ isStoragePathWithinCollectionPrefix: mocks.isStoragePathWithinCollectionPrefix,
32
+ resolveSignedURLKey: mocks.resolveSignedURLKey
33
+ }));
34
+ vi.mock('@vercel/blob/client', ()=>({
35
+ generateClientTokenFromReadWriteToken: mocks.generateClientToken
36
+ }));
37
+ import { createVercelBlobAdapter } from './adapter.js';
38
+ const generateInstructions = async ({ hasOwner })=>{
39
+ const adapter = createVercelBlobAdapter({
40
+ access: 'public',
41
+ baseUrl: 'https://example.com',
42
+ cacheControlMaxAge: 60,
43
+ clientUploads: true,
44
+ collectionSources: [
45
+ {
46
+ collectionPrefix: '',
47
+ collectionSlug: 'media',
48
+ useCompositePrefixes: false
49
+ }
50
+ ],
51
+ token: 'read-write-token'
52
+ });
53
+ const generatedAdapter = adapter({
54
+ collection: {
55
+ slug: 'media'
56
+ },
57
+ prefix: ''
58
+ });
59
+ const req = {
60
+ payload: {
61
+ collections: {
62
+ media: {
63
+ config: {
64
+ access: {
65
+ update: async ()=>true
66
+ },
67
+ upload: true
68
+ }
69
+ }
70
+ },
71
+ find: vi.fn(async ()=>({
72
+ docs: hasOwner ? [
73
+ {
74
+ filename: 'reference.png',
75
+ id: 1
76
+ }
77
+ ] : []
78
+ })),
79
+ secret: 'secret'
80
+ },
81
+ t: vi.fn()
82
+ };
83
+ return generatedAdapter.uploadInstructions?.generate({
84
+ collectionSlug: 'media',
85
+ filename: 'reference.png',
86
+ filesize: 100,
87
+ mimeType: 'image/png',
88
+ overrideAccess: true,
89
+ req
90
+ });
91
+ };
92
+ describe('createVercelBlobAdapter', ()=>{
93
+ beforeEach(()=>{
94
+ vi.clearAllMocks();
95
+ });
96
+ it('should disable overwrite when no document owns the requested key', async ()=>{
97
+ const instructions = await generateInstructions({
98
+ hasOwner: false
99
+ });
100
+ const tokenOptions = mocks.generateClientToken.mock.calls[0][0];
101
+ expect(instructions).toMatchObject({
102
+ data: {
103
+ pathname: 'reference-1.png'
104
+ }
105
+ });
106
+ expect(tokenOptions).not.toHaveProperty('allowOverwrite');
107
+ });
108
+ it('should allow an authorized owner to update the requested key', async ()=>{
109
+ const instructions = await generateInstructions({
110
+ hasOwner: true
111
+ });
112
+ expect(instructions).toMatchObject({
113
+ data: {
114
+ pathname: 'reference.png'
115
+ }
116
+ });
117
+ expect(mocks.generateClientToken).toHaveBeenCalledWith(expect.objectContaining({
118
+ allowOverwrite: true,
119
+ pathname: 'reference.png'
120
+ }));
121
+ });
122
+ });
123
+
124
+ //# sourceMappingURL=adapter.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapter.spec.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport { beforeEach, describe, expect, it, vi } from 'vitest'\n\nconst mocks = vi.hoisted(() => ({\n generateClientToken: vi.fn(async () => 'client-token'),\n // Resolves the stored location of an owning document, so it matches the requested key.\n buildStoragePathData: vi.fn(() => ({\n storageFilePath: 'reference.png',\n sanitizedCollectionPrefix: '',\n sanitizedDocPrefix: '',\n sanitizedFilename: 'reference.png',\n })),\n buildUploadStoragePathData: vi.fn(() => ({\n storageFilePath: 'reference.png',\n sanitizedCollectionPrefix: '',\n sanitizedDocPrefix: '',\n sanitizedFilename: 'reference.png',\n })),\n isStoragePathWithinCollectionPrefix: vi.fn(() => true),\n resolveSignedURLKey: vi.fn(async () => ({\n storageFilePath: 'reference-1.png',\n sanitizedDocPrefix: '',\n sanitizedFilename: 'reference-1.png',\n uploadReference: { prefix: '', signedReceipt: 'upload-receipt' },\n })),\n}))\n\nvi.mock('@payloadcms/plugin-cloud-storage/utilities', () => ({\n buildStoragePathData: mocks.buildStoragePathData,\n buildUploadStoragePathData: mocks.buildUploadStoragePathData,\n isStoragePathWithinCollectionPrefix: mocks.isStoragePathWithinCollectionPrefix,\n resolveSignedURLKey: mocks.resolveSignedURLKey,\n}))\n\nvi.mock('@vercel/blob/client', () => ({\n generateClientTokenFromReadWriteToken: mocks.generateClientToken,\n}))\n\nimport { createVercelBlobAdapter } from './adapter.js'\n\nconst generateInstructions = async ({ hasOwner }: { hasOwner: boolean }) => {\n const adapter = createVercelBlobAdapter({\n access: 'public',\n baseUrl: 'https://example.com',\n cacheControlMaxAge: 60,\n clientUploads: true,\n collectionSources: [\n { collectionPrefix: '', collectionSlug: 'media', useCompositePrefixes: false },\n ],\n token: 'read-write-token',\n })\n const generatedAdapter = adapter({\n collection: { slug: 'media' },\n prefix: '',\n } as never)\n const req = {\n payload: {\n collections: {\n media: { config: { access: { update: async () => true }, upload: true } },\n },\n find: vi.fn(async () => ({\n docs: hasOwner ? [{ filename: 'reference.png', id: 1 }] : [],\n })),\n secret: 'secret',\n },\n t: vi.fn(),\n } as unknown as PayloadRequest\n\n return generatedAdapter.uploadInstructions?.generate({\n collectionSlug: 'media',\n filename: 'reference.png',\n filesize: 100,\n mimeType: 'image/png',\n overrideAccess: true,\n req,\n })\n}\n\ndescribe('createVercelBlobAdapter', () => {\n beforeEach(() => {\n vi.clearAllMocks()\n })\n\n it('should disable overwrite when no document owns the requested key', async () => {\n const instructions = await generateInstructions({ hasOwner: false })\n const tokenOptions = mocks.generateClientToken.mock.calls[0]![0]\n\n expect(instructions).toMatchObject({ data: { pathname: 'reference-1.png' } })\n expect(tokenOptions).not.toHaveProperty('allowOverwrite')\n })\n\n it('should allow an authorized owner to update the requested key', async () => {\n const instructions = await generateInstructions({ hasOwner: true })\n\n expect(instructions).toMatchObject({ data: { pathname: 'reference.png' } })\n expect(mocks.generateClientToken).toHaveBeenCalledWith(\n expect.objectContaining({ allowOverwrite: true, pathname: 'reference.png' }),\n )\n })\n})\n"],"names":["beforeEach","describe","expect","it","vi","mocks","hoisted","generateClientToken","fn","buildStoragePathData","storageFilePath","sanitizedCollectionPrefix","sanitizedDocPrefix","sanitizedFilename","buildUploadStoragePathData","isStoragePathWithinCollectionPrefix","resolveSignedURLKey","uploadReference","prefix","signedReceipt","mock","generateClientTokenFromReadWriteToken","createVercelBlobAdapter","generateInstructions","hasOwner","adapter","access","baseUrl","cacheControlMaxAge","clientUploads","collectionSources","collectionPrefix","collectionSlug","useCompositePrefixes","token","generatedAdapter","collection","slug","req","payload","collections","media","config","update","upload","find","docs","filename","id","secret","t","uploadInstructions","generate","filesize","mimeType","overrideAccess","clearAllMocks","instructions","tokenOptions","calls","toMatchObject","data","pathname","not","toHaveProperty","toHaveBeenCalledWith","objectContaining","allowOverwrite"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { PayloadRequest } from 'payload';
2
+ export type VercelBlobCollectionSource = {
3
+ collectionPrefix: string;
4
+ collectionSlug: string;
5
+ useCompositePrefixes: boolean;
6
+ };
7
+ export declare function authorizeClientOverwrite({ collectionPrefix: collectionPrefixArg, collectionSources, overrideAccess, req, requestedCollectionSlug, requestedFilename, requestedStorageFilePath, }: {
8
+ collectionPrefix: string;
9
+ collectionSources: VercelBlobCollectionSource[];
10
+ overrideAccess?: boolean;
11
+ req: PayloadRequest;
12
+ requestedCollectionSlug: string;
13
+ requestedFilename: string;
14
+ requestedStorageFilePath: string;
15
+ }): Promise<boolean>;
16
+ //# sourceMappingURL=authorizeFileOverwrite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorizeFileOverwrite.d.ts","sourceRoot":"","sources":["../src/authorizeFileOverwrite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,cAAc,EAAqB,MAAM,SAAS,CAAA;AAU1E,MAAM,MAAM,0BAA0B,GAAG;IACvC,gBAAgB,EAAE,MAAM,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,oBAAoB,EAAE,OAAO,CAAA;CAC9B,CAAA;AAmHD,wBAAsB,wBAAwB,CAAC,EAC7C,gBAAgB,EAAE,mBAAmB,EACrC,iBAAiB,EACjB,cAAsB,EACtB,GAAG,EACH,uBAAuB,EACvB,iBAAiB,EACjB,wBAAwB,GACzB,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,iBAAiB,EAAE,0BAA0B,EAAE,CAAA;IAC/C,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,GAAG,EAAE,cAAc,CAAA;IACnB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,iBAAiB,EAAE,MAAM,CAAA;IACzB,wBAAwB,EAAE,MAAM,CAAA;CACjC,GAAG,OAAO,CAAC,OAAO,CAAC,CA8CnB"}
@@ -0,0 +1,117 @@
1
+ import { buildStoragePathData, isStoragePathWithinCollectionPrefix } from '@payloadcms/plugin-cloud-storage/utilities';
2
+ import { combineQueries, executeAccess, Forbidden } from 'payload';
3
+ function getDocumentFileKeys({ collectionPrefix, doc, useCompositePrefixes }) {
4
+ return [
5
+ doc.filename,
6
+ ...Object.values(doc.sizes || {}).map((size)=>size?.filename)
7
+ ].filter((filename)=>typeof filename === 'string').map((filename)=>buildStoragePathData({
8
+ collectionPrefix,
9
+ docPrefix: doc.prefix,
10
+ filename,
11
+ useCompositePrefixes
12
+ }).storageFilePath);
13
+ }
14
+ async function findMatchingDocs({ collectionPrefix, collectionSlug, req, requestedFilename, requestedStorageFilePath, useCompositePrefixes }) {
15
+ const collection = req.payload.collections[collectionSlug];
16
+ if (!collection) {
17
+ return [];
18
+ }
19
+ const imageSizes = collection.config.upload && typeof collection.config.upload === 'object' ? collection.config.upload.imageSizes || [] : [];
20
+ const filenameQueries = [
21
+ {
22
+ filename: {
23
+ equals: requestedFilename
24
+ }
25
+ },
26
+ ...imageSizes.map(({ name })=>({
27
+ [`sizes.${name}.filename`]: {
28
+ equals: requestedFilename
29
+ }
30
+ }))
31
+ ];
32
+ const result = await req.payload.find({
33
+ collection: collectionSlug,
34
+ depth: 0,
35
+ draft: true,
36
+ overrideAccess: true,
37
+ pagination: false,
38
+ req,
39
+ where: {
40
+ or: filenameQueries
41
+ }
42
+ });
43
+ return result.docs.filter((doc)=>getDocumentFileKeys({
44
+ collectionPrefix,
45
+ doc,
46
+ useCompositePrefixes
47
+ }).includes(requestedStorageFilePath));
48
+ }
49
+ async function canUpdateDoc({ collectionSlug, doc, req }) {
50
+ const collection = req.payload.collections[collectionSlug];
51
+ if (!collection) {
52
+ return false;
53
+ }
54
+ const accessResult = await executeAccess({
55
+ id: doc.id,
56
+ slug: collectionSlug,
57
+ disableErrors: true,
58
+ req
59
+ }, collection.config.access.update);
60
+ if (typeof accessResult === 'boolean') {
61
+ return accessResult;
62
+ }
63
+ const result = await req.payload.find({
64
+ collection: collectionSlug,
65
+ depth: 0,
66
+ draft: true,
67
+ limit: 1,
68
+ overrideAccess: true,
69
+ pagination: false,
70
+ req,
71
+ where: combineQueries({
72
+ id: {
73
+ equals: doc.id
74
+ }
75
+ }, accessResult)
76
+ });
77
+ return result.docs.length === 1;
78
+ }
79
+ export async function authorizeClientOverwrite({ collectionPrefix: collectionPrefixArg, collectionSources, overrideAccess = false, req, requestedCollectionSlug, requestedFilename, requestedStorageFilePath }) {
80
+ if (!isStoragePathWithinCollectionPrefix({
81
+ collectionPrefix: collectionPrefixArg,
82
+ docPrefix: requestedStorageFilePath
83
+ })) {
84
+ throw new Forbidden(req.t);
85
+ }
86
+ const matchedDocs = (await Promise.all(collectionSources.map(async ({ collectionPrefix, collectionSlug, useCompositePrefixes })=>{
87
+ const docs = await findMatchingDocs({
88
+ collectionPrefix,
89
+ collectionSlug,
90
+ req,
91
+ requestedFilename,
92
+ requestedStorageFilePath,
93
+ useCompositePrefixes
94
+ });
95
+ return docs.map((doc)=>({
96
+ collectionSlug,
97
+ doc
98
+ }));
99
+ }))).flat();
100
+ if (matchedDocs.length === 0) {
101
+ return false;
102
+ }
103
+ const matchedDoc = matchedDocs[0];
104
+ if (matchedDocs.length !== 1 || matchedDoc.collectionSlug !== requestedCollectionSlug) {
105
+ throw new Forbidden(req.t);
106
+ }
107
+ if (!overrideAccess && !await canUpdateDoc({
108
+ collectionSlug: matchedDoc.collectionSlug,
109
+ doc: matchedDoc.doc,
110
+ req
111
+ })) {
112
+ throw new Forbidden(req.t);
113
+ }
114
+ return true;
115
+ }
116
+
117
+ //# sourceMappingURL=authorizeFileOverwrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/authorizeFileOverwrite.ts"],"sourcesContent":["import type { FileData, PayloadRequest, TypeWithID, Where } from 'payload'\n\nimport {\n buildStoragePathData,\n isStoragePathWithinCollectionPrefix,\n} from '@payloadcms/plugin-cloud-storage/utilities'\nimport { combineQueries, executeAccess, Forbidden } from 'payload'\n\ntype OwnerDocument = { prefix?: string } & FileData & TypeWithID\n\nexport type VercelBlobCollectionSource = {\n collectionPrefix: string\n collectionSlug: string\n useCompositePrefixes: boolean\n}\n\ntype Owner = {\n collectionSlug: string\n doc: OwnerDocument\n}\n\nfunction getDocumentFileKeys({\n collectionPrefix,\n doc,\n useCompositePrefixes,\n}: {\n collectionPrefix: string\n doc: OwnerDocument\n useCompositePrefixes: boolean\n}): string[] {\n return [doc.filename, ...Object.values(doc.sizes || {}).map((size) => size?.filename)]\n .filter((filename): filename is string => typeof filename === 'string')\n .map(\n (filename) =>\n buildStoragePathData({\n collectionPrefix,\n docPrefix: doc.prefix,\n filename,\n useCompositePrefixes,\n }).storageFilePath,\n )\n}\n\nasync function findMatchingDocs({\n collectionPrefix,\n collectionSlug,\n req,\n requestedFilename,\n requestedStorageFilePath,\n useCompositePrefixes,\n}: {\n collectionPrefix: string\n collectionSlug: string\n req: PayloadRequest\n requestedFilename: string\n requestedStorageFilePath: string\n useCompositePrefixes: boolean\n}): Promise<OwnerDocument[]> {\n const collection = req.payload.collections[collectionSlug]\n\n if (!collection) {\n return []\n }\n\n const imageSizes =\n collection.config.upload && typeof collection.config.upload === 'object'\n ? collection.config.upload.imageSizes || []\n : []\n const filenameQueries: Where[] = [\n { filename: { equals: requestedFilename } },\n ...imageSizes.map(({ name }) => ({\n [`sizes.${name}.filename`]: { equals: requestedFilename },\n })),\n ]\n const result = await req.payload.find({\n collection: collectionSlug,\n depth: 0,\n draft: true,\n overrideAccess: true,\n pagination: false,\n req,\n where: { or: filenameQueries },\n })\n\n return (result.docs as OwnerDocument[]).filter((doc) =>\n getDocumentFileKeys({ collectionPrefix, doc, useCompositePrefixes }).includes(\n requestedStorageFilePath,\n ),\n )\n}\n\nasync function canUpdateDoc({\n collectionSlug,\n doc,\n req,\n}: {\n collectionSlug: string\n doc: OwnerDocument\n req: PayloadRequest\n}): Promise<boolean> {\n const collection = req.payload.collections[collectionSlug]\n\n if (!collection) {\n return false\n }\n\n const accessResult = await executeAccess(\n { id: doc.id, slug: collectionSlug, disableErrors: true, req },\n collection.config.access.update,\n )\n\n if (typeof accessResult === 'boolean') {\n return accessResult\n }\n\n const result = await req.payload.find({\n collection: collectionSlug,\n depth: 0,\n draft: true,\n limit: 1,\n overrideAccess: true,\n pagination: false,\n req,\n where: combineQueries({ id: { equals: doc.id } }, accessResult),\n })\n\n return result.docs.length === 1\n}\n\nexport async function authorizeClientOverwrite({\n collectionPrefix: collectionPrefixArg,\n collectionSources,\n overrideAccess = false,\n req,\n requestedCollectionSlug,\n requestedFilename,\n requestedStorageFilePath,\n}: {\n collectionPrefix: string\n collectionSources: VercelBlobCollectionSource[]\n overrideAccess?: boolean\n req: PayloadRequest\n requestedCollectionSlug: string\n requestedFilename: string\n requestedStorageFilePath: string\n}): Promise<boolean> {\n if (\n !isStoragePathWithinCollectionPrefix({\n collectionPrefix: collectionPrefixArg,\n docPrefix: requestedStorageFilePath,\n })\n ) {\n throw new Forbidden(req.t)\n }\n\n const matchedDocs = (\n await Promise.all(\n collectionSources.map(\n async ({ collectionPrefix, collectionSlug, useCompositePrefixes }): Promise<Owner[]> => {\n const docs = await findMatchingDocs({\n collectionPrefix,\n collectionSlug,\n req,\n requestedFilename,\n requestedStorageFilePath,\n useCompositePrefixes,\n })\n\n return docs.map((doc) => ({ collectionSlug, doc }))\n },\n ),\n )\n ).flat()\n\n if (matchedDocs.length === 0) {\n return false\n }\n\n const matchedDoc = matchedDocs[0]!\n if (matchedDocs.length !== 1 || matchedDoc.collectionSlug !== requestedCollectionSlug) {\n throw new Forbidden(req.t)\n }\n\n if (\n !overrideAccess &&\n !(await canUpdateDoc({ collectionSlug: matchedDoc.collectionSlug, doc: matchedDoc.doc, req }))\n ) {\n throw new Forbidden(req.t)\n }\n\n return true\n}\n"],"names":["buildStoragePathData","isStoragePathWithinCollectionPrefix","combineQueries","executeAccess","Forbidden","getDocumentFileKeys","collectionPrefix","doc","useCompositePrefixes","filename","Object","values","sizes","map","size","filter","docPrefix","prefix","storageFilePath","findMatchingDocs","collectionSlug","req","requestedFilename","requestedStorageFilePath","collection","payload","collections","imageSizes","config","upload","filenameQueries","equals","name","result","find","depth","draft","overrideAccess","pagination","where","or","docs","includes","canUpdateDoc","accessResult","id","slug","disableErrors","access","update","limit","length","authorizeClientOverwrite","collectionPrefixArg","collectionSources","requestedCollectionSlug","t","matchedDocs","Promise","all","flat","matchedDoc"],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { authorizeClientOverwrite } from './authorizeFileOverwrite.js';
3
+ const owner = (id)=>({
4
+ filename: 'image.png',
5
+ id,
6
+ prefix: 'shared'
7
+ });
8
+ const collectionSources = [
9
+ {
10
+ collectionPrefix: '',
11
+ collectionSlug: 'media',
12
+ useCompositePrefixes: false
13
+ },
14
+ {
15
+ collectionPrefix: '',
16
+ collectionSlug: 'protected',
17
+ useCompositePrefixes: false
18
+ }
19
+ ];
20
+ const createRequest = ({ mediaOwner = true, protectedOwner = false } = {})=>({
21
+ payload: {
22
+ collections: {
23
+ media: {
24
+ config: {
25
+ access: {
26
+ update: async ()=>true
27
+ },
28
+ upload: true
29
+ }
30
+ },
31
+ protected: {
32
+ config: {
33
+ access: {
34
+ update: async ()=>false
35
+ },
36
+ upload: true
37
+ }
38
+ }
39
+ },
40
+ find: vi.fn(async ({ collection })=>({
41
+ docs: collection === 'media' ? mediaOwner ? [
42
+ owner(1)
43
+ ] : [] : protectedOwner ? [
44
+ owner(2)
45
+ ] : []
46
+ }))
47
+ },
48
+ t: vi.fn()
49
+ });
50
+ describe('authorizeClientOverwrite', ()=>{
51
+ it('allows an update when the requested collection is the only owner', async ()=>{
52
+ await expect(authorizeClientOverwrite({
53
+ collectionSources,
54
+ requestedStorageFilePath: 'shared/image.png',
55
+ requestedFilename: 'image.png',
56
+ req: createRequest(),
57
+ requestedCollectionSlug: 'media',
58
+ collectionPrefix: ''
59
+ })).resolves.toBe(true);
60
+ });
61
+ it('rejects an update when another collection owns the same key', async ()=>{
62
+ await expect(authorizeClientOverwrite({
63
+ collectionSources,
64
+ requestedStorageFilePath: 'shared/image.png',
65
+ requestedFilename: 'image.png',
66
+ req: createRequest({
67
+ mediaOwner: false,
68
+ protectedOwner: true
69
+ }),
70
+ requestedCollectionSlug: 'media',
71
+ collectionPrefix: ''
72
+ })).rejects.toMatchObject({
73
+ status: 403
74
+ });
75
+ });
76
+ it('rejects an update when multiple collections own the same key', async ()=>{
77
+ await expect(authorizeClientOverwrite({
78
+ collectionSources,
79
+ requestedStorageFilePath: 'shared/image.png',
80
+ requestedFilename: 'image.png',
81
+ req: createRequest({
82
+ protectedOwner: true
83
+ }),
84
+ requestedCollectionSlug: 'media',
85
+ collectionPrefix: ''
86
+ })).rejects.toMatchObject({
87
+ status: 403
88
+ });
89
+ });
90
+ });
91
+
92
+ //# sourceMappingURL=authorizeFileOverwrite.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/authorizeFileOverwrite.spec.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport { describe, expect, it, vi } from 'vitest'\n\nimport { authorizeClientOverwrite } from './authorizeFileOverwrite.js'\n\nconst owner = (id: number) => ({ filename: 'image.png', id, prefix: 'shared' })\nconst collectionSources = [\n { collectionPrefix: '', collectionSlug: 'media', useCompositePrefixes: false },\n { collectionPrefix: '', collectionSlug: 'protected', useCompositePrefixes: false },\n]\n\nconst createRequest = ({\n mediaOwner = true,\n protectedOwner = false,\n}: {\n mediaOwner?: boolean\n protectedOwner?: boolean\n} = {}) =>\n ({\n payload: {\n collections: {\n media: {\n config: { access: { update: async () => true }, upload: true },\n },\n protected: {\n config: { access: { update: async () => false }, upload: true },\n },\n },\n find: vi.fn(async ({ collection }: { collection: string }) => ({\n docs:\n collection === 'media'\n ? mediaOwner\n ? [owner(1)]\n : []\n : protectedOwner\n ? [owner(2)]\n : [],\n })),\n },\n t: vi.fn(),\n }) as unknown as PayloadRequest\n\ndescribe('authorizeClientOverwrite', () => {\n it('allows an update when the requested collection is the only owner', async () => {\n await expect(\n authorizeClientOverwrite({\n collectionSources,\n requestedStorageFilePath: 'shared/image.png',\n requestedFilename: 'image.png',\n req: createRequest(),\n requestedCollectionSlug: 'media',\n collectionPrefix: '',\n }),\n ).resolves.toBe(true)\n })\n\n it('rejects an update when another collection owns the same key', async () => {\n await expect(\n authorizeClientOverwrite({\n collectionSources,\n requestedStorageFilePath: 'shared/image.png',\n requestedFilename: 'image.png',\n req: createRequest({ mediaOwner: false, protectedOwner: true }),\n requestedCollectionSlug: 'media',\n collectionPrefix: '',\n }),\n ).rejects.toMatchObject({ status: 403 })\n })\n\n it('rejects an update when multiple collections own the same key', async () => {\n await expect(\n authorizeClientOverwrite({\n collectionSources,\n requestedStorageFilePath: 'shared/image.png',\n requestedFilename: 'image.png',\n req: createRequest({ protectedOwner: true }),\n requestedCollectionSlug: 'media',\n collectionPrefix: '',\n }),\n ).rejects.toMatchObject({ status: 403 })\n })\n})\n"],"names":["describe","expect","it","vi","authorizeClientOverwrite","owner","id","filename","prefix","collectionSources","collectionPrefix","collectionSlug","useCompositePrefixes","createRequest","mediaOwner","protectedOwner","payload","collections","media","config","access","update","upload","protected","find","fn","collection","docs","t","requestedStorageFilePath","requestedFilename","req","requestedCollectionSlug","resolves","toBe","rejects","toMatchObject","status"],"mappings":"AAEA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAQ;AAEjD,SAASC,wBAAwB,QAAQ,8BAA6B;AAEtE,MAAMC,QAAQ,CAACC,KAAgB,CAAA;QAAEC,UAAU;QAAaD;QAAIE,QAAQ;IAAS,CAAA;AAC7E,MAAMC,oBAAoB;IACxB;QAAEC,kBAAkB;QAAIC,gBAAgB;QAASC,sBAAsB;IAAM;IAC7E;QAAEF,kBAAkB;QAAIC,gBAAgB;QAAaC,sBAAsB;IAAM;CAClF;AAED,MAAMC,gBAAgB,CAAC,EACrBC,aAAa,IAAI,EACjBC,iBAAiB,KAAK,EAIvB,GAAG,CAAC,CAAC,GACH,CAAA;QACCC,SAAS;YACPC,aAAa;gBACXC,OAAO;oBACLC,QAAQ;wBAAEC,QAAQ;4BAAEC,QAAQ,UAAY;wBAAK;wBAAGC,QAAQ;oBAAK;gBAC/D;gBACAC,WAAW;oBACTJ,QAAQ;wBAAEC,QAAQ;4BAAEC,QAAQ,UAAY;wBAAM;wBAAGC,QAAQ;oBAAK;gBAChE;YACF;YACAE,MAAMrB,GAAGsB,EAAE,CAAC,OAAO,EAAEC,UAAU,EAA0B,GAAM,CAAA;oBAC7DC,MACED,eAAe,UACXZ,aACE;wBAACT,MAAM;qBAAG,GACV,EAAE,GACJU,iBACE;wBAACV,MAAM;qBAAG,GACV,EAAE;gBACZ,CAAA;QACF;QACAuB,GAAGzB,GAAGsB,EAAE;IACV,CAAA;AAEFzB,SAAS,4BAA4B;IACnCE,GAAG,oEAAoE;QACrE,MAAMD,OACJG,yBAAyB;YACvBK;YACAoB,0BAA0B;YAC1BC,mBAAmB;YACnBC,KAAKlB;YACLmB,yBAAyB;YACzBtB,kBAAkB;QACpB,IACAuB,QAAQ,CAACC,IAAI,CAAC;IAClB;IAEAhC,GAAG,+DAA+D;QAChE,MAAMD,OACJG,yBAAyB;YACvBK;YACAoB,0BAA0B;YAC1BC,mBAAmB;YACnBC,KAAKlB,cAAc;gBAAEC,YAAY;gBAAOC,gBAAgB;YAAK;YAC7DiB,yBAAyB;YACzBtB,kBAAkB;QACpB,IACAyB,OAAO,CAACC,aAAa,CAAC;YAAEC,QAAQ;QAAI;IACxC;IAEAnC,GAAG,gEAAgE;QACjE,MAAMD,OACJG,yBAAyB;YACvBK;YACAoB,0BAA0B;YAC1BC,mBAAmB;YACnBC,KAAKlB,cAAc;gBAAEE,gBAAgB;YAAK;YAC1CiB,yBAAyB;YACzBtB,kBAAkB;QACpB,IACAyB,OAAO,CAACC,aAAa,CAAC;YAAEC,QAAQ;QAAI;IACxC;AACF"}
@@ -1,11 +1,8 @@
1
1
  interface DeleteFileArgs {
2
2
  baseUrl: string;
3
- collectionPrefix?: string;
4
- docPrefix: string;
5
- filename: string;
3
+ storageFilePath: string;
6
4
  token: string;
7
- useCompositePrefixes?: boolean;
8
5
  }
9
- export declare function deleteFile({ baseUrl, collectionPrefix, docPrefix, filename, token, useCompositePrefixes, }: DeleteFileArgs): Promise<void>;
6
+ export declare function deleteFile({ baseUrl, storageFilePath, token, }: DeleteFileArgs): Promise<void>;
10
7
  export {};
11
8
  //# sourceMappingURL=deleteFile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deleteFile.d.ts","sourceRoot":"","sources":["../src/deleteFile.ts"],"names":[],"mappings":"AAIA,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,wBAAsB,UAAU,CAAC,EAC/B,OAAO,EACP,gBAAqB,EACrB,SAAS,EACT,QAAQ,EACR,KAAK,EACL,oBAA4B,GAC7B,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhC"}
1
+ {"version":3,"file":"deleteFile.d.ts","sourceRoot":"","sources":["../src/deleteFile.ts"],"names":[],"mappings":"AAIA,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAsB,UAAU,CAAC,EAC/B,OAAO,EACP,eAAe,EACf,KAAK,GACN,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhC"}