@dcl/content-validator 4.2.4-20230125194827.commit-f90482b → 4.2.4-4135566596.commit-6ae9fb8
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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/the-graph-client/the-graph-client.d.ts +1 -5
- package/dist/the-graph-client/the-graph-client.d.ts.map +1 -1
- package/dist/the-graph-client/the-graph-client.js +83 -49
- package/dist/the-graph-client/the-graph-client.js.map +1 -1
- package/dist/types.d.ts +22 -45
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validations/ADR45.d.ts +2 -2
- package/dist/validations/ADR45.d.ts.map +1 -1
- package/dist/validations/ADR45.js +7 -8
- package/dist/validations/ADR45.js.map +1 -1
- package/dist/validations/ADR51.d.ts +1 -1
- package/dist/validations/ADR51.d.ts.map +1 -1
- package/dist/validations/access-checker/access.d.ts +2 -2
- package/dist/validations/access-checker/access.d.ts.map +1 -1
- package/dist/validations/access-checker/access.js +15 -17
- package/dist/validations/access-checker/access.js.map +1 -1
- package/dist/validations/access-checker/emotes.d.ts +2 -2
- package/dist/validations/access-checker/emotes.d.ts.map +1 -1
- package/dist/validations/access-checker/emotes.js +7 -8
- package/dist/validations/access-checker/emotes.js.map +1 -1
- package/dist/validations/access-checker/items/collection-asset.d.ts +2 -2
- package/dist/validations/access-checker/items/collection-asset.d.ts.map +1 -1
- package/dist/validations/access-checker/items/collection-asset.js +106 -43
- package/dist/validations/access-checker/items/collection-asset.js.map +1 -1
- package/dist/validations/access-checker/items/items.d.ts +4 -6
- package/dist/validations/access-checker/items/items.d.ts.map +1 -1
- package/dist/validations/access-checker/items/items.js +23 -24
- package/dist/validations/access-checker/items/items.js.map +1 -1
- package/dist/validations/access-checker/items/third-party-asset.d.ts.map +1 -1
- package/dist/validations/access-checker/items/third-party-asset.js +80 -21
- package/dist/validations/access-checker/items/third-party-asset.js.map +1 -1
- package/dist/validations/access-checker/profiles.d.ts +6 -6
- package/dist/validations/access-checker/profiles.d.ts.map +1 -1
- package/dist/validations/access-checker/profiles.js +59 -61
- package/dist/validations/access-checker/profiles.js.map +1 -1
- package/dist/validations/access-checker/scenes.d.ts +2 -2
- package/dist/validations/access-checker/scenes.d.ts.map +1 -1
- package/dist/validations/access-checker/scenes.js +243 -34
- package/dist/validations/access-checker/scenes.js.map +1 -1
- package/dist/validations/access-checker/stores.d.ts +2 -2
- package/dist/validations/access-checker/stores.d.ts.map +1 -1
- package/dist/validations/access-checker/stores.js +14 -15
- package/dist/validations/access-checker/stores.js.map +1 -1
- package/dist/validations/access-checker/wearables.d.ts +2 -2
- package/dist/validations/access-checker/wearables.d.ts.map +1 -1
- package/dist/validations/access-checker/wearables.js +9 -10
- package/dist/validations/access-checker/wearables.js.map +1 -1
- package/dist/validations/content.d.ts +6 -6
- package/dist/validations/content.d.ts.map +1 -1
- package/dist/validations/content.js +44 -50
- package/dist/validations/content.js.map +1 -1
- package/dist/validations/entity-structure.d.ts +2 -2
- package/dist/validations/entity-structure.d.ts.map +1 -1
- package/dist/validations/entity-structure.js +10 -11
- package/dist/validations/entity-structure.js.map +1 -1
- package/dist/validations/index.d.ts +9 -4
- package/dist/validations/index.d.ts.map +1 -1
- package/dist/validations/index.js +7 -7
- package/dist/validations/index.js.map +1 -1
- package/dist/validations/ipfs-hashing.d.ts +2 -2
- package/dist/validations/ipfs-hashing.d.ts.map +1 -1
- package/dist/validations/ipfs-hashing.js +8 -10
- package/dist/validations/ipfs-hashing.js.map +1 -1
- package/dist/validations/items/emotes.d.ts +4 -4
- package/dist/validations/items/emotes.d.ts.map +1 -1
- package/dist/validations/items/emotes.js +22 -24
- package/dist/validations/items/emotes.js.map +1 -1
- package/dist/validations/items/items.d.ts +4 -4
- package/dist/validations/items/items.d.ts.map +1 -1
- package/dist/validations/items/items.js +54 -55
- package/dist/validations/items/items.js.map +1 -1
- package/dist/validations/items/wearables.d.ts +4 -3
- package/dist/validations/items/wearables.d.ts.map +1 -1
- package/dist/validations/items/wearables.js +16 -17
- package/dist/validations/items/wearables.js.map +1 -1
- package/dist/validations/metadata-schema.d.ts +2 -2
- package/dist/validations/metadata-schema.d.ts.map +1 -1
- package/dist/validations/metadata-schema.js +17 -21
- package/dist/validations/metadata-schema.js.map +1 -1
- package/dist/validations/profile.d.ts +6 -6
- package/dist/validations/profile.d.ts.map +1 -1
- package/dist/validations/profile.js +55 -63
- package/dist/validations/profile.js.map +1 -1
- package/dist/validations/scene.d.ts +3 -3
- package/dist/validations/scene.d.ts.map +1 -1
- package/dist/validations/scene.js +5 -7
- package/dist/validations/scene.js.map +1 -1
- package/dist/validations/signature.d.ts +2 -2
- package/dist/validations/signature.d.ts.map +1 -1
- package/dist/validations/signature.js +6 -8
- package/dist/validations/signature.js.map +1 -1
- package/dist/validations/size.d.ts +2 -2
- package/dist/validations/size.d.ts.map +1 -1
- package/dist/validations/size.js +28 -29
- package/dist/validations/size.js.map +1 -1
- package/dist/validations/validations.d.ts +9 -9
- package/dist/validations/validations.d.ts.map +1 -1
- package/dist/validations/validations.js +34 -38
- package/dist/validations/validations.js.map +1 -1
- package/package.json +5 -10
- package/dist/content-validator.api.json +0 -1669
- package/dist/tsdoc-metadata.json +0 -11
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare
|
|
1
|
+
import { ContentValidatorComponents, DeploymentToValidate } from '../..';
|
|
2
|
+
export declare function emotes(components: Pick<ContentValidatorComponents, 'externalCalls' | 'logs' | 'theGraphClient'>, deployment: DeploymentToValidate): Promise<import("../..").ValidationResponse>;
|
|
3
3
|
//# sourceMappingURL=emotes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emotes.d.ts","sourceRoot":"","sources":["../../../src/validations/access-checker/emotes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"emotes.d.ts","sourceRoot":"","sources":["../../../src/validations/access-checker/emotes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AAGxE,wBAAsB,MAAM,CAC1B,UAAU,EAAE,IAAI,CAAC,0BAA0B,EAAE,eAAe,GAAG,MAAM,GAAG,gBAAgB,CAAC,EACzF,UAAU,EAAE,oBAAoB,+CAMjC"}
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.emotes = void 0;
|
|
4
4
|
const items_1 = require("./items/items");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
};
|
|
5
|
+
async function emotes(components, deployment) {
|
|
6
|
+
return (0, items_1.itemsValidation)(components, deployment, [
|
|
7
|
+
'blockchain-collection-v2-asset',
|
|
8
|
+
'blockchain-collection-third-party'
|
|
9
|
+
]);
|
|
10
|
+
}
|
|
11
|
+
exports.emotes = emotes;
|
|
13
12
|
//# sourceMappingURL=emotes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emotes.js","sourceRoot":"","sources":["../../../src/validations/access-checker/emotes.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"emotes.js","sourceRoot":"","sources":["../../../src/validations/access-checker/emotes.ts"],"names":[],"mappings":";;;AACA,yCAA+C;AAExC,KAAK,UAAU,MAAM,CAC1B,UAAyF,EACzF,UAAgC;IAEhC,OAAO,IAAA,uBAAe,EAAC,UAAU,EAAE,UAAU,EAAE;QAC7C,gCAAgC;QAChC,mCAAmC;KACpC,CAAC,CAAA;AACJ,CAAC;AARD,wBAQC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { AssetValidation } from './items';
|
|
2
|
-
type CollectionItem = {
|
|
2
|
+
declare type CollectionItem = {
|
|
3
3
|
managers: string[];
|
|
4
4
|
contentHash: string;
|
|
5
5
|
};
|
|
6
|
-
export type ItemCollection = {
|
|
6
|
+
export declare type ItemCollection = {
|
|
7
7
|
creator: string;
|
|
8
8
|
managers: string[];
|
|
9
9
|
isApproved: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-asset.d.ts","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/collection-asset.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"collection-asset.d.ts","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/collection-asset.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAoBzC,aAAK,cAAc,GAAG;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,oBAAY,cAAc,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;IACpB,KAAK,EAAE,cAAc,EAAE,CAAA;CACxB,CAAA;AAsID,eAAO,MAAM,gCAAgC,EAAE,eAqD9C,CAAA"}
|
|
@@ -5,22 +5,51 @@ const hashing_1 = require("@dcl/hashing");
|
|
|
5
5
|
const types_1 = require("../../../types");
|
|
6
6
|
const L1_NETWORKS = ['mainnet', 'kovan', 'rinkeby', 'goerli'];
|
|
7
7
|
const L2_NETWORKS = ['matic', 'mumbai'];
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
async function getCollectionItems(components, subgraph, collection, itemId, block) {
|
|
9
|
+
const query = `
|
|
10
|
+
query getCollectionRoles($collection: String!, $itemId: String!, $block: Int!) {
|
|
11
|
+
collections(where:{ id: $collection }, block: { number: $block }) {
|
|
12
|
+
creator
|
|
13
|
+
managers
|
|
14
|
+
isApproved
|
|
15
|
+
isCompleted
|
|
16
|
+
items(where:{ id: $itemId }) {
|
|
17
|
+
managers
|
|
18
|
+
contentHash
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
accounts(where:{ isCommitteeMember: true }, block: { number: $block }) {
|
|
23
|
+
id
|
|
24
|
+
}
|
|
25
|
+
}`;
|
|
26
|
+
const result = await subgraph.query(query, {
|
|
27
|
+
collection,
|
|
28
|
+
itemId: `${collection}-${itemId}`,
|
|
29
|
+
block
|
|
30
|
+
});
|
|
31
|
+
const collectionResult = result.collections[0];
|
|
32
|
+
const itemResult = collectionResult?.items[0];
|
|
33
|
+
return {
|
|
34
|
+
collectionCreator: collectionResult?.creator,
|
|
35
|
+
collectionManagers: collectionResult?.managers,
|
|
36
|
+
isApproved: collectionResult?.isApproved,
|
|
37
|
+
isCompleted: collectionResult?.isCompleted,
|
|
38
|
+
itemManagers: itemResult?.managers,
|
|
39
|
+
contentHash: itemResult?.contentHash,
|
|
40
|
+
committee: result.accounts.map(({ id }) => id.toLowerCase())
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async function hasPermission(components, subgraph, collection, itemId, block, entity, logger) {
|
|
44
|
+
try {
|
|
45
|
+
const { content, metadata } = entity;
|
|
46
|
+
const permissions = await getCollectionItems(components, subgraph, collection, itemId, block);
|
|
47
|
+
const ethAddressLowercase = entity.ethAddress.toLowerCase();
|
|
48
|
+
if (!!permissions.contentHash) {
|
|
49
|
+
const deployedByCommittee = permissions.committee.includes(ethAddressLowercase);
|
|
50
|
+
if (!deployedByCommittee) {
|
|
51
|
+
logger.debug(`The eth address ${ethAddressLowercase} is not part of committee.`);
|
|
19
52
|
}
|
|
20
|
-
return types_1.OK;
|
|
21
|
-
}
|
|
22
|
-
else if (L2_NETWORKS.includes(network)) {
|
|
23
|
-
const { timestamp, content, metadata } = deployment.entity;
|
|
24
53
|
const calculateHashes = () => {
|
|
25
54
|
// Compare both by key and hash
|
|
26
55
|
const compare = (a, b) => {
|
|
@@ -35,39 +64,73 @@ exports.v1andV2collectionAssetValidation = {
|
|
|
35
64
|
const buffer = Buffer.from(JSON.stringify({ content: contentAsJson, metadata }));
|
|
36
65
|
return Promise.all([(0, hashing_1.hashV0)(buffer), (0, hashing_1.hashV1)(buffer)]);
|
|
37
66
|
};
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const { blockAtDeployment, blockFiveMinBeforeDeployment } = await components.theGraphClient.findBlocksForTimestamp(timestamp, components.subGraphs.l2BlockSearch);
|
|
44
|
-
// NOTE(hugo): I'm calculating both hashes so I can make one RPC request (they are processed together as a batch),
|
|
45
|
-
// this may not be the right call, since it's possible to argue that a
|
|
46
|
-
// hash call is more expensive than a RPC call, but since I have no
|
|
47
|
-
// data to make a better decision, I think this is good enough
|
|
48
|
-
const hashes = await calculateHashes();
|
|
49
|
-
const batch = [];
|
|
50
|
-
for (const hash of hashes) {
|
|
51
|
-
if (blockAtDeployment) {
|
|
52
|
-
batch.push(validateWearable(hash, blockAtDeployment));
|
|
53
|
-
}
|
|
54
|
-
if (blockFiveMinBeforeDeployment) {
|
|
55
|
-
batch.push(validateWearable(hash, blockFiveMinBeforeDeployment));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
hasAccess = (await Promise.all(batch)).some((r) => r);
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
logger.error(err);
|
|
62
|
-
}
|
|
63
|
-
if (!hasAccess) {
|
|
64
|
-
return (0, types_1.validationFailed)(`The provided Eth Address '${ethAddress}' does not have access to the following item: (${asset.contractAddress}, ${asset.id})`);
|
|
67
|
+
const hashes = await calculateHashes();
|
|
68
|
+
const contentHashIsOk = hashes.includes(permissions.contentHash);
|
|
69
|
+
if (!contentHashIsOk) {
|
|
70
|
+
logger.debug(`The hash ${permissions.contentHash} doesn't match any of the calculated hashes: ${JSON.stringify(hashes)}.`);
|
|
65
71
|
}
|
|
66
|
-
return
|
|
72
|
+
return deployedByCommittee && contentHashIsOk;
|
|
67
73
|
}
|
|
68
74
|
else {
|
|
75
|
+
const addressHasAccess = (permissions.collectionCreator && permissions.collectionCreator === ethAddressLowercase) ||
|
|
76
|
+
(permissions.collectionManagers && permissions.collectionManagers.includes(ethAddressLowercase)) ||
|
|
77
|
+
(permissions.itemManagers && permissions.itemManagers.includes(ethAddressLowercase));
|
|
78
|
+
// Deployments to the content server are made after the collection is completed, so that the committee can then approve it.
|
|
79
|
+
// That's why isCompleted must be true, but isApproved must be false. After the committee approves the wearable, there can't be any more changes
|
|
80
|
+
const isCollectionValid = !permissions.isApproved && permissions.isCompleted;
|
|
81
|
+
return addressHasAccess && isCollectionValid;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
logger.error(`Error checking permission for (${collection}-${itemId}) at block ${block}. Error: ${error}`);
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function checkCollectionAccess(components, blocksSubgraph, collectionsSubgraph, collection, itemId, entity, logger) {
|
|
90
|
+
const { timestamp } = entity;
|
|
91
|
+
try {
|
|
92
|
+
const { blockNumberAtDeployment, blockNumberFiveMinBeforeDeployment } = await components.theGraphClient.findBlocksForTimestamp(blocksSubgraph, timestamp);
|
|
93
|
+
// It could happen that the subgraph hasn't synced yet, so someone who just lost access still managed to make a deployment. The problem would be that when other catalysts perform
|
|
94
|
+
// the same check, the subgraph might have synced and the deployment is no longer valid. So, in order to prevent inconsistencies between catalysts, we will allow all deployments that
|
|
95
|
+
// have access now, or had access 5 minutes ago.
|
|
96
|
+
const hasPermissionOnBlock = async (blockNumber) => !!blockNumber &&
|
|
97
|
+
(await hasPermission(components, collectionsSubgraph, collection, itemId, blockNumber, entity, logger));
|
|
98
|
+
return ((await hasPermissionOnBlock(blockNumberAtDeployment)) ||
|
|
99
|
+
(await hasPermissionOnBlock(blockNumberFiveMinBeforeDeployment)));
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
logger.error(`Error checking wearable access (${collection}, ${itemId}, ${entity.ethAddress}, ${timestamp}, ${blocksSubgraph}). Error: ${error}`);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.v1andV2collectionAssetValidation = {
|
|
107
|
+
async validateAsset(components, asset, deployment) {
|
|
108
|
+
const { externalCalls, subGraphs, logs } = components;
|
|
109
|
+
const ethAddress = externalCalls.ownerAddress(deployment.auditInfo);
|
|
110
|
+
const logger = logs.getLogger('collection asset access validation');
|
|
111
|
+
// L1 or L2 so contractAddress is present
|
|
112
|
+
const collection = asset.contractAddress;
|
|
113
|
+
const network = asset.network;
|
|
114
|
+
const isL1 = L1_NETWORKS.includes(network);
|
|
115
|
+
const isL2 = L2_NETWORKS.includes(network);
|
|
116
|
+
if (!isL1 && !isL2)
|
|
69
117
|
return (0, types_1.validationFailed)(`Found an unknown network on the urn '${network}'`);
|
|
118
|
+
const blocksSubgraphUrl = isL1 ? subGraphs.L1.blocks : subGraphs.L2.blocks;
|
|
119
|
+
const collectionsSubgraphUrl = isL1 ? subGraphs.L1.collections : subGraphs.L2.collections;
|
|
120
|
+
const hasAccess = await checkCollectionAccess(components, blocksSubgraphUrl, collectionsSubgraphUrl, collection, asset.id, {
|
|
121
|
+
...deployment.entity,
|
|
122
|
+
ethAddress
|
|
123
|
+
}, logger);
|
|
124
|
+
if (!hasAccess) {
|
|
125
|
+
if (isL2)
|
|
126
|
+
return (0, types_1.validationFailed)(`The provided Eth Address '${ethAddress}' does not have access to the following item: (${asset.contractAddress}, ${asset.id})`);
|
|
127
|
+
// L1 collections are deployed by Decentraland Address
|
|
128
|
+
const isAllowlistedCollection = asset.uri.toString().startsWith('urn:decentraland:ethereum:collections-v1');
|
|
129
|
+
if (!externalCalls.isAddressOwnedByDecentraland(ethAddress) || !isAllowlistedCollection) {
|
|
130
|
+
return (0, types_1.validationFailed)(`The provided Eth Address '${ethAddress}' does not have access to the following item: '${asset.uri}'`);
|
|
131
|
+
}
|
|
70
132
|
}
|
|
133
|
+
return types_1.OK;
|
|
71
134
|
},
|
|
72
135
|
canValidate(asset) {
|
|
73
136
|
return asset.type === 'blockchain-collection-v1-asset' || asset.type === 'blockchain-collection-v2-asset';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-asset.js","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/collection-asset.ts"],"names":[],"mappings":";;;AAAA,0CAA6C;
|
|
1
|
+
{"version":3,"file":"collection-asset.js","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/collection-asset.ts"],"names":[],"mappings":";;;AAAA,0CAA6C;AAK7C,0CAMuB;AAGvB,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;AAC7D,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AA8BvC,KAAK,UAAU,kBAAkB,CAC/B,UAA6D,EAC7D,QAA4B,EAC5B,UAAkB,EAClB,MAAc,EACd,KAAa;IAEb,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;UAgBN,CAAA;IAER,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAkB,KAAK,EAAE;QAC1D,UAAU;QACV,MAAM,EAAE,GAAG,UAAU,IAAI,MAAM,EAAE;QACjC,KAAK;KACN,CAAC,CAAA;IACF,MAAM,gBAAgB,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;IAC9C,MAAM,UAAU,GAAG,gBAAgB,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IAC7C,OAAO;QACL,iBAAiB,EAAE,gBAAgB,EAAE,OAAO;QAC5C,kBAAkB,EAAE,gBAAgB,EAAE,QAAQ;QAC9C,UAAU,EAAE,gBAAgB,EAAE,UAAU;QACxC,WAAW,EAAE,gBAAgB,EAAE,WAAW;QAC1C,YAAY,EAAE,UAAU,EAAE,QAAQ;QAClC,WAAW,EAAE,UAAU,EAAE,WAAW;QACpC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC;KAC7D,CAAA;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,UAA6D,EAC7D,QAA4B,EAC5B,UAAkB,EAClB,MAAc,EACd,KAAa,EACb,MAA4B,EAC5B,MAAgC;IAEhC,IAAI;QACF,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAA;QACpC,MAAM,WAAW,GAAwB,MAAM,kBAAkB,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;QAClH,MAAM,mBAAmB,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,CAAA;QAE3D,IAAI,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE;YAC7B,MAAM,mBAAmB,GAAG,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAA;YAC/E,IAAI,CAAC,mBAAmB,EAAE;gBACxB,MAAM,CAAC,KAAK,CAAC,mBAAmB,mBAAmB,4BAA4B,CAAC,CAAA;aACjF;YACD,MAAM,eAAe,GAAG,GAAG,EAAE;gBAC3B,+BAA+B;gBAC/B,MAAM,OAAO,GAAG,CAAC,CAAgC,EAAE,CAAgC,EAAE,EAAE;oBACrF,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI;wBAAE,OAAO,CAAC,CAAA;yBACxB,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI;wBAAE,OAAO,CAAC,CAAC,CAAA;;wBAC9B,OAAO,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;gBACpC,CAAC,CAAA;gBAED,MAAM,aAAa,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAClG,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAA;gBAChF,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAA,gBAAM,EAAC,MAAM,CAAC,EAAE,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YACtD,CAAC,CAAA;YACD,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAA;YACtC,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,CAAA;YAChE,IAAI,CAAC,eAAe,EAAE;gBACpB,MAAM,CAAC,KAAK,CACV,YAAY,WAAW,CAAC,WAAW,gDAAgD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAC7G,CAAA;aACF;YACD,OAAO,mBAAmB,IAAI,eAAe,CAAA;SAC9C;aAAM;YACL,MAAM,gBAAgB,GACpB,CAAC,WAAW,CAAC,iBAAiB,IAAI,WAAW,CAAC,iBAAiB,KAAK,mBAAmB,CAAC;gBACxF,CAAC,WAAW,CAAC,kBAAkB,IAAI,WAAW,CAAC,kBAAkB,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;gBAChG,CAAC,WAAW,CAAC,YAAY,IAAI,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAA;YAEtF,2HAA2H;YAC3H,gJAAgJ;YAChJ,MAAM,iBAAiB,GAAG,CAAC,WAAW,CAAC,UAAU,IAAI,WAAW,CAAC,WAAW,CAAA;YAE5E,OAAO,gBAAgB,IAAI,iBAAiB,CAAA;SAC7C;KACF;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,CAAC,KAAK,CAAC,kCAAkC,UAAU,IAAI,MAAM,cAAc,KAAK,YAAY,KAAK,EAAE,CAAC,CAAA;QAC1G,OAAO,KAAK,CAAA;KACb;AACH,CAAC;AAED,KAAK,UAAU,qBAAqB,CAClC,UAAgF,EAChF,cAAkC,EAClC,mBAAuC,EACvC,UAAkB,EAClB,MAAc,EACd,MAA4B,EAC5B,MAAgC;IAEhC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAA;IAC5B,IAAI;QACF,MAAM,EAAE,uBAAuB,EAAE,kCAAkC,EAAE,GACnE,MAAM,UAAU,CAAC,cAAc,CAAC,sBAAsB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAA;QACnF,kLAAkL;QAClL,sLAAsL;QACtL,gDAAgD;QAEhD,MAAM,oBAAoB,GAAG,KAAK,EAAE,WAA+B,EAAE,EAAE,CACrE,CAAC,CAAC,WAAW;YACb,CAAC,MAAM,aAAa,CAAC,UAAU,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;QACzG,OAAO,CACL,CAAC,MAAM,oBAAoB,CAAC,uBAAuB,CAAC,CAAC;YACrD,CAAC,MAAM,oBAAoB,CAAC,kCAAkC,CAAC,CAAC,CACjE,CAAA;KACF;IAAC,OAAO,KAAK,EAAE;QACd,MAAM,CAAC,KAAK,CACV,mCAAmC,UAAU,KAAK,MAAM,KAAK,MAAM,CAAC,UAAU,KAAK,SAAS,KAAK,cAAc,aAAa,KAAK,EAAE,CACpI,CAAA;QACD,OAAO,KAAK,CAAA;KACb;AACH,CAAC;AAEY,QAAA,gCAAgC,GAAoB;IAC/D,KAAK,CAAC,aAAa,CACjB,UAAuG,EACvG,KAAgE,EAChE,UAAgC;QAEhC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,UAAU,CAAA;QACrD,MAAM,UAAU,GAAG,aAAa,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;QACnE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAA;QACnE,yCAAyC;QACzC,MAAM,UAAU,GAAG,KAAK,CAAC,eAAgB,CAAA;QACzC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAA;QAE7B,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC1C,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC1C,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,IAAA,wBAAgB,EAAC,wCAAwC,OAAO,GAAG,CAAC,CAAA;QAE/F,MAAM,iBAAiB,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAA;QAE1E,MAAM,sBAAsB,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,WAAW,CAAA;QAEzF,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAC3C,UAAU,EACV,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,KAAK,CAAC,EAAE,EACR;YACE,GAAG,UAAU,CAAC,MAAM;YACpB,UAAU;SACX,EACD,MAAM,CACP,CAAA;QAED,IAAI,CAAC,SAAS,EAAE;YACd,IAAI,IAAI;gBACN,OAAO,IAAA,wBAAgB,EACrB,6BAA6B,UAAU,kDAAkD,KAAK,CAAC,eAAe,KAAK,KAAK,CAAC,EAAE,GAAG,CAC/H,CAAA;YAEH,sDAAsD;YACtD,MAAM,uBAAuB,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,0CAA0C,CAAC,CAAA;YAC3G,IAAI,CAAC,aAAa,CAAC,4BAA4B,CAAC,UAAU,CAAC,IAAI,CAAC,uBAAuB,EAAE;gBACvF,OAAO,IAAA,wBAAgB,EACrB,6BAA6B,UAAU,kDAAkD,KAAK,CAAC,GAAG,GAAG,CACtG,CAAA;aACF;SACF;QACD,OAAO,UAAE,CAAA;IACX,CAAC;IACD,WAAW,CAAC,KAAK;QACf,OAAO,KAAK,CAAC,IAAI,KAAK,gCAAgC,IAAI,KAAK,CAAC,IAAI,KAAK,gCAAgC,CAAA;IAC3G,CAAC;CACF,CAAA"}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { BlockchainCollectionThirdParty, BlockchainCollectionV1Asset, BlockchainCollectionV2Asset, OffChainAsset } from '@dcl/urn-resolver';
|
|
2
2
|
import { DeploymentToValidate } from '../../..';
|
|
3
3
|
import { ContentValidatorComponents, ValidationResponse } from '../../../types';
|
|
4
|
-
export type UrnType = 'off-chain' | 'blockchain-collection-v1-asset' | 'blockchain-collection-v2-asset' | 'blockchain-collection-third-party';
|
|
5
|
-
export type SupportedAsset = BlockchainCollectionV1Asset | BlockchainCollectionV2Asset | OffChainAsset | BlockchainCollectionThirdParty;
|
|
6
|
-
export type AssetValidation = {
|
|
4
|
+
export declare type UrnType = 'off-chain' | 'blockchain-collection-v1-asset' | 'blockchain-collection-v2-asset' | 'blockchain-collection-third-party';
|
|
5
|
+
export declare type SupportedAsset = BlockchainCollectionV1Asset | BlockchainCollectionV2Asset | OffChainAsset | BlockchainCollectionThirdParty;
|
|
6
|
+
export declare type AssetValidation = {
|
|
7
7
|
validateAsset(components: Pick<ContentValidatorComponents, 'externalCalls'>, asset: SupportedAsset, deployment: DeploymentToValidate): ValidationResponse | Promise<ValidationResponse>;
|
|
8
8
|
canValidate(asset: SupportedAsset): boolean;
|
|
9
9
|
};
|
|
10
|
-
export declare
|
|
11
|
-
validate: (components: Pick<ContentValidatorComponents, 'externalCalls' | 'logs' | 'theGraphClient'>, deployment: DeploymentToValidate, validUrnTypesForItem: UrnType[]) => Promise<ValidationResponse>;
|
|
12
|
-
};
|
|
10
|
+
export declare function itemsValidation(components: Pick<ContentValidatorComponents, 'externalCalls' | 'logs' | 'theGraphClient'>, deployment: DeploymentToValidate, validUrnTypesForItem: UrnType[]): Promise<ValidationResponse>;
|
|
13
11
|
//# sourceMappingURL=items.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/items.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,2BAA2B,EAC3B,aAAa,EAEd,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,0BAA0B,EAAoB,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAKjG,
|
|
1
|
+
{"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/items.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,2BAA2B,EAC3B,aAAa,EAEd,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EAAE,0BAA0B,EAAoB,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAKjG,oBAAY,OAAO,GACf,WAAW,GACX,gCAAgC,GAChC,gCAAgC,GAChC,mCAAmC,CAAA;AAEvC,oBAAY,cAAc,GACtB,2BAA2B,GAC3B,2BAA2B,GAC3B,aAAa,GACb,8BAA8B,CAAA;AAElC,oBAAY,eAAe,GAAG;IAC5B,aAAa,CACX,UAAU,EAAE,IAAI,CAAC,0BAA0B,EAAE,eAAe,CAAC,EAC7D,KAAK,EAAE,cAAc,EACrB,UAAU,EAAE,oBAAoB,GAC/B,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;IACnD,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAA;CAC5C,CAAA;AAsCD,wBAAsB,eAAe,CACnC,UAAU,EAAE,IAAI,CAAC,0BAA0B,EAAE,eAAe,GAAG,MAAM,GAAG,gBAAgB,CAAC,EACzF,UAAU,EAAE,oBAAoB,EAChC,oBAAoB,EAAE,OAAO,EAAE,+BAiChC"}
|
|
@@ -39,30 +39,29 @@ async function parseUrnNoFail(urn) {
|
|
|
39
39
|
catch { }
|
|
40
40
|
return null;
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return validation.validateAsset(components, parsedAsset, deployment);
|
|
63
|
-
}
|
|
42
|
+
async function itemsValidation(components, deployment, validUrnTypesForItem) {
|
|
43
|
+
const { pointers } = deployment.entity;
|
|
44
|
+
const resolvedPointers = [];
|
|
45
|
+
// deduplicate pointer resolution
|
|
46
|
+
for (const pointer of pointers) {
|
|
47
|
+
const parsed = await parseUrnNoFail(pointer);
|
|
48
|
+
if (!parsed)
|
|
49
|
+
return (0, types_1.validationFailed)(`Item pointers should be a urn, for example (urn:decentraland:{protocol}:collections-v2:{contract(0x[a-fA-F0-9]+)}:{id}). Invalid pointer: (${pointer})`);
|
|
50
|
+
if (!alreadySeen(resolvedPointers, parsed))
|
|
51
|
+
resolvedPointers.push(parsed);
|
|
52
|
+
}
|
|
53
|
+
if (resolvedPointers.length > 1)
|
|
54
|
+
return (0, types_1.validationFailed)(`Only one pointer is allowed when you create an item. Received: ${pointers}`);
|
|
55
|
+
const parsedAsset = resolvedPointers[0];
|
|
56
|
+
if (!validUrnTypesForItem.includes(parsedAsset.type)) {
|
|
57
|
+
return (0, types_1.validationFailed)(`For the entity type: ${deployment.entity.type}, the asset with urn type: ${parsedAsset.type} is invalid. Valid urn types for this entity: ${validUrnTypesForItem}`);
|
|
58
|
+
}
|
|
59
|
+
for (const validation of assetValidations) {
|
|
60
|
+
if (validation.canValidate(parsedAsset)) {
|
|
61
|
+
return validation.validateAsset(components, parsedAsset, deployment);
|
|
64
62
|
}
|
|
65
|
-
throw new Error('This should never happen. There is no validations for the asset.');
|
|
66
63
|
}
|
|
67
|
-
|
|
64
|
+
throw new Error('This should never happen. There is no validations for the asset.');
|
|
65
|
+
}
|
|
66
|
+
exports.itemsValidation = itemsValidation;
|
|
68
67
|
//# sourceMappingURL=items.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"items.js","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/items.ts"],"names":[],"mappings":";;;AAAA,oDAM0B;AAE1B,0CAAiG;AACjG,yDAAqE;AACrE,uDAA2D;AAC3D,2DAA+D;AAuB/D,MAAM,gBAAgB,GAAG,CAAC,yCAAuB,EAAE,mDAAgC,EAAE,6CAAyB,CAAC,CAAA;AAE/G,SAAS,WAAW,CAAC,gBAAkC,EAAE,MAAsB;IAC7E,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,EAAE,CAAC,cAAc,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAA;AAC5F,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,aAA6B,EAAE,MAAsB;IAC3E,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,uBAAuB,EAAE,GAAG,aAAa,CAAA;IACnE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,gBAAgB,EAAE,GAAG,MAAM,CAAA;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;AACpF,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,GAAW;IACvC,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAQ,EAAC,GAAG,CAAC,CAAA;QAClC,IAAI,MAAM,EAAE,IAAI,KAAK,gCAAgC,EAAE;YACrD,OAAO,MAAM,CAAA;SACd;QACD,IAAI,MAAM,EAAE,IAAI,KAAK,gCAAgC,EAAE;YACrD,OAAO,MAAM,CAAA;SACd;QACD,IAAI,MAAM,EAAE,IAAI,KAAK,WAAW,EAAE;YAChC,OAAO,MAAM,CAAA;SACd;QACD,IAAI,MAAM,EAAE,IAAI,KAAK,mCAAmC,EAAE;YACxD,OAAO,MAAM,CAAA;SACd;KACF;IAAC,MAAM,GAAE;IACV,OAAO,IAAI,CAAA;AACb,CAAC;
|
|
1
|
+
{"version":3,"file":"items.js","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/items.ts"],"names":[],"mappings":";;;AAAA,oDAM0B;AAE1B,0CAAiG;AACjG,yDAAqE;AACrE,uDAA2D;AAC3D,2DAA+D;AAuB/D,MAAM,gBAAgB,GAAG,CAAC,yCAAuB,EAAE,mDAAgC,EAAE,6CAAyB,CAAC,CAAA;AAE/G,SAAS,WAAW,CAAC,gBAAkC,EAAE,MAAsB;IAC7E,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,EAAE,CAAC,cAAc,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAA;AAC5F,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,aAA6B,EAAE,MAAsB;IAC3E,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,uBAAuB,EAAE,GAAG,aAAa,CAAA;IACnE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,gBAAgB,EAAE,GAAG,MAAM,CAAA;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;AACpF,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,GAAW;IACvC,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAQ,EAAC,GAAG,CAAC,CAAA;QAClC,IAAI,MAAM,EAAE,IAAI,KAAK,gCAAgC,EAAE;YACrD,OAAO,MAAM,CAAA;SACd;QACD,IAAI,MAAM,EAAE,IAAI,KAAK,gCAAgC,EAAE;YACrD,OAAO,MAAM,CAAA;SACd;QACD,IAAI,MAAM,EAAE,IAAI,KAAK,WAAW,EAAE;YAChC,OAAO,MAAM,CAAA;SACd;QACD,IAAI,MAAM,EAAE,IAAI,KAAK,mCAAmC,EAAE;YACxD,OAAO,MAAM,CAAA;SACd;KACF;IAAC,MAAM,GAAE;IACV,OAAO,IAAI,CAAA;AACb,CAAC;AAEM,KAAK,UAAU,eAAe,CACnC,UAAyF,EACzF,UAAgC,EAChC,oBAA+B;IAE/B,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,MAAM,CAAA;IAEtC,MAAM,gBAAgB,GAAqB,EAAE,CAAA;IAC7C,iCAAiC;IACjC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;QAC9B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM;YACT,OAAO,IAAA,wBAAgB,EACrB,8IAA8I,OAAO,GAAG,CACzJ,CAAA;QAEH,IAAI,CAAC,WAAW,CAAC,gBAAgB,EAAE,MAAM,CAAC;YAAE,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;KAC1E;IAED,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC;QAC7B,OAAO,IAAA,wBAAgB,EAAC,kEAAkE,QAAQ,EAAE,CAAC,CAAA;IAEvG,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAEvC,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;QACpD,OAAO,IAAA,wBAAgB,EACrB,wBAAwB,UAAU,CAAC,MAAM,CAAC,IAAI,8BAA8B,WAAW,CAAC,IAAI,iDAAiD,oBAAoB,EAAE,CACpK,CAAA;KACF;IAED,KAAK,MAAM,UAAU,IAAI,gBAAgB,EAAE;QACzC,IAAI,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE;YACvC,OAAO,UAAU,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,CAAA;SACrE;KACF;IACD,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAA;AACrF,CAAC;AApCD,0CAoCC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"third-party-asset.d.ts","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/third-party-asset.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"third-party-asset.d.ts","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/third-party-asset.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAiHzC,eAAO,MAAM,yBAAyB,EAAE,eAiBvC,CAAA"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.thirdPartyAssetValidation = void 0;
|
|
4
4
|
const content_hash_tree_1 = require("@dcl/content-hash-tree");
|
|
5
|
+
const hashing_1 = require("@dcl/hashing");
|
|
5
6
|
const schemas_1 = require("@dcl/schemas");
|
|
6
7
|
const types_1 = require("../../../types");
|
|
7
8
|
function toHexBuffer(value) {
|
|
@@ -13,29 +14,87 @@ function toHexBuffer(value) {
|
|
|
13
14
|
function getThirdPartyId(urn) {
|
|
14
15
|
return `urn:decentraland:${urn.network}:collections-thirdparty:${urn.thirdPartyName}`;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
17
|
+
async function verifyHash(metadata, merkleRoot, logger) {
|
|
18
|
+
if (!schemas_1.MerkleProof.validate(metadata.merkleProof)) {
|
|
19
|
+
logger.debug('Merkle proof is not valid', {
|
|
20
|
+
merkleProof: metadata.merkleProof
|
|
21
|
+
});
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const merkleProof = metadata.merkleProof;
|
|
25
|
+
const generatedCrcHash = (0, hashing_1.keccak256Hash)(metadata, metadata.merkleProof.hashingKeys);
|
|
26
|
+
// The hash provided in the merkleProof for the entity MUST match the hash generated by the validator.
|
|
27
|
+
if (metadata.merkleProof.entityHash !== generatedCrcHash) {
|
|
28
|
+
logger.debug(`The hash provided in the merkleProof doesn't match the one generated by the validator`, {
|
|
29
|
+
generatedCrcHash,
|
|
30
|
+
entityHash: metadata.merkleProof.entityHash
|
|
31
|
+
});
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// Verify if the entity belongs to the Merkle Tree.
|
|
35
|
+
const bufferedProofs = merkleProof.proof.map((value) => toHexBuffer(value));
|
|
36
|
+
const bufferedMerkleRoot = toHexBuffer(merkleRoot);
|
|
37
|
+
return (0, content_hash_tree_1.verifyProof)(merkleProof.index, merkleProof.entityHash, bufferedProofs, bufferedMerkleRoot);
|
|
38
|
+
}
|
|
39
|
+
async function getMerkleRoot(components, block, thirdPartyId) {
|
|
40
|
+
const query = `
|
|
41
|
+
query MerkleRoot($id: String!, $block: Int!) {
|
|
42
|
+
thirdParties(where: { id: $id, isApproved: true }, block: { number: $block }, first: 1) {
|
|
43
|
+
root
|
|
44
|
+
}
|
|
45
|
+
}`;
|
|
46
|
+
const result = await components.subGraphs.L2.thirdPartyRegistry.query(query, {
|
|
47
|
+
id: thirdPartyId,
|
|
48
|
+
block
|
|
49
|
+
});
|
|
50
|
+
if (!result.thirdParties || result.thirdParties.length < 1)
|
|
51
|
+
return;
|
|
52
|
+
return result.thirdParties[0]?.root;
|
|
53
|
+
}
|
|
54
|
+
async function verifyMerkleProofedEntity(components, urn, deployment, logger) {
|
|
55
|
+
// do merkle proofed entity validation, required keys are defined by the Catalyst and must be a subset of the hashingKeys from the MerkleProof to succeed
|
|
56
|
+
const metadata = deployment.entity.metadata;
|
|
57
|
+
if (!(0, schemas_1.isThirdParty)(deployment.entity.metadata)) {
|
|
58
|
+
// This should never happen as the metadata validation ran before
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const thirdPartyId = getThirdPartyId(urn);
|
|
62
|
+
const { blockNumberAtDeployment, blockNumberFiveMinBeforeDeployment } = await components.theGraphClient.findBlocksForTimestamp(components.subGraphs.L2.blocks, deployment.entity.timestamp);
|
|
63
|
+
const merkleRoots = [];
|
|
64
|
+
const hasPermissionOnBlock = async (blockNumber) => {
|
|
65
|
+
try {
|
|
66
|
+
if (!blockNumber)
|
|
67
|
+
return false;
|
|
68
|
+
const merkleRoot = await getMerkleRoot(components, blockNumber, thirdPartyId);
|
|
69
|
+
if (!merkleRoot) {
|
|
70
|
+
logger.debug(`Merkle proof not found for given block and third party ID`, { blockNumber, thirdPartyId });
|
|
71
|
+
return false;
|
|
36
72
|
}
|
|
37
|
-
|
|
73
|
+
merkleRoots.push(merkleRoot);
|
|
74
|
+
return await verifyHash(metadata, merkleRoot, logger);
|
|
38
75
|
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
const error = e?.message;
|
|
78
|
+
logger.debug(error);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const validMerkleProofedEntity = (await hasPermissionOnBlock(blockNumberAtDeployment)) ||
|
|
83
|
+
(await hasPermissionOnBlock(blockNumberFiveMinBeforeDeployment));
|
|
84
|
+
if (!validMerkleProofedEntity) {
|
|
85
|
+
logger.debug(`Merkle Tree based verifications failed:`, {
|
|
86
|
+
merkleProof: JSON.stringify(metadata.merkleProof),
|
|
87
|
+
merkleRoots: JSON.stringify(merkleRoots),
|
|
88
|
+
blocks: JSON.stringify([blockNumberAtDeployment, blockNumberFiveMinBeforeDeployment])
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return validMerkleProofedEntity;
|
|
92
|
+
}
|
|
93
|
+
exports.thirdPartyAssetValidation = {
|
|
94
|
+
async validateAsset(components, asset, deployment) {
|
|
95
|
+
const logger = components.logs.getLogger('collection asset access validation');
|
|
96
|
+
// Third Party wearables are validated doing merkle tree based verification proof
|
|
97
|
+
const verified = await verifyMerkleProofedEntity(components, asset, deployment, logger);
|
|
39
98
|
if (!verified) {
|
|
40
99
|
return (0, types_1.validationFailed)(`Couldn't verify merkle proofed entity`);
|
|
41
100
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"third-party-asset.js","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/third-party-asset.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"third-party-asset.js","sourceRoot":"","sources":["../../../../src/validations/access-checker/items/third-party-asset.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare
|
|
3
|
-
export declare
|
|
4
|
-
export declare
|
|
5
|
-
export declare
|
|
6
|
-
export declare const profiles:
|
|
1
|
+
import { ContentValidatorComponents, DeploymentToValidate, ValidateFn } from '../../types';
|
|
2
|
+
export declare function pointerIsValid(components: Pick<ContentValidatorComponents, 'externalCalls'>, deployment: DeploymentToValidate): Promise<import("../../types").ValidationResponse>;
|
|
3
|
+
export declare function ownsNames(components: Pick<ContentValidatorComponents, 'externalCalls' | 'theGraphClient'>, deployment: DeploymentToValidate): Promise<import("../../types").ValidationResponse>;
|
|
4
|
+
export declare function ownsItems(components: Pick<ContentValidatorComponents, 'externalCalls' | 'theGraphClient'>, deployment: DeploymentToValidate): Promise<import("../../types").ValidationResponse>;
|
|
5
|
+
export declare function profileSlotsAreNotRepeated(components: Pick<ContentValidatorComponents, 'externalCalls' | 'logs' | 'theGraphClient'>, deployment: DeploymentToValidate): Promise<import("../../types").ValidationResponse>;
|
|
6
|
+
export declare const profiles: ValidateFn;
|
|
7
7
|
//# sourceMappingURL=profiles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../../../src/validations/access-checker/profiles.ts"],"names":[],"mappings":"AAEA,OAAO,EAAM,UAAU,EAAoB,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../../../src/validations/access-checker/profiles.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAM,UAAU,EAAoB,MAAM,aAAa,CAAA;AAKhH,wBAAsB,cAAc,CAClC,UAAU,EAAE,IAAI,CAAC,0BAA0B,EAAE,eAAe,CAAC,EAC7D,UAAU,EAAE,oBAAoB,qDAqBjC;AASD,wBAAsB,SAAS,CAC7B,UAAU,EAAE,IAAI,CAAC,0BAA0B,EAAE,eAAe,GAAG,gBAAgB,CAAC,EAChF,UAAU,EAAE,oBAAoB,qDAajC;AA0CD,wBAAsB,SAAS,CAC7B,UAAU,EAAE,IAAI,CAAC,0BAA0B,EAAE,eAAe,GAAG,gBAAgB,CAAC,EAChF,UAAU,EAAE,oBAAoB,qDA8BjC;AAED,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,IAAI,CAAC,0BAA0B,EAAE,eAAe,GAAG,MAAM,GAAG,gBAAgB,CAAC,EACzF,UAAU,EAAE,oBAAoB,qDAYjC;AAED,eAAO,MAAM,QAAQ,EAAE,UAA0F,CAAA"}
|