libves 2.16.0 → 3.0.2
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 +398 -20
- package/libVES.node.js +1058 -140
- package/libves-3.0.2.tgz +0 -0
- package/package.json +4 -2
package/libVES.node.js
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
*
|
|
28
28
|
* @title libVES
|
|
29
29
|
* @dev A JavaScript end-to-end encryption interface to VESvault REST API
|
|
30
|
-
* @version
|
|
30
|
+
* @version 3.02
|
|
31
31
|
*
|
|
32
32
|
* @dev Official source code: https://github.com/vesvault/libVES
|
|
33
33
|
*
|
|
@@ -51,6 +51,7 @@ if (typeof(libVES) != 'function') function libVES(optns) {
|
|
|
51
51
|
else if (this.user) this.type = 'primary';
|
|
52
52
|
else throw new libVES.Error('InvalidValue','Required parameters: user || domain');
|
|
53
53
|
this.unlockedKeys = {};
|
|
54
|
+
this.pendingKeys = {};
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
libVES.prototype = {
|
|
@@ -62,8 +63,9 @@ libVES.prototype = {
|
|
|
62
63
|
keyOptions: {namedCurve: 'P-521'},
|
|
63
64
|
textCipher: 'AES256GCMp',
|
|
64
65
|
defaultHash: 'SHA256',
|
|
65
|
-
propagators:
|
|
66
|
+
propagators: null,
|
|
66
67
|
request: function(method,uri,body,optns) {
|
|
68
|
+
var self = this;
|
|
67
69
|
if (!optns) optns = {};
|
|
68
70
|
return new Promise(function(resolve,reject) {
|
|
69
71
|
var xhr = new XMLHttpRequest();
|
|
@@ -80,8 +82,13 @@ libVES.prototype = {
|
|
|
80
82
|
return new libVES.Error(e.type,e.message,e);
|
|
81
83
|
});
|
|
82
84
|
if (errs.length) {
|
|
85
|
+
var retry = function(o) { return self.request(method, uri, body, (o || optns)); };
|
|
83
86
|
if (optns && optns.onerror) try {
|
|
84
|
-
resolve(optns.onerror(errs));
|
|
87
|
+
resolve(optns.onerror(errs, optns, retry));
|
|
88
|
+
} catch (e) {
|
|
89
|
+
reject(e);
|
|
90
|
+
} else if (self.onerror) try {
|
|
91
|
+
resolve(self.onerror(errs, optns, retry));
|
|
85
92
|
} catch (e) {
|
|
86
93
|
reject(e);
|
|
87
94
|
}
|
|
@@ -95,7 +102,7 @@ libVES.prototype = {
|
|
|
95
102
|
if (body != null) xhr.setRequestHeader('Content-Type','application/json');
|
|
96
103
|
xhr.setRequestHeader('Accept','application/json');
|
|
97
104
|
if (this.user && optns.password) xhr.setRequestHeader('Authorization','Basic ' + btoa(this.user + ':' + optns.password));
|
|
98
|
-
else if (optns.token
|
|
105
|
+
else if (optns.token ?? this.token) xhr.setRequestHeader('Authorization','Bearer ' + (optns.token ? optns.token : this.token));
|
|
99
106
|
xhr.responseType = 'json';
|
|
100
107
|
xhr.send(body);
|
|
101
108
|
}.bind(this));
|
|
@@ -120,6 +127,10 @@ libVES.prototype = {
|
|
|
120
127
|
}
|
|
121
128
|
return '';
|
|
122
129
|
},
|
|
130
|
+
mergeFieldList: function(flds, flds2) {
|
|
131
|
+
for (var k in flds2) if (flds[k] instanceof Object) flds[k] = this.mergeFieldList(flds[k], flds2[k]); else flds[k] = flds2[k];
|
|
132
|
+
return flds;
|
|
133
|
+
},
|
|
123
134
|
elevateAuth: function(optns) {
|
|
124
135
|
var self = this;
|
|
125
136
|
if (optns && (optns.password || optns.token)) return Promise.resolve(optns);
|
|
@@ -236,7 +247,7 @@ libVES.prototype = {
|
|
|
236
247
|
unlock: function(veskey) {
|
|
237
248
|
var self = this;
|
|
238
249
|
return this.getVaultKey().then(function(vkey) {
|
|
239
|
-
return vkey.unlock(
|
|
250
|
+
return vkey.unlock(veskey).then(function(cryptoKey) {
|
|
240
251
|
if (self.VESkey === null) self.VESkey = veskey;
|
|
241
252
|
if (!self.token && self.type == 'secondary') return vkey.getSessionToken().then(function(tkn) {
|
|
242
253
|
self.token = tkn;
|
|
@@ -251,8 +262,14 @@ libVES.prototype = {
|
|
|
251
262
|
});
|
|
252
263
|
},
|
|
253
264
|
lock: function() {
|
|
254
|
-
|
|
255
|
-
|
|
265
|
+
var lock = [];
|
|
266
|
+
for (var kid in this.unlockedKeys) lock.push(this.unlockedKeys[kid].then(function(k) {
|
|
267
|
+
return k.lock();
|
|
268
|
+
}).catch(function() {}));
|
|
269
|
+
this.propagators = null;
|
|
270
|
+
return Promise.all(lock).then(function() {
|
|
271
|
+
return true;
|
|
272
|
+
});
|
|
256
273
|
},
|
|
257
274
|
reset: function(val) {
|
|
258
275
|
this.userMe = undefined;
|
|
@@ -293,11 +310,11 @@ libVES.prototype = {
|
|
|
293
310
|
});
|
|
294
311
|
});
|
|
295
312
|
},
|
|
296
|
-
getItems: function() {
|
|
313
|
+
getItems: function(flds) {
|
|
297
314
|
var self = this;
|
|
298
315
|
return this.getVaultKey().then(function(k) {
|
|
299
316
|
return k.getId().then(function(kid) {
|
|
300
|
-
return k.getVaultEntries({type: true, deleted: true, file: {creator: true, externals: true}, vaultKey: {type: true, user: true}}).then(function(ves) {
|
|
317
|
+
return k.getVaultEntries(self.mergeFieldList({type: true, deleted: true, file: {creator: true, externals: true}, vaultKey: {type: true, user: true}}, flds)).then(function(ves) {
|
|
301
318
|
var vis = {};
|
|
302
319
|
var vlst = [];
|
|
303
320
|
for (var i = 0; i < ves.length; i++) {
|
|
@@ -308,6 +325,7 @@ libVES.prototype = {
|
|
|
308
325
|
if (!vi.vaultKey) vi.vaultKey = undefined;
|
|
309
326
|
vi = vis[viid] = self.getItem(vi);
|
|
310
327
|
vlst.push(vi);
|
|
328
|
+
if (!ves[i].vaultKey) ves[i].vaultKey = {id: kid};
|
|
311
329
|
vi.vaultEntryByKey[kid] = ves[i];
|
|
312
330
|
}
|
|
313
331
|
}
|
|
@@ -346,7 +364,7 @@ libVES.prototype = {
|
|
|
346
364
|
_matchUser: function(u) {
|
|
347
365
|
if (typeof(u) == 'object') {
|
|
348
366
|
if (u instanceof libVES.User) return u;
|
|
349
|
-
else return new libVES.User(u,this);
|
|
367
|
+
else return new libVES.User((u.id ? {id: u.id} : {email: u.email}), this);
|
|
350
368
|
} else if (typeof(u) == 'string' && u.match(/^\S+\@\S+$/)) return new libVES.User({email: u},this);
|
|
351
369
|
throw new libVES.Error('BadUser',"Cannot match user: " + u,{value: u});
|
|
352
370
|
},
|
|
@@ -377,11 +395,14 @@ libVES.prototype = {
|
|
|
377
395
|
}).catch(function(e) {
|
|
378
396
|
throw new libVES.Error('NotFound', 'Cannot match externalId for domain:' + ext.domain + ', user:' + user + '. Define libVES.Domain.' + ext.domain + '.userToVaultRef(user) to return a valid reference.',{error: e});
|
|
379
397
|
})).then(function(exts) {
|
|
380
|
-
|
|
398
|
+
var keyref = {externals: exts};
|
|
399
|
+
if (self.externalId && self.externalId[0] != '!') keyref.creator = self.me();
|
|
400
|
+
var vkey = new libVES.VaultKey(keyref, self);
|
|
381
401
|
return vkey.getId().then(function() {
|
|
382
402
|
return vkey;
|
|
383
403
|
}).catch(function(e) {
|
|
384
404
|
if (e.code != 'NotFound') throw e;
|
|
405
|
+
if (!keyref.creator) throw new libVES.Error.InvalidKey('Anonymous vaults are not authorized to create temp keys');
|
|
385
406
|
return Promise.resolve(user || m().then(function(dom) {
|
|
386
407
|
return dom.vaultRefToUser(exts[0]);
|
|
387
408
|
})).catch(function(e) {
|
|
@@ -405,6 +426,20 @@ libVES.prototype = {
|
|
|
405
426
|
});
|
|
406
427
|
});
|
|
407
428
|
},
|
|
429
|
+
getPropagators: function() {
|
|
430
|
+
if (!this.propagators) {
|
|
431
|
+
let xid = (this.externalId ?? this.email);
|
|
432
|
+
this.propagators = (xid?.match(/^[^\!]+\@\w/) ? Promise.resolve(xid.replace(/\!.*/, '')) : this.me().then((me) => me.getEmail())).then((xid) => {
|
|
433
|
+
if (!xid) return [];
|
|
434
|
+
let prop = new libVES.VaultKey({externals: {domain: '.propagate', externalId: xid.toLowerCase()}}, this);
|
|
435
|
+
return prop.getId().then(() => [prop]);
|
|
436
|
+
}).catch((er) => {
|
|
437
|
+
if (er?.code == 'NotFound' || er?.code == 'Unauthorized') return [];
|
|
438
|
+
throw er;
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
return Promise.resolve(this.propagators);
|
|
442
|
+
},
|
|
408
443
|
getUserKeys: function(usr) {
|
|
409
444
|
var self = this;
|
|
410
445
|
return usr.getActiveVaultKeys().catch(function(e) {
|
|
@@ -434,13 +469,12 @@ libVES.prototype = {
|
|
|
434
469
|
return key.generate(veskey, optns).then(function(k) {
|
|
435
470
|
key.setField('vaultItems', veskey.then(function(v) {
|
|
436
471
|
var vi = new libVES.VaultItem({type: 'password'}, self);
|
|
437
|
-
return usr.getActiveVaultKeys().then(function() {
|
|
438
|
-
return [self.me(), self.getVaultKey()
|
|
472
|
+
return usr.getActiveVaultKeys().then(function(akeys) {
|
|
473
|
+
return [self.me(), self.getVaultKey()].concat(akeys);
|
|
439
474
|
}).catch(function(e) {
|
|
440
475
|
if (e.code != 'NotFound') throw e;
|
|
441
476
|
var sh = self.type == 'secondary' ? [self.me(), self.getVaultKey()] : [self.me()];
|
|
442
|
-
|
|
443
|
-
return sh;
|
|
477
|
+
return self.getPropagators().then((props) => sh.concat(props)).catch((er) => sh);
|
|
444
478
|
}).then(function(sh) {
|
|
445
479
|
return Promise.all(sh);
|
|
446
480
|
}).then(function(sh) {
|
|
@@ -573,6 +607,9 @@ libVES.prototype = {
|
|
|
573
607
|
}).catch(function(e) {
|
|
574
608
|
if (!e || e.code != 'Unauthorized') throw e;
|
|
575
609
|
}).then(function() {
|
|
610
|
+
self.vaultKey = k.lock().then(function() {
|
|
611
|
+
return k;
|
|
612
|
+
});
|
|
576
613
|
return self.unlock(veskey);
|
|
577
614
|
});
|
|
578
615
|
});
|
|
@@ -807,7 +844,7 @@ libVES.prototype = {
|
|
|
807
844
|
return self.getVaultKey().then(function(vk) {
|
|
808
845
|
return vk.getField('unlockableVaultKeys').then(function(vks) {
|
|
809
846
|
var rs = {};
|
|
810
|
-
return Promise.all(vks.map(function(e, i) {
|
|
847
|
+
return Promise.all((vks || []).map(function(e, i) {
|
|
811
848
|
return e.getId().then(function(id) {
|
|
812
849
|
rs[id] = e;
|
|
813
850
|
});
|
|
@@ -852,11 +889,20 @@ libVES.prototype = {
|
|
|
852
889
|
return vkey.rekey(optns);
|
|
853
890
|
});
|
|
854
891
|
else return vkey.getVaultItems().then(function(vis) {
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
892
|
+
return Promise.all([user.getActiveVaultKeys(), vkey.getExternals().then((exts) => {
|
|
893
|
+
let ckey = new libVES.VaultKey({externals: exts}, self);
|
|
894
|
+
return ckey.getType().then(() => [ckey]).catch((er) => {
|
|
895
|
+
if (er?.code != 'NotFound') throw er;
|
|
896
|
+
return [];
|
|
897
|
+
});
|
|
898
|
+
})]).then((klists) => {
|
|
899
|
+
let ks = (klists[0] ?? []).concat(klists[1]);
|
|
900
|
+
return Promise.all(ks.map((k) => k.getType())).then((ktypes) => ks.filter((k, i) => ktypes[i] != 'temp'));
|
|
901
|
+
}).then((ks) => self.elevateAuth().then(function(optns) {
|
|
902
|
+
return Promise.all(vis.map(function(vi, i) {
|
|
903
|
+
return vi.reshareWith(ks, undefined, optns);
|
|
904
|
+
}));
|
|
905
|
+
}));
|
|
860
906
|
});
|
|
861
907
|
});
|
|
862
908
|
});
|
|
@@ -917,6 +963,11 @@ libVES.Error.Redirect = function(msg, optns) {
|
|
|
917
963
|
};
|
|
918
964
|
libVES.Error.Redirect.prototype = new libVES.Error('Redirect');
|
|
919
965
|
|
|
966
|
+
libVES.Error.Unauthorized = function(msg, optns) {
|
|
967
|
+
this.init(msg, optns);
|
|
968
|
+
};
|
|
969
|
+
libVES.Error.Unauthorized.prototype = new libVES.Error('Unauthorized');
|
|
970
|
+
|
|
920
971
|
libVES.Error.Internal = function(msg, optns) {
|
|
921
972
|
this.init(msg, optns);
|
|
922
973
|
};
|
|
@@ -1024,6 +1075,14 @@ libVES.Util = {
|
|
|
1024
1075
|
}
|
|
1025
1076
|
return rs;
|
|
1026
1077
|
},
|
|
1078
|
+
fillUndefs: function(data, defs) {
|
|
1079
|
+
if (data instanceof Array) data.map((d) => libVES.Util.fillUndefs(d, defs));
|
|
1080
|
+
else if (data && defs) for (var k in defs) if (defs[k]) {
|
|
1081
|
+
if (data[k] === undefined) data[k] = undefined;
|
|
1082
|
+
else if (data[k] instanceof Object) libVES.Util.fillUndefs(data[k], defs[k]);
|
|
1083
|
+
}
|
|
1084
|
+
return data;
|
|
1085
|
+
},
|
|
1027
1086
|
loadWasm: function(src) {
|
|
1028
1087
|
return new Promise(function(resolve, reject) {
|
|
1029
1088
|
var sc = document.createElement('script');
|
|
@@ -1712,30 +1771,20 @@ libVES.Object.prototype = {
|
|
|
1712
1771
|
this.setFields(data,data.id == null);
|
|
1713
1772
|
if (refs) for (var k in refs) this[k] = Promise.resolve(refs[k]);
|
|
1714
1773
|
},
|
|
1715
|
-
setFields: function(
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
else if (v instanceof Array) return v.map(function(vv) { return clsf(vv); });
|
|
1730
|
-
else if (v) return new (self.fieldClass[k])(v,self.VES);
|
|
1731
|
-
})(v);
|
|
1732
|
-
return v;
|
|
1733
|
-
};
|
|
1734
|
-
})(k));
|
|
1735
|
-
else return Promise.reject(new libVES.Error('Internal',"Unknown field: " + k));
|
|
1736
|
-
}
|
|
1737
|
-
if (chg && self.trigger) self.trigger.resolve(self);
|
|
1738
|
-
return Promise.resolve(self);
|
|
1774
|
+
setFields: function(flds, up) {
|
|
1775
|
+
var res = Promise.resolve(null);
|
|
1776
|
+
for (var fld in flds) ((fld) => {
|
|
1777
|
+
if (up === undefined || up) this.fieldUpdate[fld] = true;
|
|
1778
|
+
var cls = this.fieldClass[fld];
|
|
1779
|
+
var cur = this[fld];
|
|
1780
|
+
res = this[fld] = res.then(() => Promise.resolve(flds[fld]).then((val) => Promise.resolve(cur).catch((er) => undefined).then((cur) => {
|
|
1781
|
+
if (!cls || !val) return val;
|
|
1782
|
+
else if (val instanceof Array) return val.map((v) => ((v instanceof libVES.Object) ? v : new cls(v, this.VES)));
|
|
1783
|
+
else if (cur instanceof cls) return cur.setFields(val, up);
|
|
1784
|
+
else return (val instanceof libVES.Object) ? val : new cls(val, this.VES);
|
|
1785
|
+
})));
|
|
1786
|
+
})(fld);
|
|
1787
|
+
return res.then(() => this);
|
|
1739
1788
|
},
|
|
1740
1789
|
setField: function(fld,val,upd) {
|
|
1741
1790
|
var flds = {};
|
|
@@ -1744,54 +1793,78 @@ libVES.Object.prototype = {
|
|
|
1744
1793
|
return self[fld];
|
|
1745
1794
|
});
|
|
1746
1795
|
},
|
|
1796
|
+
unsetField: function(fld) {
|
|
1797
|
+
delete(this[fld]);
|
|
1798
|
+
},
|
|
1799
|
+
_fieldsToLoad: function(fldlst, force, ld) {
|
|
1800
|
+
var flds = {};
|
|
1801
|
+
for (var k in fldlst) flds[k] ||= fldlst[k];
|
|
1802
|
+
for (var i = 0; i < this.fieldSets.length; i++) {
|
|
1803
|
+
for (var k in this.fieldSets[i]) if (fldlst[k]) {
|
|
1804
|
+
for (var k in this.fieldSets[i]) if ((force || !this[k]) && !(flds[k] instanceof Object)) (flds ||= {})[k] = this.fieldSets[i][k];
|
|
1805
|
+
break;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
var res = Promise.resolve(null);
|
|
1809
|
+
for (var fld in flds) ((fld) => {
|
|
1810
|
+
var cur = this[fld];
|
|
1811
|
+
var na = (cur === undefined);
|
|
1812
|
+
var cls = this.fieldClass[fld];
|
|
1813
|
+
res = res.then((res) => Promise.resolve(cur).catch((er) => null).then((cur) => {
|
|
1814
|
+
var lst = null;
|
|
1815
|
+
if (force || na) lst = flds[fld];
|
|
1816
|
+
else if (cls) {
|
|
1817
|
+
if (cur instanceof Array) lst = ((cur[0] instanceof cls) ? cur[0]._fieldsToLoad(flds[fld], force, ld.then((vals) => vals[fld])) : Promise.resolve(null)).then((lst) => (lst && flds[fld]));
|
|
1818
|
+
else if (cur instanceof cls) lst = cur._fieldsToLoad(flds[fld], force, ld.then((vals) => vals[fld]));
|
|
1819
|
+
}
|
|
1820
|
+
return Promise.resolve(lst).then((lst) => {
|
|
1821
|
+
if (lst) (res ||= {})[fld] = lst;
|
|
1822
|
+
return res;
|
|
1823
|
+
});
|
|
1824
|
+
}));
|
|
1825
|
+
if (na || (!cls && force)) (this[fld] = ld.then((vals) => (vals?.hasOwnProperty(fld) ? (cls && vals[fld] ? ((vals[fld] instanceof Array) ? vals[fld].map((e) => new cls(e, this.VES)) : new cls(vals[fld], this.VES)) : vals[fld]) : cur))).catch(() => null);
|
|
1826
|
+
})(fld);
|
|
1827
|
+
ld.then((vals) => {
|
|
1828
|
+
for (var fld in vals) if (!flds[fld] && !this[fld]) this.setField(fld, vals[fld], false);
|
|
1829
|
+
}).catch((er) => null);
|
|
1830
|
+
return res.then((res) => {
|
|
1831
|
+
if (res) for (var k in fldlst) if (res[k]) return res;
|
|
1832
|
+
return null;
|
|
1833
|
+
});
|
|
1834
|
+
},
|
|
1747
1835
|
getFields: function(fldlst, force) {
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
for (var k in this.fieldSets[i]) if (fldlst[k]) {
|
|
1752
|
-
for (var k in this.fieldSets[i]) if ((force || !this[k]) && !(flds[k] instanceof Object)) flds[k] = this.fieldSets[i][k];
|
|
1753
|
-
break;
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
for (var k in fldlst) if ((force || !this[k]) && !(flds[k] instanceof Object)) flds[k] = fldlst[k];
|
|
1757
|
-
for (var k in flds) {
|
|
1758
|
-
this.loadFields(flds);
|
|
1759
|
-
break;
|
|
1760
|
-
}
|
|
1836
|
+
var ldf;
|
|
1837
|
+
var ld = new Promise((resolve, reject) => ldf = [resolve, reject]);
|
|
1838
|
+
this._fieldsToLoad(fldlst, force, ld).then((flds) => this.loadFields(flds, force)).then((vals) => ldf[0](vals)).catch((er) => ldf[1](er));
|
|
1761
1839
|
var plst = [];
|
|
1762
|
-
for (var k in fldlst) {
|
|
1763
|
-
plst.push(
|
|
1840
|
+
for (var k in fldlst) ((k) => {
|
|
1841
|
+
plst.push(ld.then(() => this[k]).then(function rslv(v) {
|
|
1842
|
+
if (v instanceof Array) return Promise.all(v.map(function(e, i) {
|
|
1843
|
+
return rslv(e);
|
|
1844
|
+
}));
|
|
1764
1845
|
if (!(v instanceof libVES.Object)) return v;
|
|
1765
|
-
return v.getFields(fldlst[k]
|
|
1846
|
+
return v.getFields(fldlst[k]);
|
|
1766
1847
|
}));
|
|
1767
|
-
}
|
|
1848
|
+
})(k);
|
|
1768
1849
|
var rs = {};
|
|
1769
|
-
return Promise.all(plst).then(
|
|
1850
|
+
return Promise.all(plst).then((lst) => {
|
|
1770
1851
|
var i = 0;
|
|
1771
1852
|
for (var k in fldlst) rs[k] = lst[i++];
|
|
1772
1853
|
return rs;
|
|
1773
1854
|
});
|
|
1774
1855
|
},
|
|
1775
1856
|
getField: function(fld,fldlst,force) {
|
|
1776
|
-
var self = this;
|
|
1777
1857
|
if (!this[fld] || force) {
|
|
1778
1858
|
var flds = {};
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
break;
|
|
1782
|
-
}
|
|
1783
|
-
if (fldlst) flds[fld] = fldlst;
|
|
1784
|
-
if (!flds[fld]) {
|
|
1785
|
-
var cls = self.fieldClass[fld];
|
|
1786
|
-
flds[fld] = cls ? cls.prototype.fieldList : true;
|
|
1787
|
-
}
|
|
1788
|
-
this.loadFields(flds,force);
|
|
1859
|
+
flds[fld] = fldlst || true;
|
|
1860
|
+
this.getFields(flds, force).catch(() => null);
|
|
1789
1861
|
}
|
|
1790
1862
|
return this[fld];
|
|
1791
1863
|
},
|
|
1792
1864
|
loadFields: function(flds,force,optns) {
|
|
1865
|
+
if (!flds) return Promise.resolve({});
|
|
1793
1866
|
var self = this;
|
|
1794
|
-
|
|
1867
|
+
return (this.id && !flds.id ? this.id.then(function(id) { return self.VES.get(self.apiUri + '/' + id,flds,optns); }) : self.postData().then(function(data) {
|
|
1795
1868
|
data['$op'] = 'fetch';
|
|
1796
1869
|
return self.VES.post(self.apiUri,data,flds,optns);
|
|
1797
1870
|
}).then(function(data) {
|
|
@@ -1800,21 +1873,10 @@ libVES.Object.prototype = {
|
|
|
1800
1873
|
self.fieldUpdate = {id: true};
|
|
1801
1874
|
}
|
|
1802
1875
|
return data;
|
|
1803
|
-
});
|
|
1804
|
-
for (var k in flds) if (force || this[k] === undefined) {
|
|
1805
|
-
this[k] = req.then((function(fld) {
|
|
1806
|
-
var cls = self.fieldClass[fld];
|
|
1807
|
-
return function(data) {
|
|
1808
|
-
if (cls && data[fld]) return ((data[fld] instanceof Array) ? data[fld].map(function(v) {
|
|
1809
|
-
return new cls(v,self.VES);
|
|
1810
|
-
}) : new cls(data[fld],self.VES));
|
|
1811
|
-
return data[fld];
|
|
1812
|
-
};
|
|
1813
|
-
})(k));
|
|
1814
|
-
}
|
|
1876
|
+
})).then((data) => libVES.Util.fillUndefs(data, flds));
|
|
1815
1877
|
},
|
|
1816
1878
|
reset: function() {
|
|
1817
|
-
for (var k in this.fieldClass)
|
|
1879
|
+
for (var k in this.fieldClass) this.unsetField(k);
|
|
1818
1880
|
return Promise.resolve();
|
|
1819
1881
|
},
|
|
1820
1882
|
getId: function() {
|
|
@@ -1888,6 +1950,23 @@ libVES.Object.prototype = {
|
|
|
1888
1950
|
},
|
|
1889
1951
|
resolveError: function(e,field) {
|
|
1890
1952
|
throw e;
|
|
1953
|
+
},
|
|
1954
|
+
setUpdate: function(flds) {
|
|
1955
|
+
var rs = [];
|
|
1956
|
+
for (var k in flds) {
|
|
1957
|
+
if (flds[k]) this.fieldUpdate[k] = true;
|
|
1958
|
+
else delete(this.fieldUpdate[k]);
|
|
1959
|
+
if (this[k] && (flds[k] instanceof Object)) (function(p, k) {
|
|
1960
|
+
rs.push(p.then(function rslv(obj) {
|
|
1961
|
+
if (obj instanceof Array) return Promise.all(obj.map(rslv));
|
|
1962
|
+
if (obj instanceof libVES.Object) return obj.setUpdate(flds[k]);
|
|
1963
|
+
}));
|
|
1964
|
+
})(this[k], k);
|
|
1965
|
+
}
|
|
1966
|
+
return Promise.all(rs);
|
|
1967
|
+
},
|
|
1968
|
+
toJSON: function() {
|
|
1969
|
+
return String(this);
|
|
1891
1970
|
}
|
|
1892
1971
|
};
|
|
1893
1972
|
|
|
@@ -2040,10 +2119,16 @@ libVES.VaultKey.prototype = new libVES.Object({
|
|
|
2040
2119
|
case 'lost':
|
|
2041
2120
|
return self.getVaultItems().then(function(vis) {
|
|
2042
2121
|
var f = function(vis) {
|
|
2043
|
-
if (!vis.length) throw new libVES.Error('InvalidKey','Cannot unlock the secondary key');
|
|
2122
|
+
if (!vis || !vis.length) throw new libVES.Error('InvalidKey','Cannot unlock the secondary key');
|
|
2044
2123
|
return vis[0].getType().then(function(t) {
|
|
2045
2124
|
switch (t) {
|
|
2046
|
-
case 'password': return
|
|
2125
|
+
case 'password': return self.getId().then(function(kid) {
|
|
2126
|
+
if (!self.VES.pendingKeys) self.VES.pendingKeys = {};
|
|
2127
|
+
if (kid) self.VES.pendingKeys[kid] = true;
|
|
2128
|
+
return vis[0].get().finally(function() {
|
|
2129
|
+
self.VES.pendingKeys[kid] = false;
|
|
2130
|
+
});
|
|
2131
|
+
});
|
|
2047
2132
|
default: return f(vis.slice(1));
|
|
2048
2133
|
}
|
|
2049
2134
|
});
|
|
@@ -2054,26 +2139,57 @@ libVES.VaultKey.prototype = new libVES.Object({
|
|
|
2054
2139
|
}
|
|
2055
2140
|
});
|
|
2056
2141
|
},
|
|
2142
|
+
invalidVESkey: function() {
|
|
2143
|
+
var self = this;
|
|
2144
|
+
return self.getVaultItems().then(function(vis) {
|
|
2145
|
+
return Promise.all(vis.map(function(vi) {
|
|
2146
|
+
return vi.getVaultEntries().then(function(entries) {
|
|
2147
|
+
if (entries) for (let i = 0; i < entries.length; i++) if (self.VES.unlockedKeys[entries[i].vaultKey.id]) return Promise.resolve(self.VES.unlockedKeys[entries[i].vaultKey.id]).then(function(key) {
|
|
2148
|
+
return key.getFields({user: {email: true}, extrenals: {domain: true, externalId: true}}).then(function(flds) {
|
|
2149
|
+
return vi.unshareWith([flds.externals && flds.externals[0] ? flds.externals[0] : flds.user.email]);
|
|
2150
|
+
});
|
|
2151
|
+
});
|
|
2152
|
+
});
|
|
2153
|
+
}));
|
|
2154
|
+
});
|
|
2155
|
+
},
|
|
2057
2156
|
unlock: function(veskey) {
|
|
2058
2157
|
var self = this;
|
|
2059
|
-
if (self.wcPriv)
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2158
|
+
if (!self.wcPriv) self.wcPriv = self.getId().then(function(id) {
|
|
2159
|
+
return Promise.resolve(self.VES.unlockedKeys[id]).then(function(k) {
|
|
2160
|
+
return k.wcPriv;
|
|
2161
|
+
}).catch(function(e) {
|
|
2162
|
+
let un = self.engine().then(function(m) {
|
|
2163
|
+
return self.resolveVESkey(veskey).then(function(v) {
|
|
2164
|
+
return self.getPrivateKey().then(function(prk) {
|
|
2165
|
+
return m.import(prk, {password: v}).catch(function(e) {
|
|
2166
|
+
if (e && e.code == 'InvalidKey' && !veskey) {
|
|
2167
|
+
console.log('Bad key propagated for ' + id + ', unsharing...');
|
|
2168
|
+
return self.invalidVESkey().catch(function(e2) {
|
|
2169
|
+
console.log(e2);
|
|
2170
|
+
}).then(function(r) {
|
|
2171
|
+
console.log(r);
|
|
2172
|
+
throw e;
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
throw e;
|
|
2176
|
+
});
|
|
2177
|
+
});
|
|
2069
2178
|
});
|
|
2070
2179
|
});
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2180
|
+
let vk = self.VES.unlockedKeys[id] = un.then(function() {
|
|
2181
|
+
return self;
|
|
2182
|
+
}).catch(function(e) {
|
|
2183
|
+
if (self.VES.unlockedKeys[id] === vk) delete(self.VES.unlockedKeys[id]);
|
|
2184
|
+
});
|
|
2185
|
+
return un;
|
|
2075
2186
|
});
|
|
2076
2187
|
});
|
|
2188
|
+
else if (veskey) self.wcPriv = self.wcPriv.catch(function(e) {
|
|
2189
|
+
delete(self.wcPriv);
|
|
2190
|
+
return self.unlock(veskey);
|
|
2191
|
+
});
|
|
2192
|
+
return self.wcPriv;
|
|
2077
2193
|
},
|
|
2078
2194
|
lock: function() {
|
|
2079
2195
|
var self = this;
|
|
@@ -2251,8 +2367,20 @@ libVES.VaultKey.prototype = new libVES.Object({
|
|
|
2251
2367
|
});
|
|
2252
2368
|
});
|
|
2253
2369
|
},
|
|
2254
|
-
matchVaults: function(
|
|
2255
|
-
|
|
2370
|
+
matchVaults: function(shares) {
|
|
2371
|
+
return this.getFields({id: true, externals: {domain: true, externalId: true}, user: {email: true}}).then((flds) => (shares || []).reduce((res, sh) => res.then((res) => Promise.resolve(sh).then((sh) => {
|
|
2372
|
+
if (res) return res;
|
|
2373
|
+
var ext = flds.externals?.[0];
|
|
2374
|
+
if (sh instanceof libVES.Object) {
|
|
2375
|
+
if (sh instanceof libVES.VaultKey) return sh.getId().then((id) => (id == flds.id ? sh : res));
|
|
2376
|
+
else if ((sh instanceof libVES.External) && ext) return sh.getFields({domain: true, externalId: true}).then((xflds) => (xflds.domain == ext.domain && xflds.externalId == ext.externalId ? sh : res));
|
|
2377
|
+
else if ((sh instanceof libVES.User) && flds.user && !ext) return sh.getEmail().then((email) => (email == flds.user.email ? sh : res));
|
|
2378
|
+
} else if (sh instanceof Object) {
|
|
2379
|
+
if (sh.externalId && sh.externalId == ext?.externalId && (sh.domain || this.VES.domain) == ext.domain) return sh;
|
|
2380
|
+
else if (sh.email && sh.email == flds.user?.email && !ext) return sh;
|
|
2381
|
+
} else if (sh && flds.user?.email == sh && !ext) return sh;
|
|
2382
|
+
return res;
|
|
2383
|
+
})), Promise.resolve(false)));
|
|
2256
2384
|
},
|
|
2257
2385
|
getKeyOptions: function() {
|
|
2258
2386
|
var self = this;
|
|
@@ -2268,7 +2396,7 @@ libVES.VaultItem.prototype = new libVES.Object({
|
|
|
2268
2396
|
apiUri: 'vaultItems',
|
|
2269
2397
|
fieldList: {id: true, deleted: true, file: true},
|
|
2270
2398
|
fieldClass: {vaultKey: libVES.VaultKey, file: libVES.File},
|
|
2271
|
-
fieldSets: [{type: true, meta: true},{vaultEntries: {id: true, encData: true, vaultKey: {id: true, type: true, user: {id: true}, algo: true, externals: {id: true}}}},{vaultKey: true, file: true}],
|
|
2399
|
+
fieldSets: [{type: true, meta: true},{vaultEntries: {id: true, encData: true, vaultKey: {id: true, type: true, user: {id: true, email: true}, algo: true, externals: {id: true, domain: true, externalId: true}}}},{vaultKey: true, file: true}],
|
|
2272
2400
|
defaultCipher: 'AES256GCM',
|
|
2273
2401
|
getRaw: function() {
|
|
2274
2402
|
var self = this;
|
|
@@ -2277,9 +2405,11 @@ libVES.VaultItem.prototype = new libVES.Object({
|
|
|
2277
2405
|
var fn = function() {
|
|
2278
2406
|
if (vaultEntries) for (; i < vaultEntries.length; i++) {
|
|
2279
2407
|
var k, d;
|
|
2280
|
-
if ((d = vaultEntries[i].encData) != null &&
|
|
2408
|
+
if ((d = vaultEntries[i].encData) != null && (k = vaultKeys[vaultEntries[i].vaultKey.id]) && (!self.VES.pendingKeys || !self.VES.pendingKeys[vaultEntries[i].vaultKey.id])) {
|
|
2281
2409
|
i++;
|
|
2282
|
-
return
|
|
2410
|
+
return Promise.resolve(k).then(function(k) {
|
|
2411
|
+
return k.decrypt(d).catch(fn);
|
|
2412
|
+
});
|
|
2283
2413
|
}
|
|
2284
2414
|
}
|
|
2285
2415
|
return Promise.reject(new libVES.Error('InvalidKey',"No unlocked key to decrypt the item",{vaultItem: self}));
|
|
@@ -2338,7 +2468,10 @@ libVES.VaultItem.prototype = new libVES.Object({
|
|
|
2338
2468
|
},
|
|
2339
2469
|
build: function(data) {
|
|
2340
2470
|
var self = this;
|
|
2341
|
-
return this.getType().
|
|
2471
|
+
return this.getType().catch(function(e) {
|
|
2472
|
+
if (e && e.code == 'NotFound') return self.setField('type', libVES.VaultItem.Type._detect(data));
|
|
2473
|
+
throw e;
|
|
2474
|
+
}).then(function(type) {
|
|
2342
2475
|
return libVES.getModule(libVES.VaultItem.Type,type).then(function(m) {
|
|
2343
2476
|
return m.build.call(self,data);
|
|
2344
2477
|
});
|
|
@@ -2350,12 +2483,12 @@ libVES.VaultItem.prototype = new libVES.Object({
|
|
|
2350
2483
|
shareWith: function(usrs,val,save) {
|
|
2351
2484
|
var self = this;
|
|
2352
2485
|
return self.VES.usersToKeys(usrs).then(function(ks) {
|
|
2353
|
-
return (val == null
|
|
2486
|
+
return (val == null ? self.getVaultEntries().then(function(ves) {
|
|
2354
2487
|
var k_ves = {};
|
|
2355
2488
|
var k_used = {};
|
|
2356
2489
|
for (var j = 0; j < ves.length; j++) k_ves[ves[j].vaultKey.id] = ves[j];
|
|
2357
2490
|
return Promise.all(ks.map(function(k,j) {
|
|
2358
|
-
return k.getId().then(function(k_id) {
|
|
2491
|
+
if (!k.fieldUpdate.privateKey) return k.getId().then(function(k_id) {
|
|
2359
2492
|
k_used[k_id] = true;
|
|
2360
2493
|
return k_ves[k_id];
|
|
2361
2494
|
}).catch(function(){});
|
|
@@ -2367,21 +2500,26 @@ libVES.VaultItem.prototype = new libVES.Object({
|
|
|
2367
2500
|
var new_ves = [];
|
|
2368
2501
|
var set_ves = [];
|
|
2369
2502
|
var valr = null;
|
|
2503
|
+
var key_ids = {};
|
|
2370
2504
|
return Promise.all(ks.map(function(k,j) {
|
|
2371
2505
|
return new_ves[j] = (old_ves[j] || (valr != null ? valr : valr = self.resolveRaw(val)).then(function(v) {
|
|
2372
|
-
return
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2506
|
+
return (function(refs) {
|
|
2507
|
+
if (refs) for (var i in refs) if (refs[i] === k) return Promise.resolve({'$ref':i});
|
|
2508
|
+
return k.postData(null,refs);
|
|
2509
|
+
})(libVES.Object._refs).then(function(pd) {
|
|
2510
|
+
if (pd.id) {
|
|
2511
|
+
if (key_ids[pd.id]) return;
|
|
2512
|
+
key_ids[pd.id] = true;
|
|
2513
|
+
}
|
|
2514
|
+
return k.encrypt(v).then(function(ctext) {
|
|
2377
2515
|
return set_ves.push({vaultKey: pd, encData: ctext});
|
|
2378
2516
|
});
|
|
2379
2517
|
});
|
|
2380
2518
|
}));
|
|
2381
2519
|
})).then(function() {
|
|
2382
2520
|
return Promise.all(old_ves.slice(ks.length).map(function(ve,j) {
|
|
2383
|
-
return (new libVES.VaultKey(ve.vaultKey,self.VES)).matchVaults(
|
|
2384
|
-
if (f
|
|
2521
|
+
return (new libVES.VaultKey(ve.vaultKey,self.VES)).matchVaults(usrs).then(function(f) {
|
|
2522
|
+
if (!f) set_ves.push({vaultKey: {id: ve.vaultKey.id}, '$op': 'delete'});
|
|
2385
2523
|
});
|
|
2386
2524
|
}));
|
|
2387
2525
|
}).then(function() {
|
|
@@ -2390,12 +2528,20 @@ libVES.VaultItem.prototype = new libVES.Object({
|
|
|
2390
2528
|
});
|
|
2391
2529
|
});
|
|
2392
2530
|
}).then(function() {
|
|
2393
|
-
if (
|
|
2394
|
-
|
|
2531
|
+
if (self.id && val != null) return self.setUpdate({id: false, type: true, file: {id: false, externals: {id: false, domain: true, externalId: true}}});
|
|
2532
|
+
}).then(function() {
|
|
2533
|
+
if (save || save === undefined) return self.post(undefined, undefined, ((save instanceof Object) ? save : undefined)).then(function(flds) {
|
|
2534
|
+
self.vaultEntryByKey = {};
|
|
2535
|
+
self.setFields(flds, false);
|
|
2395
2536
|
return self;
|
|
2537
|
+
}).finally(function() {
|
|
2538
|
+
delete(self.vaultEntries);
|
|
2396
2539
|
});
|
|
2397
2540
|
return self;
|
|
2398
|
-
})
|
|
2541
|
+
}).catch(function(er) {
|
|
2542
|
+
delete(self.vaultEntries);
|
|
2543
|
+
throw er;
|
|
2544
|
+
});
|
|
2399
2545
|
},
|
|
2400
2546
|
reshareWith: function(share,val,save) {
|
|
2401
2547
|
var self = this;
|
|
@@ -2418,6 +2564,15 @@ libVES.VaultItem.prototype = new libVES.Object({
|
|
|
2418
2564
|
});
|
|
2419
2565
|
});
|
|
2420
2566
|
},
|
|
2567
|
+
unshareWith: function(share, save) {
|
|
2568
|
+
return this.getShareVaultKeys().then((vkeys) => Promise.all(vkeys.map((vkey) => vkey.matchVaults(share))).then((del) => this.shareWith(vkeys.filter((vkey, i) => !del[i]), undefined, save)));
|
|
2569
|
+
},
|
|
2570
|
+
set: function(val, save) {
|
|
2571
|
+
var self = this;
|
|
2572
|
+
return self.getShareList().then(function(sh) {
|
|
2573
|
+
return self.shareWith(sh, val, save);
|
|
2574
|
+
});
|
|
2575
|
+
},
|
|
2421
2576
|
getShareVaultKeys: function() {
|
|
2422
2577
|
var self = this;
|
|
2423
2578
|
return this.getVaultEntries().then(function(vaultEntries) {
|
|
@@ -2430,12 +2585,17 @@ libVES.VaultItem.prototype = new libVES.Object({
|
|
|
2430
2585
|
var self = this;
|
|
2431
2586
|
return this.getShareVaultKeys().then(function(vaultKeys) {
|
|
2432
2587
|
var uids = {};
|
|
2588
|
+
var xids = {};
|
|
2433
2589
|
return Promise.all(vaultKeys.map(function(e,i) {
|
|
2434
2590
|
return e.getExternals().then(function(exts) {
|
|
2435
|
-
if (exts && exts.length) return exts[0]
|
|
2591
|
+
if (exts && exts.length) return exts[0].getId().then(function(xid) {
|
|
2592
|
+
if (!xid || xids[xid]) return null;
|
|
2593
|
+
xids[xid] = true;
|
|
2594
|
+
return exts[0];
|
|
2595
|
+
});
|
|
2436
2596
|
return e.getUser().then(function(u) {
|
|
2437
2597
|
return u.getId().then(function(uid) {
|
|
2438
|
-
if (uids[uid]) return null;
|
|
2598
|
+
if (!uid || uids[uid]) return null;
|
|
2439
2599
|
uids[uid] = true;
|
|
2440
2600
|
return u;
|
|
2441
2601
|
});
|
|
@@ -2451,7 +2611,7 @@ libVES.VaultItem.prototype = new libVES.Object({
|
|
|
2451
2611
|
delete: function() {
|
|
2452
2612
|
var self = this;
|
|
2453
2613
|
return self.getId().then(function(id) {
|
|
2454
|
-
return
|
|
2614
|
+
return self.VES.post(self.apiUri + '/' + id, {'$op': 'delete'});
|
|
2455
2615
|
});
|
|
2456
2616
|
}
|
|
2457
2617
|
});
|
|
@@ -4306,7 +4466,7 @@ libVES.Watch.prototype = {
|
|
|
4306
4466
|
}).then(function(res) {
|
|
4307
4467
|
if (!res.events) return null;
|
|
4308
4468
|
return res.events.map(function(e, i) {
|
|
4309
|
-
return new libVES.Event(e, self.VES);
|
|
4469
|
+
return new libVES.Event(libVES.Util.fillUndefs(e, self.fields), self.VES);
|
|
4310
4470
|
});
|
|
4311
4471
|
});
|
|
4312
4472
|
},
|
|
@@ -4321,8 +4481,8 @@ libVES.Watch.prototype = {
|
|
|
4321
4481
|
if (!busy && this.state == 'stop') this.setState('idle');
|
|
4322
4482
|
},
|
|
4323
4483
|
start: function(pos) {
|
|
4324
|
-
if (!this.eventfn)
|
|
4325
|
-
if (this.busy)
|
|
4484
|
+
if (!this.eventfn) return Promise.reject(new libVES.Error('InvalidValue', 'eventfn is not set'));
|
|
4485
|
+
if (this.busy) return Promise.reject(new libVES.Error('Internal', 'Watch instance is busy'));
|
|
4326
4486
|
var self = this;
|
|
4327
4487
|
self.setBusy(true);
|
|
4328
4488
|
this.setState('read');
|
|
@@ -4330,13 +4490,17 @@ libVES.Watch.prototype = {
|
|
|
4330
4490
|
this.next = 0;
|
|
4331
4491
|
return this.getEvents(0, pos).then(function(evs) {
|
|
4332
4492
|
self.setBusy(false);
|
|
4333
|
-
return self.received(evs.reverse());
|
|
4334
|
-
})
|
|
4493
|
+
return self.received(evs ? evs.reverse() : null);
|
|
4494
|
+
}).finally(function() {
|
|
4495
|
+
self.setBusy(false);
|
|
4496
|
+
});
|
|
4335
4497
|
} else {
|
|
4336
4498
|
this.next = pos;
|
|
4337
4499
|
return this.getEvents(pos, 0).then(function(evs) {
|
|
4338
4500
|
self.setBusy(false);
|
|
4339
4501
|
return self.received(evs);
|
|
4502
|
+
}).finally(function() {
|
|
4503
|
+
self.setBusy(false);
|
|
4340
4504
|
});
|
|
4341
4505
|
}
|
|
4342
4506
|
},
|
|
@@ -4346,31 +4510,30 @@ libVES.Watch.prototype = {
|
|
|
4346
4510
|
received: function(evs) {
|
|
4347
4511
|
var self = this;
|
|
4348
4512
|
var p;
|
|
4349
|
-
|
|
4513
|
+
if (!evs) return null;
|
|
4514
|
+
if (evs.length) return evs.reduce(function(v, ev) {
|
|
4350
4515
|
if (self.active()) try {
|
|
4351
|
-
self.eventfn(
|
|
4516
|
+
self.eventfn(ev, self);
|
|
4352
4517
|
} catch(e) {
|
|
4353
4518
|
console.log(e);
|
|
4354
4519
|
}
|
|
4355
|
-
return
|
|
4520
|
+
return ev;
|
|
4356
4521
|
}, null).getId().then(function(id) {
|
|
4357
4522
|
self.next = id + 1;
|
|
4523
|
+
return self.request();
|
|
4358
4524
|
});
|
|
4359
4525
|
else {
|
|
4360
|
-
p = Promise.resolve(null);
|
|
4361
4526
|
if (this.state == 'read') this.setState('poll');
|
|
4527
|
+
return self.request(), true;
|
|
4362
4528
|
}
|
|
4363
|
-
return p.then(function() {
|
|
4364
|
-
return self.request();
|
|
4365
|
-
});
|
|
4366
4529
|
},
|
|
4367
4530
|
request: function() {
|
|
4368
|
-
if (this.busy || !this.active()) return;
|
|
4531
|
+
if (this.busy || !this.active()) return true;
|
|
4369
4532
|
var self = this;
|
|
4370
4533
|
self.setBusy(true);
|
|
4371
4534
|
return self.getEvents(self.next, 0, (self.state == 'poll')).then(function(evs) {
|
|
4372
4535
|
self.setBusy(false);
|
|
4373
|
-
self.received(evs);
|
|
4536
|
+
return self.received(evs);
|
|
4374
4537
|
}).catch(function(e) {
|
|
4375
4538
|
self.setBusy(false);
|
|
4376
4539
|
if (self.errorfn) try {
|
|
@@ -4393,6 +4556,761 @@ libVES.Watch.prototype = {
|
|
|
4393
4556
|
this.setState(this.busy ? 'stop' : 'idle');
|
|
4394
4557
|
}
|
|
4395
4558
|
};
|
|
4396
|
-
|
|
4559
|
+
|
|
4560
|
+
|
|
4561
|
+
|
|
4562
|
+
libVES.subtle = function(optns) {
|
|
4563
|
+
if (!(optns instanceof Object)) {
|
|
4564
|
+
let uri = String(optns);
|
|
4565
|
+
optns = uri.includes('/') ? libVES.Vault.toRef(uri) : {domain: uri};
|
|
4566
|
+
}
|
|
4567
|
+
return new libVES(optns).subtle();
|
|
4568
|
+
};
|
|
4569
|
+
|
|
4570
|
+
libVES.prototype.subtle = function(ref) {
|
|
4571
|
+
return new libVES.Vault((ref || this), this);
|
|
4572
|
+
};
|
|
4573
|
+
|
|
4574
|
+
libVES.EventTarget = class extends EventTarget {
|
|
4575
|
+
watchFields() {
|
|
4576
|
+
return {vaultKey: {id: true, user: {id: true, email: true}, externals: {domain: true, externalId: true}}, vaultItem: {id: true, type: true, deleted: true, vaultKey: {id: true, type: true, externals: {domain: true, externalId: true}, user: {id: true, email: true}}, file: {externals: {domain: true, externalId: true}, creator: true}}, authorSession: {id: true, vaultKey: {id: true, type: true, externals: {domain: true, externalId: true}}, domain: true, user: {email: true}, remote: true, userAgent: true}, session: {id: true, vaultKey: {id: true}, user: {id: true}, remote: true, userAgent: true}};
|
|
4577
|
+
}
|
|
4578
|
+
|
|
4579
|
+
dispatchEvent(ev) {
|
|
4580
|
+
if (!ev) return;
|
|
4581
|
+
super.dispatchEvent(ev);
|
|
4582
|
+
if (this['on' + ev.type]) try { this['on' + ev.type](ev) } catch (er) { console.log(er); }
|
|
4583
|
+
}
|
|
4584
|
+
|
|
4585
|
+
start(optns) {
|
|
4586
|
+
if (!this.watch) {
|
|
4587
|
+
let tr = this._eventTracker();
|
|
4588
|
+
if (optns === false) optns = {replay: true};
|
|
4589
|
+
else if (optns != null && !isNaN(optns)) optns = {startEvent: Number(optns)};
|
|
4590
|
+
else if (!(optns instanceof Object)) optns = {};
|
|
4591
|
+
if (optns.startEvent == null) optns.startEvent = -1;
|
|
4592
|
+
this.watch = this.createWatch(optns);
|
|
4593
|
+
this.watch.eventfn = (ev) => (this.eventClear = this.eventClear.then(() => tr._event(ev).then((ev) => this.dispatchEvent(ev)).catch((er) => console.log(er))));
|
|
4594
|
+
this.eventClear = optns.replay ? this.replay((optns.replay instanceof Object) ? optns.replay : optns).then((evs) => Promise.all(evs.map((ev) => this.dispatchEvent(ev)))) : Promise.resolve();
|
|
4595
|
+
return this.watch.start(optns.startEvent).then((v) => (v || this.badauth().then(() => this.watch.start(startEvent)))).catch((er) => {
|
|
4596
|
+
this.watch = null;
|
|
4597
|
+
throw er;
|
|
4598
|
+
});
|
|
4599
|
+
} else throw new libVES.Error.InvalidValue('The watch is already started');
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4602
|
+
stop() {
|
|
4603
|
+
if (this.watch) return Promise.resolve(this.watch.stop()).then(() => this.eventClear).then(() => true).finally(() => this.watch = null);
|
|
4604
|
+
return Promise.resolve(null);
|
|
4605
|
+
}
|
|
4606
|
+
|
|
4607
|
+
events(optns) {
|
|
4608
|
+
let tr = this._eventTracker();
|
|
4609
|
+
return this.createWatch(optns).getEvents(0, 0).then((evs) => (evs ? evs.reduce((res, ev) => res.then((res) => tr._event(ev, false).then((ev) => ((ev && res.push(ev)), res))), Promise.resolve([])) : this.badauth().then(() => this.events())));
|
|
4610
|
+
}
|
|
4611
|
+
|
|
4612
|
+
toJSON() {
|
|
4613
|
+
return this.uri();
|
|
4614
|
+
}
|
|
4615
|
+
};
|
|
4616
|
+
|
|
4617
|
+
libVES.Vault = class extends libVES.EventTarget {
|
|
4618
|
+
constructor(ref, ves, fields) {
|
|
4619
|
+
super();
|
|
4620
|
+
this.init(libVES.Vault.toRef(ref, ves), ves, fields);
|
|
4621
|
+
}
|
|
4622
|
+
|
|
4623
|
+
init(ref, ves, fields) {
|
|
4624
|
+
fields ||= {};
|
|
4625
|
+
if (ref.externalId) fields.externals = [{domain: (this.domain = String(ref.domain)), externalId: (this.externalId = String(ref.externalId))}];
|
|
4626
|
+
this.email = ref.email || '';
|
|
4627
|
+
if (ref.email) fields.user = {email: this.email};
|
|
4628
|
+
if (ref.version) this.version = fields.id = Number(ref.version);
|
|
4629
|
+
if (!fields.id) fields.type = this.externalId ? 'secondary' : 'current';
|
|
4630
|
+
this.vaultKey = new libVES.VaultKey(fields, ves);
|
|
4631
|
+
delete(this.admin);
|
|
4632
|
+
};
|
|
4633
|
+
|
|
4634
|
+
item(ref) {
|
|
4635
|
+
return new libVES.Item(ref, this);
|
|
4636
|
+
};
|
|
4637
|
+
|
|
4638
|
+
vault(ref) {
|
|
4639
|
+
if (!ref) return null;
|
|
4640
|
+
return new libVES.Vault(ref, this.vaultKey.VES);
|
|
4641
|
+
}
|
|
4642
|
+
|
|
4643
|
+
entries(optns) {
|
|
4644
|
+
const flds = {encData: true, vaultItem: {type: true, file: {externals: true, creator: {id: true, email: true}}, deleted: true, vaultKey: {type: true, externals: true, user: true}, type: true, meta: true}};
|
|
4645
|
+
const getfn = () => this.vaultKey.getField('vaultEntries', flds, true).then((data) => libVES.Util.fillUndefs(data, flds));
|
|
4646
|
+
if (!this._entriesCache) (this._entriesCache = getfn().then((entries) => (entries || this.badauth().then(getfn)))).catch(() => null).finally(() => this._entriesCache = null);
|
|
4647
|
+
return this._entriesCache;
|
|
4648
|
+
};
|
|
4649
|
+
|
|
4650
|
+
objects(optns) {
|
|
4651
|
+
let found = {items: {}, vaults: {}};
|
|
4652
|
+
return this.entries(optns).then((entries) => Promise.all((entries || []).map((entry) => {
|
|
4653
|
+
const ext = entry.vaultItem?.file?.externals?.[0];
|
|
4654
|
+
if (ext) {
|
|
4655
|
+
if (entry.vaultItem.deleted) return null;
|
|
4656
|
+
let d = (found.items[ext.domain] ||= {});
|
|
4657
|
+
return d[ext.externalId] ? null : (d[ext.externalId] = new libVES.Item(ext, this, entry.vaultItem));
|
|
4658
|
+
}
|
|
4659
|
+
const vkey = entry.vaultItem?.vaultKey;
|
|
4660
|
+
const kext = vkey?.externals?.[0];
|
|
4661
|
+
if (kext && vkey.type == 'secondary' && entry.vaultItem.type == 'password') {
|
|
4662
|
+
let d = (found.vaults[kext.domain] ||= {});
|
|
4663
|
+
return d[kext.externalId] ? null : (d[kext.externalId] = new libVES.Vault(kext, this.vaultKey.VES, vkey));
|
|
4664
|
+
}
|
|
4665
|
+
}))).then((objs) => objs.filter((obj) => obj));
|
|
4666
|
+
};
|
|
4667
|
+
|
|
4668
|
+
items(optns) {
|
|
4669
|
+
return this.objects(optns).then((objs) => objs.filter((obj) => (obj instanceof libVES.Item)));
|
|
4670
|
+
}
|
|
4671
|
+
|
|
4672
|
+
vaults(optns) {
|
|
4673
|
+
return this.objects(optns).then((objs) => objs.filter((obj) => (obj instanceof libVES.Vault)));
|
|
4674
|
+
}
|
|
4675
|
+
|
|
4676
|
+
reauth() {
|
|
4677
|
+
clearTimeout(this.refreshTmout);
|
|
4678
|
+
return this.vaultKey.loadFields({encSessionToken: true}, true, {token: ''}).then((flds) => this.vaultKey.setFields(flds)).then(() => this.vaultKey.getSessionToken()).then((tk) => {
|
|
4679
|
+
this.vaultKey.VES.token = tk;
|
|
4680
|
+
return this;
|
|
4681
|
+
});
|
|
4682
|
+
}
|
|
4683
|
+
|
|
4684
|
+
_setunlock(reauth) {
|
|
4685
|
+
this.current = true;
|
|
4686
|
+
this.owner = this.externalId?.[0] != '!';
|
|
4687
|
+
this.lock(600);
|
|
4688
|
+
let rf;
|
|
4689
|
+
if (reauth !== false && this.externalId) (rf = (tmout) => {
|
|
4690
|
+
this.refreshTmout = setTimeout(() => {
|
|
4691
|
+
this.reauth().then(() => rf()).catch((er) => {
|
|
4692
|
+
console.log(er);
|
|
4693
|
+
rf(60000);
|
|
4694
|
+
});
|
|
4695
|
+
}, (tmout || 14400000));
|
|
4696
|
+
})();
|
|
4697
|
+
if (this.appUrl === undefined) try {
|
|
4698
|
+
this.appUrl = document.location.origin;
|
|
4699
|
+
} catch(er) {}
|
|
4700
|
+
return this;
|
|
4701
|
+
}
|
|
4702
|
+
|
|
4703
|
+
unlock(optns) {
|
|
4704
|
+
if (this.lockInProgress) return this.lock().then(() => this.unlock(optns));
|
|
4705
|
+
if (optns && !(optns instanceof Object)) optns = libVES.Vault.toRef(optns, this.vaultKey.VES);
|
|
4706
|
+
if (optns?.veskey) return this.vaultKey.VES.logout().then(() => {
|
|
4707
|
+
let ves = new libVES(optns);
|
|
4708
|
+
delete(ves.veskey);
|
|
4709
|
+
return ((reauth) => ves.unlock(String(optns.veskey)).then(() => this.init(ves, ves)).then(() => this._setunlock(reauth)))(!this.vaultKey.VES.token);
|
|
4710
|
+
});
|
|
4711
|
+
return this.vaultKey.VES.unlock().catch((er) => {
|
|
4712
|
+
let mode = optns?.mode || 'delegate';
|
|
4713
|
+
switch (mode) {
|
|
4714
|
+
case 'delegate': return this.vaultKey.VES.delegate(optns).then((ves) => this.init(ves, ves));
|
|
4715
|
+
case 'flow': return this.vaultKey.VES.flow(true, optns).then((ves) => this.init(ves, ves));
|
|
4716
|
+
case 'veskey': throw new libVES.Error.InvalidValue('No veskey provided');
|
|
4717
|
+
default: throw new libVES.Error.InvalidValue('Unknown unlock mode: ' + mode + ', expected: delegate|flow');
|
|
4718
|
+
}
|
|
4719
|
+
}).then(() => this._setunlock());
|
|
4720
|
+
}
|
|
4721
|
+
|
|
4722
|
+
unlocked(optns) {
|
|
4723
|
+
return this.vaultKey.VES.unlock().catch((er) => {
|
|
4724
|
+
if (optns?.mode != 'flow') throw er;
|
|
4725
|
+
return this.vaultKey.VES.flow(false, optns).then((ves) => this.init(ves, ves)).then(() => this._setunlock());
|
|
4726
|
+
}).then(() => true).catch((er) => false);
|
|
4727
|
+
}
|
|
4728
|
+
|
|
4729
|
+
anonymous(optns) {
|
|
4730
|
+
if (!(optns instanceof Object)) {
|
|
4731
|
+
if (optns && typeof(optns) == 'string') optns = {veskey: optns};
|
|
4732
|
+
else optns = {};
|
|
4733
|
+
}
|
|
4734
|
+
if (!optns.veskey) return Promise.reject(libVES.Error.InvalidValue('Required: veskey'));
|
|
4735
|
+
if (!this.vaultKey.VES.domain) return Promise.reject(libVES.Error.InvalidValue('Cannot create an anonymous vault without a VES domain'));
|
|
4736
|
+
this.vaultKey.VES.logout();
|
|
4737
|
+
return (optns.externalId ? Promise.resolve(this.vaultKey.VES.externalId = optns.externalId) : crypto.subtle.digest('sha-256', libVES.Util.StringToByteArray('libVES.subtle\0' + this.vaultKey.VES.domain + '\0' + optns.veskey)).then((hash) => {
|
|
4738
|
+
const hex = '0123456789abcdef';
|
|
4739
|
+
let xid = new Uint8Array(hash).reduce(((v, e) => v + hex[e >> 4] + hex[e & 0x0f]), '!');
|
|
4740
|
+
this.vaultKey.VES.externalId = xid;
|
|
4741
|
+
})).then(() => this.vaultKey.VES.unlock(optns.veskey).catch((er) => {
|
|
4742
|
+
if (er?.code == 'NotFound') return this.vaultKey.VES.setAnonymousKey(optns.veskey, optns);
|
|
4743
|
+
else throw er;
|
|
4744
|
+
})).then(() => this.init(this.vaultKey.VES, this.vaultKey.VES)).then(() => this._setunlock());
|
|
4745
|
+
}
|
|
4746
|
+
|
|
4747
|
+
lock(tmout) {
|
|
4748
|
+
this.lockInProgress = false;
|
|
4749
|
+
clearTimeout(this.lockTmout);
|
|
4750
|
+
this.lockTmout = null;
|
|
4751
|
+
if (tmout > 0) {
|
|
4752
|
+
if (tmout > 3600) tmout = 3600;
|
|
4753
|
+
this.lockTmout = setTimeout(() => {
|
|
4754
|
+
this.lockInProgress = true;
|
|
4755
|
+
this.dispatchEvent(new libVES.CustomEvent('authexpire', {detail: {vault: this}}));
|
|
4756
|
+
if (this.lockInProgress) this.lock();
|
|
4757
|
+
}, tmout * 1000);
|
|
4758
|
+
return Promise.resolve(true);
|
|
4759
|
+
}
|
|
4760
|
+
clearTimeout(this.refreshTmout);
|
|
4761
|
+
this.refreshTmout = null;
|
|
4762
|
+
this.stop();
|
|
4763
|
+
return this.vaultKey.VES.logout();
|
|
4764
|
+
}
|
|
4765
|
+
|
|
4766
|
+
random() {
|
|
4767
|
+
return this.vaultKey.VES.generateVESkey();
|
|
4768
|
+
}
|
|
4769
|
+
|
|
4770
|
+
static toRef(value, ves) {
|
|
4771
|
+
switch (typeof(value)) {
|
|
4772
|
+
case 'object':
|
|
4773
|
+
return value;
|
|
4774
|
+
case 'number':
|
|
4775
|
+
value = String(value);
|
|
4776
|
+
case 'string':
|
|
4777
|
+
let uri = new URL(value, "ves://" + (ves && ves.domain ? ves.domain : ''));
|
|
4778
|
+
if (uri.protocol != 'ves:') throw new libVES.Error.InvalidValue("Invalid schema: '" + uri.protocol + "', expected 'ves:'");
|
|
4779
|
+
let p = uri.pathname.split('/');
|
|
4780
|
+
let id = p.length > 1 ? decodeURIComponent(p[1]) : '';
|
|
4781
|
+
let ref = uri.host ? {domain: uri.host, externalId: id} : {version: Number(id)};
|
|
4782
|
+
if (p[2] != null) ref.email = decodeURIComponent(p[2]);
|
|
4783
|
+
if (uri.password) ref.veskey = uri.password;
|
|
4784
|
+
return ref;
|
|
4785
|
+
}
|
|
4786
|
+
};
|
|
4787
|
+
|
|
4788
|
+
static toRefs(refs, ves, owner) {
|
|
4789
|
+
if (!refs) return [];
|
|
4790
|
+
if (!(refs instanceof Array)) refs = [refs];
|
|
4791
|
+
refs = refs.map((ref) => libVES.Vault.toRef(ref, ves)).filter((ref) => ref);
|
|
4792
|
+
if (owner) {
|
|
4793
|
+
if (ves.externalId) refs.push({domain: ves.domain, externalId: ves.externalId});
|
|
4794
|
+
else if (ves.user) refs.push({email: ves.user});
|
|
4795
|
+
else throw new libVES.Error.Unauthorized('The vault is locked');
|
|
4796
|
+
}
|
|
4797
|
+
return refs;
|
|
4798
|
+
}
|
|
4799
|
+
|
|
4800
|
+
static toUri(ref, short) {
|
|
4801
|
+
if (ref.externalId && short) return (ref.domain == short ? '' : '//' + encodeURIComponent(ref.domain) + '/') + encodeURIComponent(ref.externalId).replaceAll('%40', '@');
|
|
4802
|
+
let uri = ref.externalId ? "ves://" + encodeURIComponent(ref.domain) + "/" + encodeURIComponent(ref.externalId) : "ves://" + (ref.version ? "/" + String(Number(ref.version)) : encodeURIComponent(ref.domain ?? '') + "/");
|
|
4803
|
+
if (ref.email != null) uri += '/' + encodeURIComponent(ref.email);
|
|
4804
|
+
return uri;
|
|
4805
|
+
}
|
|
4806
|
+
|
|
4807
|
+
uri() {
|
|
4808
|
+
if (!this.externalId && !this.version && !this.email) return null;
|
|
4809
|
+
return libVES.Vault.toUri(this);
|
|
4810
|
+
}
|
|
4811
|
+
|
|
4812
|
+
short() {
|
|
4813
|
+
return libVES.Vault.toUri(this, this.vaultKey.VES.domain);
|
|
4814
|
+
}
|
|
4815
|
+
|
|
4816
|
+
badauth() {
|
|
4817
|
+
const ves = this.vaultKey.VES;
|
|
4818
|
+
if (!this.externalId || (this.externalId == ves.externalId && this.domain == ves.domain)) return Promise.reject(new libVES.Error.InvalidKey('Not authorized for this key'));
|
|
4819
|
+
return this.vaultKey.getFields({encSessionToken: true, type: true, algo: true, publicKey: true, privateKey: true, vaultItems: {type: true, vaultEntries: {vaultKey : {id: true}, encData: true}, meta: true}}).then(() => {
|
|
4820
|
+
const ves2 = new libVES({domain: this.domain, externalId: this.externalId});
|
|
4821
|
+
ves2.vaultKey = Promise.resolve(this.vaultKey);
|
|
4822
|
+
ves2.unlockedKeys = ves.unlockedKeys;
|
|
4823
|
+
ves2.pendingKeys = ves.pendingKeys;
|
|
4824
|
+
this.vaultKey.VES = ves2;
|
|
4825
|
+
return ves2.unlock();
|
|
4826
|
+
});
|
|
4827
|
+
}
|
|
4828
|
+
|
|
4829
|
+
createWatch() {
|
|
4830
|
+
let w = new libVES.Watch(this.vaultKey);
|
|
4831
|
+
w.fields = {vaultItem: {id: true, type: true, deleted: true, vaultKey: {id: true, type: true, algo: true, publicKey: true, externals: {domain: true, externalId: true}, user: {id: true, email: true}}, file: {externals: {domain: true, externalId: true}, creator: true}, meta: true}, authorSession: {vaultKey: {id: true, externals: {domain: true, externalId: true}, user: {email: true}, type: true}, domain: true, user: {email: true}, remote: true, userAgent: true}, session: {id: true, remote: true, userAgent: true, vaultKey: {id: true}, user: {id: true}}};
|
|
4832
|
+
return w;
|
|
4833
|
+
}
|
|
4834
|
+
|
|
4835
|
+
replay(optns) {
|
|
4836
|
+
return this.objects(optns).then((objs) => Promise.all(objs.map((obj) => {
|
|
4837
|
+
if (obj instanceof libVES.Item) return new libVES.CustomEvent('itemadd', {detail: {replay: true, item: obj, share: this}});
|
|
4838
|
+
else if (obj instanceof libVES.Vault) return new libVES.CustomEvent('vaultadd', {detail: {replay: true, vault: obj, share: this}});
|
|
4839
|
+
})));
|
|
4840
|
+
}
|
|
4841
|
+
|
|
4842
|
+
password() {
|
|
4843
|
+
return this.vaultKey.getVaultItems().then((vitems) => {
|
|
4844
|
+
if (!vitems) return this.badauth().then(() => this.password());
|
|
4845
|
+
return vitems.reduce((p, vitem) => p.catch((e) => vitem.getType().then((type) => (type == 'password' ? vitem.getId().then((id) => this.item({version: id})) : Promise.reject(e)))), Promise.reject(new libVES.Error.NotFound('No password item found')));
|
|
4846
|
+
});
|
|
4847
|
+
}
|
|
4848
|
+
|
|
4849
|
+
verify() {
|
|
4850
|
+
if (this.current !== undefined) return Promise.resolve(this);
|
|
4851
|
+
return this.vaultKey.VES.usersToKeys([(this.externalId ? {domain: this.domain, externalId: this.externalId} : this.email)]).then((vkeys) => Promise.all(vkeys.map((vkey) => vkey.getFields(vkey.id ? {id: true, type: true} : {type: true}))).then((flds) => flds.reduce((res, fld, idx) => {
|
|
4852
|
+
if (res) return res;
|
|
4853
|
+
if (this.version) return this.version == fld.id ? vkeys[idx] : null;
|
|
4854
|
+
switch (fld.type) {
|
|
4855
|
+
case 'secondary': case 'current': case 'temp': return vkeys[idx];
|
|
4856
|
+
}
|
|
4857
|
+
}, null))).then((vkey) => {
|
|
4858
|
+
if (!vkey) throw new libVES.Error.NotFound('Cannot find or create a matching key');
|
|
4859
|
+
return vkey.getType().then((type) => {
|
|
4860
|
+
this.current = (type == 'current' || type == 'secondary');
|
|
4861
|
+
this.owner = (this.externalId != null && this.externalId == vkey.VES.externalId && this.domain == vkey.VES.domain) || (!!this.email && this.email == vkey.VES.email);
|
|
4862
|
+
this.vaultKey = vkey;
|
|
4863
|
+
return this;
|
|
4864
|
+
});
|
|
4865
|
+
});
|
|
4866
|
+
}
|
|
4867
|
+
|
|
4868
|
+
_eventTracker() {
|
|
4869
|
+
return new libVES.EventTracker(this);
|
|
4870
|
+
}
|
|
4871
|
+
|
|
4872
|
+
toAppRefs(refs, ves, owner) {
|
|
4873
|
+
let shares = libVES.Vault.toRefs(refs, ves, owner);
|
|
4874
|
+
if (this.appUrl !== undefined) shares.map((share) => {
|
|
4875
|
+
if (share.appUrl === undefined) share.appUrl = this.appUrl;
|
|
4876
|
+
});
|
|
4877
|
+
return shares;
|
|
4878
|
+
}
|
|
4879
|
+
|
|
4880
|
+
toString() {
|
|
4881
|
+
return 'libVES.Vault(' + (this.uri() ?? '[pending]') + ')';
|
|
4882
|
+
}
|
|
4883
|
+
|
|
4884
|
+
};
|
|
4885
|
+
|
|
4886
|
+
libVES.Author = class {
|
|
4887
|
+
constructor(sess, ves) {
|
|
4888
|
+
this.sessid = sess.id;
|
|
4889
|
+
if (sess.vaultKey?.externals?.[0]) this.vault = new libVES.Vault(sess.vaultKey.externals[0], ves);
|
|
4890
|
+
else if (sess.user?.email) this.vault = new libVES.Vault({email: sess.user.email}, ves);
|
|
4891
|
+
this.remote = sess.remote;
|
|
4892
|
+
this.userAgent = sess.userAgent;
|
|
4893
|
+
}
|
|
4894
|
+
toString() {
|
|
4895
|
+
return 'libVES.Author(' + (this.sessid ?? '') + ')';
|
|
4896
|
+
}
|
|
4897
|
+
toJSON() {
|
|
4898
|
+
return this.sessid;
|
|
4899
|
+
}
|
|
4900
|
+
};
|
|
4901
|
+
|
|
4902
|
+
libVES.CustomEvent = class extends CustomEvent {
|
|
4903
|
+
toString() {
|
|
4904
|
+
return 'libVES.CustomEvent(' + this.type + (this.detail?.id ? '[' + this.detail.id + ']' : '') + (this.detail?.at ? ' @' + this.detail.at : '') + ')';
|
|
4905
|
+
}
|
|
4906
|
+
toJSON() {
|
|
4907
|
+
return this.detail?.id;
|
|
4908
|
+
}
|
|
4909
|
+
};
|
|
4910
|
+
|
|
4911
|
+
libVES.EventTracker = class {
|
|
4912
|
+
constructor(vault, share) {
|
|
4913
|
+
this.vault = vault;
|
|
4914
|
+
this.share = share;
|
|
4915
|
+
this.items = {};
|
|
4916
|
+
}
|
|
4917
|
+
|
|
4918
|
+
_event(e, attn) {
|
|
4919
|
+
const event = (type, detail) => {
|
|
4920
|
+
detail.event = e;
|
|
4921
|
+
return e.getFields({id: true, recordedAt: true, authorSession: {vaultKey: {id: true, externals: {domain: true, externalId: true}, user: {email: true}}, user: {email: true}, domain: true, remote: true, userAgent: true}}).then((flds) => {
|
|
4922
|
+
detail.id = flds?.id;
|
|
4923
|
+
if (flds?.recordedAt) detail.at = new Date(flds.recordedAt);
|
|
4924
|
+
detail.author = new libVES.Author((flds?.authorSession ?? {}), this.vault.vaultKey.VES);
|
|
4925
|
+
}).catch(() => null).then(() => new libVES.CustomEvent(type, {detail: detail}));
|
|
4926
|
+
}
|
|
4927
|
+
return e.getType().then((type) => {
|
|
4928
|
+
const itemfn = (ac, attn, sh) => e.getVaultItem().then((vitem) => vitem.getType().then((itype) => {
|
|
4929
|
+
switch (itype) {
|
|
4930
|
+
case 'string': case 'file':
|
|
4931
|
+
return vitem.getFields({id: true, file: {externals: {domain: true, externalId: true}}, deleted: true, type: true, meta: true}).then((flds) => {
|
|
4932
|
+
let ext = flds?.file?.externals?.[0];
|
|
4933
|
+
if (!ext) return null;
|
|
4934
|
+
let item = new libVES.Item({domain: ext.domain, externalId: ext.externalId, version: flds.id}, this.vault, flds);
|
|
4935
|
+
let ids = (this.items[item.uri()] ||= []);
|
|
4936
|
+
let idx = ids.indexOf(flds.id);
|
|
4937
|
+
if (idx < 0 && (flds.deleted === false || (ac == 'create' || ac == 'add'))) ids.unshift(flds.id), idx = 0;
|
|
4938
|
+
return event((idx == 0 ? '' : 'old') + 'item' + ac, {item: item, share: sh});
|
|
4939
|
+
});
|
|
4940
|
+
case 'password':
|
|
4941
|
+
return vitem.getFields({vaultKey: {type: true, externals: {domain: true, externalId: true}}}).then((flds) => {
|
|
4942
|
+
switch (flds?.vaultKey?.type) {
|
|
4943
|
+
case 'secondary':
|
|
4944
|
+
return event('vault' + ac, {vault: this.vault.vault(flds.vaultKey.externals?.[0]), share: sh});
|
|
4945
|
+
default:
|
|
4946
|
+
if (attn) return vitem.getVaultKey().then((vkey) => this.vault.vaultKey.VES.attnVaultKeys([vkey])).catch((e) => console.log(e)).then(() => null);
|
|
4947
|
+
}
|
|
4948
|
+
});
|
|
4949
|
+
}
|
|
4950
|
+
}));
|
|
4951
|
+
const sharefn = () => (this.share ? e.getVaultKey().then((vkey) => vkey.getFields({id: true, type: true, externals: {domain: true, externalId: true}, user: {id: true, email: true}}).then((flds) => {
|
|
4952
|
+
let f = flds?.externals?.[0] ? flds.externals[0] : (flds?.user?.email ? {email: flds.user.email} : {});
|
|
4953
|
+
f.version = flds.id;
|
|
4954
|
+
let vault = this.vault.vault(f);
|
|
4955
|
+
vault.current = (f.externals && flds.type == 'secondary') || (f.email && flds.type == 'current');
|
|
4956
|
+
return vault;
|
|
4957
|
+
})) : Promise.resolve(this.vault));
|
|
4958
|
+
switch (type) {
|
|
4959
|
+
case 'vaultEntry.deleted':
|
|
4960
|
+
return sharefn().then((sh) => itemfn('remove', false, sh));
|
|
4961
|
+
case 'vaultEntry.created':
|
|
4962
|
+
return sharefn().then((sh) => itemfn('add', attn !== false, sh));
|
|
4963
|
+
case 'vaultItem.deleted':
|
|
4964
|
+
return itemfn('delete');
|
|
4965
|
+
case 'vaultItem.created':
|
|
4966
|
+
return itemfn('create');
|
|
4967
|
+
case 'vaultItem.listening':
|
|
4968
|
+
case 'vaultKey.listening':
|
|
4969
|
+
return itemfn('change', attn !== false);
|
|
4970
|
+
case 'session.created':
|
|
4971
|
+
return e.getFields({session: {id: true, remote: true, userAgent: true, vaultKey: {id: true}, user: {id: true}}}).then((flds) => {
|
|
4972
|
+
if (!flds?.session) return null;
|
|
4973
|
+
let ses = new libVES.Author(flds.session, this.vault.vaultKey.VES);
|
|
4974
|
+
ses.vault = this.vault;
|
|
4975
|
+
return event('sessioncreate', {vault: this.vault, session: ses});
|
|
4976
|
+
});
|
|
4977
|
+
}
|
|
4978
|
+
}).catch((er) => (console.log(er), event('error', {error: er})));
|
|
4979
|
+
}
|
|
4980
|
+
};
|
|
4981
|
+
|
|
4982
|
+
|
|
4983
|
+
|
|
4984
|
+
libVES.Item = class extends libVES.EventTarget {
|
|
4985
|
+
constructor(ref, vault, fields) {
|
|
4986
|
+
const ves = vault.vaultKey.VES;
|
|
4987
|
+
super();
|
|
4988
|
+
if (ref == null || typeof(ref) == 'function') {
|
|
4989
|
+
this.provisional = {share: [vault], ref: (ref || libVES.Item.newRef)};
|
|
4990
|
+
} else {
|
|
4991
|
+
ref = libVES.Vault.toRef(ref, ves);
|
|
4992
|
+
if ((!ref.domain || !ref.externalId) && !ref.version) throw new libVES.Error.InvalidValue('Bad item reference');
|
|
4993
|
+
this.domain = ref.domain;
|
|
4994
|
+
this.externalId = ref.externalId;
|
|
4995
|
+
this.version = ref.version || null;
|
|
4996
|
+
}
|
|
4997
|
+
this.vault = vault;
|
|
4998
|
+
this._vaultItem(ves, fields);
|
|
4999
|
+
};
|
|
5000
|
+
|
|
5001
|
+
static newRef() {
|
|
5002
|
+
let d = new Date();
|
|
5003
|
+
return ((d.getFullYear() * 100 + d.getMonth() + 1) * 100 + d.getDate()).toFixed(0) + '.' + (((d.getHours() + 100) * 100 + d.getMinutes()) * 100 + d.getSeconds() + d.getMilliseconds() / 1000).toFixed(3).slice(-10);
|
|
5004
|
+
}
|
|
5005
|
+
|
|
5006
|
+
_vaultItem(ves, fields) {
|
|
5007
|
+
if (this.vaultItem && this._entriesCache !== null) return this.vaultItem;
|
|
5008
|
+
ves ||= this.vaultItem.VES;
|
|
5009
|
+
if (!fields) {
|
|
5010
|
+
fields = this.externalId ? {file: {externals: [{domain: this.domain, externalId: this.externalId}]}} : {};
|
|
5011
|
+
if (this.version) fields.id = this.version;
|
|
5012
|
+
} else if (fields.vaultEntries) this._entriesCache = Promise.resolve(fields).finally(() => this._entriesCache = null);
|
|
5013
|
+
return this.vaultItem = new libVES.VaultItem(fields, ves);
|
|
5014
|
+
};
|
|
5015
|
+
|
|
5016
|
+
_entries() {
|
|
5017
|
+
if (this.provisional) return Promise.reject(new libVES.Error.NotFound('Not available for a provisional item'));
|
|
5018
|
+
if (this._entriesCache) return this._entriesCache;
|
|
5019
|
+
this._entriesCache = this._vaultItem().getFields({vaultEntries: {encData: true, vaultKey: {id: true, type: true, algo: true, privateKey: true, publicKey: true, user: {id: true, email: true}, externals: {domain: true, externalId: true}}}, file: {creator: {id: true}}, vaultKey: {user: {id: true}}, deleted: true}).then((flds) => {
|
|
5020
|
+
if (!flds?.vaultEntries) return Promise.reject(new libVES.Error.InvalidKey('Not authorized to access this item'));
|
|
5021
|
+
return flds;
|
|
5022
|
+
});
|
|
5023
|
+
this._entriesCache.catch((er) => null).finally(() => this._entriesCache = null);
|
|
5024
|
+
return this._entriesCache;
|
|
5025
|
+
};
|
|
5026
|
+
|
|
5027
|
+
_get() {
|
|
5028
|
+
return this._entries().then(() => this.vaultItem.get());
|
|
5029
|
+
};
|
|
5030
|
+
|
|
5031
|
+
_reset() {
|
|
5032
|
+
this._entriesCache = null;
|
|
5033
|
+
};
|
|
5034
|
+
|
|
5035
|
+
latest() {
|
|
5036
|
+
return this.externalId && this.version ? this.vault.item({domain: this.domain, externalId: this.externalId}) : this;
|
|
5037
|
+
};
|
|
5038
|
+
|
|
5039
|
+
get() {
|
|
5040
|
+
return this._get().then((val) => {
|
|
5041
|
+
if (typeof(val) != 'string') throw new libVES.Error.InvalidValue('The item value is not a string');
|
|
5042
|
+
return val;
|
|
5043
|
+
});
|
|
5044
|
+
};
|
|
5045
|
+
|
|
5046
|
+
put(value, shares) {
|
|
5047
|
+
if (value == null) return Promise.reject(new libVES.Error.InvalidValue('The item value cannot be empty'));
|
|
5048
|
+
let prref;
|
|
5049
|
+
return (shares ? Promise.resolve(this.vault.toAppRefs(shares, this.vaultItem.VES, true)) : this.share().then((shares) => {
|
|
5050
|
+
let owner = shares.reduce((cur, sh) => (cur || ((sh.owner && sh.externalId?.match(/@/)) ? sh : null)), null);
|
|
5051
|
+
if (owner && owner.uri() != this.vault.uri()) shares.push(this.vault.vault({domain: '.admin', externalId: owner.externalId}));
|
|
5052
|
+
return shares;
|
|
5053
|
+
}).catch((e) => {
|
|
5054
|
+
if (e && e.code == 'NotFound') return libVES.Vault.toRefs([], this.vaultItem.VES, true);
|
|
5055
|
+
throw e;
|
|
5056
|
+
})).then((shares) => {
|
|
5057
|
+
if (!this.provisional) return shares;
|
|
5058
|
+
prref = libVES.Vault.toRef(this.provisional.ref(), this.vaultItem.VES);
|
|
5059
|
+
if (!prref?.externalId) return Promise.reject(new libVES.Error.InvalidValue('Bad provisional reference generated by the supplied function'));
|
|
5060
|
+
return this.vaultItem.setFields({file: {externals: [prref]}}).then(() => shares);
|
|
5061
|
+
}).then((shares) => this.vaultItem.shareWith(shares, value)).then(() => {
|
|
5062
|
+
if (prref) {
|
|
5063
|
+
this.externalId = prref.externalId;
|
|
5064
|
+
this.domain = prref.domain;
|
|
5065
|
+
delete(this.provisional);
|
|
5066
|
+
}
|
|
5067
|
+
this.version = null;
|
|
5068
|
+
this._reset();
|
|
5069
|
+
return value;
|
|
5070
|
+
});
|
|
5071
|
+
};
|
|
5072
|
+
|
|
5073
|
+
cipher(optns, shares) {
|
|
5074
|
+
return this._get().then((val) => {
|
|
5075
|
+
if (!(val instanceof libVES.Cipher)) throw new libVES.Error.InvalidValue('The item value is not a cipher');
|
|
5076
|
+
return (shares ? this.share(shares) : Promise.resolve(null)).then(() => val);
|
|
5077
|
+
}).catch((e) => {
|
|
5078
|
+
if (e && e.code == 'NotFound') {
|
|
5079
|
+
let algo = optns?.algo || this.vaultItem.VES.cipherAlgo || 'AES256GCM1K';
|
|
5080
|
+
if (!libVES.Cipher[algo]) throw new libVES.Error.InvalidValue('Unsupported cipher: ' + algo);
|
|
5081
|
+
let ci = new libVES.Cipher[algo]();
|
|
5082
|
+
return this.put(ci, shares);
|
|
5083
|
+
}
|
|
5084
|
+
throw e;
|
|
5085
|
+
}).then((ci) => new libVES.ItemCipher(ci, this));
|
|
5086
|
+
};
|
|
5087
|
+
|
|
5088
|
+
json(val, shares) {
|
|
5089
|
+
if (val === undefined) return this.get().then((val) => JSON.parse(val));
|
|
5090
|
+
return this.put(JSON.stringify(val), shares).then(() => val);
|
|
5091
|
+
};
|
|
5092
|
+
|
|
5093
|
+
exists() {
|
|
5094
|
+
return this._entries().then((flds) => !flds?.deleted).catch((e) => {
|
|
5095
|
+
if (e?.code == 'NotFound') return false;
|
|
5096
|
+
if (e?.code == 'InvalidKey') return true;
|
|
5097
|
+
throw e;
|
|
5098
|
+
});
|
|
5099
|
+
};
|
|
5100
|
+
|
|
5101
|
+
_provShare(shares, del) {
|
|
5102
|
+
return new Promise((resolve, reject) => {
|
|
5103
|
+
let uris = libVES.Vault.toRefs(shares, this.vaultItem.VES).map((ref) => this.vault.vault(ref).uri());
|
|
5104
|
+
let prov = {};
|
|
5105
|
+
this.provisional.share.map((sh) => prov[sh.uri()] = sh);
|
|
5106
|
+
resolve(this.vaultItem.VES.usersToKeys(libVES.Vault.toRefs(uris.filter((uri) => !prov[uri]))));
|
|
5107
|
+
}).then((vkeys) => Promise.all(vkeys.map((vkey => vkey.getFields({user: {email: true}, externals: {domain: true, externalId: true}, type: true}).then((flds) => {
|
|
5108
|
+
let sh = new libVES.Vault((flds?.externals?.[0] ?? flds?.user?.email), this.vaultItem.VES, flds);
|
|
5109
|
+
if (sh) return sh.verify();
|
|
5110
|
+
}))))).then((shares) => shares.filter((sh) => sh)).then((shares) => {
|
|
5111
|
+
this.provisional.share = this.provisional.share.concat(this.vault.toAppRefs(shares));
|
|
5112
|
+
if (del) {
|
|
5113
|
+
let uris = {};
|
|
5114
|
+
shares.map((sh) => uris[sh.uri()] = sh);
|
|
5115
|
+
uris[this.vault.uri()] = this.vault;
|
|
5116
|
+
this.provisional.share = this.provisional.share.filter((sh) => uris[sh.uri()]);
|
|
5117
|
+
}
|
|
5118
|
+
return this.provisional.share;
|
|
5119
|
+
});
|
|
5120
|
+
}
|
|
5121
|
+
|
|
5122
|
+
share(shares) {
|
|
5123
|
+
if (this.provisional) {
|
|
5124
|
+
if (shares) return this._provShare(shares, true);
|
|
5125
|
+
return Promise.resolve(this.provisional.share);
|
|
5126
|
+
}
|
|
5127
|
+
return (shares ? (this._reset(), this.vaultItem.shareWith(this.vault.toAppRefs(shares, this.vaultItem.VES, true))) : Promise.resolve(null)).then(() => {
|
|
5128
|
+
let result = [];
|
|
5129
|
+
let found = {};
|
|
5130
|
+
let admins = {};
|
|
5131
|
+
return this._entries().then((flds) => flds.vaultEntries.map((entry) => {
|
|
5132
|
+
let vkey = entry?.vaultKey;
|
|
5133
|
+
let ref = vkey?.externals?.[0];
|
|
5134
|
+
if (!ref) {
|
|
5135
|
+
const email = vkey?.user?.email;
|
|
5136
|
+
ref = email ? {email: email} : {version: vkey?.id};
|
|
5137
|
+
}
|
|
5138
|
+
let vault = new libVES.Vault(ref, this.vaultItem.VES);
|
|
5139
|
+
let uri = vault.uri();
|
|
5140
|
+
if (!found[uri]) {
|
|
5141
|
+
result.push(found[uri] = vault);
|
|
5142
|
+
let uid = vkey?.user?.id;
|
|
5143
|
+
vault.owner = !!uid && uid == (flds.file?.creator?.id ?? flds.vaultKey?.user?.id);
|
|
5144
|
+
if (vault.domain == '.admin') admins[vault.externalId] = true;
|
|
5145
|
+
}
|
|
5146
|
+
switch (vkey?.type) {
|
|
5147
|
+
case 'current': case 'secondary':
|
|
5148
|
+
found[uri].current = true;
|
|
5149
|
+
break;
|
|
5150
|
+
default:
|
|
5151
|
+
vault.current = false;
|
|
5152
|
+
}
|
|
5153
|
+
})).then(() => {
|
|
5154
|
+
result.map((sh) => sh.admin = !!admins[sh.externalId]);
|
|
5155
|
+
return result;
|
|
5156
|
+
});
|
|
5157
|
+
});
|
|
5158
|
+
};
|
|
5159
|
+
|
|
5160
|
+
add(shares) {
|
|
5161
|
+
if (this.provisional) return this._provShare(shares, false).then(() => true);
|
|
5162
|
+
return this._entries().then(() => this.vaultItem.getShareVaultKeys()).then((vkeys) => {
|
|
5163
|
+
if (!vkeys) throw new libVES.Error.InvalidKey('Not authorized to share this item');
|
|
5164
|
+
if (!shares) return true;
|
|
5165
|
+
this.vault.toAppRefs(shares, this.vaultItem.VES).map((share) => vkeys.push(share));
|
|
5166
|
+
this._reset();
|
|
5167
|
+
return this.vaultItem.shareWith(vkeys);
|
|
5168
|
+
}).then(() => true);
|
|
5169
|
+
};
|
|
5170
|
+
|
|
5171
|
+
remove(shares) {
|
|
5172
|
+
shares = libVES.Vault.toRefs(shares, this.vaultItem.VES);
|
|
5173
|
+
if (!shares || !shares.length) return Promise.resolve(true);
|
|
5174
|
+
if (this.provisional) return new Promise((resolve, reject) => {
|
|
5175
|
+
let uris = {};
|
|
5176
|
+
shares.map((sh) => uris[this.vault.vault(sh).uri()] = true);
|
|
5177
|
+
this.provisional.share = this.provisional.share.filter((sh) => !uris[sh.uri()]);
|
|
5178
|
+
resolve(true);
|
|
5179
|
+
});
|
|
5180
|
+
return this._entries().then(() => this.vaultItem.unshareWith(shares)).then(() => (this._reset(), true));
|
|
5181
|
+
};
|
|
5182
|
+
|
|
5183
|
+
refuse() {
|
|
5184
|
+
return this.remove(this.vault);
|
|
5185
|
+
};
|
|
5186
|
+
|
|
5187
|
+
delete() {
|
|
5188
|
+
this._reset();
|
|
5189
|
+
return this.vaultItem.delete().then(() => true);
|
|
5190
|
+
}
|
|
5191
|
+
|
|
5192
|
+
badauth() {
|
|
5193
|
+
return (this.vaultItem.VES == this.vault.vaultKey.VES ? this.vault.badauth() : Promise.resolve(null)).then(() => this.vaultItem.VES = this.vault.vaultKey.VES);
|
|
5194
|
+
}
|
|
5195
|
+
|
|
5196
|
+
shareFor(share) {
|
|
5197
|
+
let uri = this.vault.vault(share).uri();
|
|
5198
|
+
return uri ? this.share().then((shares) => shares.reduce((res, sh) => (res ?? (sh.uri() == uri ? sh : null)), null)) : null;
|
|
5199
|
+
}
|
|
5200
|
+
|
|
5201
|
+
uri() {
|
|
5202
|
+
if (!this.externalId && !this.version) return null;
|
|
5203
|
+
return libVES.Vault.toUri(this);
|
|
5204
|
+
}
|
|
5205
|
+
|
|
5206
|
+
short() {
|
|
5207
|
+
if (!this.externalId) return null;
|
|
5208
|
+
return libVES.Vault.toUri(this, this.vaultItem.VES.domain);
|
|
5209
|
+
}
|
|
5210
|
+
|
|
5211
|
+
_eventTracker() {
|
|
5212
|
+
return new libVES.EventTracker(this.vault, true);
|
|
5213
|
+
}
|
|
5214
|
+
|
|
5215
|
+
createWatch() {
|
|
5216
|
+
let w = new libVES.Watch(this.vaultItem);
|
|
5217
|
+
w.fields = {vaultKey: {id: true, type: true, algo: true, publicKey: true, externals: {domain: true, externalId: true}, user: {id: true, email: true}}, vaultItem: {id: true, type: true, meta: true, deleted: true, vaultKey: {id: true, type: true, algo: true, publicKey: true, externals: {domain: true, externalId: true}, user: {id: true, email: true}}, file: {externals: {domain: true, externalId: true}, creator: true}}, authorSession: {vaultKey: {id: true, type: true, externals: {domain: true, externalId: true}}, domain: true, user: {email: true}, remote: true, userAgent: true}};
|
|
5218
|
+
return w;
|
|
5219
|
+
}
|
|
5220
|
+
|
|
5221
|
+
replay() {
|
|
5222
|
+
return this.share().then((vaults) => Promise.all(vaults.map((vault) => {
|
|
5223
|
+
if (this.externalId) return new libVES.CustomEvent('itemadd', {detail: {replay: true, item: this, share: vault}});
|
|
5224
|
+
else return new libVES.CustomEvent('vaultadd', {detail: {replay: true, vault: this.vault, share: vault}});
|
|
5225
|
+
})));
|
|
5226
|
+
}
|
|
5227
|
+
|
|
5228
|
+
readable() {
|
|
5229
|
+
return this._get().then(() => true).catch((er) => {
|
|
5230
|
+
switch (er?.code) {
|
|
5231
|
+
case 'NotFound':
|
|
5232
|
+
case 'InvalidKey': return false;
|
|
5233
|
+
default: throw er;
|
|
5234
|
+
}
|
|
5235
|
+
});
|
|
5236
|
+
}
|
|
5237
|
+
|
|
5238
|
+
writable() {
|
|
5239
|
+
return this.shareFor(this.vault).then((sh) => sh && (sh.owner || sh.admin)).catch((er) => {
|
|
5240
|
+
switch (er?.code) {
|
|
5241
|
+
case 'NotFound': return true;
|
|
5242
|
+
case 'InvalidKey': return false;
|
|
5243
|
+
default: throw er;
|
|
5244
|
+
}
|
|
5245
|
+
});
|
|
5246
|
+
}
|
|
5247
|
+
|
|
5248
|
+
toString() {
|
|
5249
|
+
return 'libVES.Item(' + (this.uri() ?? '[provisional]') + ')';
|
|
5250
|
+
}
|
|
5251
|
+
|
|
5252
|
+
};
|
|
5253
|
+
|
|
5254
|
+
libVES.ItemCipher = class {
|
|
5255
|
+
constructor(ci, item) {
|
|
5256
|
+
this.cipher = ci;
|
|
5257
|
+
this.item = item;
|
|
5258
|
+
}
|
|
5259
|
+
|
|
5260
|
+
meta(val) {
|
|
5261
|
+
if (val == null) return Promise.resolve(this.cipher.meta);
|
|
5262
|
+
if (!(val instanceof Object)) return Promise.reject(new libVES.Error.InvalidValue('Cipher metadata must be an object'));
|
|
5263
|
+
this.cipher.meta = val;
|
|
5264
|
+
return this.item.put(this.cipher).then(() => this.cipher.meta);
|
|
5265
|
+
}
|
|
5266
|
+
|
|
5267
|
+
reset(final) {
|
|
5268
|
+
if (final && !this.final) return Promise.resolve(null);
|
|
5269
|
+
this.final = false;
|
|
5270
|
+
return this.item.vaultItem.get().then((ci) => this.cipher = ci);
|
|
5271
|
+
}
|
|
5272
|
+
|
|
5273
|
+
encrypt(data, optns) {
|
|
5274
|
+
return this.reset(true).then(() => {
|
|
5275
|
+
this.final = optns?.final !== false;
|
|
5276
|
+
if (data instanceof Blob) {
|
|
5277
|
+
return data.arrayBuffer().then((buf) => this.cipher.encrypt(buf, this.final)).then((ctext) => {
|
|
5278
|
+
const op = {type: 'application/vnd.ves.encrypted'};
|
|
5279
|
+
if (optns) optns.type = data.type;
|
|
5280
|
+
if (data instanceof File) {
|
|
5281
|
+
if (optns) optns.name = data.name;
|
|
5282
|
+
return new File([ctext], this.item.externalId, op);
|
|
5283
|
+
}
|
|
5284
|
+
return new Blob([ctext], op);
|
|
5285
|
+
});
|
|
5286
|
+
} else if (data instanceof ArrayBuffer) return this.cipher.encrypt(data, this.final).then((ctext) => ctext.buffer);
|
|
5287
|
+
else if ((data instanceof Object) && (data.buffer instanceof ArrayBuffer)) return this.cipher.encrypt(data.buffer, this.final).then((ctext) => new data.constructor(ctext.buffer));
|
|
5288
|
+
else return this.cipher.encrypt(libVES.Util.StringToByteArray(String(data)), this.final).then((ctext) => libVES.Util.ByteArrayToB64(ctext));
|
|
5289
|
+
});
|
|
5290
|
+
}
|
|
5291
|
+
|
|
5292
|
+
decrypt(data, optns) {
|
|
5293
|
+
return this.reset(true).then(() => {
|
|
5294
|
+
this.final = optns?.final !== false;
|
|
5295
|
+
if (data instanceof Blob) {
|
|
5296
|
+
return data.arrayBuffer().then((buf) => this.cipher.decrypt(buf, this.final)).then((ctext) => {
|
|
5297
|
+
if (data instanceof File) return new File([ctext], (optns?.name || ''), optns);
|
|
5298
|
+
return new Blob([ctext], optns);
|
|
5299
|
+
});
|
|
5300
|
+
} else if (data instanceof ArrayBuffer) return this.cipher.decrypt(data, this.final).then((ctext) => ctext.buffer);
|
|
5301
|
+
else if ((data instanceof Object) && (data.buffer instanceof ArrayBuffer)) return this.cipher.decrypt(data.buffer, this.final).then((ctext) => new data.constructor(ctext.buffer));
|
|
5302
|
+
else return this.cipher.decrypt(libVES.Util.B64ToByteArray(String(data)), this.final).then((ctext) => libVES.Util.ByteArrayToString(ctext));
|
|
5303
|
+
});
|
|
5304
|
+
}
|
|
5305
|
+
|
|
5306
|
+
toString() {
|
|
5307
|
+
return 'libVES.ItemCipher(' + String(this.item) + ')';
|
|
5308
|
+
}
|
|
5309
|
+
|
|
5310
|
+
toJSON() {
|
|
5311
|
+
return this.item?.uri();
|
|
5312
|
+
}
|
|
5313
|
+
};
|
|
5314
|
+
libVES.version = '3.02';
|
|
4397
5315
|
|
|
4398
5316
|
module.exports = libVES;
|