@contember/engine-s3-plugin 2.1.0-alpha.36 → 2.1.0-alpha.39
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.
- package/dist/development/index.cjs +27 -0
- package/dist/development/index.cjs.map +1 -0
- package/dist/development/index.js +28 -0
- package/dist/development/index.js.map +1 -0
- package/dist/development/src/Config.cjs +73 -0
- package/dist/development/src/Config.cjs.map +1 -0
- package/dist/development/src/Config.js +56 -0
- package/dist/development/src/Config.js.map +1 -0
- package/dist/development/src/S3ConfigProcessor.cjs +60 -0
- package/dist/development/src/S3ConfigProcessor.cjs.map +1 -0
- package/dist/development/src/S3ConfigProcessor.js +43 -0
- package/dist/development/src/S3ConfigProcessor.js.map +1 -0
- package/dist/development/src/S3ObjectAuthorizator.cjs +46 -0
- package/dist/development/src/S3ObjectAuthorizator.cjs.map +1 -0
- package/dist/development/src/S3ObjectAuthorizator.js +46 -0
- package/dist/development/src/S3ObjectAuthorizator.js.map +1 -0
- package/dist/development/src/S3SchemaContributor.cjs +105 -0
- package/dist/development/src/S3SchemaContributor.cjs.map +1 -0
- package/dist/development/src/S3SchemaContributor.js +105 -0
- package/dist/development/src/S3SchemaContributor.js.map +1 -0
- package/dist/development/src/S3SchemaTypes.cjs +71 -0
- package/dist/development/src/S3SchemaTypes.cjs.map +1 -0
- package/dist/development/src/S3SchemaTypes.js +71 -0
- package/dist/development/src/S3SchemaTypes.js.map +1 -0
- package/dist/development/src/S3Service.cjs +105 -0
- package/dist/development/src/S3Service.cjs.map +1 -0
- package/dist/development/src/S3Service.js +105 -0
- package/dist/development/src/S3Service.js.map +1 -0
- package/dist/development/src/S3Signer.cjs +84 -0
- package/dist/development/src/S3Signer.cjs.map +1 -0
- package/dist/development/src/S3Signer.js +84 -0
- package/dist/development/src/S3Signer.js.map +1 -0
- package/dist/production/index.cjs +27 -0
- package/dist/production/index.cjs.map +1 -0
- package/dist/production/index.js +28 -0
- package/dist/production/index.js.map +1 -0
- package/dist/production/src/Config.cjs +73 -0
- package/dist/production/src/Config.cjs.map +1 -0
- package/dist/production/src/Config.js +56 -0
- package/dist/production/src/Config.js.map +1 -0
- package/dist/production/src/S3ConfigProcessor.cjs +60 -0
- package/dist/production/src/S3ConfigProcessor.cjs.map +1 -0
- package/dist/production/src/S3ConfigProcessor.js +43 -0
- package/dist/production/src/S3ConfigProcessor.js.map +1 -0
- package/dist/production/src/S3ObjectAuthorizator.cjs +46 -0
- package/dist/production/src/S3ObjectAuthorizator.cjs.map +1 -0
- package/dist/production/src/S3ObjectAuthorizator.js +46 -0
- package/dist/production/src/S3ObjectAuthorizator.js.map +1 -0
- package/dist/production/src/S3SchemaContributor.cjs +105 -0
- package/dist/production/src/S3SchemaContributor.cjs.map +1 -0
- package/dist/production/src/S3SchemaContributor.js +105 -0
- package/dist/production/src/S3SchemaContributor.js.map +1 -0
- package/dist/production/src/S3SchemaTypes.cjs +71 -0
- package/dist/production/src/S3SchemaTypes.cjs.map +1 -0
- package/dist/production/src/S3SchemaTypes.js +71 -0
- package/dist/production/src/S3SchemaTypes.js.map +1 -0
- package/dist/production/src/S3Service.cjs +105 -0
- package/dist/production/src/S3Service.cjs.map +1 -0
- package/dist/production/src/S3Service.js +105 -0
- package/dist/production/src/S3Service.js.map +1 -0
- package/dist/production/src/S3Signer.cjs +84 -0
- package/dist/production/src/S3Signer.cjs.map +1 -0
- package/dist/production/src/S3Signer.js +84 -0
- package/dist/production/src/S3Signer.js.map +1 -0
- package/dist/tests/cases/authorizator.test.d.ts +2 -0
- package/dist/tests/cases/authorizator.test.d.ts.map +1 -0
- package/dist/tests/cases/signRequest.test.d.ts +2 -0
- package/dist/tests/cases/signRequest.test.d.ts.map +1 -0
- package/dist/tests/tsconfig.tsbuildinfo +1 -0
- package/dist/types/Config.d.ts +33 -0
- package/dist/types/Config.d.ts.map +1 -0
- package/dist/types/S3ConfigProcessor.d.ts +9 -0
- package/dist/types/S3ConfigProcessor.d.ts.map +1 -0
- package/dist/types/S3ObjectAuthorizator.d.ts +22 -0
- package/dist/types/S3ObjectAuthorizator.d.ts.map +1 -0
- package/dist/types/S3SchemaContributor.d.ts +21 -0
- package/dist/types/S3SchemaContributor.d.ts.map +1 -0
- package/dist/types/S3SchemaTypes.d.ts +21 -0
- package/dist/types/S3SchemaTypes.d.ts.map +1 -0
- package/dist/types/S3Service.d.ts +44 -0
- package/dist/types/S3Service.d.ts.map +1 -0
- package/dist/types/S3Signer.d.ts +22 -0
- package/dist/types/S3Signer.d.ts.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +13 -13
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const S3ConfigProcessor = require("./src/S3ConfigProcessor.cjs");
|
|
4
|
+
const S3SchemaContributor = require("./src/S3SchemaContributor.cjs");
|
|
5
|
+
const S3Service = require("./src/S3Service.cjs");
|
|
6
|
+
const S3ObjectAuthorizator = require("./src/S3ObjectAuthorizator.cjs");
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "", value);
|
|
10
|
+
class S3 {
|
|
11
|
+
constructor() {
|
|
12
|
+
__publicField(this, "name", "contember/s3");
|
|
13
|
+
}
|
|
14
|
+
getConfigProcessor() {
|
|
15
|
+
return new S3ConfigProcessor.S3ConfigProcessor();
|
|
16
|
+
}
|
|
17
|
+
getSchemaContributor({ providers }) {
|
|
18
|
+
const s3ServiceFactory = new S3Service.S3ServiceFactory();
|
|
19
|
+
return new S3SchemaContributor.S3SchemaContributor(s3ServiceFactory, providers);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.S3SchemaContributor = S3SchemaContributor.S3SchemaContributor;
|
|
23
|
+
exports.S3Service = S3Service.S3Service;
|
|
24
|
+
exports.S3ServiceFactory = S3Service.S3ServiceFactory;
|
|
25
|
+
exports.S3ObjectAuthorizator = S3ObjectAuthorizator.S3ObjectAuthorizator;
|
|
26
|
+
exports.default = S3;
|
|
27
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../packages/engine-s3-plugin/src/index.ts"],"sourcesContent":["import { Plugin, SchemaContributorArgs } from '@contember/engine-plugins'\nimport { S3ConfigProcessor } from './S3ConfigProcessor'\nimport { S3SchemaContributor } from './S3SchemaContributor'\nimport { S3ServiceFactory } from './S3Service'\nimport { Project3Config } from './Config'\n\nexport * from './S3ObjectAuthorizator'\nexport * from './S3SchemaContributor'\nexport * from './S3Service'\n\nexport default class S3 implements Plugin<Project3Config> {\n\tname = 'contember/s3'\n\n\tgetConfigProcessor() {\n\t\treturn new S3ConfigProcessor()\n\t}\n\n\tgetSchemaContributor({ providers }: SchemaContributorArgs) {\n\t\tconst s3ServiceFactory = new S3ServiceFactory()\n\t\treturn new S3SchemaContributor(s3ServiceFactory, providers)\n\t}\n}\n"],"names":["S3ConfigProcessor","S3ServiceFactory","S3SchemaContributor"],"mappings":";;;;;;;;;AAUA,MAAqB,GAAqC;AAAA,EAA1D,cAAA;AACC,kBAAA,MAAA,QAAO,cAAA;AAAA,EAAA;AAAA,EAEP,qBAAqB;AACpB,WAAO,IAAIA,kBAAAA,kBAAA;AAAA,EACZ;AAAA,EAEA,qBAAqB,EAAE,aAAoC;AAC1D,UAAM,mBAAmB,IAAIC,2BAAA;AAC7B,WAAO,IAAIC,oBAAAA,oBAAoB,kBAAkB,SAAS;AAAA,EAC3D;AACD;;;;;;"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { S3ConfigProcessor } from "./src/S3ConfigProcessor.js";
|
|
2
|
+
import { S3SchemaContributor } from "./src/S3SchemaContributor.js";
|
|
3
|
+
import { S3ServiceFactory } from "./src/S3Service.js";
|
|
4
|
+
import { S3Service } from "./src/S3Service.js";
|
|
5
|
+
import { S3ObjectAuthorizator } from "./src/S3ObjectAuthorizator.js";
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "", value);
|
|
9
|
+
class S3 {
|
|
10
|
+
constructor() {
|
|
11
|
+
__publicField(this, "name", "contember/s3");
|
|
12
|
+
}
|
|
13
|
+
getConfigProcessor() {
|
|
14
|
+
return new S3ConfigProcessor();
|
|
15
|
+
}
|
|
16
|
+
getSchemaContributor({ providers }) {
|
|
17
|
+
const s3ServiceFactory = new S3ServiceFactory();
|
|
18
|
+
return new S3SchemaContributor(s3ServiceFactory, providers);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
S3ObjectAuthorizator,
|
|
23
|
+
S3SchemaContributor,
|
|
24
|
+
S3Service,
|
|
25
|
+
S3ServiceFactory,
|
|
26
|
+
S3 as default
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../packages/engine-s3-plugin/src/index.ts"],"sourcesContent":["import { Plugin, SchemaContributorArgs } from '@contember/engine-plugins'\nimport { S3ConfigProcessor } from './S3ConfigProcessor'\nimport { S3SchemaContributor } from './S3SchemaContributor'\nimport { S3ServiceFactory } from './S3Service'\nimport { Project3Config } from './Config'\n\nexport * from './S3ObjectAuthorizator'\nexport * from './S3SchemaContributor'\nexport * from './S3Service'\n\nexport default class S3 implements Plugin<Project3Config> {\n\tname = 'contember/s3'\n\n\tgetConfigProcessor() {\n\t\treturn new S3ConfigProcessor()\n\t}\n\n\tgetSchemaContributor({ providers }: SchemaContributorArgs) {\n\t\tconst s3ServiceFactory = new S3ServiceFactory()\n\t\treturn new S3SchemaContributor(s3ServiceFactory, providers)\n\t}\n}\n"],"names":[],"mappings":";;;;;;;;AAUA,MAAqB,GAAqC;AAAA,EAA1D,cAAA;AACC,kBAAA,MAAA,QAAO,cAAA;AAAA,EAAA;AAAA,EAEP,qBAAqB;AACpB,WAAO,IAAI,kBAAA;AAAA,EACZ;AAAA,EAEA,qBAAqB,EAAE,aAAoC;AAC1D,UAAM,mBAAmB,IAAI,iBAAA;AAC7B,WAAO,IAAI,oBAAoB,kBAAkB,SAAS;AAAA,EAC3D;AACD;"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const Typesafe = require("@contember/typesafe");
|
|
4
|
+
function _interopNamespaceDefault(e) {
|
|
5
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
6
|
+
if (e) {
|
|
7
|
+
for (const k in e) {
|
|
8
|
+
if (k !== "default") {
|
|
9
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
10
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: () => e[k]
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
n.default = e;
|
|
18
|
+
return Object.freeze(n);
|
|
19
|
+
}
|
|
20
|
+
const Typesafe__namespace = /* @__PURE__ */ _interopNamespaceDefault(Typesafe);
|
|
21
|
+
const s3ConfigSchema = Typesafe__namespace.intersection(
|
|
22
|
+
Typesafe__namespace.object({
|
|
23
|
+
bucket: Typesafe__namespace.string,
|
|
24
|
+
region: Typesafe__namespace.string,
|
|
25
|
+
prefix: Typesafe__namespace.string,
|
|
26
|
+
credentials: Typesafe__namespace.object({
|
|
27
|
+
key: Typesafe__namespace.string,
|
|
28
|
+
secret: Typesafe__namespace.string
|
|
29
|
+
})
|
|
30
|
+
}),
|
|
31
|
+
Typesafe__namespace.partial({
|
|
32
|
+
endpoint: Typesafe__namespace.string,
|
|
33
|
+
cdnEndpoint: Typesafe__namespace.string,
|
|
34
|
+
provider: Typesafe__namespace.enumeration(
|
|
35
|
+
"aws",
|
|
36
|
+
"minio",
|
|
37
|
+
"ceph",
|
|
38
|
+
"localstack",
|
|
39
|
+
"cloudserver"
|
|
40
|
+
/* cloudserver */
|
|
41
|
+
),
|
|
42
|
+
noAcl: Typesafe__namespace.boolean
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
const serversWithoutAclSupport = [
|
|
46
|
+
"minio"
|
|
47
|
+
/* minio */
|
|
48
|
+
];
|
|
49
|
+
const resolveS3Config = (config) => {
|
|
50
|
+
return {
|
|
51
|
+
noAcl: !!config.provider && serversWithoutAclSupport.includes(config.provider),
|
|
52
|
+
...config
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const defaultRegion = "eu-west-1";
|
|
56
|
+
const resolveS3Endpoint = (config) => {
|
|
57
|
+
const hasLegacyPath = !!config.endpoint || config.bucket.includes(".");
|
|
58
|
+
const endpoint = config.endpoint || `https://${hasLegacyPath ? "" : `${config.bucket}.`}s3.${config.region || defaultRegion}.amazonaws.com`;
|
|
59
|
+
const basePath = hasLegacyPath ? `/${config.bucket}` : "";
|
|
60
|
+
return { endpoint, basePath };
|
|
61
|
+
};
|
|
62
|
+
const resolveS3PublicBaseUrl = (config) => {
|
|
63
|
+
if (config.cdnEndpoint) {
|
|
64
|
+
return config.cdnEndpoint;
|
|
65
|
+
}
|
|
66
|
+
const { endpoint, basePath } = resolveS3Endpoint(config);
|
|
67
|
+
return endpoint + basePath;
|
|
68
|
+
};
|
|
69
|
+
exports.resolveS3Config = resolveS3Config;
|
|
70
|
+
exports.resolveS3Endpoint = resolveS3Endpoint;
|
|
71
|
+
exports.resolveS3PublicBaseUrl = resolveS3PublicBaseUrl;
|
|
72
|
+
exports.s3ConfigSchema = s3ConfigSchema;
|
|
73
|
+
//# sourceMappingURL=Config.cjs.map
|
|
@@ -0,0 +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;;;;;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as Typesafe from "@contember/typesafe";
|
|
2
|
+
const s3ConfigSchema = Typesafe.intersection(
|
|
3
|
+
Typesafe.object({
|
|
4
|
+
bucket: Typesafe.string,
|
|
5
|
+
region: Typesafe.string,
|
|
6
|
+
prefix: Typesafe.string,
|
|
7
|
+
credentials: Typesafe.object({
|
|
8
|
+
key: Typesafe.string,
|
|
9
|
+
secret: Typesafe.string
|
|
10
|
+
})
|
|
11
|
+
}),
|
|
12
|
+
Typesafe.partial({
|
|
13
|
+
endpoint: Typesafe.string,
|
|
14
|
+
cdnEndpoint: Typesafe.string,
|
|
15
|
+
provider: Typesafe.enumeration(
|
|
16
|
+
"aws",
|
|
17
|
+
"minio",
|
|
18
|
+
"ceph",
|
|
19
|
+
"localstack",
|
|
20
|
+
"cloudserver"
|
|
21
|
+
/* cloudserver */
|
|
22
|
+
),
|
|
23
|
+
noAcl: Typesafe.boolean
|
|
24
|
+
})
|
|
25
|
+
);
|
|
26
|
+
const serversWithoutAclSupport = [
|
|
27
|
+
"minio"
|
|
28
|
+
/* minio */
|
|
29
|
+
];
|
|
30
|
+
const resolveS3Config = (config) => {
|
|
31
|
+
return {
|
|
32
|
+
noAcl: !!config.provider && serversWithoutAclSupport.includes(config.provider),
|
|
33
|
+
...config
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
const defaultRegion = "eu-west-1";
|
|
37
|
+
const resolveS3Endpoint = (config) => {
|
|
38
|
+
const hasLegacyPath = !!config.endpoint || config.bucket.includes(".");
|
|
39
|
+
const endpoint = config.endpoint || `https://${hasLegacyPath ? "" : `${config.bucket}.`}s3.${config.region || defaultRegion}.amazonaws.com`;
|
|
40
|
+
const basePath = hasLegacyPath ? `/${config.bucket}` : "";
|
|
41
|
+
return { endpoint, basePath };
|
|
42
|
+
};
|
|
43
|
+
const resolveS3PublicBaseUrl = (config) => {
|
|
44
|
+
if (config.cdnEndpoint) {
|
|
45
|
+
return config.cdnEndpoint;
|
|
46
|
+
}
|
|
47
|
+
const { endpoint, basePath } = resolveS3Endpoint(config);
|
|
48
|
+
return endpoint + basePath;
|
|
49
|
+
};
|
|
50
|
+
export {
|
|
51
|
+
resolveS3Config,
|
|
52
|
+
resolveS3Endpoint,
|
|
53
|
+
resolveS3PublicBaseUrl,
|
|
54
|
+
s3ConfigSchema
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=Config.js.map
|
|
@@ -0,0 +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;"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const Config = require("./Config.cjs");
|
|
4
|
+
const Typesafe = require("@contember/typesafe");
|
|
5
|
+
function _interopNamespaceDefault(e) {
|
|
6
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
7
|
+
if (e) {
|
|
8
|
+
for (const k in e) {
|
|
9
|
+
if (k !== "default") {
|
|
10
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
11
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: () => e[k]
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
n.default = e;
|
|
19
|
+
return Object.freeze(n);
|
|
20
|
+
}
|
|
21
|
+
const Typesafe__namespace = /* @__PURE__ */ _interopNamespaceDefault(Typesafe);
|
|
22
|
+
class S3ConfigProcessor {
|
|
23
|
+
getDefaultEnv() {
|
|
24
|
+
return {
|
|
25
|
+
DEFAULT_S3_ENDPOINT: "",
|
|
26
|
+
DEFAULT_S3_REGION: "us-east-1",
|
|
27
|
+
DEFAULT_S3_PROVIDER: "aws"
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
prepareConfigTemplate(template, { env }) {
|
|
31
|
+
return {
|
|
32
|
+
...template,
|
|
33
|
+
projectDefaults: {
|
|
34
|
+
...template.projectDefaults,
|
|
35
|
+
s3: {
|
|
36
|
+
bucket: `%?project.env.S3_BUCKET%`,
|
|
37
|
+
prefix: `%?project.env.S3_PREFIX||project.slug%`,
|
|
38
|
+
region: `%project.env.S3_REGION%`,
|
|
39
|
+
endpoint: `%project.env.S3_ENDPOINT%`,
|
|
40
|
+
cdnEndpoint: `%?project.env.S3_CDN%`,
|
|
41
|
+
provider: "%project.env.S3_PROVIDER%",
|
|
42
|
+
credentials: {
|
|
43
|
+
key: `%?project.secret.s3.key||project.env.S3_KEY%`,
|
|
44
|
+
secret: `%?project.secret.s3.secret||project.env.S3_SECRET%`
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
getProjectConfigSchema(slug) {
|
|
51
|
+
return Typesafe__namespace.union(
|
|
52
|
+
(input, path = []) => Typesafe__namespace.valueAt(input, ["s3", "credentials", "key"]) === void 0 ? {} : Typesafe__namespace.fail(path),
|
|
53
|
+
Typesafe__namespace.object({
|
|
54
|
+
s3: Config.s3ConfigSchema
|
|
55
|
+
})
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.S3ConfigProcessor = S3ConfigProcessor;
|
|
60
|
+
//# sourceMappingURL=S3ConfigProcessor.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"S3ConfigProcessor.cjs","sources":["../../../../packages/engine-s3-plugin/src/S3ConfigProcessor.ts"],"sourcesContent":["import { ConfigProcessor, ConfigTemplate, ConfigTemplateContext } from '@contember/engine-plugins'\nimport { Project3Config, s3ConfigSchema } from './Config'\nimport * as Typesafe from '@contember/typesafe'\n\nexport class S3ConfigProcessor implements ConfigProcessor<Project3Config> {\n\tgetDefaultEnv(): Record<string, string> {\n\t\treturn {\n\t\t\tDEFAULT_S3_ENDPOINT: '',\n\t\t\tDEFAULT_S3_REGION: 'us-east-1',\n\t\t\tDEFAULT_S3_PROVIDER: 'aws',\n\t\t}\n\t}\n\n\tprepareConfigTemplate(template: ConfigTemplate, { env }: ConfigTemplateContext) {\n\t\treturn {\n\t\t\t...template,\n\t\t\tprojectDefaults: {\n\t\t\t\t...template.projectDefaults,\n\t\t\t\ts3: {\n\t\t\t\t\tbucket: `%?project.env.S3_BUCKET%`,\n\t\t\t\t\tprefix: `%?project.env.S3_PREFIX||project.slug%`,\n\t\t\t\t\tregion: `%project.env.S3_REGION%`,\n\t\t\t\t\tendpoint: `%project.env.S3_ENDPOINT%`,\n\t\t\t\t\tcdnEndpoint: `%?project.env.S3_CDN%`,\n\t\t\t\t\tprovider: '%project.env.S3_PROVIDER%',\n\t\t\t\t\tcredentials: {\n\t\t\t\t\t\tkey: `%?project.secret.s3.key||project.env.S3_KEY%`,\n\t\t\t\t\t\tsecret: `%?project.secret.s3.secret||project.env.S3_SECRET%`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n\n\tgetProjectConfigSchema(slug: string): Typesafe.Type<Record<string, any>> {\n\t\treturn Typesafe.union(\n\t\t\t(input: unknown, path: PropertyKey[] = []) => Typesafe.valueAt(input, ['s3', 'credentials', 'key']) === undefined ? {} : Typesafe.fail(path),\n\t\t\tTypesafe.object({\n\t\t\t\ts3: s3ConfigSchema,\n\t\t\t}),\n\t\t)\n\t}\n}\n"],"names":["Typesafe","s3ConfigSchema"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAIO,MAAM,kBAA6D;AAAA,EACzE,gBAAwC;AACvC,WAAO;AAAA,MACN,qBAAqB;AAAA,MACrB,mBAAmB;AAAA,MACnB,qBAAqB;AAAA,IAAA;AAAA,EAEvB;AAAA,EAEA,sBAAsB,UAA0B,EAAE,OAA8B;AAC/E,WAAO;AAAA,MACN,GAAG;AAAA,MACH,iBAAiB;AAAA,QAChB,GAAG,SAAS;AAAA,QACZ,IAAI;AAAA,UACH,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,aAAa;AAAA,UACb,UAAU;AAAA,UACV,aAAa;AAAA,YACZ,KAAK;AAAA,YACL,QAAQ;AAAA,UAAA;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAAA,EAEF;AAAA,EAEA,uBAAuB,MAAkD;AACxE,WAAOA,oBAAS;AAAA,MACf,CAAC,OAAgB,OAAsB,CAAA,MAAOA,oBAAS,QAAQ,OAAO,CAAC,MAAM,eAAe,KAAK,CAAC,MAAM,SAAY,CAAA,IAAKA,oBAAS,KAAK,IAAI;AAAA,MAC3IA,oBAAS,OAAO;AAAA,QACf,IAAIC,OAAAA;AAAAA,MAAA,CACJ;AAAA,IAAA;AAAA,EAEH;AACD;;"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { s3ConfigSchema } from "./Config.js";
|
|
2
|
+
import * as Typesafe from "@contember/typesafe";
|
|
3
|
+
class S3ConfigProcessor {
|
|
4
|
+
getDefaultEnv() {
|
|
5
|
+
return {
|
|
6
|
+
DEFAULT_S3_ENDPOINT: "",
|
|
7
|
+
DEFAULT_S3_REGION: "us-east-1",
|
|
8
|
+
DEFAULT_S3_PROVIDER: "aws"
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
prepareConfigTemplate(template, { env }) {
|
|
12
|
+
return {
|
|
13
|
+
...template,
|
|
14
|
+
projectDefaults: {
|
|
15
|
+
...template.projectDefaults,
|
|
16
|
+
s3: {
|
|
17
|
+
bucket: `%?project.env.S3_BUCKET%`,
|
|
18
|
+
prefix: `%?project.env.S3_PREFIX||project.slug%`,
|
|
19
|
+
region: `%project.env.S3_REGION%`,
|
|
20
|
+
endpoint: `%project.env.S3_ENDPOINT%`,
|
|
21
|
+
cdnEndpoint: `%?project.env.S3_CDN%`,
|
|
22
|
+
provider: "%project.env.S3_PROVIDER%",
|
|
23
|
+
credentials: {
|
|
24
|
+
key: `%?project.secret.s3.key||project.env.S3_KEY%`,
|
|
25
|
+
secret: `%?project.secret.s3.secret||project.env.S3_SECRET%`
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
getProjectConfigSchema(slug) {
|
|
32
|
+
return Typesafe.union(
|
|
33
|
+
(input, path = []) => Typesafe.valueAt(input, ["s3", "credentials", "key"]) === void 0 ? {} : Typesafe.fail(path),
|
|
34
|
+
Typesafe.object({
|
|
35
|
+
s3: s3ConfigSchema
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
S3ConfigProcessor
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=S3ConfigProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"S3ConfigProcessor.js","sources":["../../../../packages/engine-s3-plugin/src/S3ConfigProcessor.ts"],"sourcesContent":["import { ConfigProcessor, ConfigTemplate, ConfigTemplateContext } from '@contember/engine-plugins'\nimport { Project3Config, s3ConfigSchema } from './Config'\nimport * as Typesafe from '@contember/typesafe'\n\nexport class S3ConfigProcessor implements ConfigProcessor<Project3Config> {\n\tgetDefaultEnv(): Record<string, string> {\n\t\treturn {\n\t\t\tDEFAULT_S3_ENDPOINT: '',\n\t\t\tDEFAULT_S3_REGION: 'us-east-1',\n\t\t\tDEFAULT_S3_PROVIDER: 'aws',\n\t\t}\n\t}\n\n\tprepareConfigTemplate(template: ConfigTemplate, { env }: ConfigTemplateContext) {\n\t\treturn {\n\t\t\t...template,\n\t\t\tprojectDefaults: {\n\t\t\t\t...template.projectDefaults,\n\t\t\t\ts3: {\n\t\t\t\t\tbucket: `%?project.env.S3_BUCKET%`,\n\t\t\t\t\tprefix: `%?project.env.S3_PREFIX||project.slug%`,\n\t\t\t\t\tregion: `%project.env.S3_REGION%`,\n\t\t\t\t\tendpoint: `%project.env.S3_ENDPOINT%`,\n\t\t\t\t\tcdnEndpoint: `%?project.env.S3_CDN%`,\n\t\t\t\t\tprovider: '%project.env.S3_PROVIDER%',\n\t\t\t\t\tcredentials: {\n\t\t\t\t\t\tkey: `%?project.secret.s3.key||project.env.S3_KEY%`,\n\t\t\t\t\t\tsecret: `%?project.secret.s3.secret||project.env.S3_SECRET%`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n\n\tgetProjectConfigSchema(slug: string): Typesafe.Type<Record<string, any>> {\n\t\treturn Typesafe.union(\n\t\t\t(input: unknown, path: PropertyKey[] = []) => Typesafe.valueAt(input, ['s3', 'credentials', 'key']) === undefined ? {} : Typesafe.fail(path),\n\t\t\tTypesafe.object({\n\t\t\t\ts3: s3ConfigSchema,\n\t\t\t}),\n\t\t)\n\t}\n}\n"],"names":[],"mappings":";;AAIO,MAAM,kBAA6D;AAAA,EACzE,gBAAwC;AACvC,WAAO;AAAA,MACN,qBAAqB;AAAA,MACrB,mBAAmB;AAAA,MACnB,qBAAqB;AAAA,IAAA;AAAA,EAEvB;AAAA,EAEA,sBAAsB,UAA0B,EAAE,OAA8B;AAC/E,WAAO;AAAA,MACN,GAAG;AAAA,MACH,iBAAiB;AAAA,QAChB,GAAG,SAAS;AAAA,QACZ,IAAI;AAAA,UACH,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,aAAa;AAAA,UACb,UAAU;AAAA,UACV,aAAa;AAAA,YACZ,KAAK;AAAA,YACL,QAAQ;AAAA,UAAA;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAAA,EAEF;AAAA,EAEA,uBAAuB,MAAkD;AACxE,WAAO,SAAS;AAAA,MACf,CAAC,OAAgB,OAAsB,CAAA,MAAO,SAAS,QAAQ,OAAO,CAAC,MAAM,eAAe,KAAK,CAAC,MAAM,SAAY,CAAA,IAAK,SAAS,KAAK,IAAI;AAAA,MAC3I,SAAS,OAAO;AAAA,QACf,IAAI;AAAA,MAAA,CACJ;AAAA,IAAA;AAAA,EAEH;AACD;"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const pm = require("picomatch");
|
|
4
|
+
const graphqlUtils = require("@contember/graphql-utils");
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
8
|
+
class S3ObjectAuthorizator {
|
|
9
|
+
constructor(uploadRules, readRules) {
|
|
10
|
+
__publicField(this, "uploadRules");
|
|
11
|
+
__publicField(this, "readRules");
|
|
12
|
+
this.uploadRules = uploadRules;
|
|
13
|
+
this.readRules = readRules;
|
|
14
|
+
}
|
|
15
|
+
verifyReadAccess({ key }) {
|
|
16
|
+
for (const rule of this.readRules) {
|
|
17
|
+
rule.matcher ?? (rule.matcher = pm(rule.pattern));
|
|
18
|
+
if (rule.matcher(key)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
throw new graphqlUtils.ForbiddenError(`Read access forbidden for object key ${key}`);
|
|
23
|
+
}
|
|
24
|
+
verifyUploadAccess({ key, size }) {
|
|
25
|
+
const matchedPatterns = [];
|
|
26
|
+
for (const rule of this.uploadRules) {
|
|
27
|
+
rule.matcher ?? (rule.matcher = pm(rule.pattern));
|
|
28
|
+
if (rule.matcher(key)) {
|
|
29
|
+
if (!rule.maxSize || size !== null && size <= rule.maxSize) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
matchedPatterns.push(rule);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (matchedPatterns.length > 0) {
|
|
36
|
+
if (size === null) {
|
|
37
|
+
throw new graphqlUtils.ForbiddenError("File size must be provided");
|
|
38
|
+
} else {
|
|
39
|
+
throw new graphqlUtils.ForbiddenError("Uploaded file is too large");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
throw new graphqlUtils.ForbiddenError(`Upload access forbidden for object key ${key}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.S3ObjectAuthorizator = S3ObjectAuthorizator;
|
|
46
|
+
//# sourceMappingURL=S3ObjectAuthorizator.cjs.map
|
|
@@ -0,0 +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;;"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import pm from "picomatch";
|
|
2
|
+
import { ForbiddenError } from "@contember/graphql-utils";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
|
+
class S3ObjectAuthorizator {
|
|
7
|
+
constructor(uploadRules, readRules) {
|
|
8
|
+
__publicField(this, "uploadRules");
|
|
9
|
+
__publicField(this, "readRules");
|
|
10
|
+
this.uploadRules = uploadRules;
|
|
11
|
+
this.readRules = readRules;
|
|
12
|
+
}
|
|
13
|
+
verifyReadAccess({ key }) {
|
|
14
|
+
for (const rule of this.readRules) {
|
|
15
|
+
rule.matcher ?? (rule.matcher = pm(rule.pattern));
|
|
16
|
+
if (rule.matcher(key)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
throw new ForbiddenError(`Read access forbidden for object key ${key}`);
|
|
21
|
+
}
|
|
22
|
+
verifyUploadAccess({ key, size }) {
|
|
23
|
+
const matchedPatterns = [];
|
|
24
|
+
for (const rule of this.uploadRules) {
|
|
25
|
+
rule.matcher ?? (rule.matcher = pm(rule.pattern));
|
|
26
|
+
if (rule.matcher(key)) {
|
|
27
|
+
if (!rule.maxSize || size !== null && size <= rule.maxSize) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
matchedPatterns.push(rule);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (matchedPatterns.length > 0) {
|
|
34
|
+
if (size === null) {
|
|
35
|
+
throw new ForbiddenError("File size must be provided");
|
|
36
|
+
} else {
|
|
37
|
+
throw new ForbiddenError("Uploaded file is too large");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
throw new ForbiddenError(`Upload access forbidden for object key ${key}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
S3ObjectAuthorizator
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=S3ObjectAuthorizator.js.map
|
|
@@ -0,0 +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;"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const graphql = require("graphql");
|
|
4
|
+
const Config = require("./Config.cjs");
|
|
5
|
+
const S3SchemaTypes = require("./S3SchemaTypes.cjs");
|
|
6
|
+
const S3ObjectAuthorizator = require("./S3ObjectAuthorizator.cjs");
|
|
7
|
+
class S3SchemaContributor {
|
|
8
|
+
constructor(s3Factory, providers) {
|
|
9
|
+
this.s3Factory = s3Factory;
|
|
10
|
+
this.providers = providers;
|
|
11
|
+
}
|
|
12
|
+
getCacheKey({ project }) {
|
|
13
|
+
return project.s3 ? "yes" : "no";
|
|
14
|
+
}
|
|
15
|
+
createSchema(context) {
|
|
16
|
+
if (!context.project.s3) {
|
|
17
|
+
return void 0;
|
|
18
|
+
}
|
|
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);
|
|
31
|
+
const uploadMutation = this.createUploadMutation(authorizator);
|
|
32
|
+
const readMutation = this.createReadMutation(authorizator);
|
|
33
|
+
const mutation = {
|
|
34
|
+
generateUploadUrl: uploadMutation,
|
|
35
|
+
generateReadUrl: readMutation
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
mutation: new graphql.GraphQLObjectType({
|
|
39
|
+
name: "Mutation",
|
|
40
|
+
fields: () => mutation
|
|
41
|
+
}),
|
|
42
|
+
query: new graphql.GraphQLObjectType({
|
|
43
|
+
name: "Query",
|
|
44
|
+
fields: () => ({
|
|
45
|
+
s3DummyQuery: {
|
|
46
|
+
type: graphql.GraphQLString
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
createReadMutation(authorizator) {
|
|
53
|
+
return {
|
|
54
|
+
type: new graphql.GraphQLNonNull(S3SchemaTypes.S3SignedRead),
|
|
55
|
+
args: {
|
|
56
|
+
objectKey: {
|
|
57
|
+
type: new graphql.GraphQLNonNull(graphql.GraphQLString)
|
|
58
|
+
},
|
|
59
|
+
expiration: {
|
|
60
|
+
type: graphql.GraphQLInt
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
resolve: async (parent, args, ctx) => {
|
|
64
|
+
if (!ctx.project.s3) {
|
|
65
|
+
throw new graphql.GraphQLError("S3 is not configured for this project");
|
|
66
|
+
}
|
|
67
|
+
const s3Config = Config.resolveS3Config(ctx.project.s3);
|
|
68
|
+
const s3 = this.s3Factory.create(s3Config, this.providers, authorizator);
|
|
69
|
+
return s3.getSignedReadUrl({ objectKey: args.objectKey, expiration: args.expiration ?? null });
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
createUploadMutation(authorizator) {
|
|
74
|
+
return {
|
|
75
|
+
type: new graphql.GraphQLNonNull(S3SchemaTypes.S3SignedUpload),
|
|
76
|
+
args: {
|
|
77
|
+
input: { type: S3SchemaTypes.S3GenerateSignedUploadInput },
|
|
78
|
+
contentType: { type: graphql.GraphQLString, deprecationReason: "Use input.contentType" },
|
|
79
|
+
expiration: { type: graphql.GraphQLInt, deprecationReason: "Use input.expiration" },
|
|
80
|
+
prefix: { type: graphql.GraphQLString, deprecationReason: "Use input.prefix" },
|
|
81
|
+
acl: { type: S3SchemaTypes.S3Acl, deprecationReason: "Use input.acl" }
|
|
82
|
+
},
|
|
83
|
+
resolve: async (parent, args, ctx) => {
|
|
84
|
+
if (!ctx.project.s3) {
|
|
85
|
+
throw new graphql.GraphQLError("S3 is not configured for this project");
|
|
86
|
+
}
|
|
87
|
+
const s3Config = Config.resolveS3Config(ctx.project.s3);
|
|
88
|
+
const s3 = this.s3Factory.create(s3Config, this.providers, authorizator);
|
|
89
|
+
return s3.getSignedUploadUrl({
|
|
90
|
+
acl: args.input?.acl ?? args.acl ?? null,
|
|
91
|
+
contentDisposition: args.input?.contentDisposition ?? null,
|
|
92
|
+
contentType: args.input?.contentType ?? args.contentType ?? null,
|
|
93
|
+
expiration: args.input?.expiration ?? args.expiration ?? null,
|
|
94
|
+
extension: args.input?.extension ?? null,
|
|
95
|
+
fileName: args.input?.fileName ?? null,
|
|
96
|
+
prefix: args.input?.prefix ?? args.prefix ?? null,
|
|
97
|
+
suffix: args.input?.suffix ?? null,
|
|
98
|
+
size: args.input?.size ?? null
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.S3SchemaContributor = S3SchemaContributor;
|
|
105
|
+
//# sourceMappingURL=S3SchemaContributor.cjs.map
|
|
@@ -0,0 +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'\nimport { Project3Config, resolveS3Config, S3Config } from './Config'\nimport { GraphQLSchemaContributor, GraphQLSchemaContributorContext, Providers } from '@contember/engine-plugins'\nimport * as types from './S3SchemaTypes'\nimport { S3Acl, S3GenerateSignedUploadInput, S3SignedRead, S3SignedUpload } from './S3SchemaTypes'\nimport { S3ObjectAuthorizator } from './S3ObjectAuthorizator'\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":"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"}
|