@eluvio/elv-client-js 4.2.27 → 4.2.30
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/ElvClient-min.js +1 -1
- package/dist/ElvClient-node-min.js +1 -1
- package/dist/ElvFrameClient-min.js +1 -1
- package/dist/ElvPermissionsClient-min.js +1 -1
- package/dist/ElvWalletClient-min.js +1 -1
- package/dist/ElvWalletClient-node-min.js +1 -1
- package/dist/src/ElvClient.js +355 -275
- package/dist/src/EthClient.js +3 -2
- package/dist/src/FrameClient.js +1 -1
- package/dist/src/client/ABRPublishing.js +71 -60
- package/dist/src/client/ContentAccess.js +298 -204
- package/dist/src/client/Files.js +1400 -844
- package/dist/src/client/LiveConf.js +54 -37
- package/dist/src/client/LiveStream.js +123 -81
- package/package.json +1 -1
- package/src/ElvClient.js +51 -0
- package/src/EthClient.js +2 -1
- package/src/FrameClient.js +1 -0
- package/src/client/ContentAccess.js +70 -1
- package/src/client/Files.js +413 -208
- package/src/client/LiveStream.js +32 -16
- package/utilities/MigrateEncryptionConkForNewUser.js +62 -0
- package/utilities/ObjectAddFiles.js +29 -9
- package/utilities/lib/concerns/CloudFile.js +2 -1
- package/utilities/lib/concerns/LocalFile.js +2 -1
- package/dist/src/ContentObjectVerification.js +0 -281
package/src/client/LiveStream.js
CHANGED
|
@@ -1090,9 +1090,9 @@ exports.StreamStatus = async function({name, showParams=false, writeToken}) {
|
|
|
1090
1090
|
status.recordingStatus = lroStatus.custom.status;
|
|
1091
1091
|
}
|
|
1092
1092
|
} catch(error) {
|
|
1093
|
-
console.log("LRO Status (failed): ", error.response
|
|
1093
|
+
console.log("LRO Status (failed): ", error.response?.statusCode);
|
|
1094
1094
|
status.state = "stopped";
|
|
1095
|
-
status.error = error.response;
|
|
1095
|
+
status.error = error.response || error.message;
|
|
1096
1096
|
return status;
|
|
1097
1097
|
}
|
|
1098
1098
|
|
|
@@ -3532,6 +3532,13 @@ exports.OutputsList = async function({libraryId, objectId, includeState=true}) {
|
|
|
3532
3532
|
method: "live/outputs",
|
|
3533
3533
|
constant: true
|
|
3534
3534
|
});
|
|
3535
|
+
} catch(error) {
|
|
3536
|
+
if(error.status === 404) {
|
|
3537
|
+
// Stream object may have been deleted
|
|
3538
|
+
return {};
|
|
3539
|
+
}
|
|
3540
|
+
|
|
3541
|
+
throw error;
|
|
3535
3542
|
} finally {
|
|
3536
3543
|
restore();
|
|
3537
3544
|
}
|
|
@@ -3544,17 +3551,22 @@ exports.OutputsList = async function({libraryId, objectId, includeState=true}) {
|
|
|
3544
3551
|
const streamId = value.input?.stream;
|
|
3545
3552
|
if(!streamId) { return; }
|
|
3546
3553
|
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3554
|
+
try {
|
|
3555
|
+
const [streamLibraryId, streamStatus] = await Promise.all([
|
|
3556
|
+
this.ContentObjectLibraryId({objectId: streamId}),
|
|
3557
|
+
this.StreamStatus({name: streamId})
|
|
3558
|
+
]);
|
|
3559
|
+
|
|
3560
|
+
value.input.name = await this.ContentObjectMetadata({
|
|
3561
|
+
libraryId: streamLibraryId,
|
|
3562
|
+
objectId: streamId,
|
|
3563
|
+
metadataSubtree: "/public/name",
|
|
3564
|
+
});
|
|
3565
|
+
value.input.status = streamStatus?.state;
|
|
3566
|
+
} catch(error) {
|
|
3567
|
+
// Stream object may have been deleted
|
|
3568
|
+
value.input.status = "unavailable";
|
|
3569
|
+
}
|
|
3558
3570
|
}
|
|
3559
3571
|
);
|
|
3560
3572
|
|
|
@@ -3569,9 +3581,13 @@ exports.OutputsList = async function({libraryId, objectId, includeState=true}) {
|
|
|
3569
3581
|
|
|
3570
3582
|
const nodeUrls = {};
|
|
3571
3583
|
await this.utils.LimitedMap(10, nodeIds, async nodeId => {
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3584
|
+
try {
|
|
3585
|
+
const nodes = await this.SpaceNodes({matchNodeId: nodeId});
|
|
3586
|
+
const fabricUrl = nodes?.[0]?.services?.fabric_api?.urls?.[0];
|
|
3587
|
+
if(fabricUrl) { nodeUrls[nodeId] = fabricUrl; }
|
|
3588
|
+
} catch(error) {
|
|
3589
|
+
this.Log(`Failed to resolve node ${nodeId}: ${error.message}`, true);
|
|
3590
|
+
}
|
|
3575
3591
|
});
|
|
3576
3592
|
|
|
3577
3593
|
// Rewrite fabric-generated srt_pull URLs to the egress host, and group outputs by node
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const {NewOpt} = require("./lib/options");
|
|
2
|
+
const Utility = require("./lib/Utility");
|
|
3
|
+
|
|
4
|
+
const Client = require("./lib/concerns/Client");
|
|
5
|
+
const Edit = require("./lib/concerns/Edit");
|
|
6
|
+
|
|
7
|
+
class MigrateEncryptionConkForNewUser extends Utility {
|
|
8
|
+
blueprint() {
|
|
9
|
+
return {
|
|
10
|
+
concerns: [Client, Edit],
|
|
11
|
+
options: [
|
|
12
|
+
NewOpt("objectId",
|
|
13
|
+
{
|
|
14
|
+
descTemplate: "object Id",
|
|
15
|
+
type: "string",
|
|
16
|
+
demand: true
|
|
17
|
+
}),
|
|
18
|
+
NewOpt("publicKey",
|
|
19
|
+
{
|
|
20
|
+
descTemplate: "new user public key with/without encoded form",
|
|
21
|
+
type: "string",
|
|
22
|
+
demand: true
|
|
23
|
+
})
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async body() {
|
|
29
|
+
const logger = this.logger;
|
|
30
|
+
const {objectId, publicKey} = this.args;
|
|
31
|
+
|
|
32
|
+
const client = await this.concerns.Client.get();
|
|
33
|
+
const libraryId = await client.ContentObjectLibraryId({objectId});
|
|
34
|
+
|
|
35
|
+
const res = await client.EditContentObject({libraryId, objectId});
|
|
36
|
+
|
|
37
|
+
await client.MigrateEncryptionConkForUserProvided({
|
|
38
|
+
libraryId,
|
|
39
|
+
objectId,
|
|
40
|
+
writeToken: res.writeToken,
|
|
41
|
+
newEncodedUserPublicKey: publicKey
|
|
42
|
+
});
|
|
43
|
+
logger.log("Migration of encryption conk is complete...");
|
|
44
|
+
|
|
45
|
+
const versionHash = await this.concerns.Edit.finalize({
|
|
46
|
+
libraryId,
|
|
47
|
+
objectId,
|
|
48
|
+
writeToken:res.writeToken
|
|
49
|
+
});
|
|
50
|
+
logger.log("version hash", versionHash);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
header() {
|
|
54
|
+
return `Add encryption conk for user provided '${this.args.objectId}':`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if(require.main === module) {
|
|
59
|
+
Utility.cmdLineInvoke(MigrateEncryptionConkForNewUser);
|
|
60
|
+
} else {
|
|
61
|
+
module.exports = MigrateEncryptionConkForNewUser;
|
|
62
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Create new production master from specified file(s)
|
|
2
2
|
|
|
3
|
-
const {ModOpt, StdOpt} = require("./lib/options");
|
|
3
|
+
const {ModOpt, StdOpt, NewOpt} = require("./lib/options");
|
|
4
4
|
const Utility = require("./lib/Utility");
|
|
5
5
|
|
|
6
6
|
const ArgNoWait = require("./lib/concerns/ArgNoWait");
|
|
@@ -16,14 +16,19 @@ class ObjectAddFiles extends Utility {
|
|
|
16
16
|
concerns: [Logger, ExistObj, Edit, ArgNoWait, LocalFile, CloudFile],
|
|
17
17
|
options: [
|
|
18
18
|
ModOpt("files", {X: "to add"}),
|
|
19
|
-
StdOpt("encrypt", {X: "uploaded files"})
|
|
19
|
+
StdOpt("encrypt", {X: "uploaded files"}),
|
|
20
|
+
NewOpt("resume", {
|
|
21
|
+
descTemplate: "If specified, resume jobs for the given write token (--resume 'write_token')",
|
|
22
|
+
group: "Main",
|
|
23
|
+
type: "string"
|
|
24
|
+
})
|
|
20
25
|
]
|
|
21
26
|
};
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
async body() {
|
|
25
30
|
const logger = this.logger;
|
|
26
|
-
const {encrypt, noWait} = this.args;
|
|
31
|
+
const {encrypt, noWait, resume: resumeArg} = this.args;
|
|
27
32
|
|
|
28
33
|
let access;
|
|
29
34
|
if(this.args.s3Reference || this.args.s3Copy) access = this.concerns.CloudFile.credentialSet();
|
|
@@ -35,10 +40,22 @@ class ObjectAddFiles extends Utility {
|
|
|
35
40
|
|
|
36
41
|
const {libraryId, objectId} = await this.concerns.ExistObj.argsProc();
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
let writeToken;
|
|
44
|
+
let resume=false;
|
|
45
|
+
if(resumeArg) {
|
|
46
|
+
writeToken = resumeArg;
|
|
47
|
+
resume=true;
|
|
48
|
+
} else {
|
|
49
|
+
// create new write token
|
|
50
|
+
writeToken = await this.concerns.Edit.getWriteToken({
|
|
51
|
+
libraryId,
|
|
52
|
+
objectId
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
logger.data("WRITE_TOKEN", writeToken);
|
|
56
|
+
// eslint-disable-next-line no-console
|
|
57
|
+
console.log("Using write token:", writeToken);
|
|
58
|
+
|
|
42
59
|
|
|
43
60
|
if(access) {
|
|
44
61
|
await this.concerns.CloudFile.add({
|
|
@@ -47,7 +64,8 @@ class ObjectAddFiles extends Utility {
|
|
|
47
64
|
writeToken,
|
|
48
65
|
access,
|
|
49
66
|
fileInfo,
|
|
50
|
-
encrypt
|
|
67
|
+
encrypt,
|
|
68
|
+
resume,
|
|
51
69
|
});
|
|
52
70
|
} else {
|
|
53
71
|
await this.concerns.LocalFile.add({
|
|
@@ -55,12 +73,14 @@ class ObjectAddFiles extends Utility {
|
|
|
55
73
|
objectId,
|
|
56
74
|
writeToken,
|
|
57
75
|
fileInfo,
|
|
58
|
-
encrypt
|
|
76
|
+
encrypt,
|
|
77
|
+
resume,
|
|
59
78
|
});
|
|
60
79
|
// Close file handles
|
|
61
80
|
this.concerns.LocalFile.closeFileHandles(fileHandles);
|
|
62
81
|
}
|
|
63
82
|
|
|
83
|
+
// finalize the write token
|
|
64
84
|
const hash = await this.concerns.Edit.finalize({
|
|
65
85
|
libraryId,
|
|
66
86
|
noWait,
|
|
@@ -95,7 +95,7 @@ const New = context => {
|
|
|
95
95
|
);
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
-
const add = async ({libraryId, objectId, writeToken, files, access, encrypt, copy}) => {
|
|
98
|
+
const add = async ({libraryId, objectId, writeToken, files, access, encrypt, copy, resume}) => {
|
|
99
99
|
if(kindOf(copy) === "undefined") copy = isCopy();
|
|
100
100
|
files = files || context.args.files;
|
|
101
101
|
const groupedFiles = groupByPathMatch(access, files);
|
|
@@ -125,6 +125,7 @@ const New = context => {
|
|
|
125
125
|
secret,
|
|
126
126
|
signedUrl,
|
|
127
127
|
copy,
|
|
128
|
+
resume,
|
|
128
129
|
callback,
|
|
129
130
|
encryption: encrypt ? "cgck" : "none"
|
|
130
131
|
});
|
|
@@ -19,7 +19,7 @@ const blueprint = {
|
|
|
19
19
|
|
|
20
20
|
const New = context => {
|
|
21
21
|
|
|
22
|
-
const add = async ({libraryId, objectId, writeToken, fileInfo, encrypt}) => {
|
|
22
|
+
const add = async ({libraryId, objectId, writeToken, fileInfo, encrypt, resume}) => {
|
|
23
23
|
const client = await context.concerns.Client.get();
|
|
24
24
|
await client.UploadFiles({
|
|
25
25
|
libraryId,
|
|
@@ -27,6 +27,7 @@ const New = context => {
|
|
|
27
27
|
writeToken,
|
|
28
28
|
fileInfo,
|
|
29
29
|
callback,
|
|
30
|
+
resume,
|
|
30
31
|
encryption: encrypt ? "cgck" : "none"
|
|
31
32
|
});
|
|
32
33
|
};
|
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
var _regeneratorRuntime = require("@babel/runtime/regenerator");
|
|
2
|
-
var _asyncToGenerator = require("@babel/runtime/helpers/asyncToGenerator");
|
|
3
|
-
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
4
|
-
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
5
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
6
|
-
var CBOR = require("cbor");
|
|
7
|
-
var SJCL = require("sjcl");
|
|
8
|
-
var MultiHash = require("multihashes");
|
|
9
|
-
var DeepEqual = require("deep-equal");
|
|
10
|
-
var Utils = require("./Utils");
|
|
11
|
-
var ContentObjectVerification = {
|
|
12
|
-
VerifyContentObject: function VerifyContentObject(_ref) {
|
|
13
|
-
return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
14
|
-
var client, libraryId, objectId, versionHash, response, partHash, qpartsResponse, partVerification, qmdHash, metadataPartHash, metadataPartResponse, metadataVerification, metadata, qstructHash, structPartHash, structPartResponse, structVerification;
|
|
15
|
-
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
16
|
-
while (1) switch (_context.prev = _context.next) {
|
|
17
|
-
case 0:
|
|
18
|
-
client = _ref.client, libraryId = _ref.libraryId, objectId = _ref.objectId, versionHash = _ref.versionHash;
|
|
19
|
-
response = {
|
|
20
|
-
hash: versionHash
|
|
21
|
-
};
|
|
22
|
-
partHash = Utils.DecodeVersionHash(versionHash).partHash;
|
|
23
|
-
_context.next = 5;
|
|
24
|
-
return client.QParts({
|
|
25
|
-
libraryId: libraryId,
|
|
26
|
-
objectId: objectId,
|
|
27
|
-
partHash: partHash,
|
|
28
|
-
format: "arrayBuffer"
|
|
29
|
-
}).then(function (response) {
|
|
30
|
-
return Buffer.from(response);
|
|
31
|
-
});
|
|
32
|
-
case 5:
|
|
33
|
-
qpartsResponse = _context.sent;
|
|
34
|
-
partVerification = ContentObjectVerification._VerifyPart({
|
|
35
|
-
partHash: partHash,
|
|
36
|
-
qpartsResponse: qpartsResponse
|
|
37
|
-
});
|
|
38
|
-
if (partVerification.valid) {
|
|
39
|
-
response.qref = {
|
|
40
|
-
valid: true
|
|
41
|
-
};
|
|
42
|
-
} else {
|
|
43
|
-
response.qref = {
|
|
44
|
-
valid: false,
|
|
45
|
-
error: partVerification.error.message
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
response.qref.hash = partHash;
|
|
49
|
-
if (!response.qref.valid) {
|
|
50
|
-
_context.next = 32;
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
// Validate Metadata
|
|
54
|
-
qmdHash = partVerification.cbor.QmdHash.value;
|
|
55
|
-
metadataPartHash = "hqp_" + MultiHash.toB58String(qmdHash.slice(1, qmdHash.length));
|
|
56
|
-
_context.next = 14;
|
|
57
|
-
return client.QParts({
|
|
58
|
-
libraryId: libraryId,
|
|
59
|
-
objectId: objectId,
|
|
60
|
-
partHash: metadataPartHash,
|
|
61
|
-
format: "arrayBuffer"
|
|
62
|
-
}).then(function (response) {
|
|
63
|
-
return Buffer.from(response);
|
|
64
|
-
});
|
|
65
|
-
case 14:
|
|
66
|
-
metadataPartResponse = _context.sent;
|
|
67
|
-
metadataVerification = ContentObjectVerification._VerifyPart({
|
|
68
|
-
partHash: metadataPartHash,
|
|
69
|
-
qpartsResponse: metadataPartResponse
|
|
70
|
-
});
|
|
71
|
-
if (metadataVerification.valid) {
|
|
72
|
-
response.qmd = {
|
|
73
|
-
valid: true
|
|
74
|
-
};
|
|
75
|
-
} else {
|
|
76
|
-
response.qmd = {
|
|
77
|
-
valid: false,
|
|
78
|
-
error: metadataVerification.error.message
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
response.qmd.hash = metadataPartHash;
|
|
82
|
-
if (!(response.qmd.valid && libraryId)) {
|
|
83
|
-
_context.next = 23;
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
_context.next = 21;
|
|
87
|
-
return client.ContentObjectMetadata({
|
|
88
|
-
libraryId: libraryId,
|
|
89
|
-
objectId: objectId,
|
|
90
|
-
versionHash: partHash.replace("hqp_", "hq__")
|
|
91
|
-
});
|
|
92
|
-
case 21:
|
|
93
|
-
metadata = _context.sent;
|
|
94
|
-
response.qmd.check = ContentObjectVerification._VerifyMetadata({
|
|
95
|
-
metadataCbor: metadataVerification.cbor,
|
|
96
|
-
metadata: metadata
|
|
97
|
-
});
|
|
98
|
-
case 23:
|
|
99
|
-
// Validate Qstruct
|
|
100
|
-
qstructHash = partVerification.cbor.QstructHash.value;
|
|
101
|
-
structPartHash = "hqp_" + MultiHash.toB58String(qstructHash.slice(1, qstructHash.length));
|
|
102
|
-
_context.next = 27;
|
|
103
|
-
return client.QParts({
|
|
104
|
-
libraryId: libraryId,
|
|
105
|
-
objectId: objectId,
|
|
106
|
-
partHash: structPartHash,
|
|
107
|
-
format: "arrayBuffer"
|
|
108
|
-
}).then(function (response) {
|
|
109
|
-
return Buffer.from(response);
|
|
110
|
-
});
|
|
111
|
-
case 27:
|
|
112
|
-
structPartResponse = _context.sent;
|
|
113
|
-
structVerification = ContentObjectVerification._VerifyPart({
|
|
114
|
-
partHash: structPartHash,
|
|
115
|
-
qpartsResponse: structPartResponse
|
|
116
|
-
});
|
|
117
|
-
if (structVerification.valid) {
|
|
118
|
-
response.qstruct = {
|
|
119
|
-
valid: true
|
|
120
|
-
};
|
|
121
|
-
} else {
|
|
122
|
-
response.qstruct = {
|
|
123
|
-
valid: false,
|
|
124
|
-
error: structVerification.error.message
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
response.qstruct.hash = structPartHash;
|
|
128
|
-
if (response.qstruct.valid) {
|
|
129
|
-
response.qstruct.parts = ContentObjectVerification._FormatQStruct(structVerification.cbor.Parts);
|
|
130
|
-
}
|
|
131
|
-
case 32:
|
|
132
|
-
response.valid = response.qref.valid && response.qmd.valid && response.qstruct.valid && (!response.qmd.check || response.qmd.check.valid);
|
|
133
|
-
return _context.abrupt("return", response);
|
|
134
|
-
case 34:
|
|
135
|
-
case "end":
|
|
136
|
-
return _context.stop();
|
|
137
|
-
}
|
|
138
|
-
}, _callee);
|
|
139
|
-
}))();
|
|
140
|
-
},
|
|
141
|
-
// Content verification methods //
|
|
142
|
-
_FormatQStruct: function _FormatQStruct(structParts) {
|
|
143
|
-
if (!structParts) {
|
|
144
|
-
return [];
|
|
145
|
-
}
|
|
146
|
-
return structParts.map(function (structPart) {
|
|
147
|
-
return {
|
|
148
|
-
hash: "hqp_" + MultiHash.toB58String(structPart.Hash.value.slice(1, structPart.Hash.length)),
|
|
149
|
-
size: structPart.Size
|
|
150
|
-
};
|
|
151
|
-
});
|
|
152
|
-
},
|
|
153
|
-
_Hash: function _Hash(thing) {
|
|
154
|
-
function fromBits(arr) {
|
|
155
|
-
var out = [],
|
|
156
|
-
bl = SJCL.bitArray.bitLength(arr),
|
|
157
|
-
i,
|
|
158
|
-
tmp;
|
|
159
|
-
for (i = 0; i < bl / 8; i++) {
|
|
160
|
-
if ((i & 3) === 0) {
|
|
161
|
-
tmp = arr[i / 4];
|
|
162
|
-
}
|
|
163
|
-
out.push(tmp >>> 24);
|
|
164
|
-
tmp <<= 8;
|
|
165
|
-
}
|
|
166
|
-
return out;
|
|
167
|
-
}
|
|
168
|
-
function toBits(bytes) {
|
|
169
|
-
var out = [],
|
|
170
|
-
i,
|
|
171
|
-
tmp = 0;
|
|
172
|
-
for (i = 0; i < bytes.length; i++) {
|
|
173
|
-
tmp = tmp << 8 | bytes[i];
|
|
174
|
-
if ((i & 3) === 3) {
|
|
175
|
-
out.push(tmp);
|
|
176
|
-
tmp = 0;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (i & 3) {
|
|
180
|
-
out.push(SJCL.bitArray.partial(8 * (i & 3), tmp));
|
|
181
|
-
}
|
|
182
|
-
return out;
|
|
183
|
-
}
|
|
184
|
-
var digest = SJCL.hash.sha256.hash(toBits(thing));
|
|
185
|
-
var bytes = fromBits(digest);
|
|
186
|
-
var out = Buffer.from(bytes, "binary");
|
|
187
|
-
return MultiHash.toB58String(MultiHash.encode(out, "sha2-256"));
|
|
188
|
-
},
|
|
189
|
-
_ParseCBOR: function _ParseCBOR(cborResponse) {
|
|
190
|
-
var buffer = cborResponse.slice(7, cborResponse.length);
|
|
191
|
-
var hex = buffer.toString("hex");
|
|
192
|
-
return CBOR.decodeFirstSync(hex);
|
|
193
|
-
},
|
|
194
|
-
_VerifyPart: function _VerifyPart(_ref2) {
|
|
195
|
-
var partHash = _ref2.partHash,
|
|
196
|
-
qpartsResponse = _ref2.qpartsResponse;
|
|
197
|
-
try {
|
|
198
|
-
if (ContentObjectVerification._Hash(qpartsResponse) !== partHash.replace("hqp_", "")) {
|
|
199
|
-
throw Error("Hashes do not match");
|
|
200
|
-
}
|
|
201
|
-
var cbor = ContentObjectVerification._ParseCBOR(qpartsResponse);
|
|
202
|
-
return {
|
|
203
|
-
valid: true,
|
|
204
|
-
cbor: cbor
|
|
205
|
-
};
|
|
206
|
-
} catch (error) {
|
|
207
|
-
return {
|
|
208
|
-
valid: false,
|
|
209
|
-
error: error
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
},
|
|
213
|
-
_VerifyMetadata: function _VerifyMetadata(_ref3) {
|
|
214
|
-
var metadataCbor = _ref3.metadataCbor,
|
|
215
|
-
metadata = _ref3.metadata;
|
|
216
|
-
if (!metadataCbor) {
|
|
217
|
-
metadataCbor = {};
|
|
218
|
-
}
|
|
219
|
-
if (!metadata) {
|
|
220
|
-
metadata = {};
|
|
221
|
-
}
|
|
222
|
-
var response = {
|
|
223
|
-
valid: true,
|
|
224
|
-
invalidValues: []
|
|
225
|
-
};
|
|
226
|
-
var cborKeys = Object.keys(metadataCbor);
|
|
227
|
-
var metadataKeys = Object.keys(metadata);
|
|
228
|
-
|
|
229
|
-
// Find any difference between top level keys
|
|
230
|
-
var differentKeys = cborKeys.filter(function (x) {
|
|
231
|
-
return !metadataKeys.includes(x);
|
|
232
|
-
}).concat(metadataKeys.filter(function (x) {
|
|
233
|
-
return !cborKeys.includes(x);
|
|
234
|
-
}));
|
|
235
|
-
var _iterator = _createForOfIteratorHelper(differentKeys),
|
|
236
|
-
_step;
|
|
237
|
-
try {
|
|
238
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
239
|
-
var key = _step.value;
|
|
240
|
-
var cborValue = metadataCbor[key];
|
|
241
|
-
var metadataValue = metadata[key];
|
|
242
|
-
response.invalidValues.push({
|
|
243
|
-
key: key,
|
|
244
|
-
cborValue: cborValue,
|
|
245
|
-
metadataValue: metadataValue
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Deep comparison of up to 5 keys
|
|
250
|
-
} catch (err) {
|
|
251
|
-
_iterator.e(err);
|
|
252
|
-
} finally {
|
|
253
|
-
_iterator.f();
|
|
254
|
-
}
|
|
255
|
-
var _iterator2 = _createForOfIteratorHelper(Object.keys(metadataCbor).slice(0, 5)),
|
|
256
|
-
_step2;
|
|
257
|
-
try {
|
|
258
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
259
|
-
var fieldToValidate = _step2.value;
|
|
260
|
-
var _cborValue = metadataCbor[fieldToValidate];
|
|
261
|
-
var _metadataValue = metadata[fieldToValidate];
|
|
262
|
-
if (!DeepEqual(_cborValue, _metadataValue)) {
|
|
263
|
-
response.invalidValues.push({
|
|
264
|
-
key: fieldToValidate,
|
|
265
|
-
cborValue: _cborValue,
|
|
266
|
-
metadataValue: _metadataValue
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
} catch (err) {
|
|
271
|
-
_iterator2.e(err);
|
|
272
|
-
} finally {
|
|
273
|
-
_iterator2.f();
|
|
274
|
-
}
|
|
275
|
-
if (response.invalidValues.length !== 0) {
|
|
276
|
-
response.valid = false;
|
|
277
|
-
}
|
|
278
|
-
return response;
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
module.exports = ContentObjectVerification;
|