@contember/engine-s3-plugin 2.2.0-alpha.1 → 2.2.0-alpha.10

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 (68) hide show
  1. package/dist/development/src/Config.cjs.map +1 -1
  2. package/dist/development/src/Config.js.map +1 -1
  3. package/dist/development/src/S3ObjectAuthorizator.cjs +12 -1
  4. package/dist/development/src/S3ObjectAuthorizator.cjs.map +1 -1
  5. package/dist/development/src/S3ObjectAuthorizator.js +12 -1
  6. package/dist/development/src/S3ObjectAuthorizator.js.map +1 -1
  7. package/dist/development/src/S3SchemaContributor.cjs +48 -16
  8. package/dist/development/src/S3SchemaContributor.cjs.map +1 -1
  9. package/dist/development/src/S3SchemaContributor.js +49 -17
  10. package/dist/development/src/S3SchemaContributor.js.map +1 -1
  11. package/dist/development/src/S3SchemaTypes.cjs +8 -0
  12. package/dist/development/src/S3SchemaTypes.cjs.map +1 -1
  13. package/dist/development/src/S3SchemaTypes.js +8 -0
  14. package/dist/development/src/S3SchemaTypes.js.map +1 -1
  15. package/dist/development/src/S3Service.cjs +44 -14
  16. package/dist/development/src/S3Service.cjs.map +1 -1
  17. package/dist/development/src/S3Service.js +44 -14
  18. package/dist/development/src/S3Service.js.map +1 -1
  19. package/dist/development/src/S3Signer.cjs +6 -1
  20. package/dist/development/src/S3Signer.cjs.map +1 -1
  21. package/dist/development/src/S3Signer.js +6 -1
  22. package/dist/development/src/S3Signer.js.map +1 -1
  23. package/dist/production/src/Config.cjs.map +1 -1
  24. package/dist/production/src/Config.js.map +1 -1
  25. package/dist/production/src/S3ObjectAuthorizator.cjs +12 -1
  26. package/dist/production/src/S3ObjectAuthorizator.cjs.map +1 -1
  27. package/dist/production/src/S3ObjectAuthorizator.js +12 -1
  28. package/dist/production/src/S3ObjectAuthorizator.js.map +1 -1
  29. package/dist/production/src/S3SchemaContributor.cjs +48 -16
  30. package/dist/production/src/S3SchemaContributor.cjs.map +1 -1
  31. package/dist/production/src/S3SchemaContributor.js +49 -17
  32. package/dist/production/src/S3SchemaContributor.js.map +1 -1
  33. package/dist/production/src/S3SchemaTypes.cjs +8 -0
  34. package/dist/production/src/S3SchemaTypes.cjs.map +1 -1
  35. package/dist/production/src/S3SchemaTypes.js +8 -0
  36. package/dist/production/src/S3SchemaTypes.js.map +1 -1
  37. package/dist/production/src/S3Service.cjs +44 -14
  38. package/dist/production/src/S3Service.cjs.map +1 -1
  39. package/dist/production/src/S3Service.js +44 -14
  40. package/dist/production/src/S3Service.js.map +1 -1
  41. package/dist/production/src/S3Signer.cjs +6 -1
  42. package/dist/production/src/S3Signer.cjs.map +1 -1
  43. package/dist/production/src/S3Signer.js +6 -1
  44. package/dist/production/src/S3Signer.js.map +1 -1
  45. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  46. package/dist/types/Config.d.ts.map +1 -1
  47. package/dist/types/S3ConfigProcessor.d.ts.map +1 -1
  48. package/dist/types/S3ObjectAuthorizator.d.ts +9 -1
  49. package/dist/types/S3ObjectAuthorizator.d.ts.map +1 -1
  50. package/dist/types/S3SchemaContributor.d.ts +4 -1
  51. package/dist/types/S3SchemaContributor.d.ts.map +1 -1
  52. package/dist/types/S3SchemaTypes.d.ts +1 -0
  53. package/dist/types/S3SchemaTypes.d.ts.map +1 -1
  54. package/dist/types/S3Service.d.ts +22 -1
  55. package/dist/types/S3Service.d.ts.map +1 -1
  56. package/dist/types/S3Signer.d.ts +1 -1
  57. package/dist/types/S3Signer.d.ts.map +1 -1
  58. package/dist/types/index.d.ts.map +1 -1
  59. package/dist/types/tsconfig.tsbuildinfo +1 -1
  60. package/package.json +4 -4
  61. package/src/Config.ts +1 -0
  62. package/src/S3ObjectAuthorizator.ts +20 -0
  63. package/src/S3SchemaContributor.ts +54 -18
  64. package/src/S3SchemaTypes.ts +8 -0
  65. package/src/S3Service.ts +64 -14
  66. package/src/S3Signer.ts +8 -2
  67. package/tests/cases/authorizator.test.ts +11 -0
  68. package/tests/cases/signRequest.test.ts +81 -3
@@ -1 +1 @@
1
- {"version":3,"file":"Config.cjs","sources":["../../../../packages/engine-s3-plugin/src/Config.ts"],"sourcesContent":["import * as Typesafe from '@contember/typesafe'\n\nexport enum S3Providers {\n\taws = 'aws',\n\tminio = 'minio',\n\tceph = 'ceph',\n\tlocalstack = 'localstack',\n\tcloudserver = 'cloudserver',\n}\n\nexport const s3ConfigSchema = Typesafe.intersection(\n\tTypesafe.object({\n\t\tbucket: Typesafe.string,\n\t\tregion: Typesafe.string,\n\t\tprefix: Typesafe.string,\n\t\tcredentials: Typesafe.object({\n\t\t\tkey: Typesafe.string,\n\t\t\tsecret: Typesafe.string,\n\t\t}),\n\t}),\n\tTypesafe.partial({\n\t\tendpoint: Typesafe.string,\n\t\tcdnEndpoint: Typesafe.string,\n\t\tprovider: Typesafe.enumeration(S3Providers.aws, S3Providers.minio, S3Providers.ceph, S3Providers.localstack, S3Providers.cloudserver),\n\t\tnoAcl: Typesafe.boolean,\n\t}),\n)\n\nexport type S3Config = ReturnType<typeof s3ConfigSchema>\n\nexport type Project3Config = { s3?: S3Config }\n\n// todo\nconst serversWithoutAclSupport = [S3Providers.minio]\n\nexport const resolveS3Config = (config: S3Config): S3Config => {\n\treturn {\n\t\tnoAcl: !!config.provider && serversWithoutAclSupport.includes(config.provider),\n\t\t...config,\n\t}\n}\n\nconst defaultRegion = 'eu-west-1'\n\nexport const resolveS3Endpoint = (\n\tconfig: S3Config,\n): {\n\tendpoint: string\n\tbasePath: string\n} => {\n\tconst hasLegacyPath = !!config.endpoint || config.bucket.includes('.')\n\tconst endpoint = config.endpoint || `https://${hasLegacyPath ? '' : `${config.bucket}.`}s3.${config.region || defaultRegion}.amazonaws.com`\n\tconst basePath = hasLegacyPath ? `/${config.bucket}` : ''\n\n\treturn { endpoint, basePath }\n}\n\nexport const resolveS3PublicBaseUrl = (config: S3Config): string => {\n\tif (config.cdnEndpoint) {\n\t\treturn config.cdnEndpoint\n\t}\n\tconst { endpoint, basePath } = resolveS3Endpoint(config)\n\treturn endpoint + basePath\n}\n"],"names":["Typesafe"],"mappings":";;;;;;;;;;;;;;;;;;;;AAUO,MAAM,iBAAiBA,oBAAS;AAAA,EACtCA,oBAAS,OAAO;AAAA,IACf,QAAQA,oBAAS;AAAA,IACjB,QAAQA,oBAAS;AAAA,IACjB,QAAQA,oBAAS;AAAA,IACjB,aAAaA,oBAAS,OAAO;AAAA,MAC5B,KAAKA,oBAAS;AAAA,MACd,QAAQA,oBAAS;AAAA,IAAA,CACjB;AAAA,EAAA,CACD;AAAA,EACDA,oBAAS,QAAQ;AAAA,IAChB,UAAUA,oBAAS;AAAA,IACnB,aAAaA,oBAAS;AAAA,IACtB,UAAUA,oBAAS;AAAA,MAAY;AAAA,MAAiB;AAAA,MAAmB;AAAA,MAAkB;AAAA,MAAwB;AAAA;AAAA,IAAA;AAAA,IAC7G,OAAOA,oBAAS;AAAA,EAAA,CAChB;AACF;AAOA,MAAM,2BAA2B;AAAA,EAAC;AAAA;AAAA;AAE3B,MAAM,kBAAkB,CAAC,WAA+B;AAC9D,SAAO;AAAA,IACN,OAAO,CAAC,CAAC,OAAO,YAAY,yBAAyB,SAAS,OAAO,QAAQ;AAAA,IAC7E,GAAG;AAAA,EAAA;AAEL;AAEA,MAAM,gBAAgB;AAEf,MAAM,oBAAoB,CAChC,WAII;AACJ,QAAM,gBAAgB,CAAC,CAAC,OAAO,YAAY,OAAO,OAAO,SAAS,GAAG;AACrE,QAAM,WAAW,OAAO,YAAY,WAAW,gBAAgB,KAAK,GAAG,OAAO,MAAM,GAAG,MAAM,OAAO,UAAU,aAAa;AAC3H,QAAM,WAAW,gBAAgB,IAAI,OAAO,MAAM,KAAK;AAEvD,SAAO,EAAE,UAAU,SAAA;AACpB;AAEO,MAAM,yBAAyB,CAAC,WAA6B;AACnE,MAAI,OAAO,aAAa;AACvB,WAAO,OAAO;AAAA,EACf;AACA,QAAM,EAAE,UAAU,aAAa,kBAAkB,MAAM;AACvD,SAAO,WAAW;AACnB;;;;;"}
1
+ {"version":3,"file":"Config.cjs","sources":["../../../../packages/engine-s3-plugin/src/Config.ts"],"sourcesContent":["import * as Typesafe from '@contember/typesafe'\n\nexport enum S3Providers {\n\taws = 'aws',\n\t// Path-style addressing with no object ACL — the right value for any MinIO-compatible server, SeaweedFS included.\n\tminio = 'minio',\n\tceph = 'ceph',\n\tlocalstack = 'localstack',\n\tcloudserver = 'cloudserver',\n}\n\nexport const s3ConfigSchema = Typesafe.intersection(\n\tTypesafe.object({\n\t\tbucket: Typesafe.string,\n\t\tregion: Typesafe.string,\n\t\tprefix: Typesafe.string,\n\t\tcredentials: Typesafe.object({\n\t\t\tkey: Typesafe.string,\n\t\t\tsecret: Typesafe.string,\n\t\t}),\n\t}),\n\tTypesafe.partial({\n\t\tendpoint: Typesafe.string,\n\t\tcdnEndpoint: Typesafe.string,\n\t\tprovider: Typesafe.enumeration(S3Providers.aws, S3Providers.minio, S3Providers.ceph, S3Providers.localstack, S3Providers.cloudserver),\n\t\tnoAcl: Typesafe.boolean,\n\t}),\n)\n\nexport type S3Config = ReturnType<typeof s3ConfigSchema>\n\nexport type Project3Config = { s3?: S3Config }\n\n// todo\nconst serversWithoutAclSupport = [S3Providers.minio]\n\nexport const resolveS3Config = (config: S3Config): S3Config => {\n\treturn {\n\t\tnoAcl: !!config.provider && serversWithoutAclSupport.includes(config.provider),\n\t\t...config,\n\t}\n}\n\nconst defaultRegion = 'eu-west-1'\n\nexport const resolveS3Endpoint = (\n\tconfig: S3Config,\n): {\n\tendpoint: string\n\tbasePath: string\n} => {\n\tconst hasLegacyPath = !!config.endpoint || config.bucket.includes('.')\n\tconst endpoint = config.endpoint || `https://${hasLegacyPath ? '' : `${config.bucket}.`}s3.${config.region || defaultRegion}.amazonaws.com`\n\tconst basePath = hasLegacyPath ? `/${config.bucket}` : ''\n\n\treturn { endpoint, basePath }\n}\n\nexport const resolveS3PublicBaseUrl = (config: S3Config): string => {\n\tif (config.cdnEndpoint) {\n\t\treturn config.cdnEndpoint\n\t}\n\tconst { endpoint, basePath } = resolveS3Endpoint(config)\n\treturn endpoint + basePath\n}\n"],"names":["Typesafe"],"mappings":";;;;;;;;;;;;;;;;;;;;AAWO,MAAM,iBAAiBA,oBAAS;AAAA,EACtCA,oBAAS,OAAO;AAAA,IACf,QAAQA,oBAAS;AAAA,IACjB,QAAQA,oBAAS;AAAA,IACjB,QAAQA,oBAAS;AAAA,IACjB,aAAaA,oBAAS,OAAO;AAAA,MAC5B,KAAKA,oBAAS;AAAA,MACd,QAAQA,oBAAS;AAAA,IAAA,CACjB;AAAA,EAAA,CACD;AAAA,EACDA,oBAAS,QAAQ;AAAA,IAChB,UAAUA,oBAAS;AAAA,IACnB,aAAaA,oBAAS;AAAA,IACtB,UAAUA,oBAAS;AAAA,MAAY;AAAA,MAAiB;AAAA,MAAmB;AAAA,MAAkB;AAAA,MAAwB;AAAA;AAAA,IAAA;AAAA,IAC7G,OAAOA,oBAAS;AAAA,EAAA,CAChB;AACF;AAOA,MAAM,2BAA2B;AAAA,EAAC;AAAA;AAAA;AAE3B,MAAM,kBAAkB,CAAC,WAA+B;AAC9D,SAAO;AAAA,IACN,OAAO,CAAC,CAAC,OAAO,YAAY,yBAAyB,SAAS,OAAO,QAAQ;AAAA,IAC7E,GAAG;AAAA,EAAA;AAEL;AAEA,MAAM,gBAAgB;AAEf,MAAM,oBAAoB,CAChC,WAII;AACJ,QAAM,gBAAgB,CAAC,CAAC,OAAO,YAAY,OAAO,OAAO,SAAS,GAAG;AACrE,QAAM,WAAW,OAAO,YAAY,WAAW,gBAAgB,KAAK,GAAG,OAAO,MAAM,GAAG,MAAM,OAAO,UAAU,aAAa;AAC3H,QAAM,WAAW,gBAAgB,IAAI,OAAO,MAAM,KAAK;AAEvD,SAAO,EAAE,UAAU,SAAA;AACpB;AAEO,MAAM,yBAAyB,CAAC,WAA6B;AACnE,MAAI,OAAO,aAAa;AACvB,WAAO,OAAO;AAAA,EACf;AACA,QAAM,EAAE,UAAU,aAAa,kBAAkB,MAAM;AACvD,SAAO,WAAW;AACnB;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Config.js","sources":["../../../../packages/engine-s3-plugin/src/Config.ts"],"sourcesContent":["import * as Typesafe from '@contember/typesafe'\n\nexport enum S3Providers {\n\taws = 'aws',\n\tminio = 'minio',\n\tceph = 'ceph',\n\tlocalstack = 'localstack',\n\tcloudserver = 'cloudserver',\n}\n\nexport const s3ConfigSchema = Typesafe.intersection(\n\tTypesafe.object({\n\t\tbucket: Typesafe.string,\n\t\tregion: Typesafe.string,\n\t\tprefix: Typesafe.string,\n\t\tcredentials: Typesafe.object({\n\t\t\tkey: Typesafe.string,\n\t\t\tsecret: Typesafe.string,\n\t\t}),\n\t}),\n\tTypesafe.partial({\n\t\tendpoint: Typesafe.string,\n\t\tcdnEndpoint: Typesafe.string,\n\t\tprovider: Typesafe.enumeration(S3Providers.aws, S3Providers.minio, S3Providers.ceph, S3Providers.localstack, S3Providers.cloudserver),\n\t\tnoAcl: Typesafe.boolean,\n\t}),\n)\n\nexport type S3Config = ReturnType<typeof s3ConfigSchema>\n\nexport type Project3Config = { s3?: S3Config }\n\n// todo\nconst serversWithoutAclSupport = [S3Providers.minio]\n\nexport const resolveS3Config = (config: S3Config): S3Config => {\n\treturn {\n\t\tnoAcl: !!config.provider && serversWithoutAclSupport.includes(config.provider),\n\t\t...config,\n\t}\n}\n\nconst defaultRegion = 'eu-west-1'\n\nexport const resolveS3Endpoint = (\n\tconfig: S3Config,\n): {\n\tendpoint: string\n\tbasePath: string\n} => {\n\tconst hasLegacyPath = !!config.endpoint || config.bucket.includes('.')\n\tconst endpoint = config.endpoint || `https://${hasLegacyPath ? '' : `${config.bucket}.`}s3.${config.region || defaultRegion}.amazonaws.com`\n\tconst basePath = hasLegacyPath ? `/${config.bucket}` : ''\n\n\treturn { endpoint, basePath }\n}\n\nexport const resolveS3PublicBaseUrl = (config: S3Config): string => {\n\tif (config.cdnEndpoint) {\n\t\treturn config.cdnEndpoint\n\t}\n\tconst { endpoint, basePath } = resolveS3Endpoint(config)\n\treturn endpoint + basePath\n}\n"],"names":[],"mappings":";AAUO,MAAM,iBAAiB,SAAS;AAAA,EACtC,SAAS,OAAO;AAAA,IACf,QAAQ,SAAS;AAAA,IACjB,QAAQ,SAAS;AAAA,IACjB,QAAQ,SAAS;AAAA,IACjB,aAAa,SAAS,OAAO;AAAA,MAC5B,KAAK,SAAS;AAAA,MACd,QAAQ,SAAS;AAAA,IAAA,CACjB;AAAA,EAAA,CACD;AAAA,EACD,SAAS,QAAQ;AAAA,IAChB,UAAU,SAAS;AAAA,IACnB,aAAa,SAAS;AAAA,IACtB,UAAU,SAAS;AAAA,MAAY;AAAA,MAAiB;AAAA,MAAmB;AAAA,MAAkB;AAAA,MAAwB;AAAA;AAAA,IAAA;AAAA,IAC7G,OAAO,SAAS;AAAA,EAAA,CAChB;AACF;AAOA,MAAM,2BAA2B;AAAA,EAAC;AAAA;AAAA;AAE3B,MAAM,kBAAkB,CAAC,WAA+B;AAC9D,SAAO;AAAA,IACN,OAAO,CAAC,CAAC,OAAO,YAAY,yBAAyB,SAAS,OAAO,QAAQ;AAAA,IAC7E,GAAG;AAAA,EAAA;AAEL;AAEA,MAAM,gBAAgB;AAEf,MAAM,oBAAoB,CAChC,WAII;AACJ,QAAM,gBAAgB,CAAC,CAAC,OAAO,YAAY,OAAO,OAAO,SAAS,GAAG;AACrE,QAAM,WAAW,OAAO,YAAY,WAAW,gBAAgB,KAAK,GAAG,OAAO,MAAM,GAAG,MAAM,OAAO,UAAU,aAAa;AAC3H,QAAM,WAAW,gBAAgB,IAAI,OAAO,MAAM,KAAK;AAEvD,SAAO,EAAE,UAAU,SAAA;AACpB;AAEO,MAAM,yBAAyB,CAAC,WAA6B;AACnE,MAAI,OAAO,aAAa;AACvB,WAAO,OAAO;AAAA,EACf;AACA,QAAM,EAAE,UAAU,aAAa,kBAAkB,MAAM;AACvD,SAAO,WAAW;AACnB;"}
1
+ {"version":3,"file":"Config.js","sources":["../../../../packages/engine-s3-plugin/src/Config.ts"],"sourcesContent":["import * as Typesafe from '@contember/typesafe'\n\nexport enum S3Providers {\n\taws = 'aws',\n\t// Path-style addressing with no object ACL — the right value for any MinIO-compatible server, SeaweedFS included.\n\tminio = 'minio',\n\tceph = 'ceph',\n\tlocalstack = 'localstack',\n\tcloudserver = 'cloudserver',\n}\n\nexport const s3ConfigSchema = Typesafe.intersection(\n\tTypesafe.object({\n\t\tbucket: Typesafe.string,\n\t\tregion: Typesafe.string,\n\t\tprefix: Typesafe.string,\n\t\tcredentials: Typesafe.object({\n\t\t\tkey: Typesafe.string,\n\t\t\tsecret: Typesafe.string,\n\t\t}),\n\t}),\n\tTypesafe.partial({\n\t\tendpoint: Typesafe.string,\n\t\tcdnEndpoint: Typesafe.string,\n\t\tprovider: Typesafe.enumeration(S3Providers.aws, S3Providers.minio, S3Providers.ceph, S3Providers.localstack, S3Providers.cloudserver),\n\t\tnoAcl: Typesafe.boolean,\n\t}),\n)\n\nexport type S3Config = ReturnType<typeof s3ConfigSchema>\n\nexport type Project3Config = { s3?: S3Config }\n\n// todo\nconst serversWithoutAclSupport = [S3Providers.minio]\n\nexport const resolveS3Config = (config: S3Config): S3Config => {\n\treturn {\n\t\tnoAcl: !!config.provider && serversWithoutAclSupport.includes(config.provider),\n\t\t...config,\n\t}\n}\n\nconst defaultRegion = 'eu-west-1'\n\nexport const resolveS3Endpoint = (\n\tconfig: S3Config,\n): {\n\tendpoint: string\n\tbasePath: string\n} => {\n\tconst hasLegacyPath = !!config.endpoint || config.bucket.includes('.')\n\tconst endpoint = config.endpoint || `https://${hasLegacyPath ? '' : `${config.bucket}.`}s3.${config.region || defaultRegion}.amazonaws.com`\n\tconst basePath = hasLegacyPath ? `/${config.bucket}` : ''\n\n\treturn { endpoint, basePath }\n}\n\nexport const resolveS3PublicBaseUrl = (config: S3Config): string => {\n\tif (config.cdnEndpoint) {\n\t\treturn config.cdnEndpoint\n\t}\n\tconst { endpoint, basePath } = resolveS3Endpoint(config)\n\treturn endpoint + basePath\n}\n"],"names":[],"mappings":";AAWO,MAAM,iBAAiB,SAAS;AAAA,EACtC,SAAS,OAAO;AAAA,IACf,QAAQ,SAAS;AAAA,IACjB,QAAQ,SAAS;AAAA,IACjB,QAAQ,SAAS;AAAA,IACjB,aAAa,SAAS,OAAO;AAAA,MAC5B,KAAK,SAAS;AAAA,MACd,QAAQ,SAAS;AAAA,IAAA,CACjB;AAAA,EAAA,CACD;AAAA,EACD,SAAS,QAAQ;AAAA,IAChB,UAAU,SAAS;AAAA,IACnB,aAAa,SAAS;AAAA,IACtB,UAAU,SAAS;AAAA,MAAY;AAAA,MAAiB;AAAA,MAAmB;AAAA,MAAkB;AAAA,MAAwB;AAAA;AAAA,IAAA;AAAA,IAC7G,OAAO,SAAS;AAAA,EAAA,CAChB;AACF;AAOA,MAAM,2BAA2B;AAAA,EAAC;AAAA;AAAA;AAE3B,MAAM,kBAAkB,CAAC,WAA+B;AAC9D,SAAO;AAAA,IACN,OAAO,CAAC,CAAC,OAAO,YAAY,yBAAyB,SAAS,OAAO,QAAQ;AAAA,IAC7E,GAAG;AAAA,EAAA;AAEL;AAEA,MAAM,gBAAgB;AAEf,MAAM,oBAAoB,CAChC,WAII;AACJ,QAAM,gBAAgB,CAAC,CAAC,OAAO,YAAY,OAAO,OAAO,SAAS,GAAG;AACrE,QAAM,WAAW,OAAO,YAAY,WAAW,gBAAgB,KAAK,GAAG,OAAO,MAAM,GAAG,MAAM,OAAO,UAAU,aAAa;AAC3H,QAAM,WAAW,gBAAgB,IAAI,OAAO,MAAM,KAAK;AAEvD,SAAO,EAAE,UAAU,SAAA;AACpB;AAEO,MAAM,yBAAyB,CAAC,WAA6B;AACnE,MAAI,OAAO,aAAa;AACvB,WAAO,OAAO;AAAA,EACf;AACA,QAAM,EAAE,UAAU,aAAa,kBAAkB,MAAM;AACvD,SAAO,WAAW;AACnB;"}
@@ -6,11 +6,13 @@ var __defProp = Object.defineProperty;
6
6
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
7
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8
8
  class S3ObjectAuthorizator {
9
- constructor(uploadRules, readRules) {
9
+ constructor(uploadRules, readRules, deleteRules = []) {
10
10
  __publicField(this, "uploadRules");
11
11
  __publicField(this, "readRules");
12
+ __publicField(this, "deleteRules");
12
13
  this.uploadRules = uploadRules;
13
14
  this.readRules = readRules;
15
+ this.deleteRules = deleteRules;
14
16
  }
15
17
  verifyReadAccess({ key }) {
16
18
  for (const rule of this.readRules) {
@@ -21,6 +23,15 @@ class S3ObjectAuthorizator {
21
23
  }
22
24
  throw new graphqlUtils.ForbiddenError(`Read access forbidden for object key ${key}`);
23
25
  }
26
+ verifyDeleteAccess({ key }) {
27
+ for (const rule of this.deleteRules) {
28
+ rule.matcher ?? (rule.matcher = pm(rule.pattern));
29
+ if (rule.matcher(key)) {
30
+ return;
31
+ }
32
+ }
33
+ throw new graphqlUtils.ForbiddenError(`Delete access forbidden for object key ${key}`);
34
+ }
24
35
  verifyUploadAccess({ key, size }) {
25
36
  const matchedPatterns = [];
26
37
  for (const rule of this.uploadRules) {
@@ -1 +1 @@
1
- {"version":3,"file":"S3ObjectAuthorizator.cjs","sources":["../../../../packages/engine-s3-plugin/src/S3ObjectAuthorizator.ts"],"sourcesContent":["/// <reference path=\"../types/picomatch/index.d.ts\" />\nimport pm from 'picomatch'\nimport { ForbiddenError } from '@contember/graphql-utils'\n\nexport type S3ObjectUploadRule = {\n\tpattern: string\n\tmaxSize?: number\n\tmatcher?: (key: string) => boolean\n}\n\nexport type S3ObjectReadRule = {\n\tpattern: string\n\tmatcher?: (key: string) => boolean\n}\n\nexport class S3ObjectAuthorizator {\n\tprivate readonly uploadRules: S3ObjectUploadRule[]\n\tprivate readonly readRules: S3ObjectReadRule[]\n\n\tconstructor(\n\t\tuploadRules: Omit<S3ObjectUploadRule, 'matcher'>[],\n\t\treadRules: Omit<S3ObjectReadRule, 'matcher'>[],\n\t) {\n\t\tthis.uploadRules = uploadRules\n\t\tthis.readRules = readRules\n\t}\n\n\tpublic verifyReadAccess({ key }: { key: string }): void {\n\t\tfor (const rule of this.readRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Read access forbidden for object key ${key}`)\n\t}\n\n\tpublic verifyUploadAccess({ key, size }: { key: string; size: number | null }): void {\n\t\tconst matchedPatterns: S3ObjectUploadRule[] = []\n\n\t\tfor (const rule of this.uploadRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\tif (!rule.maxSize || (size !== null && size <= rule.maxSize)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tmatchedPatterns.push(rule)\n\t\t\t}\n\t\t}\n\n\t\tif (matchedPatterns.length > 0) {\n\t\t\tif (size === null) {\n\t\t\t\tthrow new ForbiddenError('File size must be provided')\n\t\t\t} else {\n\t\t\t\tthrow new ForbiddenError('Uploaded file is too large')\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Upload access forbidden for object key ${key}`)\n\t}\n}\n"],"names":["ForbiddenError"],"mappings":";;;;;;;AAeO,MAAM,qBAAqB;AAAA,EAIjC,YACC,aACA,WACC;AANF,kBAAA,MAAiB,aAAA;AACjB,kBAAA,MAAiB,WAAA;AAMhB,SAAK,cAAc;AACnB,SAAK,YAAY;AAAA,EAClB;AAAA,EAEO,iBAAiB,EAAE,OAA8B;AACvD,eAAW,QAAQ,KAAK,WAAW;AAClC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,IAAIA,aAAAA,eAAe,wCAAwC,GAAG,EAAE;AAAA,EACvE;AAAA,EAEO,mBAAmB,EAAE,KAAK,QAAoD;AACpF,UAAM,kBAAwC,CAAA;AAE9C,eAAW,QAAQ,KAAK,aAAa;AACpC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB,YAAI,CAAC,KAAK,WAAY,SAAS,QAAQ,QAAQ,KAAK,SAAU;AAC7D;AAAA,QACD;AACA,wBAAgB,KAAK,IAAI;AAAA,MAC1B;AAAA,IACD;AAEA,QAAI,gBAAgB,SAAS,GAAG;AAC/B,UAAI,SAAS,MAAM;AAClB,cAAM,IAAIA,aAAAA,eAAe,4BAA4B;AAAA,MACtD,OAAO;AACN,cAAM,IAAIA,aAAAA,eAAe,4BAA4B;AAAA,MACtD;AAAA,IACD;AAEA,UAAM,IAAIA,aAAAA,eAAe,0CAA0C,GAAG,EAAE;AAAA,EACzE;AACD;;"}
1
+ {"version":3,"file":"S3ObjectAuthorizator.cjs","sources":["../../../../packages/engine-s3-plugin/src/S3ObjectAuthorizator.ts"],"sourcesContent":["/// <reference path=\"../types/picomatch/index.d.ts\" />\nimport pm from 'picomatch'\nimport { ForbiddenError } from '@contember/graphql-utils'\n\nexport type S3ObjectUploadRule = {\n\tpattern: string\n\tmaxSize?: number\n\tmatcher?: (key: string) => boolean\n}\n\nexport type S3ObjectReadRule = {\n\tpattern: string\n\tmatcher?: (key: string) => boolean\n}\n\nexport type S3ObjectDeleteRule = {\n\tpattern: string\n\tmatcher?: (key: string) => boolean\n}\n\nexport class S3ObjectAuthorizator {\n\tprivate readonly uploadRules: S3ObjectUploadRule[]\n\tprivate readonly readRules: S3ObjectReadRule[]\n\tprivate readonly deleteRules: S3ObjectDeleteRule[]\n\n\tconstructor(\n\t\tuploadRules: Omit<S3ObjectUploadRule, 'matcher'>[],\n\t\treadRules: Omit<S3ObjectReadRule, 'matcher'>[],\n\t\tdeleteRules: Omit<S3ObjectDeleteRule, 'matcher'>[] = [],\n\t) {\n\t\tthis.uploadRules = uploadRules\n\t\tthis.readRules = readRules\n\t\tthis.deleteRules = deleteRules\n\t}\n\n\tpublic verifyReadAccess({ key }: { key: string }): void {\n\t\tfor (const rule of this.readRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Read access forbidden for object key ${key}`)\n\t}\n\n\tpublic verifyDeleteAccess({ key }: { key: string }): void {\n\t\tfor (const rule of this.deleteRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Delete access forbidden for object key ${key}`)\n\t}\n\n\tpublic verifyUploadAccess({ key, size }: { key: string; size: number | null }): void {\n\t\tconst matchedPatterns: S3ObjectUploadRule[] = []\n\n\t\tfor (const rule of this.uploadRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\tif (!rule.maxSize || (size !== null && size <= rule.maxSize)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tmatchedPatterns.push(rule)\n\t\t\t}\n\t\t}\n\n\t\tif (matchedPatterns.length > 0) {\n\t\t\tif (size === null) {\n\t\t\t\tthrow new ForbiddenError('File size must be provided')\n\t\t\t} else {\n\t\t\t\tthrow new ForbiddenError('Uploaded file is too large')\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Upload access forbidden for object key ${key}`)\n\t}\n}\n"],"names":["ForbiddenError"],"mappings":";;;;;;;AAoBO,MAAM,qBAAqB;AAAA,EAKjC,YACC,aACA,WACA,cAAqD,CAAA,GACpD;AARF,kBAAA,MAAiB,aAAA;AACjB,kBAAA,MAAiB,WAAA;AACjB,kBAAA,MAAiB,aAAA;AAOhB,SAAK,cAAc;AACnB,SAAK,YAAY;AACjB,SAAK,cAAc;AAAA,EACpB;AAAA,EAEO,iBAAiB,EAAE,OAA8B;AACvD,eAAW,QAAQ,KAAK,WAAW;AAClC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,IAAIA,aAAAA,eAAe,wCAAwC,GAAG,EAAE;AAAA,EACvE;AAAA,EAEO,mBAAmB,EAAE,OAA8B;AACzD,eAAW,QAAQ,KAAK,aAAa;AACpC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,IAAIA,aAAAA,eAAe,0CAA0C,GAAG,EAAE;AAAA,EACzE;AAAA,EAEO,mBAAmB,EAAE,KAAK,QAAoD;AACpF,UAAM,kBAAwC,CAAA;AAE9C,eAAW,QAAQ,KAAK,aAAa;AACpC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB,YAAI,CAAC,KAAK,WAAY,SAAS,QAAQ,QAAQ,KAAK,SAAU;AAC7D;AAAA,QACD;AACA,wBAAgB,KAAK,IAAI;AAAA,MAC1B;AAAA,IACD;AAEA,QAAI,gBAAgB,SAAS,GAAG;AAC/B,UAAI,SAAS,MAAM;AAClB,cAAM,IAAIA,aAAAA,eAAe,4BAA4B;AAAA,MACtD,OAAO;AACN,cAAM,IAAIA,aAAAA,eAAe,4BAA4B;AAAA,MACtD;AAAA,IACD;AAEA,UAAM,IAAIA,aAAAA,eAAe,0CAA0C,GAAG,EAAE;AAAA,EACzE;AACD;;"}
@@ -4,11 +4,13 @@ var __defProp = Object.defineProperty;
4
4
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
5
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6
6
  class S3ObjectAuthorizator {
7
- constructor(uploadRules, readRules) {
7
+ constructor(uploadRules, readRules, deleteRules = []) {
8
8
  __publicField(this, "uploadRules");
9
9
  __publicField(this, "readRules");
10
+ __publicField(this, "deleteRules");
10
11
  this.uploadRules = uploadRules;
11
12
  this.readRules = readRules;
13
+ this.deleteRules = deleteRules;
12
14
  }
13
15
  verifyReadAccess({ key }) {
14
16
  for (const rule of this.readRules) {
@@ -19,6 +21,15 @@ class S3ObjectAuthorizator {
19
21
  }
20
22
  throw new ForbiddenError(`Read access forbidden for object key ${key}`);
21
23
  }
24
+ verifyDeleteAccess({ key }) {
25
+ for (const rule of this.deleteRules) {
26
+ rule.matcher ?? (rule.matcher = pm(rule.pattern));
27
+ if (rule.matcher(key)) {
28
+ return;
29
+ }
30
+ }
31
+ throw new ForbiddenError(`Delete access forbidden for object key ${key}`);
32
+ }
22
33
  verifyUploadAccess({ key, size }) {
23
34
  const matchedPatterns = [];
24
35
  for (const rule of this.uploadRules) {
@@ -1 +1 @@
1
- {"version":3,"file":"S3ObjectAuthorizator.js","sources":["../../../../packages/engine-s3-plugin/src/S3ObjectAuthorizator.ts"],"sourcesContent":["/// <reference path=\"../types/picomatch/index.d.ts\" />\nimport pm from 'picomatch'\nimport { ForbiddenError } from '@contember/graphql-utils'\n\nexport type S3ObjectUploadRule = {\n\tpattern: string\n\tmaxSize?: number\n\tmatcher?: (key: string) => boolean\n}\n\nexport type S3ObjectReadRule = {\n\tpattern: string\n\tmatcher?: (key: string) => boolean\n}\n\nexport class S3ObjectAuthorizator {\n\tprivate readonly uploadRules: S3ObjectUploadRule[]\n\tprivate readonly readRules: S3ObjectReadRule[]\n\n\tconstructor(\n\t\tuploadRules: Omit<S3ObjectUploadRule, 'matcher'>[],\n\t\treadRules: Omit<S3ObjectReadRule, 'matcher'>[],\n\t) {\n\t\tthis.uploadRules = uploadRules\n\t\tthis.readRules = readRules\n\t}\n\n\tpublic verifyReadAccess({ key }: { key: string }): void {\n\t\tfor (const rule of this.readRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Read access forbidden for object key ${key}`)\n\t}\n\n\tpublic verifyUploadAccess({ key, size }: { key: string; size: number | null }): void {\n\t\tconst matchedPatterns: S3ObjectUploadRule[] = []\n\n\t\tfor (const rule of this.uploadRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\tif (!rule.maxSize || (size !== null && size <= rule.maxSize)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tmatchedPatterns.push(rule)\n\t\t\t}\n\t\t}\n\n\t\tif (matchedPatterns.length > 0) {\n\t\t\tif (size === null) {\n\t\t\t\tthrow new ForbiddenError('File size must be provided')\n\t\t\t} else {\n\t\t\t\tthrow new ForbiddenError('Uploaded file is too large')\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Upload access forbidden for object key ${key}`)\n\t}\n}\n"],"names":[],"mappings":";;;;;AAeO,MAAM,qBAAqB;AAAA,EAIjC,YACC,aACA,WACC;AANF,kBAAA,MAAiB,aAAA;AACjB,kBAAA,MAAiB,WAAA;AAMhB,SAAK,cAAc;AACnB,SAAK,YAAY;AAAA,EAClB;AAAA,EAEO,iBAAiB,EAAE,OAA8B;AACvD,eAAW,QAAQ,KAAK,WAAW;AAClC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,IAAI,eAAe,wCAAwC,GAAG,EAAE;AAAA,EACvE;AAAA,EAEO,mBAAmB,EAAE,KAAK,QAAoD;AACpF,UAAM,kBAAwC,CAAA;AAE9C,eAAW,QAAQ,KAAK,aAAa;AACpC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB,YAAI,CAAC,KAAK,WAAY,SAAS,QAAQ,QAAQ,KAAK,SAAU;AAC7D;AAAA,QACD;AACA,wBAAgB,KAAK,IAAI;AAAA,MAC1B;AAAA,IACD;AAEA,QAAI,gBAAgB,SAAS,GAAG;AAC/B,UAAI,SAAS,MAAM;AAClB,cAAM,IAAI,eAAe,4BAA4B;AAAA,MACtD,OAAO;AACN,cAAM,IAAI,eAAe,4BAA4B;AAAA,MACtD;AAAA,IACD;AAEA,UAAM,IAAI,eAAe,0CAA0C,GAAG,EAAE;AAAA,EACzE;AACD;"}
1
+ {"version":3,"file":"S3ObjectAuthorizator.js","sources":["../../../../packages/engine-s3-plugin/src/S3ObjectAuthorizator.ts"],"sourcesContent":["/// <reference path=\"../types/picomatch/index.d.ts\" />\nimport pm from 'picomatch'\nimport { ForbiddenError } from '@contember/graphql-utils'\n\nexport type S3ObjectUploadRule = {\n\tpattern: string\n\tmaxSize?: number\n\tmatcher?: (key: string) => boolean\n}\n\nexport type S3ObjectReadRule = {\n\tpattern: string\n\tmatcher?: (key: string) => boolean\n}\n\nexport type S3ObjectDeleteRule = {\n\tpattern: string\n\tmatcher?: (key: string) => boolean\n}\n\nexport class S3ObjectAuthorizator {\n\tprivate readonly uploadRules: S3ObjectUploadRule[]\n\tprivate readonly readRules: S3ObjectReadRule[]\n\tprivate readonly deleteRules: S3ObjectDeleteRule[]\n\n\tconstructor(\n\t\tuploadRules: Omit<S3ObjectUploadRule, 'matcher'>[],\n\t\treadRules: Omit<S3ObjectReadRule, 'matcher'>[],\n\t\tdeleteRules: Omit<S3ObjectDeleteRule, 'matcher'>[] = [],\n\t) {\n\t\tthis.uploadRules = uploadRules\n\t\tthis.readRules = readRules\n\t\tthis.deleteRules = deleteRules\n\t}\n\n\tpublic verifyReadAccess({ key }: { key: string }): void {\n\t\tfor (const rule of this.readRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Read access forbidden for object key ${key}`)\n\t}\n\n\tpublic verifyDeleteAccess({ key }: { key: string }): void {\n\t\tfor (const rule of this.deleteRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Delete access forbidden for object key ${key}`)\n\t}\n\n\tpublic verifyUploadAccess({ key, size }: { key: string; size: number | null }): void {\n\t\tconst matchedPatterns: S3ObjectUploadRule[] = []\n\n\t\tfor (const rule of this.uploadRules) {\n\t\t\trule.matcher ??= pm(rule.pattern)\n\n\t\t\tif (rule.matcher(key)) {\n\t\t\t\tif (!rule.maxSize || (size !== null && size <= rule.maxSize)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tmatchedPatterns.push(rule)\n\t\t\t}\n\t\t}\n\n\t\tif (matchedPatterns.length > 0) {\n\t\t\tif (size === null) {\n\t\t\t\tthrow new ForbiddenError('File size must be provided')\n\t\t\t} else {\n\t\t\t\tthrow new ForbiddenError('Uploaded file is too large')\n\t\t\t}\n\t\t}\n\n\t\tthrow new ForbiddenError(`Upload access forbidden for object key ${key}`)\n\t}\n}\n"],"names":[],"mappings":";;;;;AAoBO,MAAM,qBAAqB;AAAA,EAKjC,YACC,aACA,WACA,cAAqD,CAAA,GACpD;AARF,kBAAA,MAAiB,aAAA;AACjB,kBAAA,MAAiB,WAAA;AACjB,kBAAA,MAAiB,aAAA;AAOhB,SAAK,cAAc;AACnB,SAAK,YAAY;AACjB,SAAK,cAAc;AAAA,EACpB;AAAA,EAEO,iBAAiB,EAAE,OAA8B;AACvD,eAAW,QAAQ,KAAK,WAAW;AAClC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,IAAI,eAAe,wCAAwC,GAAG,EAAE;AAAA,EACvE;AAAA,EAEO,mBAAmB,EAAE,OAA8B;AACzD,eAAW,QAAQ,KAAK,aAAa;AACpC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,IAAI,eAAe,0CAA0C,GAAG,EAAE;AAAA,EACzE;AAAA,EAEO,mBAAmB,EAAE,KAAK,QAAoD;AACpF,UAAM,kBAAwC,CAAA;AAE9C,eAAW,QAAQ,KAAK,aAAa;AACpC,WAAK,YAAL,KAAK,UAAY,GAAG,KAAK,OAAO;AAEhC,UAAI,KAAK,QAAQ,GAAG,GAAG;AACtB,YAAI,CAAC,KAAK,WAAY,SAAS,QAAQ,QAAQ,KAAK,SAAU;AAC7D;AAAA,QACD;AACA,wBAAgB,KAAK,IAAI;AAAA,MAC1B;AAAA,IACD;AAEA,QAAI,gBAAgB,SAAS,GAAG;AAC/B,UAAI,SAAS,MAAM;AAClB,cAAM,IAAI,eAAe,4BAA4B;AAAA,MACtD,OAAO;AACN,cAAM,IAAI,eAAe,4BAA4B;AAAA,MACtD;AAAA,IACD;AAEA,UAAM,IAAI,eAAe,0CAA0C,GAAG,EAAE;AAAA,EACzE;AACD;"}
@@ -9,30 +9,24 @@ class S3SchemaContributor {
9
9
  this.s3Factory = s3Factory;
10
10
  this.providers = providers;
11
11
  }
12
- getCacheKey({ project }) {
13
- return project.s3 ? "yes" : "no";
12
+ getCacheKey(context) {
13
+ const rules = this.resolveRules(context);
14
+ return rules ? JSON.stringify(rules) : "no";
14
15
  }
15
16
  createSchema(context) {
16
- if (!context.project.s3) {
17
+ const rules = this.resolveRules(context);
18
+ if (!rules) {
17
19
  return void 0;
18
20
  }
19
- const rules = context.identity.projectRoles.flatMap((it) => Object.entries(context.schema.acl.roles[it]?.s3 || {}));
20
- const uploadRules = rules.filter(([, it]) => it.upload).map(([it, val]) => ({
21
- pattern: it,
22
- ...typeof val.upload !== "boolean" ? val.upload : {}
23
- }));
24
- const readRules = rules.filter(([, it]) => it.read).map(([it]) => ({
25
- pattern: it
26
- }));
27
- if (uploadRules.length === 0 && readRules.length === 0) {
28
- return void 0;
29
- }
30
- const authorizator = new S3ObjectAuthorizator.S3ObjectAuthorizator(uploadRules, readRules);
21
+ const authorizator = new S3ObjectAuthorizator.S3ObjectAuthorizator(rules.uploadRules, rules.readRules, rules.deleteRules);
31
22
  const uploadMutation = this.createUploadMutation(authorizator);
32
23
  const readMutation = this.createReadMutation(authorizator);
24
+ const deleteMutation = this.createDeleteMutation(authorizator);
33
25
  const mutation = {
34
26
  generateUploadUrl: uploadMutation,
35
- generateReadUrl: readMutation
27
+ generateReadUrl: readMutation,
28
+ // not "deleteObject" — a content mutation for an entity named "Object" would shadow it
29
+ deleteS3Object: deleteMutation
36
30
  };
37
31
  return {
38
32
  mutation: new graphql.GraphQLObjectType({
@@ -49,6 +43,26 @@ class S3SchemaContributor {
49
43
  })
50
44
  };
51
45
  }
46
+ resolveRules({ project, schema, identity }) {
47
+ if (!project.s3) {
48
+ return void 0;
49
+ }
50
+ const rules = [...identity.projectRoles].sort().flatMap((it) => Object.entries(schema.acl.roles[it]?.s3 || {}));
51
+ const uploadRules = rules.filter(([, it]) => it.upload).map(([it, val]) => ({
52
+ pattern: it,
53
+ ...typeof val.upload !== "boolean" ? val.upload : {}
54
+ }));
55
+ const readRules = rules.filter(([, it]) => it.read).map(([it]) => ({
56
+ pattern: it
57
+ }));
58
+ const deleteRules = rules.filter(([, it]) => it.delete).map(([it]) => ({
59
+ pattern: it
60
+ }));
61
+ if (uploadRules.length === 0 && readRules.length === 0 && deleteRules.length === 0) {
62
+ return void 0;
63
+ }
64
+ return { uploadRules, readRules, deleteRules };
65
+ }
52
66
  createReadMutation(authorizator) {
53
67
  return {
54
68
  type: new graphql.GraphQLNonNull(S3SchemaTypes.S3SignedRead),
@@ -70,6 +84,24 @@ class S3SchemaContributor {
70
84
  }
71
85
  };
72
86
  }
87
+ createDeleteMutation(authorizator) {
88
+ return {
89
+ type: new graphql.GraphQLNonNull(S3SchemaTypes.S3DeletedObject),
90
+ args: {
91
+ objectKey: {
92
+ type: new graphql.GraphQLNonNull(graphql.GraphQLString)
93
+ }
94
+ },
95
+ resolve: async (parent, args, ctx) => {
96
+ if (!ctx.project.s3) {
97
+ throw new graphql.GraphQLError("S3 is not configured for this project");
98
+ }
99
+ const s3Config = Config.resolveS3Config(ctx.project.s3);
100
+ const s3 = this.s3Factory.create(s3Config, this.providers, authorizator);
101
+ return await s3.deleteObject({ objectKey: args.objectKey });
102
+ }
103
+ };
104
+ }
73
105
  createUploadMutation(authorizator) {
74
106
  return {
75
107
  type: new graphql.GraphQLNonNull(S3SchemaTypes.S3SignedUpload),
@@ -1 +1 @@
1
- {"version":3,"file":"S3SchemaContributor.cjs","sources":["../../../../packages/engine-s3-plugin/src/S3SchemaContributor.ts"],"sourcesContent":["import {\n\tGraphQLError,\n\tGraphQLFieldConfig,\n\tGraphQLInt,\n\tGraphQLNonNull,\n\tGraphQLObjectType,\n\tGraphQLSchema,\n\tGraphQLSchemaConfig,\n\tGraphQLString,\n} from 'graphql'\nimport { S3Service, S3ServiceFactory } from './S3Service.js'\nimport { Project3Config, resolveS3Config, S3Config } from './Config.js'\nimport { GraphQLSchemaContributor, GraphQLSchemaContributorContext, Providers } from '@contember/engine-plugins'\nimport * as types from './S3SchemaTypes.js'\nimport { S3Acl, S3GenerateSignedUploadInput, S3SignedRead, S3SignedUpload } from './S3SchemaTypes.js'\nimport { S3ObjectAuthorizator } from './S3ObjectAuthorizator.js'\n\ninterface Identity {\n\tprojectRoles: string[]\n}\n\nexport type S3SchemaUploadAcl =\n\t| boolean\n\t| {\n\t\tmaxSize?: number\n\t}\n\nexport type S3SchemaAcl = Record<\n\tstring, // public/*.jpg\n\t{\n\t\tread?: boolean\n\t\tupload?: S3SchemaUploadAcl\n\t}\n>\n\nexport class S3SchemaContributor implements GraphQLSchemaContributor {\n\tconstructor(\n\t\tprivate readonly s3Factory: S3ServiceFactory,\n\t\tprivate readonly providers: Providers,\n\t) {}\n\n\tgetCacheKey?({ project }: GraphQLSchemaContributorContext): string {\n\t\treturn project.s3 ? 'yes' : 'no'\n\t}\n\n\tcreateSchema(context: GraphQLSchemaContributorContext): GraphQLSchemaConfig | undefined {\n\t\tif (!context.project.s3) {\n\t\t\treturn undefined\n\t\t}\n\t\tconst rules = context.identity.projectRoles.flatMap(it => Object.entries((context.schema.acl.roles[it]?.s3 as S3SchemaAcl) || {}))\n\n\t\tconst uploadRules = rules.filter(([, it]) => it.upload).map(([it, val]) => ({\n\t\t\tpattern: it,\n\t\t\t...(typeof val.upload !== 'boolean' ? val.upload : {}),\n\t\t}))\n\t\tconst readRules = rules.filter(([, it]) => it.read).map(([it]) => ({\n\t\t\tpattern: it,\n\t\t}))\n\n\t\tif (uploadRules.length === 0 && readRules.length === 0) {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst authorizator = new S3ObjectAuthorizator(uploadRules, readRules)\n\t\tconst uploadMutation = this.createUploadMutation(authorizator)\n\t\tconst readMutation = this.createReadMutation(authorizator)\n\t\tconst mutation = {\n\t\t\tgenerateUploadUrl: uploadMutation as GraphQLFieldConfig<any, any, any>,\n\t\t\tgenerateReadUrl: readMutation,\n\t\t}\n\t\treturn {\n\t\t\tmutation: new GraphQLObjectType({\n\t\t\t\tname: 'Mutation',\n\t\t\t\tfields: () => mutation,\n\t\t\t}),\n\t\t\tquery: new GraphQLObjectType({\n\t\t\t\tname: 'Query',\n\t\t\t\tfields: () => ({\n\t\t\t\t\ts3DummyQuery: {\n\t\t\t\t\t\ttype: GraphQLString,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t}),\n\t\t}\n\t}\n\n\tprivate createReadMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, { project: Project3Config }, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3SignedRead),\n\t\t\targs: {\n\t\t\t\tobjectKey: {\n\t\t\t\t\ttype: new GraphQLNonNull(GraphQLString),\n\t\t\t\t},\n\t\t\t\texpiration: {\n\t\t\t\t\ttype: GraphQLInt,\n\t\t\t\t},\n\t\t\t},\n\t\t\tresolve: async (parent: any, args: { objectKey: string; expiration?: number }, ctx: { project: Project3Config }) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn s3.getSignedReadUrl({ objectKey: args.objectKey, expiration: args.expiration ?? null })\n\t\t\t},\n\t\t} as GraphQLFieldConfig<any, any, any>\n\t}\n\n\tprivate createUploadMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, any, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3SignedUpload),\n\t\t\targs: {\n\t\t\t\tinput: { type: types.S3GenerateSignedUploadInput },\n\t\t\t\tcontentType: { type: GraphQLString, deprecationReason: 'Use input.contentType' },\n\t\t\t\texpiration: { type: GraphQLInt, deprecationReason: 'Use input.expiration' },\n\t\t\t\tprefix: { type: GraphQLString, deprecationReason: 'Use input.prefix' },\n\t\t\t\tacl: { type: types.S3Acl, deprecationReason: 'Use input.acl' },\n\t\t\t},\n\t\t\tresolve: async (\n\t\t\t\tparent: any,\n\t\t\t\targs: { input?: Partial<S3GenerateSignedUploadInput>; contentType?: string; acl?: S3Acl; expiration?: number; prefix?: string },\n\t\t\t\tctx: { project: Project3Config },\n\t\t\t) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn s3.getSignedUploadUrl({\n\t\t\t\t\tacl: args.input?.acl ?? args.acl ?? null,\n\t\t\t\t\tcontentDisposition: args.input?.contentDisposition ?? null,\n\t\t\t\t\tcontentType: args.input?.contentType ?? args.contentType ?? null,\n\t\t\t\t\texpiration: args.input?.expiration ?? args.expiration ?? null,\n\t\t\t\t\textension: args.input?.extension ?? null,\n\t\t\t\t\tfileName: args.input?.fileName ?? null,\n\t\t\t\t\tprefix: args.input?.prefix ?? args.prefix ?? null,\n\t\t\t\t\tsuffix: args.input?.suffix ?? null,\n\t\t\t\t\tsize: args.input?.size ?? null,\n\t\t\t\t})\n\t\t\t},\n\t\t}\n\t}\n}\n"],"names":["S3ObjectAuthorizator","GraphQLObjectType","GraphQLString","GraphQLNonNull","S3SignedRead","GraphQLInt","GraphQLError","resolveS3Config","S3SignedUpload","types.S3GenerateSignedUploadInput","types.S3Acl"],"mappings":";;;;;;AAmCO,MAAM,oBAAwD;AAAA,EACpE,YACkB,WACA,WAChB;AAFgB,SAAA,YAAA;AACA,SAAA,YAAA;AAAA,EACf;AAAA,EAEH,YAAa,EAAE,WAAoD;AAClE,WAAO,QAAQ,KAAK,QAAQ;AAAA,EAC7B;AAAA,EAEA,aAAa,SAA2E;AACvF,QAAI,CAAC,QAAQ,QAAQ,IAAI;AACxB,aAAO;AAAA,IACR;AACA,UAAM,QAAQ,QAAQ,SAAS,aAAa,QAAQ,QAAM,OAAO,QAAS,QAAQ,OAAO,IAAI,MAAM,EAAE,GAAG,MAAsB,CAAA,CAAE,CAAC;AAEjI,UAAM,cAAc,MAAM,OAAO,CAAC,CAAA,EAAG,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,GAAG,OAAO;AAAA,MAC3E,SAAS;AAAA,MACT,GAAI,OAAO,IAAI,WAAW,YAAY,IAAI,SAAS,CAAA;AAAA,IAAC,EACnD;AACF,UAAM,YAAY,MAAM,OAAO,CAAC,CAAA,EAAG,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,OAAO;AAAA,MAClE,SAAS;AAAA,IAAA,EACR;AAEF,QAAI,YAAY,WAAW,KAAK,UAAU,WAAW,GAAG;AACvD,aAAO;AAAA,IACR;AAEA,UAAM,eAAe,IAAIA,0CAAqB,aAAa,SAAS;AACpE,UAAM,iBAAiB,KAAK,qBAAqB,YAAY;AAC7D,UAAM,eAAe,KAAK,mBAAmB,YAAY;AACzD,UAAM,WAAW;AAAA,MAChB,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,IAAA;AAElB,WAAO;AAAA,MACN,UAAU,IAAIC,QAAAA,kBAAkB;AAAA,QAC/B,MAAM;AAAA,QACN,QAAQ,MAAM;AAAA,MAAA,CACd;AAAA,MACD,OAAO,IAAIA,QAAAA,kBAAkB;AAAA,QAC5B,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,UACd,cAAc;AAAA,YACb,MAAMC,QAAAA;AAAAA,UAAA;AAAA,QACP;AAAA,MACD,CACA;AAAA,IAAA;AAAA,EAEH;AAAA,EAEQ,mBAAmB,cAA+F;AACzH,WAAO;AAAA,MACN,MAAM,IAAIC,QAAAA,eAAeC,0BAAY;AAAA,MACrC,MAAM;AAAA,QACL,WAAW;AAAA,UACV,MAAM,IAAID,QAAAA,eAAeD,QAAAA,aAAa;AAAA,QAAA;AAAA,QAEvC,YAAY;AAAA,UACX,MAAMG,QAAAA;AAAAA,QAAA;AAAA,MACP;AAAA,MAED,SAAS,OAAO,QAAa,MAAkD,QAAqC;AACnH,YAAI,CAAC,IAAI,QAAQ,IAAI;AACpB,gBAAM,IAAIC,QAAAA,aAAa,uCAAuC;AAAA,QAC/D;AACA,cAAM,WAAWC,OAAAA,gBAAgB,IAAI,QAAQ,EAAE;AAC/C,cAAM,KAAK,KAAK,UAAU,OAAO,UAAU,KAAK,WAAW,YAAY;AACvE,eAAO,GAAG,iBAAiB,EAAE,WAAW,KAAK,WAAW,YAAY,KAAK,cAAc,MAAM;AAAA,MAC9F;AAAA,IAAA;AAAA,EAEF;AAAA,EAEQ,qBAAqB,cAAuE;AACnG,WAAO;AAAA,MACN,MAAM,IAAIJ,QAAAA,eAAeK,4BAAc;AAAA,MACvC,MAAM;AAAA,QACL,OAAO,EAAE,MAAMC,0CAAM;AAAA,QACrB,aAAa,EAAE,MAAMP,uBAAe,mBAAmB,wBAAA;AAAA,QACvD,YAAY,EAAE,MAAMG,oBAAY,mBAAmB,uBAAA;AAAA,QACnD,QAAQ,EAAE,MAAMH,uBAAe,mBAAmB,mBAAA;AAAA,QAClD,KAAK,EAAE,MAAMQ,cAAAA,OAAa,mBAAmB,gBAAA;AAAA,MAAgB;AAAA,MAE9D,SAAS,OACR,QACA,MACA,QACI;AACJ,YAAI,CAAC,IAAI,QAAQ,IAAI;AACpB,gBAAM,IAAIJ,QAAAA,aAAa,uCAAuC;AAAA,QAC/D;AACA,cAAM,WAAWC,OAAAA,gBAAgB,IAAI,QAAQ,EAAE;AAC/C,cAAM,KAAK,KAAK,UAAU,OAAO,UAAU,KAAK,WAAW,YAAY;AACvE,eAAO,GAAG,mBAAmB;AAAA,UAC5B,KAAK,KAAK,OAAO,OAAO,KAAK,OAAO;AAAA,UACpC,oBAAoB,KAAK,OAAO,sBAAsB;AAAA,UACtD,aAAa,KAAK,OAAO,eAAe,KAAK,eAAe;AAAA,UAC5D,YAAY,KAAK,OAAO,cAAc,KAAK,cAAc;AAAA,UACzD,WAAW,KAAK,OAAO,aAAa;AAAA,UACpC,UAAU,KAAK,OAAO,YAAY;AAAA,UAClC,QAAQ,KAAK,OAAO,UAAU,KAAK,UAAU;AAAA,UAC7C,QAAQ,KAAK,OAAO,UAAU;AAAA,UAC9B,MAAM,KAAK,OAAO,QAAQ;AAAA,QAAA,CAC1B;AAAA,MACF;AAAA,IAAA;AAAA,EAEF;AACD;;"}
1
+ {"version":3,"file":"S3SchemaContributor.cjs","sources":["../../../../packages/engine-s3-plugin/src/S3SchemaContributor.ts"],"sourcesContent":["import {\n\tGraphQLError,\n\tGraphQLFieldConfig,\n\tGraphQLInt,\n\tGraphQLNonNull,\n\tGraphQLObjectType,\n\tGraphQLSchema,\n\tGraphQLSchemaConfig,\n\tGraphQLString,\n} from 'graphql'\nimport { S3Service, S3ServiceFactory } from './S3Service.js'\nimport { Project3Config, resolveS3Config, S3Config } from './Config.js'\nimport { GraphQLSchemaContributor, GraphQLSchemaContributorContext, Providers } from '@contember/engine-plugins'\nimport * as types from './S3SchemaTypes.js'\nimport { S3Acl, S3DeletedObject, S3GenerateSignedUploadInput, S3SignedRead, S3SignedUpload } from './S3SchemaTypes.js'\nimport { S3ObjectAuthorizator } from './S3ObjectAuthorizator.js'\n\ninterface Identity {\n\tprojectRoles: string[]\n}\n\nexport type S3SchemaUploadAcl =\n\t| boolean\n\t| {\n\t\tmaxSize?: number\n\t}\n\nexport type S3SchemaAcl = Record<\n\tstring, // public/*.jpg\n\t{\n\t\tread?: boolean\n\t\tupload?: S3SchemaUploadAcl\n\t\tdelete?: boolean\n\t}\n>\n\nexport class S3SchemaContributor implements GraphQLSchemaContributor {\n\tconstructor(\n\t\tprivate readonly s3Factory: S3ServiceFactory,\n\t\tprivate readonly providers: Providers,\n\t) {}\n\n\tgetCacheKey(context: GraphQLSchemaContributorContext): string {\n\t\tconst rules = this.resolveRules(context)\n\t\treturn rules ? JSON.stringify(rules) : 'no'\n\t}\n\n\tcreateSchema(context: GraphQLSchemaContributorContext): GraphQLSchemaConfig | undefined {\n\t\tconst rules = this.resolveRules(context)\n\t\tif (!rules) {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst authorizator = new S3ObjectAuthorizator(rules.uploadRules, rules.readRules, rules.deleteRules)\n\t\tconst uploadMutation = this.createUploadMutation(authorizator)\n\t\tconst readMutation = this.createReadMutation(authorizator)\n\t\tconst deleteMutation = this.createDeleteMutation(authorizator)\n\t\tconst mutation = {\n\t\t\tgenerateUploadUrl: uploadMutation as GraphQLFieldConfig<any, any, any>,\n\t\t\tgenerateReadUrl: readMutation,\n\t\t\t// not \"deleteObject\" — a content mutation for an entity named \"Object\" would shadow it\n\t\t\tdeleteS3Object: deleteMutation,\n\t\t}\n\t\treturn {\n\t\t\tmutation: new GraphQLObjectType({\n\t\t\t\tname: 'Mutation',\n\t\t\t\tfields: () => mutation,\n\t\t\t}),\n\t\t\tquery: new GraphQLObjectType({\n\t\t\t\tname: 'Query',\n\t\t\t\tfields: () => ({\n\t\t\t\t\ts3DummyQuery: {\n\t\t\t\t\t\ttype: GraphQLString,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t}),\n\t\t}\n\t}\n\n\tprivate resolveRules({ project, schema, identity }: GraphQLSchemaContributorContext) {\n\t\tif (!project.s3) {\n\t\t\treturn undefined\n\t\t}\n\t\t// sorted, so getCacheKey does not depend on the order of memberships\n\t\tconst rules = [...identity.projectRoles].sort().flatMap(it => Object.entries((schema.acl.roles[it]?.s3 as S3SchemaAcl) || {}))\n\n\t\tconst uploadRules = rules.filter(([, it]) => it.upload).map(([it, val]) => ({\n\t\t\tpattern: it,\n\t\t\t...(typeof val.upload !== 'boolean' ? val.upload : {}),\n\t\t}))\n\t\tconst readRules = rules.filter(([, it]) => it.read).map(([it]) => ({\n\t\t\tpattern: it,\n\t\t}))\n\t\tconst deleteRules = rules.filter(([, it]) => it.delete).map(([it]) => ({\n\t\t\tpattern: it,\n\t\t}))\n\n\t\tif (uploadRules.length === 0 && readRules.length === 0 && deleteRules.length === 0) {\n\t\t\treturn undefined\n\t\t}\n\t\treturn { uploadRules, readRules, deleteRules }\n\t}\n\n\tprivate createReadMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, { project: Project3Config }, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3SignedRead),\n\t\t\targs: {\n\t\t\t\tobjectKey: {\n\t\t\t\t\ttype: new GraphQLNonNull(GraphQLString),\n\t\t\t\t},\n\t\t\t\texpiration: {\n\t\t\t\t\ttype: GraphQLInt,\n\t\t\t\t},\n\t\t\t},\n\t\t\tresolve: async (parent: any, args: { objectKey: string; expiration?: number }, ctx: { project: Project3Config }) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn s3.getSignedReadUrl({ objectKey: args.objectKey, expiration: args.expiration ?? null })\n\t\t\t},\n\t\t} as GraphQLFieldConfig<any, any, any>\n\t}\n\n\tprivate createDeleteMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, any, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3DeletedObject),\n\t\t\targs: {\n\t\t\t\tobjectKey: {\n\t\t\t\t\ttype: new GraphQLNonNull(GraphQLString),\n\t\t\t\t},\n\t\t\t},\n\t\t\tresolve: async (parent: any, args: { objectKey: string }, ctx: { project: Project3Config }) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn await s3.deleteObject({ objectKey: args.objectKey })\n\t\t\t},\n\t\t}\n\t}\n\n\tprivate createUploadMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, any, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3SignedUpload),\n\t\t\targs: {\n\t\t\t\tinput: { type: types.S3GenerateSignedUploadInput },\n\t\t\t\tcontentType: { type: GraphQLString, deprecationReason: 'Use input.contentType' },\n\t\t\t\texpiration: { type: GraphQLInt, deprecationReason: 'Use input.expiration' },\n\t\t\t\tprefix: { type: GraphQLString, deprecationReason: 'Use input.prefix' },\n\t\t\t\tacl: { type: types.S3Acl, deprecationReason: 'Use input.acl' },\n\t\t\t},\n\t\t\tresolve: async (\n\t\t\t\tparent: any,\n\t\t\t\targs: { input?: Partial<S3GenerateSignedUploadInput>; contentType?: string; acl?: S3Acl; expiration?: number; prefix?: string },\n\t\t\t\tctx: { project: Project3Config },\n\t\t\t) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn s3.getSignedUploadUrl({\n\t\t\t\t\tacl: args.input?.acl ?? args.acl ?? null,\n\t\t\t\t\tcontentDisposition: args.input?.contentDisposition ?? null,\n\t\t\t\t\tcontentType: args.input?.contentType ?? args.contentType ?? null,\n\t\t\t\t\texpiration: args.input?.expiration ?? args.expiration ?? null,\n\t\t\t\t\textension: args.input?.extension ?? null,\n\t\t\t\t\tfileName: args.input?.fileName ?? null,\n\t\t\t\t\tprefix: args.input?.prefix ?? args.prefix ?? null,\n\t\t\t\t\tsuffix: args.input?.suffix ?? null,\n\t\t\t\t\tsize: args.input?.size ?? null,\n\t\t\t\t})\n\t\t\t},\n\t\t}\n\t}\n}\n"],"names":["S3ObjectAuthorizator","GraphQLObjectType","GraphQLString","GraphQLNonNull","S3SignedRead","GraphQLInt","GraphQLError","resolveS3Config","S3DeletedObject","S3SignedUpload","types.S3GenerateSignedUploadInput","types.S3Acl"],"mappings":"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"}
@@ -1,36 +1,30 @@
1
1
  import { GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLNonNull, GraphQLError } from "graphql";
2
2
  import { resolveS3Config } from "./Config.js";
3
- import { S3SignedRead, S3Acl, S3GenerateSignedUploadInput, S3SignedUpload } from "./S3SchemaTypes.js";
3
+ import { S3SignedRead, S3DeletedObject, S3Acl, S3GenerateSignedUploadInput, S3SignedUpload } from "./S3SchemaTypes.js";
4
4
  import { S3ObjectAuthorizator } from "./S3ObjectAuthorizator.js";
5
5
  class S3SchemaContributor {
6
6
  constructor(s3Factory, providers) {
7
7
  this.s3Factory = s3Factory;
8
8
  this.providers = providers;
9
9
  }
10
- getCacheKey({ project }) {
11
- return project.s3 ? "yes" : "no";
10
+ getCacheKey(context) {
11
+ const rules = this.resolveRules(context);
12
+ return rules ? JSON.stringify(rules) : "no";
12
13
  }
13
14
  createSchema(context) {
14
- if (!context.project.s3) {
15
+ const rules = this.resolveRules(context);
16
+ if (!rules) {
15
17
  return void 0;
16
18
  }
17
- const rules = context.identity.projectRoles.flatMap((it) => Object.entries(context.schema.acl.roles[it]?.s3 || {}));
18
- const uploadRules = rules.filter(([, it]) => it.upload).map(([it, val]) => ({
19
- pattern: it,
20
- ...typeof val.upload !== "boolean" ? val.upload : {}
21
- }));
22
- const readRules = rules.filter(([, it]) => it.read).map(([it]) => ({
23
- pattern: it
24
- }));
25
- if (uploadRules.length === 0 && readRules.length === 0) {
26
- return void 0;
27
- }
28
- const authorizator = new S3ObjectAuthorizator(uploadRules, readRules);
19
+ const authorizator = new S3ObjectAuthorizator(rules.uploadRules, rules.readRules, rules.deleteRules);
29
20
  const uploadMutation = this.createUploadMutation(authorizator);
30
21
  const readMutation = this.createReadMutation(authorizator);
22
+ const deleteMutation = this.createDeleteMutation(authorizator);
31
23
  const mutation = {
32
24
  generateUploadUrl: uploadMutation,
33
- generateReadUrl: readMutation
25
+ generateReadUrl: readMutation,
26
+ // not "deleteObject" — a content mutation for an entity named "Object" would shadow it
27
+ deleteS3Object: deleteMutation
34
28
  };
35
29
  return {
36
30
  mutation: new GraphQLObjectType({
@@ -47,6 +41,26 @@ class S3SchemaContributor {
47
41
  })
48
42
  };
49
43
  }
44
+ resolveRules({ project, schema, identity }) {
45
+ if (!project.s3) {
46
+ return void 0;
47
+ }
48
+ const rules = [...identity.projectRoles].sort().flatMap((it) => Object.entries(schema.acl.roles[it]?.s3 || {}));
49
+ const uploadRules = rules.filter(([, it]) => it.upload).map(([it, val]) => ({
50
+ pattern: it,
51
+ ...typeof val.upload !== "boolean" ? val.upload : {}
52
+ }));
53
+ const readRules = rules.filter(([, it]) => it.read).map(([it]) => ({
54
+ pattern: it
55
+ }));
56
+ const deleteRules = rules.filter(([, it]) => it.delete).map(([it]) => ({
57
+ pattern: it
58
+ }));
59
+ if (uploadRules.length === 0 && readRules.length === 0 && deleteRules.length === 0) {
60
+ return void 0;
61
+ }
62
+ return { uploadRules, readRules, deleteRules };
63
+ }
50
64
  createReadMutation(authorizator) {
51
65
  return {
52
66
  type: new GraphQLNonNull(S3SignedRead),
@@ -68,6 +82,24 @@ class S3SchemaContributor {
68
82
  }
69
83
  };
70
84
  }
85
+ createDeleteMutation(authorizator) {
86
+ return {
87
+ type: new GraphQLNonNull(S3DeletedObject),
88
+ args: {
89
+ objectKey: {
90
+ type: new GraphQLNonNull(GraphQLString)
91
+ }
92
+ },
93
+ resolve: async (parent, args, ctx) => {
94
+ if (!ctx.project.s3) {
95
+ throw new GraphQLError("S3 is not configured for this project");
96
+ }
97
+ const s3Config = resolveS3Config(ctx.project.s3);
98
+ const s3 = this.s3Factory.create(s3Config, this.providers, authorizator);
99
+ return await s3.deleteObject({ objectKey: args.objectKey });
100
+ }
101
+ };
102
+ }
71
103
  createUploadMutation(authorizator) {
72
104
  return {
73
105
  type: new GraphQLNonNull(S3SignedUpload),
@@ -1 +1 @@
1
- {"version":3,"file":"S3SchemaContributor.js","sources":["../../../../packages/engine-s3-plugin/src/S3SchemaContributor.ts"],"sourcesContent":["import {\n\tGraphQLError,\n\tGraphQLFieldConfig,\n\tGraphQLInt,\n\tGraphQLNonNull,\n\tGraphQLObjectType,\n\tGraphQLSchema,\n\tGraphQLSchemaConfig,\n\tGraphQLString,\n} from 'graphql'\nimport { S3Service, S3ServiceFactory } from './S3Service.js'\nimport { Project3Config, resolveS3Config, S3Config } from './Config.js'\nimport { GraphQLSchemaContributor, GraphQLSchemaContributorContext, Providers } from '@contember/engine-plugins'\nimport * as types from './S3SchemaTypes.js'\nimport { S3Acl, S3GenerateSignedUploadInput, S3SignedRead, S3SignedUpload } from './S3SchemaTypes.js'\nimport { S3ObjectAuthorizator } from './S3ObjectAuthorizator.js'\n\ninterface Identity {\n\tprojectRoles: string[]\n}\n\nexport type S3SchemaUploadAcl =\n\t| boolean\n\t| {\n\t\tmaxSize?: number\n\t}\n\nexport type S3SchemaAcl = Record<\n\tstring, // public/*.jpg\n\t{\n\t\tread?: boolean\n\t\tupload?: S3SchemaUploadAcl\n\t}\n>\n\nexport class S3SchemaContributor implements GraphQLSchemaContributor {\n\tconstructor(\n\t\tprivate readonly s3Factory: S3ServiceFactory,\n\t\tprivate readonly providers: Providers,\n\t) {}\n\n\tgetCacheKey?({ project }: GraphQLSchemaContributorContext): string {\n\t\treturn project.s3 ? 'yes' : 'no'\n\t}\n\n\tcreateSchema(context: GraphQLSchemaContributorContext): GraphQLSchemaConfig | undefined {\n\t\tif (!context.project.s3) {\n\t\t\treturn undefined\n\t\t}\n\t\tconst rules = context.identity.projectRoles.flatMap(it => Object.entries((context.schema.acl.roles[it]?.s3 as S3SchemaAcl) || {}))\n\n\t\tconst uploadRules = rules.filter(([, it]) => it.upload).map(([it, val]) => ({\n\t\t\tpattern: it,\n\t\t\t...(typeof val.upload !== 'boolean' ? val.upload : {}),\n\t\t}))\n\t\tconst readRules = rules.filter(([, it]) => it.read).map(([it]) => ({\n\t\t\tpattern: it,\n\t\t}))\n\n\t\tif (uploadRules.length === 0 && readRules.length === 0) {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst authorizator = new S3ObjectAuthorizator(uploadRules, readRules)\n\t\tconst uploadMutation = this.createUploadMutation(authorizator)\n\t\tconst readMutation = this.createReadMutation(authorizator)\n\t\tconst mutation = {\n\t\t\tgenerateUploadUrl: uploadMutation as GraphQLFieldConfig<any, any, any>,\n\t\t\tgenerateReadUrl: readMutation,\n\t\t}\n\t\treturn {\n\t\t\tmutation: new GraphQLObjectType({\n\t\t\t\tname: 'Mutation',\n\t\t\t\tfields: () => mutation,\n\t\t\t}),\n\t\t\tquery: new GraphQLObjectType({\n\t\t\t\tname: 'Query',\n\t\t\t\tfields: () => ({\n\t\t\t\t\ts3DummyQuery: {\n\t\t\t\t\t\ttype: GraphQLString,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t}),\n\t\t}\n\t}\n\n\tprivate createReadMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, { project: Project3Config }, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3SignedRead),\n\t\t\targs: {\n\t\t\t\tobjectKey: {\n\t\t\t\t\ttype: new GraphQLNonNull(GraphQLString),\n\t\t\t\t},\n\t\t\t\texpiration: {\n\t\t\t\t\ttype: GraphQLInt,\n\t\t\t\t},\n\t\t\t},\n\t\t\tresolve: async (parent: any, args: { objectKey: string; expiration?: number }, ctx: { project: Project3Config }) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn s3.getSignedReadUrl({ objectKey: args.objectKey, expiration: args.expiration ?? null })\n\t\t\t},\n\t\t} as GraphQLFieldConfig<any, any, any>\n\t}\n\n\tprivate createUploadMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, any, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3SignedUpload),\n\t\t\targs: {\n\t\t\t\tinput: { type: types.S3GenerateSignedUploadInput },\n\t\t\t\tcontentType: { type: GraphQLString, deprecationReason: 'Use input.contentType' },\n\t\t\t\texpiration: { type: GraphQLInt, deprecationReason: 'Use input.expiration' },\n\t\t\t\tprefix: { type: GraphQLString, deprecationReason: 'Use input.prefix' },\n\t\t\t\tacl: { type: types.S3Acl, deprecationReason: 'Use input.acl' },\n\t\t\t},\n\t\t\tresolve: async (\n\t\t\t\tparent: any,\n\t\t\t\targs: { input?: Partial<S3GenerateSignedUploadInput>; contentType?: string; acl?: S3Acl; expiration?: number; prefix?: string },\n\t\t\t\tctx: { project: Project3Config },\n\t\t\t) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn s3.getSignedUploadUrl({\n\t\t\t\t\tacl: args.input?.acl ?? args.acl ?? null,\n\t\t\t\t\tcontentDisposition: args.input?.contentDisposition ?? null,\n\t\t\t\t\tcontentType: args.input?.contentType ?? args.contentType ?? null,\n\t\t\t\t\texpiration: args.input?.expiration ?? args.expiration ?? null,\n\t\t\t\t\textension: args.input?.extension ?? null,\n\t\t\t\t\tfileName: args.input?.fileName ?? null,\n\t\t\t\t\tprefix: args.input?.prefix ?? args.prefix ?? null,\n\t\t\t\t\tsuffix: args.input?.suffix ?? null,\n\t\t\t\t\tsize: args.input?.size ?? null,\n\t\t\t\t})\n\t\t\t},\n\t\t}\n\t}\n}\n"],"names":["types.S3GenerateSignedUploadInput","types.S3Acl"],"mappings":"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"}
1
+ {"version":3,"file":"S3SchemaContributor.js","sources":["../../../../packages/engine-s3-plugin/src/S3SchemaContributor.ts"],"sourcesContent":["import {\n\tGraphQLError,\n\tGraphQLFieldConfig,\n\tGraphQLInt,\n\tGraphQLNonNull,\n\tGraphQLObjectType,\n\tGraphQLSchema,\n\tGraphQLSchemaConfig,\n\tGraphQLString,\n} from 'graphql'\nimport { S3Service, S3ServiceFactory } from './S3Service.js'\nimport { Project3Config, resolveS3Config, S3Config } from './Config.js'\nimport { GraphQLSchemaContributor, GraphQLSchemaContributorContext, Providers } from '@contember/engine-plugins'\nimport * as types from './S3SchemaTypes.js'\nimport { S3Acl, S3DeletedObject, S3GenerateSignedUploadInput, S3SignedRead, S3SignedUpload } from './S3SchemaTypes.js'\nimport { S3ObjectAuthorizator } from './S3ObjectAuthorizator.js'\n\ninterface Identity {\n\tprojectRoles: string[]\n}\n\nexport type S3SchemaUploadAcl =\n\t| boolean\n\t| {\n\t\tmaxSize?: number\n\t}\n\nexport type S3SchemaAcl = Record<\n\tstring, // public/*.jpg\n\t{\n\t\tread?: boolean\n\t\tupload?: S3SchemaUploadAcl\n\t\tdelete?: boolean\n\t}\n>\n\nexport class S3SchemaContributor implements GraphQLSchemaContributor {\n\tconstructor(\n\t\tprivate readonly s3Factory: S3ServiceFactory,\n\t\tprivate readonly providers: Providers,\n\t) {}\n\n\tgetCacheKey(context: GraphQLSchemaContributorContext): string {\n\t\tconst rules = this.resolveRules(context)\n\t\treturn rules ? JSON.stringify(rules) : 'no'\n\t}\n\n\tcreateSchema(context: GraphQLSchemaContributorContext): GraphQLSchemaConfig | undefined {\n\t\tconst rules = this.resolveRules(context)\n\t\tif (!rules) {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst authorizator = new S3ObjectAuthorizator(rules.uploadRules, rules.readRules, rules.deleteRules)\n\t\tconst uploadMutation = this.createUploadMutation(authorizator)\n\t\tconst readMutation = this.createReadMutation(authorizator)\n\t\tconst deleteMutation = this.createDeleteMutation(authorizator)\n\t\tconst mutation = {\n\t\t\tgenerateUploadUrl: uploadMutation as GraphQLFieldConfig<any, any, any>,\n\t\t\tgenerateReadUrl: readMutation,\n\t\t\t// not \"deleteObject\" — a content mutation for an entity named \"Object\" would shadow it\n\t\t\tdeleteS3Object: deleteMutation,\n\t\t}\n\t\treturn {\n\t\t\tmutation: new GraphQLObjectType({\n\t\t\t\tname: 'Mutation',\n\t\t\t\tfields: () => mutation,\n\t\t\t}),\n\t\t\tquery: new GraphQLObjectType({\n\t\t\t\tname: 'Query',\n\t\t\t\tfields: () => ({\n\t\t\t\t\ts3DummyQuery: {\n\t\t\t\t\t\ttype: GraphQLString,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t}),\n\t\t}\n\t}\n\n\tprivate resolveRules({ project, schema, identity }: GraphQLSchemaContributorContext) {\n\t\tif (!project.s3) {\n\t\t\treturn undefined\n\t\t}\n\t\t// sorted, so getCacheKey does not depend on the order of memberships\n\t\tconst rules = [...identity.projectRoles].sort().flatMap(it => Object.entries((schema.acl.roles[it]?.s3 as S3SchemaAcl) || {}))\n\n\t\tconst uploadRules = rules.filter(([, it]) => it.upload).map(([it, val]) => ({\n\t\t\tpattern: it,\n\t\t\t...(typeof val.upload !== 'boolean' ? val.upload : {}),\n\t\t}))\n\t\tconst readRules = rules.filter(([, it]) => it.read).map(([it]) => ({\n\t\t\tpattern: it,\n\t\t}))\n\t\tconst deleteRules = rules.filter(([, it]) => it.delete).map(([it]) => ({\n\t\t\tpattern: it,\n\t\t}))\n\n\t\tif (uploadRules.length === 0 && readRules.length === 0 && deleteRules.length === 0) {\n\t\t\treturn undefined\n\t\t}\n\t\treturn { uploadRules, readRules, deleteRules }\n\t}\n\n\tprivate createReadMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, { project: Project3Config }, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3SignedRead),\n\t\t\targs: {\n\t\t\t\tobjectKey: {\n\t\t\t\t\ttype: new GraphQLNonNull(GraphQLString),\n\t\t\t\t},\n\t\t\t\texpiration: {\n\t\t\t\t\ttype: GraphQLInt,\n\t\t\t\t},\n\t\t\t},\n\t\t\tresolve: async (parent: any, args: { objectKey: string; expiration?: number }, ctx: { project: Project3Config }) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn s3.getSignedReadUrl({ objectKey: args.objectKey, expiration: args.expiration ?? null })\n\t\t\t},\n\t\t} as GraphQLFieldConfig<any, any, any>\n\t}\n\n\tprivate createDeleteMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, any, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3DeletedObject),\n\t\t\targs: {\n\t\t\t\tobjectKey: {\n\t\t\t\t\ttype: new GraphQLNonNull(GraphQLString),\n\t\t\t\t},\n\t\t\t},\n\t\t\tresolve: async (parent: any, args: { objectKey: string }, ctx: { project: Project3Config }) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn await s3.deleteObject({ objectKey: args.objectKey })\n\t\t\t},\n\t\t}\n\t}\n\n\tprivate createUploadMutation(authorizator: S3ObjectAuthorizator): GraphQLFieldConfig<any, any, any> {\n\t\treturn {\n\t\t\ttype: new GraphQLNonNull(S3SignedUpload),\n\t\t\targs: {\n\t\t\t\tinput: { type: types.S3GenerateSignedUploadInput },\n\t\t\t\tcontentType: { type: GraphQLString, deprecationReason: 'Use input.contentType' },\n\t\t\t\texpiration: { type: GraphQLInt, deprecationReason: 'Use input.expiration' },\n\t\t\t\tprefix: { type: GraphQLString, deprecationReason: 'Use input.prefix' },\n\t\t\t\tacl: { type: types.S3Acl, deprecationReason: 'Use input.acl' },\n\t\t\t},\n\t\t\tresolve: async (\n\t\t\t\tparent: any,\n\t\t\t\targs: { input?: Partial<S3GenerateSignedUploadInput>; contentType?: string; acl?: S3Acl; expiration?: number; prefix?: string },\n\t\t\t\tctx: { project: Project3Config },\n\t\t\t) => {\n\t\t\t\tif (!ctx.project.s3) {\n\t\t\t\t\tthrow new GraphQLError('S3 is not configured for this project')\n\t\t\t\t}\n\t\t\t\tconst s3Config = resolveS3Config(ctx.project.s3)\n\t\t\t\tconst s3 = this.s3Factory.create(s3Config, this.providers, authorizator)\n\t\t\t\treturn s3.getSignedUploadUrl({\n\t\t\t\t\tacl: args.input?.acl ?? args.acl ?? null,\n\t\t\t\t\tcontentDisposition: args.input?.contentDisposition ?? null,\n\t\t\t\t\tcontentType: args.input?.contentType ?? args.contentType ?? null,\n\t\t\t\t\texpiration: args.input?.expiration ?? args.expiration ?? null,\n\t\t\t\t\textension: args.input?.extension ?? null,\n\t\t\t\t\tfileName: args.input?.fileName ?? null,\n\t\t\t\t\tprefix: args.input?.prefix ?? args.prefix ?? null,\n\t\t\t\t\tsuffix: args.input?.suffix ?? null,\n\t\t\t\t\tsize: args.input?.size ?? null,\n\t\t\t\t})\n\t\t\t},\n\t\t}\n\t}\n}\n"],"names":["types.S3GenerateSignedUploadInput","types.S3Acl"],"mappings":"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"}
@@ -40,6 +40,13 @@ const S3SignedUpload = new graphql.GraphQLObjectType({
40
40
  publicUrl: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) }
41
41
  }
42
42
  });
43
+ const S3DeletedObject = new graphql.GraphQLObjectType({
44
+ name: "S3DeletedObject",
45
+ fields: {
46
+ objectKey: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
47
+ bucket: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) }
48
+ }
49
+ });
43
50
  const S3Acl = new graphql.GraphQLEnumType({
44
51
  name: "S3Acl",
45
52
  values: {
@@ -64,6 +71,7 @@ const S3GenerateSignedUploadInput = new graphql.GraphQLInputObjectType({
64
71
  });
65
72
  exports.S3Acl = S3Acl;
66
73
  exports.S3ContentDisposition = S3ContentDisposition;
74
+ exports.S3DeletedObject = S3DeletedObject;
67
75
  exports.S3GenerateSignedUploadInput = S3GenerateSignedUploadInput;
68
76
  exports.S3Header = S3Header;
69
77
  exports.S3SignedRead = S3SignedRead;
@@ -1 +1 @@
1
- {"version":3,"file":"S3SchemaTypes.cjs","sources":["../../../../packages/engine-s3-plugin/src/S3SchemaTypes.ts"],"sourcesContent":["import { GraphQLEnumType, GraphQLInputObjectType, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLString } from 'graphql'\n\nexport const S3Header = new GraphQLObjectType({\n\tname: 'S3Header',\n\tfields: {\n\t\tkey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tvalue: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3ContentDisposition = new GraphQLEnumType({\n\tname: 'S33ContentDisposition',\n\tvalues: {\n\t\tATTACHMENT: {},\n\t\tINLINE: {},\n\t},\n})\nexport type S3ContentDisposition = 'ATTACHMENT' | 'INLINE'\n\nexport const S3SignedRead = new GraphQLObjectType({\n\tname: 'S3SignedRead',\n\tfields: {\n\t\turl: { type: new GraphQLNonNull(GraphQLString) },\n\t\theaders: {\n\t\t\ttype: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(S3Header))),\n\t\t},\n\t\tmethod: { type: new GraphQLNonNull(GraphQLString) },\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3SignedUpload = new GraphQLObjectType({\n\tname: 'S3SignedUpload',\n\tfields: {\n\t\turl: { type: new GraphQLNonNull(GraphQLString) },\n\t\theaders: {\n\t\t\ttype: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(S3Header))),\n\t\t},\n\t\tmethod: { type: new GraphQLNonNull(GraphQLString) },\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t\tpublicUrl: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3Acl = new GraphQLEnumType({\n\tname: 'S3Acl',\n\tvalues: {\n\t\tPUBLIC_READ: {},\n\t\tPRIVATE: {},\n\t\tNONE: {},\n\t},\n})\n\nexport type S3Acl = 'PUBLIC_READ' | 'PRIVATE' | 'NONE'\n\nexport const S3GenerateSignedUploadInput = new GraphQLInputObjectType({\n\tname: 'S3GenerateSignedUploadInput',\n\tfields: {\n\t\tcontentType: { type: GraphQLString },\n\t\textension: { type: GraphQLString, description: 'If not provided, extension is detected from a content-type.' },\n\t\texpiration: { type: GraphQLInt, description: 'Signed URL expiration.' },\n\t\tsize: { type: GraphQLInt, description: 'Uploaded file size. Required when you enable ACL size limits.' },\n\t\tprefix: { type: GraphQLString, description: 'Can be used as a \"directory\".' },\n\t\tsuffix: { type: GraphQLString, description: 'Suffix after generated id and before the extension.' },\n\t\tfileName: { type: GraphQLString, description: 'This only affects Content-disposition header. Does not affect actual object key.' },\n\t\tcontentDisposition: { type: S3ContentDisposition },\n\t\tacl: { type: S3Acl, description: 'If not supported by S3 provider, an error is thrown.' },\n\t},\n})\nexport interface S3GenerateSignedUploadInput {\n\tcontentType: null | string\n\textension: null | string\n\texpiration: null | number\n\tsize: null | number\n\tprefix: null | string\n\tsuffix: null | string\n\tfileName: null | string\n\tcontentDisposition: null | S3ContentDisposition\n\tacl: null | S3Acl\n}\n"],"names":["GraphQLObjectType","GraphQLNonNull","GraphQLString","GraphQLEnumType","GraphQLList","GraphQLInputObjectType","GraphQLInt"],"mappings":";;;AAEO,MAAM,WAAW,IAAIA,QAAAA,kBAAkB;AAAA,EAC7C,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,KAAK,EAAE,MAAM,IAAIC,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,IAC7C,OAAO,EAAE,MAAM,IAAID,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,EAAE;AAEnD,CAAC;AAEM,MAAM,uBAAuB,IAAIC,QAAAA,gBAAgB;AAAA,EACvD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,YAAY,CAAA;AAAA,IACZ,QAAQ,CAAA;AAAA,EAAC;AAEX,CAAC;AAGM,MAAM,eAAe,IAAIH,QAAAA,kBAAkB;AAAA,EACjD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,KAAK,EAAE,MAAM,IAAIC,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,IAC7C,SAAS;AAAA,MACR,MAAM,IAAID,QAAAA,eAAe,IAAIG,QAAAA,YAAY,IAAIH,QAAAA,eAAe,QAAQ,CAAC,CAAC;AAAA,IAAA;AAAA,IAEvE,QAAQ,EAAE,MAAM,IAAIA,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,IAChD,WAAW,EAAE,MAAM,IAAID,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,IACnD,QAAQ,EAAE,MAAM,IAAID,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,EAAE;AAEpD,CAAC;AAEM,MAAM,iBAAiB,IAAIF,QAAAA,kBAAkB;AAAA,EACnD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,KAAK,EAAE,MAAM,IAAIC,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,IAC7C,SAAS;AAAA,MACR,MAAM,IAAID,QAAAA,eAAe,IAAIG,QAAAA,YAAY,IAAIH,QAAAA,eAAe,QAAQ,CAAC,CAAC;AAAA,IAAA;AAAA,IAEvE,QAAQ,EAAE,MAAM,IAAIA,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,IAChD,WAAW,EAAE,MAAM,IAAID,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,IACnD,QAAQ,EAAE,MAAM,IAAID,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,IAChD,WAAW,EAAE,MAAM,IAAID,QAAAA,eAAeC,QAAAA,aAAa,EAAA;AAAA,EAAE;AAEvD,CAAC;AAEM,MAAM,QAAQ,IAAIC,QAAAA,gBAAgB;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,aAAa,CAAA;AAAA,IACb,SAAS,CAAA;AAAA,IACT,MAAM,CAAA;AAAA,EAAC;AAET,CAAC;AAIM,MAAM,8BAA8B,IAAIE,QAAAA,uBAAuB;AAAA,EACrE,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,aAAa,EAAE,MAAMH,sBAAA;AAAA,IACrB,WAAW,EAAE,MAAMA,uBAAe,aAAa,8DAAA;AAAA,IAC/C,YAAY,EAAE,MAAMI,oBAAY,aAAa,yBAAA;AAAA,IAC7C,MAAM,EAAE,MAAMA,oBAAY,aAAa,gEAAA;AAAA,IACvC,QAAQ,EAAE,MAAMJ,uBAAe,aAAa,gCAAA;AAAA,IAC5C,QAAQ,EAAE,MAAMA,uBAAe,aAAa,sDAAA;AAAA,IAC5C,UAAU,EAAE,MAAMA,uBAAe,aAAa,mFAAA;AAAA,IAC9C,oBAAoB,EAAE,MAAM,qBAAA;AAAA,IAC5B,KAAK,EAAE,MAAM,OAAO,aAAa,uDAAA;AAAA,EAAuD;AAE1F,CAAC;;;;;;;"}
1
+ {"version":3,"file":"S3SchemaTypes.cjs","sources":["../../../../packages/engine-s3-plugin/src/S3SchemaTypes.ts"],"sourcesContent":["import { GraphQLEnumType, GraphQLInputObjectType, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLString } from 'graphql'\n\nexport const S3Header = new GraphQLObjectType({\n\tname: 'S3Header',\n\tfields: {\n\t\tkey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tvalue: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3ContentDisposition = new GraphQLEnumType({\n\tname: 'S33ContentDisposition',\n\tvalues: {\n\t\tATTACHMENT: {},\n\t\tINLINE: {},\n\t},\n})\nexport type S3ContentDisposition = 'ATTACHMENT' | 'INLINE'\n\nexport const S3SignedRead = new GraphQLObjectType({\n\tname: 'S3SignedRead',\n\tfields: {\n\t\turl: { type: new GraphQLNonNull(GraphQLString) },\n\t\theaders: {\n\t\t\ttype: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(S3Header))),\n\t\t},\n\t\tmethod: { type: new GraphQLNonNull(GraphQLString) },\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3SignedUpload = new GraphQLObjectType({\n\tname: 'S3SignedUpload',\n\tfields: {\n\t\turl: { type: new GraphQLNonNull(GraphQLString) },\n\t\theaders: {\n\t\t\ttype: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(S3Header))),\n\t\t},\n\t\tmethod: { type: new GraphQLNonNull(GraphQLString) },\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t\tpublicUrl: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3DeletedObject = new GraphQLObjectType({\n\tname: 'S3DeletedObject',\n\tfields: {\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3Acl = new GraphQLEnumType({\n\tname: 'S3Acl',\n\tvalues: {\n\t\tPUBLIC_READ: {},\n\t\tPRIVATE: {},\n\t\tNONE: {},\n\t},\n})\n\nexport type S3Acl = 'PUBLIC_READ' | 'PRIVATE' | 'NONE'\n\nexport const S3GenerateSignedUploadInput = new GraphQLInputObjectType({\n\tname: 'S3GenerateSignedUploadInput',\n\tfields: {\n\t\tcontentType: { type: GraphQLString },\n\t\textension: { type: GraphQLString, description: 'If not provided, extension is detected from a content-type.' },\n\t\texpiration: { type: GraphQLInt, description: 'Signed URL expiration.' },\n\t\tsize: { type: GraphQLInt, description: 'Uploaded file size. Required when you enable ACL size limits.' },\n\t\tprefix: { type: GraphQLString, description: 'Can be used as a \"directory\".' },\n\t\tsuffix: { type: GraphQLString, description: 'Suffix after generated id and before the extension.' },\n\t\tfileName: { type: GraphQLString, description: 'This only affects Content-disposition header. Does not affect actual object key.' },\n\t\tcontentDisposition: { type: S3ContentDisposition },\n\t\tacl: { type: S3Acl, description: 'If not supported by S3 provider, an error is thrown.' },\n\t},\n})\nexport interface S3GenerateSignedUploadInput {\n\tcontentType: null | string\n\textension: null | string\n\texpiration: null | number\n\tsize: null | number\n\tprefix: null | string\n\tsuffix: null | string\n\tfileName: null | string\n\tcontentDisposition: null | S3ContentDisposition\n\tacl: null | S3Acl\n}\n"],"names":["GraphQLObjectType","GraphQLNonNull","GraphQLString","GraphQLEnumType","GraphQLList","GraphQLInputObjectType","GraphQLInt"],"mappings":"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"}
@@ -38,6 +38,13 @@ const S3SignedUpload = new GraphQLObjectType({
38
38
  publicUrl: { type: new GraphQLNonNull(GraphQLString) }
39
39
  }
40
40
  });
41
+ const S3DeletedObject = new GraphQLObjectType({
42
+ name: "S3DeletedObject",
43
+ fields: {
44
+ objectKey: { type: new GraphQLNonNull(GraphQLString) },
45
+ bucket: { type: new GraphQLNonNull(GraphQLString) }
46
+ }
47
+ });
41
48
  const S3Acl = new GraphQLEnumType({
42
49
  name: "S3Acl",
43
50
  values: {
@@ -63,6 +70,7 @@ const S3GenerateSignedUploadInput = new GraphQLInputObjectType({
63
70
  export {
64
71
  S3Acl,
65
72
  S3ContentDisposition,
73
+ S3DeletedObject,
66
74
  S3GenerateSignedUploadInput,
67
75
  S3Header,
68
76
  S3SignedRead,
@@ -1 +1 @@
1
- {"version":3,"file":"S3SchemaTypes.js","sources":["../../../../packages/engine-s3-plugin/src/S3SchemaTypes.ts"],"sourcesContent":["import { GraphQLEnumType, GraphQLInputObjectType, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLString } from 'graphql'\n\nexport const S3Header = new GraphQLObjectType({\n\tname: 'S3Header',\n\tfields: {\n\t\tkey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tvalue: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3ContentDisposition = new GraphQLEnumType({\n\tname: 'S33ContentDisposition',\n\tvalues: {\n\t\tATTACHMENT: {},\n\t\tINLINE: {},\n\t},\n})\nexport type S3ContentDisposition = 'ATTACHMENT' | 'INLINE'\n\nexport const S3SignedRead = new GraphQLObjectType({\n\tname: 'S3SignedRead',\n\tfields: {\n\t\turl: { type: new GraphQLNonNull(GraphQLString) },\n\t\theaders: {\n\t\t\ttype: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(S3Header))),\n\t\t},\n\t\tmethod: { type: new GraphQLNonNull(GraphQLString) },\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3SignedUpload = new GraphQLObjectType({\n\tname: 'S3SignedUpload',\n\tfields: {\n\t\turl: { type: new GraphQLNonNull(GraphQLString) },\n\t\theaders: {\n\t\t\ttype: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(S3Header))),\n\t\t},\n\t\tmethod: { type: new GraphQLNonNull(GraphQLString) },\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t\tpublicUrl: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3Acl = new GraphQLEnumType({\n\tname: 'S3Acl',\n\tvalues: {\n\t\tPUBLIC_READ: {},\n\t\tPRIVATE: {},\n\t\tNONE: {},\n\t},\n})\n\nexport type S3Acl = 'PUBLIC_READ' | 'PRIVATE' | 'NONE'\n\nexport const S3GenerateSignedUploadInput = new GraphQLInputObjectType({\n\tname: 'S3GenerateSignedUploadInput',\n\tfields: {\n\t\tcontentType: { type: GraphQLString },\n\t\textension: { type: GraphQLString, description: 'If not provided, extension is detected from a content-type.' },\n\t\texpiration: { type: GraphQLInt, description: 'Signed URL expiration.' },\n\t\tsize: { type: GraphQLInt, description: 'Uploaded file size. Required when you enable ACL size limits.' },\n\t\tprefix: { type: GraphQLString, description: 'Can be used as a \"directory\".' },\n\t\tsuffix: { type: GraphQLString, description: 'Suffix after generated id and before the extension.' },\n\t\tfileName: { type: GraphQLString, description: 'This only affects Content-disposition header. Does not affect actual object key.' },\n\t\tcontentDisposition: { type: S3ContentDisposition },\n\t\tacl: { type: S3Acl, description: 'If not supported by S3 provider, an error is thrown.' },\n\t},\n})\nexport interface S3GenerateSignedUploadInput {\n\tcontentType: null | string\n\textension: null | string\n\texpiration: null | number\n\tsize: null | number\n\tprefix: null | string\n\tsuffix: null | string\n\tfileName: null | string\n\tcontentDisposition: null | S3ContentDisposition\n\tacl: null | S3Acl\n}\n"],"names":[],"mappings":";AAEO,MAAM,WAAW,IAAI,kBAAkB;AAAA,EAC7C,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,KAAK,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAC7C,OAAO,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,EAAE;AAEnD,CAAC;AAEM,MAAM,uBAAuB,IAAI,gBAAgB;AAAA,EACvD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,YAAY,CAAA;AAAA,IACZ,QAAQ,CAAA;AAAA,EAAC;AAEX,CAAC;AAGM,MAAM,eAAe,IAAI,kBAAkB;AAAA,EACjD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,KAAK,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAC7C,SAAS;AAAA,MACR,MAAM,IAAI,eAAe,IAAI,YAAY,IAAI,eAAe,QAAQ,CAAC,CAAC;AAAA,IAAA;AAAA,IAEvE,QAAQ,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAChD,WAAW,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IACnD,QAAQ,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,EAAE;AAEpD,CAAC;AAEM,MAAM,iBAAiB,IAAI,kBAAkB;AAAA,EACnD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,KAAK,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAC7C,SAAS;AAAA,MACR,MAAM,IAAI,eAAe,IAAI,YAAY,IAAI,eAAe,QAAQ,CAAC,CAAC;AAAA,IAAA;AAAA,IAEvE,QAAQ,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAChD,WAAW,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IACnD,QAAQ,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAChD,WAAW,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,EAAE;AAEvD,CAAC;AAEM,MAAM,QAAQ,IAAI,gBAAgB;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,aAAa,CAAA;AAAA,IACb,SAAS,CAAA;AAAA,IACT,MAAM,CAAA;AAAA,EAAC;AAET,CAAC;AAIM,MAAM,8BAA8B,IAAI,uBAAuB;AAAA,EACrE,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,aAAa,EAAE,MAAM,cAAA;AAAA,IACrB,WAAW,EAAE,MAAM,eAAe,aAAa,8DAAA;AAAA,IAC/C,YAAY,EAAE,MAAM,YAAY,aAAa,yBAAA;AAAA,IAC7C,MAAM,EAAE,MAAM,YAAY,aAAa,gEAAA;AAAA,IACvC,QAAQ,EAAE,MAAM,eAAe,aAAa,gCAAA;AAAA,IAC5C,QAAQ,EAAE,MAAM,eAAe,aAAa,sDAAA;AAAA,IAC5C,UAAU,EAAE,MAAM,eAAe,aAAa,mFAAA;AAAA,IAC9C,oBAAoB,EAAE,MAAM,qBAAA;AAAA,IAC5B,KAAK,EAAE,MAAM,OAAO,aAAa,uDAAA;AAAA,EAAuD;AAE1F,CAAC;"}
1
+ {"version":3,"file":"S3SchemaTypes.js","sources":["../../../../packages/engine-s3-plugin/src/S3SchemaTypes.ts"],"sourcesContent":["import { GraphQLEnumType, GraphQLInputObjectType, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLString } from 'graphql'\n\nexport const S3Header = new GraphQLObjectType({\n\tname: 'S3Header',\n\tfields: {\n\t\tkey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tvalue: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3ContentDisposition = new GraphQLEnumType({\n\tname: 'S33ContentDisposition',\n\tvalues: {\n\t\tATTACHMENT: {},\n\t\tINLINE: {},\n\t},\n})\nexport type S3ContentDisposition = 'ATTACHMENT' | 'INLINE'\n\nexport const S3SignedRead = new GraphQLObjectType({\n\tname: 'S3SignedRead',\n\tfields: {\n\t\turl: { type: new GraphQLNonNull(GraphQLString) },\n\t\theaders: {\n\t\t\ttype: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(S3Header))),\n\t\t},\n\t\tmethod: { type: new GraphQLNonNull(GraphQLString) },\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3SignedUpload = new GraphQLObjectType({\n\tname: 'S3SignedUpload',\n\tfields: {\n\t\turl: { type: new GraphQLNonNull(GraphQLString) },\n\t\theaders: {\n\t\t\ttype: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(S3Header))),\n\t\t},\n\t\tmethod: { type: new GraphQLNonNull(GraphQLString) },\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t\tpublicUrl: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3DeletedObject = new GraphQLObjectType({\n\tname: 'S3DeletedObject',\n\tfields: {\n\t\tobjectKey: { type: new GraphQLNonNull(GraphQLString) },\n\t\tbucket: { type: new GraphQLNonNull(GraphQLString) },\n\t},\n})\n\nexport const S3Acl = new GraphQLEnumType({\n\tname: 'S3Acl',\n\tvalues: {\n\t\tPUBLIC_READ: {},\n\t\tPRIVATE: {},\n\t\tNONE: {},\n\t},\n})\n\nexport type S3Acl = 'PUBLIC_READ' | 'PRIVATE' | 'NONE'\n\nexport const S3GenerateSignedUploadInput = new GraphQLInputObjectType({\n\tname: 'S3GenerateSignedUploadInput',\n\tfields: {\n\t\tcontentType: { type: GraphQLString },\n\t\textension: { type: GraphQLString, description: 'If not provided, extension is detected from a content-type.' },\n\t\texpiration: { type: GraphQLInt, description: 'Signed URL expiration.' },\n\t\tsize: { type: GraphQLInt, description: 'Uploaded file size. Required when you enable ACL size limits.' },\n\t\tprefix: { type: GraphQLString, description: 'Can be used as a \"directory\".' },\n\t\tsuffix: { type: GraphQLString, description: 'Suffix after generated id and before the extension.' },\n\t\tfileName: { type: GraphQLString, description: 'This only affects Content-disposition header. Does not affect actual object key.' },\n\t\tcontentDisposition: { type: S3ContentDisposition },\n\t\tacl: { type: S3Acl, description: 'If not supported by S3 provider, an error is thrown.' },\n\t},\n})\nexport interface S3GenerateSignedUploadInput {\n\tcontentType: null | string\n\textension: null | string\n\texpiration: null | number\n\tsize: null | number\n\tprefix: null | string\n\tsuffix: null | string\n\tfileName: null | string\n\tcontentDisposition: null | S3ContentDisposition\n\tacl: null | S3Acl\n}\n"],"names":[],"mappings":";AAEO,MAAM,WAAW,IAAI,kBAAkB;AAAA,EAC7C,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,KAAK,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAC7C,OAAO,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,EAAE;AAEnD,CAAC;AAEM,MAAM,uBAAuB,IAAI,gBAAgB;AAAA,EACvD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,YAAY,CAAA;AAAA,IACZ,QAAQ,CAAA;AAAA,EAAC;AAEX,CAAC;AAGM,MAAM,eAAe,IAAI,kBAAkB;AAAA,EACjD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,KAAK,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAC7C,SAAS;AAAA,MACR,MAAM,IAAI,eAAe,IAAI,YAAY,IAAI,eAAe,QAAQ,CAAC,CAAC;AAAA,IAAA;AAAA,IAEvE,QAAQ,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAChD,WAAW,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IACnD,QAAQ,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,EAAE;AAEpD,CAAC;AAEM,MAAM,iBAAiB,IAAI,kBAAkB;AAAA,EACnD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,KAAK,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAC7C,SAAS;AAAA,MACR,MAAM,IAAI,eAAe,IAAI,YAAY,IAAI,eAAe,QAAQ,CAAC,CAAC;AAAA,IAAA;AAAA,IAEvE,QAAQ,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAChD,WAAW,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IACnD,QAAQ,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IAChD,WAAW,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,EAAE;AAEvD,CAAC;AAEM,MAAM,kBAAkB,IAAI,kBAAkB;AAAA,EACpD,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,WAAW,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,IACnD,QAAQ,EAAE,MAAM,IAAI,eAAe,aAAa,EAAA;AAAA,EAAE;AAEpD,CAAC;AAEM,MAAM,QAAQ,IAAI,gBAAgB;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,aAAa,CAAA;AAAA,IACb,SAAS,CAAA;AAAA,IACT,MAAM,CAAA;AAAA,EAAC;AAET,CAAC;AAIM,MAAM,8BAA8B,IAAI,uBAAuB;AAAA,EACrE,MAAM;AAAA,EACN,QAAQ;AAAA,IACP,aAAa,EAAE,MAAM,cAAA;AAAA,IACrB,WAAW,EAAE,MAAM,eAAe,aAAa,8DAAA;AAAA,IAC/C,YAAY,EAAE,MAAM,YAAY,aAAa,yBAAA;AAAA,IAC7C,MAAM,EAAE,MAAM,YAAY,aAAa,gEAAA;AAAA,IACvC,QAAQ,EAAE,MAAM,eAAe,aAAa,gCAAA;AAAA,IAC5C,QAAQ,EAAE,MAAM,eAAe,aAAa,sDAAA;AAAA,IAC5C,UAAU,EAAE,MAAM,eAAe,aAAa,mFAAA;AAAA,IAC9C,oBAAoB,EAAE,MAAM,qBAAA;AAAA,IAC5B,KAAK,EAAE,MAAM,OAAO,aAAa,uDAAA;AAAA,EAAuD;AAE1F,CAAC;"}
@@ -7,11 +7,14 @@ const S3Signer = require("./S3Signer.cjs");
7
7
  var __defProp = Object.defineProperty;
8
8
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
9
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
10
+ const deleteUrlExpiration = 60;
11
+ const deleteTimeoutMs = 1e4;
10
12
  class S3Service {
11
- constructor(config, providers, authorizator) {
13
+ constructor(config, providers, authorizator, fetch = (url, init) => globalThis.fetch(url, init)) {
12
14
  this.config = config;
13
15
  this.providers = providers;
14
16
  this.authorizator = authorizator;
17
+ this.fetch = fetch;
15
18
  __publicField(this, "publicBaseUrl");
16
19
  __publicField(this, "signer");
17
20
  this.publicBaseUrl = Config.resolveS3PublicBaseUrl(config);
@@ -66,34 +69,61 @@ class S3Service {
66
69
  }
67
70
  getSignedReadUrl({ objectKey, expiration }) {
68
71
  const bucket = this.config.bucket;
69
- const publicPrefix = this.formatPublicUrl("");
70
- if (objectKey.startsWith(publicPrefix)) {
71
- objectKey = objectKey.substring(publicPrefix.length);
72
- }
73
- if (this.config.prefix && !objectKey.startsWith(this.config.prefix)) {
74
- throw new graphqlUtils.ForbiddenError(
75
- `Given object key "${objectKey}" does not start with a project prefix "${this.config.prefix}"`
76
- );
77
- }
78
- const localObjectKey = this.config.prefix ? objectKey.substring(this.config.prefix.length + 1) : objectKey;
79
- this.authorizator.verifyReadAccess({ key: localObjectKey });
72
+ const resolved = this.resolveObjectKey(objectKey);
73
+ this.authorizator.verifyReadAccess({ key: resolved.localObjectKey });
80
74
  const url = this.signer.sign({
81
75
  action: "read",
82
76
  expiration: expiration ?? 3600,
83
- key: objectKey,
77
+ key: resolved.objectKey,
84
78
  headers: {}
85
79
  });
86
80
  return {
87
81
  bucket,
88
- objectKey,
82
+ objectKey: resolved.objectKey,
89
83
  url,
90
84
  headers: [],
91
85
  method: "GET"
92
86
  };
93
87
  }
88
+ /**
89
+ * Unlike an upload or a read, a delete carries no payload, so the signed URL never leaves the server.
90
+ */
91
+ async deleteObject({ objectKey }) {
92
+ const bucket = this.config.bucket;
93
+ const resolved = this.resolveObjectKey(objectKey);
94
+ this.authorizator.verifyDeleteAccess({ key: resolved.localObjectKey });
95
+ const url = this.signer.sign({
96
+ action: "delete",
97
+ expiration: deleteUrlExpiration,
98
+ key: resolved.objectKey,
99
+ headers: {}
100
+ });
101
+ const response = await this.fetch(url, { method: "DELETE", signal: AbortSignal.timeout(deleteTimeoutMs) });
102
+ if (!response.ok) {
103
+ throw new Error(`Failed to delete an object "${resolved.objectKey}": S3 responded with ${response.status}: ${await response.text()}`);
104
+ }
105
+ return {
106
+ bucket,
107
+ objectKey: resolved.objectKey
108
+ };
109
+ }
94
110
  formatPublicUrl(key) {
95
111
  return `${this.publicBaseUrl}/${key}`;
96
112
  }
113
+ resolveObjectKey(objectKey) {
114
+ const publicPrefix = this.formatPublicUrl("");
115
+ if (objectKey.startsWith(publicPrefix)) {
116
+ objectKey = objectKey.substring(publicPrefix.length);
117
+ }
118
+ const prefix = this.config.prefix ? this.config.prefix + "/" : "";
119
+ if (prefix && !objectKey.startsWith(prefix)) {
120
+ throw new graphqlUtils.ForbiddenError(
121
+ `Given object key "${objectKey}" does not start with a project prefix "${this.config.prefix}"`
122
+ );
123
+ }
124
+ const localObjectKey = objectKey.substring(prefix.length);
125
+ return { objectKey, localObjectKey };
126
+ }
97
127
  }
98
128
  class S3ServiceFactory {
99
129
  create(config, providers, authorizator) {