@dcl/content-validator 1.0.0-20220104134007.commit-80072ed
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/README.md +29 -0
- package/dist/content-validator.api.json +1177 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/types.d.ts +114 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +36 -0
- package/dist/types.js.map +1 -0
- package/dist/validations/access-checker/access.d.ts +7 -0
- package/dist/validations/access-checker/access.d.ts.map +1 -0
- package/dist/validations/access-checker/access.js +28 -0
- package/dist/validations/access-checker/access.js.map +1 -0
- package/dist/validations/access-checker/profiles.d.ts +7 -0
- package/dist/validations/access-checker/profiles.d.ts.map +1 -0
- package/dist/validations/access-checker/profiles.js +30 -0
- package/dist/validations/access-checker/profiles.js.map +1 -0
- package/dist/validations/access-checker/scenes.d.ts +7 -0
- package/dist/validations/access-checker/scenes.d.ts.map +1 -0
- package/dist/validations/access-checker/scenes.js +246 -0
- package/dist/validations/access-checker/scenes.js.map +1 -0
- package/dist/validations/access-checker/wearables.d.ts +20 -0
- package/dist/validations/access-checker/wearables.d.ts.map +1 -0
- package/dist/validations/access-checker/wearables.js +247 -0
- package/dist/validations/access-checker/wearables.js.map +1 -0
- package/dist/validations/content.d.ts +7 -0
- package/dist/validations/content.d.ts.map +1 -0
- package/dist/validations/content.js +48 -0
- package/dist/validations/content.js.map +1 -0
- package/dist/validations/decentraland-address.d.ts +6 -0
- package/dist/validations/decentraland-address.d.ts.map +1 -0
- package/dist/validations/decentraland-address.js +19 -0
- package/dist/validations/decentraland-address.js.map +1 -0
- package/dist/validations/entity-structure.d.ts +7 -0
- package/dist/validations/entity-structure.d.ts.map +1 -0
- package/dist/validations/entity-structure.js +21 -0
- package/dist/validations/entity-structure.js.map +1 -0
- package/dist/validations/index.d.ts +22 -0
- package/dist/validations/index.d.ts.map +1 -0
- package/dist/validations/index.js +76 -0
- package/dist/validations/index.js.map +1 -0
- package/dist/validations/ipfs-hashing.d.ts +7 -0
- package/dist/validations/ipfs-hashing.d.ts.map +1 -0
- package/dist/validations/ipfs-hashing.js +25 -0
- package/dist/validations/ipfs-hashing.js.map +1 -0
- package/dist/validations/metadata-schema.d.ts +6 -0
- package/dist/validations/metadata-schema.d.ts.map +1 -0
- package/dist/validations/metadata-schema.js +26 -0
- package/dist/validations/metadata-schema.js.map +1 -0
- package/dist/validations/must-have-failed-before.d.ts +6 -0
- package/dist/validations/must-have-failed-before.d.ts.map +1 -0
- package/dist/validations/must-have-failed-before.js +13 -0
- package/dist/validations/must-have-failed-before.js.map +1 -0
- package/dist/validations/no-newer.d.ts +6 -0
- package/dist/validations/no-newer.d.ts.map +1 -0
- package/dist/validations/no-newer.js +14 -0
- package/dist/validations/no-newer.js.map +1 -0
- package/dist/validations/no-redeploy.d.ts +6 -0
- package/dist/validations/no-redeploy.d.ts.map +1 -0
- package/dist/validations/no-redeploy.js +13 -0
- package/dist/validations/no-redeploy.js.map +1 -0
- package/dist/validations/rate-limit.d.ts +6 -0
- package/dist/validations/rate-limit.d.ts.map +1 -0
- package/dist/validations/rate-limit.js +13 -0
- package/dist/validations/rate-limit.js.map +1 -0
- package/dist/validations/recent.d.ts +7 -0
- package/dist/validations/recent.d.ts.map +1 -0
- package/dist/validations/recent.js +27 -0
- package/dist/validations/recent.js.map +1 -0
- package/dist/validations/signature.d.ts +7 -0
- package/dist/validations/signature.d.ts.map +1 -0
- package/dist/validations/signature.js +17 -0
- package/dist/validations/signature.js.map +1 -0
- package/dist/validations/size.d.ts +8 -0
- package/dist/validations/size.d.ts.map +1 -0
- package/dist/validations/size.js +39 -0
- package/dist/validations/size.js.map +1 -0
- package/dist/validations/wearable.d.ts +10 -0
- package/dist/validations/wearable.d.ts.map +1 -0
- package/dist/validations/wearable.js +76 -0
- package/dist/validations/wearable.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-newer.d.ts","sourceRoot":"","sources":["../../src/validations/no-newer.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,OAAO,+BAIlB,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noNewer = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/**
|
|
6
|
+
* Validate that there are no newer deployments on the entity's pointers
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
exports.noNewer = (0, types_1.conditionalValidation)({
|
|
10
|
+
// Validate that pointers aren't referring to an entity with a higher timestamp
|
|
11
|
+
predicate: async ({ deployment, externalCalls }) => await externalCalls.areThereNewerEntities(deployment.entity),
|
|
12
|
+
message: () => 'There is a newer entity pointed by one or more of the pointers you provided.',
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=no-newer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-newer.js","sourceRoot":"","sources":["../../src/validations/no-newer.ts"],"names":[],"mappings":";;;AAAA,oCAAgD;AAEhD;;;GAGG;AACU,QAAA,OAAO,GAAG,IAAA,6BAAqB,EAAC;IAC3C,+EAA+E;IAC/E,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,MAAM,aAAa,CAAC,qBAAqB,CAAC,UAAU,CAAC,MAAM,CAAC;IAChH,OAAO,EAAE,GAAG,EAAE,CAAC,8EAA8E;CAC9F,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-redeploy.d.ts","sourceRoot":"","sources":["../../src/validations/no-redeploy.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,UAAU,+BAGrB,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noRedeploy = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/**
|
|
6
|
+
* Validate if the entity can be re deployed or not
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
exports.noRedeploy = (0, types_1.conditionalValidation)({
|
|
10
|
+
predicate: async ({ externalCalls }) => await externalCalls.isEntityDeployedAlready(),
|
|
11
|
+
message: () => "This entity was already deployed. You can't redeploy it",
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=no-redeploy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-redeploy.js","sourceRoot":"","sources":["../../src/validations/no-redeploy.ts"],"names":[],"mappings":";;;AAAA,oCAAgD;AAEhD;;;GAGG;AACU,QAAA,UAAU,GAAG,IAAA,6BAAqB,EAAC;IAC9C,SAAS,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,MAAM,aAAa,CAAC,uBAAuB,EAAE;IACrF,OAAO,EAAE,GAAG,EAAE,CAAC,yDAAyD;CACzE,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/validations/rate-limit.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,SAAS,+BAIpB,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rateLimit = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/**
|
|
6
|
+
* Validate the deployment is not rate limited
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
exports.rateLimit = (0, types_1.conditionalValidation)({
|
|
10
|
+
predicate: async ({ deployment, externalCalls }) => !(await externalCalls.isEntityRateLimited(deployment.entity)),
|
|
11
|
+
message: ({ deployment }) => `Entity rate limited (entityId=${deployment.entity.id} pointers=${deployment.entity.pointers.join(',')}).`,
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=rate-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/validations/rate-limit.ts"],"names":[],"mappings":";;;AAAA,oCAAgD;AAEhD;;;GAGG;AACU,QAAA,SAAS,GAAG,IAAA,6BAAqB,EAAC;IAC7C,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,mBAAmB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACjH,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAC1B,iCAAiC,UAAU,CAAC,MAAM,CAAC,EAAE,aAAa,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;CAC7G,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recent.d.ts","sourceRoot":"","sources":["../../src/validations/recent.ts"],"names":[],"mappings":"AACA,OAAO,EAAM,UAAU,EAAoB,MAAM,UAAU,CAAA;AAI3D;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,UAWpB,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.recent = void 0;
|
|
7
|
+
const ms_1 = __importDefault(require("ms"));
|
|
8
|
+
const types_1 = require("../types");
|
|
9
|
+
const REQUEST_TTL_FORWARDS = (0, ms_1.default)('15m');
|
|
10
|
+
/**
|
|
11
|
+
* Validate that the deployment is recent
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
exports.recent = {
|
|
15
|
+
validate: ({ deployment, externalCalls }) => {
|
|
16
|
+
// Verify that the timestamp is recent enough. We need to make sure that the definition of recent works with the synchronization mechanism
|
|
17
|
+
const delta = Date.now() - deployment.entity.timestamp;
|
|
18
|
+
if (delta > externalCalls.requestTtlBackwards) {
|
|
19
|
+
return (0, types_1.validationFailed)('The request is not recent enough, please submit it again with a new timestamp.');
|
|
20
|
+
}
|
|
21
|
+
else if (delta < -REQUEST_TTL_FORWARDS) {
|
|
22
|
+
return (0, types_1.validationFailed)('The request is too far in the future, please submit it again with a new timestamp.');
|
|
23
|
+
}
|
|
24
|
+
return types_1.OK;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=recent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recent.js","sourceRoot":"","sources":["../../src/validations/recent.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAmB;AACnB,oCAA2D;AAE3D,MAAM,oBAAoB,GAAW,IAAA,YAAE,EAAC,KAAK,CAAC,CAAA;AAE9C;;;GAGG;AACU,QAAA,MAAM,GAAe;IAChC,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,EAAE,EAAE;QAC1C,0IAA0I;QAC1I,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,CAAA;QACtD,IAAI,KAAK,GAAG,aAAa,CAAC,mBAAmB,EAAE;YAC7C,OAAO,IAAA,wBAAgB,EAAC,gFAAgF,CAAC,CAAA;SAC1G;aAAM,IAAI,KAAK,GAAG,CAAC,oBAAoB,EAAE;YACxC,OAAO,IAAA,wBAAgB,EAAC,oFAAoF,CAAC,CAAA;SAC9G;QACD,OAAO,UAAE,CAAA;IACX,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../src/validations/signature.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,UAAU,EAAoB,MAAM,UAAU,CAAA;AAE3D;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,UAOvB,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.signature = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/**
|
|
6
|
+
* Validate that the signature belongs to the Ethereum address
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
exports.signature = {
|
|
10
|
+
// todo: should we include signature result message?
|
|
11
|
+
validate: async ({ deployment, externalCalls }) => {
|
|
12
|
+
const { entity, auditInfo } = deployment;
|
|
13
|
+
const validationResult = await externalCalls.validateSignature(entity.id, auditInfo, entity.timestamp);
|
|
14
|
+
return !validationResult.ok ? (0, types_1.validationFailed)('The signature is invalid. ' + validationResult.message) : types_1.OK;
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.js","sourceRoot":"","sources":["../../src/validations/signature.ts"],"names":[],"mappings":";;;AAAA,oCAA2D;AAE3D;;;GAGG;AACU,QAAA,SAAS,GAAe;IACnC,oDAAoD;IACpD,QAAQ,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,EAAE,EAAE;QAChD,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,UAAU,CAAA;QACxC,MAAM,gBAAgB,GAAG,MAAM,aAAa,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;QACtG,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,wBAAgB,EAAC,4BAA4B,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAE,CAAA;IAC9G,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Validation } from '../types';
|
|
2
|
+
/** Validate that the full request size is within limits
|
|
3
|
+
*
|
|
4
|
+
* ADR X: After given TIMESTAMPT will also include previous deployments in the validation
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export declare const size: Validation;
|
|
8
|
+
//# sourceMappingURL=size.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"size.d.ts","sourceRoot":"","sources":["../../src/validations/size.ts"],"names":[],"mappings":"AACA,OAAO,EAAM,UAAU,EAAoB,MAAM,UAAU,CAAA;AAE3D;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,UA2BlB,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.size = void 0;
|
|
4
|
+
const _1 = require(".");
|
|
5
|
+
const types_1 = require("../types");
|
|
6
|
+
/** Validate that the full request size is within limits
|
|
7
|
+
*
|
|
8
|
+
* ADR X: After given TIMESTAMPT will also include previous deployments in the validation
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
exports.size = {
|
|
12
|
+
validate: async ({ deployment, externalCalls }) => {
|
|
13
|
+
const { entity } = deployment;
|
|
14
|
+
const maxSizeInMB = externalCalls.getMaxUploadSizePerTypeInMB(entity.type);
|
|
15
|
+
let errors = [];
|
|
16
|
+
if (!maxSizeInMB) {
|
|
17
|
+
return (0, types_1.validationFailed)(`Type ${entity.type} is not supported yet`);
|
|
18
|
+
}
|
|
19
|
+
const maxSizeInBytes = maxSizeInMB * 1024 * 1024;
|
|
20
|
+
let totalSize = 0;
|
|
21
|
+
if (entity.timestamp > _1.ADR_X_TIMESTAMP) {
|
|
22
|
+
const result = await (0, _1.calculateDeploymentSize)(deployment, externalCalls);
|
|
23
|
+
if (typeof result === 'string')
|
|
24
|
+
return (0, types_1.validationFailed)(result);
|
|
25
|
+
totalSize = result;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
totalSize = Array.from(deployment.files.values()).reduce((acc, file) => acc + file.byteLength, 0);
|
|
29
|
+
}
|
|
30
|
+
const sizePerPointer = totalSize / entity.pointers.length;
|
|
31
|
+
if (sizePerPointer > maxSizeInBytes) {
|
|
32
|
+
errors = [
|
|
33
|
+
`The deployment is too big. The maximum allowed size per pointer is ${maxSizeInMB} MB for ${entity.type}. You can upload up to ${entity.pointers.length * maxSizeInBytes} bytes but you tried to upload ${totalSize}.`,
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
return errors.length > 0 ? (0, types_1.validationFailed)(...errors) : types_1.OK;
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=size.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"size.js","sourceRoot":"","sources":["../../src/validations/size.ts"],"names":[],"mappings":";;;AAAA,wBAA4D;AAC5D,oCAA2D;AAE3D;;;;GAIG;AACU,QAAA,IAAI,GAAe;IAC9B,QAAQ,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,EAAE,EAAE;QAChD,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAA;QAC7B,MAAM,WAAW,GAAG,aAAa,CAAC,2BAA2B,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC1E,IAAI,MAAM,GAAa,EAAE,CAAA;QACzB,IAAI,CAAC,WAAW,EAAE;YAChB,OAAO,IAAA,wBAAgB,EAAC,QAAQ,MAAM,CAAC,IAAI,uBAAuB,CAAC,CAAA;SACpE;QACD,MAAM,cAAc,GAAG,WAAW,GAAG,IAAI,GAAG,IAAI,CAAA;QAChD,IAAI,SAAS,GAAG,CAAC,CAAA;QACjB,IAAI,MAAM,CAAC,SAAS,GAAG,kBAAe,EAAE;YACtC,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAuB,EAAC,UAAU,EAAE,aAAa,CAAC,CAAA;YACvE,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO,IAAA,wBAAgB,EAAC,MAAM,CAAC,CAAA;YAC/D,SAAS,GAAG,MAAM,CAAA;SACnB;aAAM;YACL,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAA;SAClG;QACD,MAAM,cAAc,GAAG,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAA;QACzD,IAAI,cAAc,GAAG,cAAc,EAAE;YACnC,MAAM,GAAG;gBACP,sEAAsE,WAAW,WAC/E,MAAM,CAAC,IACT,0BAA0B,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,cAAc,kCAAkC,SAAS,GAAG;aAChH,CAAA;SACF;QACD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAA,wBAAgB,EAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,UAAE,CAAA;IAC7D,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Validation } from '../types';
|
|
2
|
+
/** Validate wearable files size, excluding thumbnail, is less than expected */
|
|
3
|
+
export declare const wearableSize: Validation;
|
|
4
|
+
export declare const wearableThumbnail: Validation;
|
|
5
|
+
/**
|
|
6
|
+
* Validate that given wearable deployment includes the thumbnail and doesn't exceed file sizes
|
|
7
|
+
* * @public
|
|
8
|
+
*/
|
|
9
|
+
export declare const wearable: Validation;
|
|
10
|
+
//# sourceMappingURL=wearable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wearable.d.ts","sourceRoot":"","sources":["../../src/validations/wearable.ts"],"names":[],"mappings":"AAIA,OAAO,EAAM,UAAU,EAAoB,MAAM,UAAU,CAAA;AAE3D,+EAA+E;AAC/E,eAAO,MAAM,YAAY,EAAE,UAyB1B,CAAA;AAID,eAAO,MAAM,iBAAiB,EAAE,UAyB/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,UAKtB,CAAA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.wearable = exports.wearableThumbnail = exports.wearableSize = void 0;
|
|
7
|
+
const dcl_catalyst_commons_1 = require("dcl-catalyst-commons");
|
|
8
|
+
const sharp_1 = __importDefault(require("sharp"));
|
|
9
|
+
const _1 = require(".");
|
|
10
|
+
const types_1 = require("../types");
|
|
11
|
+
/** Validate wearable files size, excluding thumbnail, is less than expected */
|
|
12
|
+
exports.wearableSize = {
|
|
13
|
+
validate: async ({ deployment, externalCalls }) => {
|
|
14
|
+
const entity = deployment.entity;
|
|
15
|
+
const maxSizeInMB = externalCalls.getMaxUploadSizePerTypeInMB(dcl_catalyst_commons_1.EntityType.WEARABLE);
|
|
16
|
+
if (!maxSizeInMB)
|
|
17
|
+
return (0, types_1.validationFailed)(`Type ${dcl_catalyst_commons_1.EntityType.WEARABLE} is not supported yet`);
|
|
18
|
+
const modelSizeInMB = externalCalls.wearableSizeLimitInMB;
|
|
19
|
+
const metadata = entity.metadata;
|
|
20
|
+
const thumbnailHash = entity.content?.find(({ file }) => file === metadata.thumbnail)?.hash;
|
|
21
|
+
if (!thumbnailHash)
|
|
22
|
+
return (0, types_1.validationFailed)("Couldn't find the thumbnail hash");
|
|
23
|
+
const result = await (0, _1.calculateDeploymentSize)(deployment, externalCalls);
|
|
24
|
+
if (typeof result === 'string')
|
|
25
|
+
return (0, types_1.validationFailed)(result);
|
|
26
|
+
const totalDeploymentSize = result;
|
|
27
|
+
const thumbnailSize = deployment.files.get(thumbnailHash)?.byteLength ?? 0;
|
|
28
|
+
const modelSize = totalDeploymentSize - thumbnailSize;
|
|
29
|
+
if (modelSize > modelSizeInMB * 1024 * 1024)
|
|
30
|
+
return (0, types_1.validationFailed)(`The deployment is too big. The maximum allowed size for wearable model files is ${modelSizeInMB} MB. You can upload up to ${modelSizeInMB * 1024 * 1024} bytes but you tried to upload ${modelSize}.`);
|
|
31
|
+
return types_1.OK;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
/** Validate that given wearable deployment includes a thumbnail with valid format and size */
|
|
35
|
+
const defaultThumbnailSize = 1024;
|
|
36
|
+
exports.wearableThumbnail = {
|
|
37
|
+
validate: async ({ deployment }) => {
|
|
38
|
+
// read thumbnail field from metadata
|
|
39
|
+
const metadata = deployment.entity.metadata;
|
|
40
|
+
const hash = deployment.entity.content?.find(({ file }) => file === metadata.thumbnail)?.hash;
|
|
41
|
+
if (!hash)
|
|
42
|
+
return (0, types_1.validationFailed)(`Couldn't find hash for thumbnail file with name: ${metadata.thumbnail}`);
|
|
43
|
+
const errors = [];
|
|
44
|
+
// check size
|
|
45
|
+
const thumbnailBuffer = deployment.files.get(hash);
|
|
46
|
+
if (!thumbnailBuffer)
|
|
47
|
+
return (0, types_1.validationFailed)(`Couldn't find thumbnail file with hash: ${hash}`);
|
|
48
|
+
try {
|
|
49
|
+
const { width, height, format } = await (0, sharp_1.default)(thumbnailBuffer).metadata();
|
|
50
|
+
if (!format || format !== 'png')
|
|
51
|
+
errors.push(`Invalid or unknown image format. Only 'PNG' format is accepted.`);
|
|
52
|
+
if (!width || !height) {
|
|
53
|
+
errors.push(`Couldn't validate thumbnail size for file ${metadata.thumbnail}`);
|
|
54
|
+
}
|
|
55
|
+
else if (width !== defaultThumbnailSize || height !== defaultThumbnailSize) {
|
|
56
|
+
errors.push(`Invalid thumbnail image size (width = ${width} / height = ${height})`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
errors.push(`Couldn't parse thumbnail, please check image format.`);
|
|
61
|
+
}
|
|
62
|
+
return errors.length > 0 ? (0, types_1.validationFailed)(...errors) : types_1.OK;
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Validate that given wearable deployment includes the thumbnail and doesn't exceed file sizes
|
|
67
|
+
* * @public
|
|
68
|
+
*/
|
|
69
|
+
exports.wearable = {
|
|
70
|
+
validate: async (args) => {
|
|
71
|
+
if (args.deployment.entity.type !== dcl_catalyst_commons_1.EntityType.WEARABLE)
|
|
72
|
+
return types_1.OK;
|
|
73
|
+
return (0, _1.validateInRow)(args, exports.wearableThumbnail, exports.wearableSize);
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=wearable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wearable.js","sourceRoot":"","sources":["../../src/validations/wearable.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dcl/content-validator",
|
|
3
|
+
"version": "1.0.0-20220104134007.commit-80072ed",
|
|
4
|
+
"description": "Catalyst content validations",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"typings": "dist/index.d.ts",
|
|
7
|
+
"scripts": {},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/decentraland/content-validator.git"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [],
|
|
13
|
+
"author": "Decentraland Contributors",
|
|
14
|
+
"license": "Apache-2.0",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/decentraland/content-validator/issues"
|
|
17
|
+
},
|
|
18
|
+
"prettier": {
|
|
19
|
+
"printWidth": 120,
|
|
20
|
+
"semi": false,
|
|
21
|
+
"singleQuote": true
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/decentraland/content-validator#readme",
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@dcl/eslint-config": "^1.0.0",
|
|
26
|
+
"@microsoft/api-extractor": "^7.19.3",
|
|
27
|
+
"@types/jest": "^27.4.0",
|
|
28
|
+
"@types/ms": "^0.7.31",
|
|
29
|
+
"@types/node": "^17.0.6",
|
|
30
|
+
"@types/sharp": "^0.29.5",
|
|
31
|
+
"jest": "^27.0.6",
|
|
32
|
+
"ts-jest": "^27.0.5",
|
|
33
|
+
"typescript": "^4.3.5"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@dcl/schemas": "^3.1.1",
|
|
37
|
+
"@dcl/urn-resolver": "^1.3.0",
|
|
38
|
+
"dcl-catalyst-commons": "^7.1.3",
|
|
39
|
+
"ethers": "^5.5.2",
|
|
40
|
+
"ms": "^2.1.3",
|
|
41
|
+
"sharp": "^0.29.3"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist"
|
|
45
|
+
],
|
|
46
|
+
"commit": "80072edc37c4a659139412d5f2eafb33339ed833"
|
|
47
|
+
}
|