cassproject 5.0.20 → 5.0.23
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/package.json +49 -52
- package/src/com/eduworks/ec/array/EcArray.js +1 -1
- package/src/com/eduworks/ec/array/EcAsyncHelper.js +1 -1
- package/src/com/eduworks/ec/array/EcObject.js +1 -1
- package/src/com/eduworks/ec/crypto/EcAes.js +1 -1
- package/src/com/eduworks/ec/crypto/EcAesCtrAsync.js +20 -22
- package/src/com/eduworks/ec/crypto/EcCrypto.js +8 -4
- package/src/com/eduworks/ec/crypto/EcPk.js +7 -7
- package/src/com/eduworks/ec/crypto/EcPpk.js +7 -7
- package/src/com/eduworks/ec/crypto/EcRsaOaepAsync.js +20 -19
- package/src/com/eduworks/ec/crypto/EcRsaOaepAsyncWorker.js +7 -6
- package/src/com/eduworks/ec/crypto/forgeAsync.js +1 -9
- package/src/com/eduworks/ec/crypto/forgeAsyncNode.js +8 -8
- package/src/com/eduworks/ec/graph/EcDirectedGraph.js +1 -2
- package/src/com/eduworks/ec/graph/EcFrameworkGraph.js +18 -24
- package/src/com/eduworks/ec/promises/helpers.js +1 -3
- package/src/com/eduworks/ec/remote/EcRemote.js +9 -9
- package/src/com/eduworks/ec/task/EcAsyncTask.js +5 -20
- package/src/com/eduworks/ec/task/EcAsyncTaskManager.js +3 -4
- package/src/com/eduworks/ec/task/EcAsyncTaskWorker.js +9 -11
- package/src/com/eduworks/schema/cfd/competency/CfdFramework.js +36 -37
- package/src/com/eduworks/schema/ebac/EbacContact.js +3 -9
- package/src/com/eduworks/schema/ebac/EbacContactGrant.js +3 -9
- package/src/com/eduworks/schema/ebac/EbacCredential.js +3 -9
- package/src/com/eduworks/schema/ebac/EbacCredentialCommit.js +3 -9
- package/src/com/eduworks/schema/ebac/EbacCredentialRequest.js +3 -9
- package/src/com/eduworks/schema/ebac/EbacCredentials.js +3 -9
- package/src/com/eduworks/schema/ebac/EbacEncryptedSecret.js +3 -9
- package/src/com/eduworks/schema/ebac/EbacEncryptedValue.js +5 -12
- package/src/com/eduworks/schema/ebac/EbacSignature.js +1 -6
- package/src/index/env.js +6 -3
- package/src/index/polyfills.js +13 -27
- package/src/org/angles/schema/angles/VideoStory.js +1 -1
- package/src/org/cass/competency/EcCompetency.js +1 -2
- package/src/org/cass/competency/EcDirectory.js +1 -2
- package/src/org/cass/competency/EcFramework.js +9 -12
- package/src/org/cass/exporter/CSVExport.js +12 -13
- package/src/org/cass/importer/ASNImport.js +3 -6
- package/src/org/cass/importer/CSVImport.js +9 -17
- package/src/org/cass/importer/CTDLASNCSVConceptImport.js +25 -121
- package/src/org/cass/importer/CTDLASNCSVImport.js +88 -133
- package/src/org/cass/importer/FrameworkImport.js +16 -30
- package/src/org/cass/importer/MedbiqImport.js +3 -4
- package/src/org/cass/importer/TabStructuredImport.js +6 -6
- package/src/org/cass/profile/EcAssertion.js +40 -51
- package/src/org/cassproject/ebac/identity/EcContactGrant.js +2 -2
- package/src/org/cassproject/ebac/identity/EcIdentityManager.js +56 -62
- package/src/org/cassproject/ebac/identity/EcRekeyRequest.js +3 -2
- package/src/org/cassproject/ebac/identity/remote/EcRemoteIdentityManager.js +51 -62
- package/src/org/cassproject/ebac/identity/remote/OAuth2FileBasedRemoteIdentityManager.js +56 -70
- package/src/org/cassproject/ebac/identity/remote/RemoteIdentityManagerInterface.js +3 -3
- package/src/org/cassproject/ebac/repository/EcEncryptedValue.js +51 -44
- package/src/org/cassproject/ebac/repository/EcRepository.js +228 -301
- package/src/org/cassproject/general/repository/GeneralFile.js +8 -9
- package/src/org/cassproject/schema/cass/competency/Competency.js +10 -11
- package/src/org/cassproject/schema/cass/competency/Framework.js +10 -11
- package/src/org/cassproject/schema/cass/competency/Level.js +10 -11
- package/src/org/cassproject/schema/cass/competency/Relation.js +10 -11
- package/src/org/cassproject/schema/cass/competency/RollupRule.js +7 -7
- package/src/org/cassproject/schema/cass/profile/Assertion.js +20 -27
- package/src/org/cassproject/schema/cass/profile/AssertionEnvelope.js +3 -5
- package/src/org/cassproject/schema/general/EcRemoteLinkedData.js +41 -44
- package/src/org/json/ld/EcLinkedData.js +10 -12
- package/src/org/schema/EcOrganization.js +10 -10
- package/src/org/schema/EcQuestion.js +8 -8
- package/src/org/w3/skos/Concept.js +6 -6
- package/src/org/w3/skos/ConceptScheme.js +6 -6
- package/src/org/w3/skos/EcConcept.js +1 -2
- package/src/org/w3/skos/EcConceptScheme.js +1 -2
- package/src/test/0.start.test.js +1 -1
- package/src/test/0.testLibraries.test.js +172 -0
- package/src/test/1.ASNImport.test.js +122 -0
- package/src/test/1.CSVExport.test.js +57 -0
- package/src/test/1.CSVImport.test.js +185 -0
- package/src/test/1.CTDLASNCSVConceptImport.test.js +348 -0
- package/src/test/1.CTDLASNCSVImport.import.test.js +497 -0
- package/src/test/1.Ebac.schema.test.js +107 -0
- package/src/test/1.EcAssertion.decrypt.test.js +98 -0
- package/src/test/1.EcAssertion.pinned.test.js +160 -0
- package/src/test/1.EcCrypto.formats.test.js +293 -0
- package/src/test/1.EcCrypto.generateUUID.test.js +47 -0
- package/src/test/1.EcEncryptedValue.helpers.test.js +236 -0
- package/src/test/1.EcHelpers.misc.test.js +259 -0
- package/src/test/1.EcIdentityManager.keys.test.js +439 -0
- package/src/test/1.EcOrganization.rekey.test.js +68 -0
- package/src/test/1.EcRemote.responses.test.js +155 -0
- package/src/test/1.EcRemoteIdentityManager.flows.test.js +326 -0
- package/src/test/1.EcRemoteLinkedData.pinned.test.js +473 -0
- package/src/test/1.EcRepository.l0.test.js +14 -5
- package/src/test/1.EcRepository.l1.test.js +16 -7
- package/src/test/1.EcRepository.l2.test.js +20 -11
- package/src/test/1.EcRepository.unit.test.js +961 -0
- package/src/test/1.EcRsaOaep.test.js +2 -12
- package/src/test/1.EcRsaOaepAsync.test.js +2 -12
- package/src/test/1.EcRsaOaepAsyncWorker.test.js +2 -12
- package/src/test/1.EcRsaOaepAsyncWorker.workers.test.js +147 -0
- package/src/test/1.FrameworkImport.test.js +170 -0
- package/src/test/1.MedbiqImport.test.js +92 -0
- package/src/test/1.OAuth2FileBasedRemoteIdentityManager.test.js +399 -0
- package/src/test/1.TabStructuredImport.test.js +61 -0
- package/src/test/1.polyfills.test.js +89 -0
- package/src/test/1.schema.competency.pinned.test.js +384 -0
- package/src/test/3.EcFrameworkGraph.test.js +3 -2
- package/src/test/4.schema.test.js +33 -28
- package/src/test/4.skyId.test.js +4 -2
- package/src/test/cypressValue.js +9 -0
- package/src/test/2.EcCompetency.test.js +0 -17
|
@@ -68,9 +68,9 @@ module.exports = class TabStructuredImport {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
let c = null;
|
|
71
|
-
for (let
|
|
72
|
-
if (
|
|
73
|
-
c =
|
|
71
|
+
for (let competency of competencies) {
|
|
72
|
+
if (competency.getName().trim() == lines[index].trim()) {
|
|
73
|
+
c = competency;
|
|
74
74
|
break;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -86,9 +86,9 @@ module.exports = class TabStructuredImport {
|
|
|
86
86
|
}
|
|
87
87
|
if (parentI != -1) {
|
|
88
88
|
let parent = null;
|
|
89
|
-
for (let
|
|
90
|
-
if (
|
|
91
|
-
parent =
|
|
89
|
+
for (let competency of competencies) {
|
|
90
|
+
if (competency.getName().trim() == lines[parentI].trim()) {
|
|
91
|
+
parent = competency;
|
|
92
92
|
break;
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -19,20 +19,15 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
19
19
|
async decrypt(eim) {
|
|
20
20
|
eim = eim || EcIdentityManager.default;
|
|
21
21
|
let a = new Assertion().copyFrom(this);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
assertionDate = await assertionDate;
|
|
32
|
-
expirationDate = await expirationDate;
|
|
33
|
-
evidences = await evidences;
|
|
34
|
-
negative = await negative;
|
|
35
|
-
decayFunction = await decayFunction;
|
|
22
|
+
const [subject, agent, assertionDate, expirationDate, evidences, negative, decayFunction] = await Promise.all([
|
|
23
|
+
this.getSubject(eim),
|
|
24
|
+
this.getAgent(eim),
|
|
25
|
+
this.getAssertionDate(eim),
|
|
26
|
+
this.getExpirationDate(eim),
|
|
27
|
+
this.getEvidences(eim),
|
|
28
|
+
this.getNegative(eim),
|
|
29
|
+
this.getDecayFunction(eim)
|
|
30
|
+
]);
|
|
36
31
|
if (subject)
|
|
37
32
|
a.setSubject(subject);
|
|
38
33
|
if (agent)
|
|
@@ -95,13 +90,13 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
95
90
|
*
|
|
96
91
|
* @param pk
|
|
97
92
|
*/
|
|
98
|
-
async setSubject(pk) {
|
|
93
|
+
async setSubject(pk) { // NOSONAR - Encrypts asynchronously; making Assertion's setters async would turn their errors into rejections
|
|
99
94
|
let owners = [];
|
|
100
95
|
let readers = null;
|
|
101
96
|
if (this.reader == null)
|
|
102
97
|
readers = [];
|
|
103
98
|
else
|
|
104
|
-
readers = JSON.parse(JSON.stringify(this.reader));
|
|
99
|
+
readers = JSON.parse(JSON.stringify(this.reader)); // NOSONAR - structuredClone throws on Proxy-wrapped arrays (e.g. Vue reactive state); the JSON round trip does not.
|
|
105
100
|
if (this.subject != null) {
|
|
106
101
|
if (this.subject.owner != null)
|
|
107
102
|
owners = owners.concat(this.subject.owner);
|
|
@@ -119,13 +114,12 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
119
114
|
}
|
|
120
115
|
// @deprecated
|
|
121
116
|
setSubjectAsync(pk, success, failure) {
|
|
122
|
-
let me = this;
|
|
123
117
|
let owners = [];
|
|
124
118
|
let readers = null;
|
|
125
119
|
if (this.reader == null)
|
|
126
120
|
readers = [];
|
|
127
121
|
else
|
|
128
|
-
readers = JSON.parse(JSON.stringify(this.reader));
|
|
122
|
+
readers = JSON.parse(JSON.stringify(this.reader)); // NOSONAR - structuredClone throws on Proxy-wrapped arrays (e.g. Vue reactive state); the JSON round trip does not.
|
|
129
123
|
if (this.subject != null) {
|
|
130
124
|
if (this.subject.owner != null)
|
|
131
125
|
owners = owners.concat(this.subject.owner);
|
|
@@ -139,8 +133,8 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
139
133
|
this.id,
|
|
140
134
|
owners,
|
|
141
135
|
readers,
|
|
142
|
-
|
|
143
|
-
|
|
136
|
+
(subject) => {
|
|
137
|
+
this.subject = subject;
|
|
144
138
|
success();
|
|
145
139
|
},
|
|
146
140
|
failure
|
|
@@ -188,7 +182,7 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
188
182
|
if (decryptedString == null) return null;
|
|
189
183
|
return EcPk.fromPem(decryptedString);
|
|
190
184
|
}
|
|
191
|
-
async setAgent(pk) {
|
|
185
|
+
async setAgent(pk) { // NOSONAR - Encrypts asynchronously; making Assertion's setters async would turn their errors into rejections
|
|
192
186
|
this.agent = await EcEncryptedValue.encryptValue(
|
|
193
187
|
pk.toPem(),
|
|
194
188
|
this.id,
|
|
@@ -198,14 +192,13 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
198
192
|
}
|
|
199
193
|
// @deprecated
|
|
200
194
|
setAgentAsync(pk, success, failure) {
|
|
201
|
-
let me = this;
|
|
202
195
|
return EcEncryptedValue.encryptValueAsync(
|
|
203
196
|
pk.toPem(),
|
|
204
197
|
this.id,
|
|
205
198
|
this.subject.owner,
|
|
206
199
|
this.subject.reader,
|
|
207
|
-
|
|
208
|
-
|
|
200
|
+
(agent) => {
|
|
201
|
+
this.agent = agent;
|
|
209
202
|
success();
|
|
210
203
|
},
|
|
211
204
|
failure
|
|
@@ -295,9 +288,9 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
295
288
|
.catch((error) => null);
|
|
296
289
|
}
|
|
297
290
|
if (decryptedString == null) return null;
|
|
298
|
-
return parseInt(decryptedString);
|
|
291
|
+
return Number.parseInt(decryptedString);
|
|
299
292
|
}
|
|
300
|
-
async setAssertionDate(assertionDateMs) {
|
|
293
|
+
async setAssertionDate(assertionDateMs) { // NOSONAR - Encrypts asynchronously; making Assertion's setters async would turn their errors into rejections
|
|
301
294
|
this.assertionDate = await EcEncryptedValue.encryptValue(
|
|
302
295
|
assertionDateMs.toString(),
|
|
303
296
|
this.id,
|
|
@@ -307,14 +300,13 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
307
300
|
}
|
|
308
301
|
// @deprecated
|
|
309
302
|
setAssertionDateAsync(assertionDateMs, success, failure) {
|
|
310
|
-
let me = this;
|
|
311
303
|
return EcEncryptedValue.encryptValueAsync(
|
|
312
304
|
assertionDateMs.toString(),
|
|
313
305
|
this.id,
|
|
314
306
|
this.subject.owner,
|
|
315
307
|
this.subject.reader,
|
|
316
|
-
|
|
317
|
-
|
|
308
|
+
(assertionDate) => {
|
|
309
|
+
this.assertionDate = assertionDate;
|
|
318
310
|
success();
|
|
319
311
|
},
|
|
320
312
|
failure
|
|
@@ -331,7 +323,7 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
331
323
|
let decrypted = function (decryptedString) {
|
|
332
324
|
if (decryptedString == null)
|
|
333
325
|
failure("Could not decrypt assertion date.");
|
|
334
|
-
else success(parseInt(decryptedString));
|
|
326
|
+
else success(Number.parseInt(decryptedString));
|
|
335
327
|
};
|
|
336
328
|
let codebook = Assertion.getCodebook(this);
|
|
337
329
|
if (codebook != null)
|
|
@@ -358,9 +350,9 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
358
350
|
.catch((error) => null);
|
|
359
351
|
}
|
|
360
352
|
if (decryptedString == null) return null;
|
|
361
|
-
return parseInt(decryptedString);
|
|
353
|
+
return Number.parseInt(decryptedString);
|
|
362
354
|
}
|
|
363
|
-
async setExpirationDate(expirationDateMs) {
|
|
355
|
+
async setExpirationDate(expirationDateMs) { // NOSONAR - Encrypts asynchronously; making Assertion's setters async would turn their errors into rejections
|
|
364
356
|
this.expirationDate = await EcEncryptedValue.encryptValue(
|
|
365
357
|
expirationDateMs.toString(),
|
|
366
358
|
this.id,
|
|
@@ -370,14 +362,13 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
370
362
|
}
|
|
371
363
|
// @deprecated
|
|
372
364
|
setExpirationDateAsync(expirationDateMs, success, failure) {
|
|
373
|
-
let me = this;
|
|
374
365
|
return EcEncryptedValue.encryptValueAsync(
|
|
375
366
|
expirationDateMs.toString(),
|
|
376
367
|
this.id,
|
|
377
368
|
this.subject.owner,
|
|
378
369
|
this.subject.reader,
|
|
379
|
-
|
|
380
|
-
|
|
370
|
+
(expirationDate) => {
|
|
371
|
+
this.expirationDate = expirationDate;
|
|
381
372
|
success();
|
|
382
373
|
},
|
|
383
374
|
failure
|
|
@@ -394,7 +385,7 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
394
385
|
let decrypted = function (decryptedString) {
|
|
395
386
|
if (decryptedString == null)
|
|
396
387
|
failure("Could not decrypt expiration date.");
|
|
397
|
-
else success(parseInt(decryptedString));
|
|
388
|
+
else success(Number.parseInt(decryptedString));
|
|
398
389
|
};
|
|
399
390
|
let codebook = Assertion.getCodebook(this);
|
|
400
391
|
if (codebook != null)
|
|
@@ -498,7 +489,7 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
498
489
|
if (decryptedString == null) return null;
|
|
499
490
|
return decryptedString;
|
|
500
491
|
}
|
|
501
|
-
async setDecayFunction(decayFunctionText) {
|
|
492
|
+
async setDecayFunction(decayFunctionText) { // NOSONAR - Encrypts asynchronously; making Assertion's setters async would turn their errors into rejections
|
|
502
493
|
this.decayFunction = await EcEncryptedValue.encryptValue(
|
|
503
494
|
decayFunctionText.toString(),
|
|
504
495
|
this.id,
|
|
@@ -508,14 +499,13 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
508
499
|
}
|
|
509
500
|
// @deprecated
|
|
510
501
|
setDecayFunctionAsync(decayFunctionText, success, failure) {
|
|
511
|
-
let me = this;
|
|
512
502
|
return EcEncryptedValue.encryptValueAsync(
|
|
513
503
|
decayFunctionText,
|
|
514
504
|
this.id,
|
|
515
505
|
this.subject.owner,
|
|
516
506
|
this.subject.reader,
|
|
517
|
-
|
|
518
|
-
|
|
507
|
+
(decayFunction) => {
|
|
508
|
+
this.decayFunction = decayFunction;
|
|
519
509
|
success();
|
|
520
510
|
},
|
|
521
511
|
failure
|
|
@@ -561,7 +551,7 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
561
551
|
if (decryptedString != null) decryptedString.toLowerCase();
|
|
562
552
|
return "true" == decryptedString;
|
|
563
553
|
}
|
|
564
|
-
async setNegative(negativeB) {
|
|
554
|
+
async setNegative(negativeB) { // NOSONAR - Encrypts asynchronously; making Assertion's setters async would turn their errors into rejections
|
|
565
555
|
this.negative = await EcEncryptedValue.encryptValue(
|
|
566
556
|
negativeB.toString(),
|
|
567
557
|
this.id,
|
|
@@ -571,14 +561,13 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
571
561
|
}
|
|
572
562
|
// @deprecated
|
|
573
563
|
setNegativeAsync(negativeB, success, failure) {
|
|
574
|
-
let me = this;
|
|
575
564
|
return EcEncryptedValue.encryptValueAsync(
|
|
576
565
|
negativeB.toString(),
|
|
577
566
|
this.id,
|
|
578
567
|
this.subject.owner,
|
|
579
568
|
this.subject.reader,
|
|
580
|
-
|
|
581
|
-
|
|
569
|
+
(negative) => {
|
|
570
|
+
this.negative = negative;
|
|
582
571
|
success();
|
|
583
572
|
},
|
|
584
573
|
failure
|
|
@@ -619,12 +608,12 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
619
608
|
setConfidence(confidenceZeroToOne) {
|
|
620
609
|
this.confidence = confidenceZeroToOne;
|
|
621
610
|
}
|
|
622
|
-
async setEvidence(evidences) {
|
|
611
|
+
async setEvidence(evidences) { // NOSONAR - Encrypts asynchronously; making Assertion's setters async would turn their errors into rejections
|
|
623
612
|
let encryptedValues = [];
|
|
624
|
-
for (let
|
|
613
|
+
for (let evidence of evidences)
|
|
625
614
|
encryptedValues.push(
|
|
626
615
|
await EcEncryptedValue.encryptValue(
|
|
627
|
-
|
|
616
|
+
evidence,
|
|
628
617
|
this.id,
|
|
629
618
|
this.subject.owner,
|
|
630
619
|
this.subject.reader
|
|
@@ -690,8 +679,8 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
690
679
|
await this.decayFunction.addReader(newReader, eim);
|
|
691
680
|
}
|
|
692
681
|
if (this.evidence != null)
|
|
693
|
-
for (let
|
|
694
|
-
await
|
|
682
|
+
for (let evidence of this.evidence) {
|
|
683
|
+
await evidence.addReader(newReader, eim);
|
|
695
684
|
}
|
|
696
685
|
if (this.expirationDate != null) {
|
|
697
686
|
await this.expirationDate.addReader(newReader, eim);
|
|
@@ -715,8 +704,8 @@ module.exports = class EcAssertion extends Assertion {
|
|
|
715
704
|
await this.decayFunction.removeReader(newReader, eim);
|
|
716
705
|
}
|
|
717
706
|
if (this.evidence != null)
|
|
718
|
-
for (let
|
|
719
|
-
await
|
|
707
|
+
for (let evidence of this.evidence) {
|
|
708
|
+
await evidence.removeReader(newReader, eim);
|
|
720
709
|
}
|
|
721
710
|
if (this.expirationDate != null) {
|
|
722
711
|
await this.expirationDate.removeReader(newReader, eim);
|
|
@@ -19,10 +19,10 @@ module.exports = class EcContactGrant extends EbacContactGrant {
|
|
|
19
19
|
if (!this.verify()) return false;
|
|
20
20
|
if (this.invalid()) return false;
|
|
21
21
|
let found = false;
|
|
22
|
-
for (
|
|
22
|
+
for (const id of eim.ids) {
|
|
23
23
|
if (
|
|
24
24
|
EcRsaOaep.verify(
|
|
25
|
-
|
|
25
|
+
id.ppk.toPk(),
|
|
26
26
|
this.responseToken,
|
|
27
27
|
this.responseSignature
|
|
28
28
|
)
|
|
@@ -4,7 +4,7 @@ const EcPpkFacade = require("../../../../com/eduworks/ec/crypto/EcPpkFacade");
|
|
|
4
4
|
const EcRsaOaepAsyncWorker = require("../../../../com/eduworks/ec/crypto/EcRsaOaepAsyncWorker");
|
|
5
5
|
const {cassReturnAsPromise, cassPromisify} = require("../../../../com/eduworks/ec/promises/helpers");
|
|
6
6
|
const EbacSignature = require("../../../../com/eduworks/schema/ebac/EbacSignature");
|
|
7
|
-
let realCrypto = require('crypto');
|
|
7
|
+
let realCrypto = require('crypto'); // NOSONAR - Bare specifier on purpose: browser bundlers polyfill "crypto", but webpack rejects "node:" URIs.
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Manages identities and contacts, provides hooks to respond to identity and
|
|
@@ -20,8 +20,6 @@ let realCrypto = require('crypto');
|
|
|
20
20
|
*/
|
|
21
21
|
module.exports = class EcIdentityManager {
|
|
22
22
|
static default = new this();
|
|
23
|
-
constructor() {
|
|
24
|
-
}
|
|
25
23
|
eimId = EcCrypto.generateUUID();
|
|
26
24
|
/**
|
|
27
25
|
* The current user's owned identities (keys+displayName)
|
|
@@ -97,17 +95,16 @@ module.exports = class EcIdentityManager {
|
|
|
97
95
|
return;
|
|
98
96
|
}
|
|
99
97
|
let c = JSON.parse(localStore);
|
|
100
|
-
for (
|
|
98
|
+
for (const o of c) {
|
|
101
99
|
let contact = new EcContact();
|
|
102
|
-
let o = c[i];
|
|
103
100
|
let props = o;
|
|
104
101
|
contact.displayName = props["displayName"];
|
|
105
102
|
contact.pk = EcPk.fromPem(props["pk"]);
|
|
106
103
|
contact.source = props["source"];
|
|
107
104
|
let cont = false;
|
|
108
|
-
for (
|
|
105
|
+
for (const existing of this.contacts) {
|
|
109
106
|
if (
|
|
110
|
-
|
|
107
|
+
existing.pk.toPem() ==
|
|
111
108
|
contact.pk.toPem()
|
|
112
109
|
) {
|
|
113
110
|
cont = true;
|
|
@@ -128,10 +125,9 @@ module.exports = class EcIdentityManager {
|
|
|
128
125
|
*/
|
|
129
126
|
saveContacts() {
|
|
130
127
|
let c = [];
|
|
131
|
-
for (
|
|
128
|
+
for (const contact of this.contacts) {
|
|
132
129
|
let o = {};
|
|
133
130
|
let props = o;
|
|
134
|
-
let contact = this.contacts[i];
|
|
135
131
|
props["displayName"] = contact.displayName;
|
|
136
132
|
props["pk"] = contact.pk.toPem();
|
|
137
133
|
props["source"] = contact.source;
|
|
@@ -153,17 +149,16 @@ module.exports = class EcIdentityManager {
|
|
|
153
149
|
return;
|
|
154
150
|
}
|
|
155
151
|
let c = JSON.parse(localStore);
|
|
156
|
-
for (
|
|
152
|
+
for (const o of c) {
|
|
157
153
|
let identity = new EcIdentity();
|
|
158
|
-
let o = c[i];
|
|
159
154
|
let props = o;
|
|
160
155
|
identity.displayName = props["displayName"];
|
|
161
156
|
identity.ppk = EcPpk.fromPem(props["ppk"]);
|
|
162
157
|
identity.source = props["source"];
|
|
163
158
|
let cont = false;
|
|
164
|
-
for (
|
|
159
|
+
for (const existing of this.ids) {
|
|
165
160
|
if (
|
|
166
|
-
|
|
161
|
+
existing.ppk.toPem() == identity.ppk.toPem()
|
|
167
162
|
) {
|
|
168
163
|
cont = true;
|
|
169
164
|
}
|
|
@@ -183,10 +178,9 @@ module.exports = class EcIdentityManager {
|
|
|
183
178
|
*/
|
|
184
179
|
saveIdentities() {
|
|
185
180
|
let c = [];
|
|
186
|
-
for (
|
|
181
|
+
for (const identity of this.ids) {
|
|
187
182
|
let o = {};
|
|
188
183
|
let props = o;
|
|
189
|
-
let identity = this.ids[i];
|
|
190
184
|
props["displayName"] = identity.displayName;
|
|
191
185
|
props["ppk"] = identity.ppk.toPem();
|
|
192
186
|
props["source"] = identity.source;
|
|
@@ -229,8 +223,8 @@ module.exports = class EcIdentityManager {
|
|
|
229
223
|
* @static
|
|
230
224
|
*/
|
|
231
225
|
addIdentity(identity) {
|
|
232
|
-
for (
|
|
233
|
-
if (
|
|
226
|
+
for (const id of this.ids) {
|
|
227
|
+
if (id.equals(identity)) {
|
|
234
228
|
return;
|
|
235
229
|
}
|
|
236
230
|
}
|
|
@@ -247,8 +241,8 @@ module.exports = class EcIdentityManager {
|
|
|
247
241
|
* @static
|
|
248
242
|
*/
|
|
249
243
|
addIdentityQuietly(identity) {
|
|
250
|
-
for (
|
|
251
|
-
if (
|
|
244
|
+
for (const id of this.ids) {
|
|
245
|
+
if (id.equals(identity)) {
|
|
252
246
|
return;
|
|
253
247
|
}
|
|
254
248
|
}
|
|
@@ -264,29 +258,29 @@ module.exports = class EcIdentityManager {
|
|
|
264
258
|
* @static
|
|
265
259
|
*/
|
|
266
260
|
addContact(contact) {
|
|
267
|
-
for (
|
|
261
|
+
for (const id of this.ids) {
|
|
268
262
|
if (
|
|
269
|
-
|
|
263
|
+
id.ppk
|
|
270
264
|
.toPk()
|
|
271
265
|
.toPem()
|
|
272
266
|
.equals(contact.pk.toPem())
|
|
273
267
|
) {
|
|
274
|
-
|
|
275
|
-
this.identityChanged(
|
|
268
|
+
id.displayName = contact.displayName;
|
|
269
|
+
this.identityChanged(id);
|
|
276
270
|
}
|
|
277
271
|
}
|
|
278
|
-
for (
|
|
272
|
+
for (const existing of this.contacts) {
|
|
279
273
|
if (
|
|
280
|
-
|
|
274
|
+
existing.pk
|
|
281
275
|
.toPem()
|
|
282
276
|
.equals(contact.pk.toPem())
|
|
283
277
|
) {
|
|
284
|
-
|
|
285
|
-
this.contactChanged(
|
|
278
|
+
existing.displayName = contact.displayName;
|
|
279
|
+
this.contactChanged(existing);
|
|
286
280
|
}
|
|
287
281
|
}
|
|
288
|
-
for (
|
|
289
|
-
if (
|
|
282
|
+
for (const existing of this.contacts) {
|
|
283
|
+
if (existing.equals(contact)) {
|
|
290
284
|
return;
|
|
291
285
|
}
|
|
292
286
|
}
|
|
@@ -303,27 +297,27 @@ module.exports = class EcIdentityManager {
|
|
|
303
297
|
* @static
|
|
304
298
|
*/
|
|
305
299
|
addContactQuietly(contact) {
|
|
306
|
-
for (
|
|
300
|
+
for (const id of this.ids) {
|
|
307
301
|
if (
|
|
308
|
-
|
|
302
|
+
id.ppk
|
|
309
303
|
.toPk()
|
|
310
304
|
.toPem()
|
|
311
305
|
.equals(contact.pk.toPem())
|
|
312
306
|
) {
|
|
313
|
-
|
|
307
|
+
id.displayName = contact.displayName;
|
|
314
308
|
}
|
|
315
309
|
}
|
|
316
|
-
for (
|
|
310
|
+
for (const existing of this.contacts) {
|
|
317
311
|
if (
|
|
318
|
-
|
|
312
|
+
existing.pk
|
|
319
313
|
.toPem()
|
|
320
314
|
.equals(contact.pk.toPem())
|
|
321
315
|
) {
|
|
322
|
-
|
|
316
|
+
existing.displayName = contact.displayName;
|
|
323
317
|
}
|
|
324
318
|
}
|
|
325
|
-
for (
|
|
326
|
-
if (
|
|
319
|
+
for (const existing of this.contacts) {
|
|
320
|
+
if (existing.equals(contact)) {
|
|
327
321
|
return;
|
|
328
322
|
}
|
|
329
323
|
}
|
|
@@ -356,7 +350,7 @@ module.exports = class EcIdentityManager {
|
|
|
356
350
|
if (this.signatureSheetCaching) {
|
|
357
351
|
cache = this.signatureSheetCache[server];
|
|
358
352
|
if (cache != null) {
|
|
359
|
-
if (cache[0] >
|
|
353
|
+
if (cache[0] > Date.now() + duration) {
|
|
360
354
|
return cassReturnAsPromise(cache[1], success, failure);
|
|
361
355
|
}
|
|
362
356
|
}
|
|
@@ -371,12 +365,12 @@ module.exports = class EcIdentityManager {
|
|
|
371
365
|
);
|
|
372
366
|
let p = Promise.all(promises);
|
|
373
367
|
p = p.then((signatureCandidates) => {
|
|
374
|
-
let signatures = signatureCandidates.filter(
|
|
368
|
+
let signatures = signatureCandidates.filter(Boolean);
|
|
375
369
|
let cache = null;
|
|
376
370
|
let stringified = JSON.stringify(signatures);
|
|
377
371
|
if (this.signatureSheetCaching) {
|
|
378
372
|
cache = [];
|
|
379
|
-
cache[0] =
|
|
373
|
+
cache[0] = Date.now() + finalDuration;
|
|
380
374
|
cache[1] = stringified;
|
|
381
375
|
this.signatureSheetCache[server] = cache;
|
|
382
376
|
}
|
|
@@ -401,7 +395,7 @@ module.exports = class EcIdentityManager {
|
|
|
401
395
|
if (this.signatureSheetCaching) {
|
|
402
396
|
cache = this.signatureSheetCache[server];
|
|
403
397
|
if (cache != null) {
|
|
404
|
-
if (cache[0] >
|
|
398
|
+
if (cache[0] > Date.now() + duration) {
|
|
405
399
|
return cassReturnAsPromise(cache[1], success, failure);
|
|
406
400
|
}
|
|
407
401
|
}
|
|
@@ -413,12 +407,12 @@ module.exports = class EcIdentityManager {
|
|
|
413
407
|
);
|
|
414
408
|
let p = Promise.all(promises);
|
|
415
409
|
p = p.then((signatureCandidates) => {
|
|
416
|
-
let signatures = signatureCandidates.filter(
|
|
410
|
+
let signatures = signatureCandidates.filter(Boolean);
|
|
417
411
|
let stringified = JSON.stringify(signatures);
|
|
418
412
|
if (this.signatureSheetCaching) {
|
|
419
413
|
let cache = null;
|
|
420
414
|
cache = [];
|
|
421
|
-
cache[0] =
|
|
415
|
+
cache[0] = Date.now() + finalDuration;
|
|
422
416
|
cache[1] = stringified;
|
|
423
417
|
this.signatureSheetCache[server] = cache;
|
|
424
418
|
}
|
|
@@ -440,7 +434,7 @@ module.exports = class EcIdentityManager {
|
|
|
440
434
|
* @static
|
|
441
435
|
*/
|
|
442
436
|
createSignature(duration, server, ppk, algorithm) {
|
|
443
|
-
if (typeof process !== 'undefined' && process
|
|
437
|
+
if (typeof process !== 'undefined' && process?.env && process.env.FIPS == null && realCrypto.getFips?.() == 1)
|
|
444
438
|
{
|
|
445
439
|
algorithm = "SHA-256";
|
|
446
440
|
}
|
|
@@ -448,7 +442,7 @@ module.exports = class EcIdentityManager {
|
|
|
448
442
|
return null;
|
|
449
443
|
}
|
|
450
444
|
let s = new EbacSignature();
|
|
451
|
-
s.expiry =
|
|
445
|
+
s.expiry = Date.now() + duration;
|
|
452
446
|
s.server = server;
|
|
453
447
|
delete s.owner;
|
|
454
448
|
delete s.signature;
|
|
@@ -475,9 +469,9 @@ module.exports = class EcIdentityManager {
|
|
|
475
469
|
*/
|
|
476
470
|
getPpk(fromPem) {
|
|
477
471
|
let pem = fromPem.toPem();
|
|
478
|
-
for (
|
|
479
|
-
if (pem ==
|
|
480
|
-
return
|
|
472
|
+
for (const id of this.ids) {
|
|
473
|
+
if (pem == id.ppk.toPk().toPem()) {
|
|
474
|
+
return id.ppk;
|
|
481
475
|
}
|
|
482
476
|
}
|
|
483
477
|
return null;
|
|
@@ -492,9 +486,9 @@ module.exports = class EcIdentityManager {
|
|
|
492
486
|
* @static
|
|
493
487
|
*/
|
|
494
488
|
getContact(pk) {
|
|
495
|
-
for (
|
|
496
|
-
if (pk.equals(
|
|
497
|
-
return
|
|
489
|
+
for (const contact of this.contacts) {
|
|
490
|
+
if (pk.equals(contact.pk)) {
|
|
491
|
+
return contact;
|
|
498
492
|
}
|
|
499
493
|
}
|
|
500
494
|
return null;
|
|
@@ -509,9 +503,9 @@ module.exports = class EcIdentityManager {
|
|
|
509
503
|
* @static
|
|
510
504
|
*/
|
|
511
505
|
getIdentity(pk) {
|
|
512
|
-
for (
|
|
513
|
-
if (pk.equals(
|
|
514
|
-
return
|
|
506
|
+
for (const id of this.ids) {
|
|
507
|
+
if (pk.equals(id.ppk.toPk())) {
|
|
508
|
+
return id;
|
|
515
509
|
}
|
|
516
510
|
}
|
|
517
511
|
return null;
|
|
@@ -527,9 +521,9 @@ module.exports = class EcIdentityManager {
|
|
|
527
521
|
async sign(d) {
|
|
528
522
|
let promises = [];
|
|
529
523
|
if (d.owner != null) {
|
|
530
|
-
for (
|
|
524
|
+
for (const owner of d.owner) {
|
|
531
525
|
let attempt = this.getPpk(
|
|
532
|
-
EcPk.fromPem(
|
|
526
|
+
EcPk.fromPem(owner)
|
|
533
527
|
);
|
|
534
528
|
if (attempt != null) {
|
|
535
529
|
promises.push(d.signWith(attempt));
|
|
@@ -537,8 +531,8 @@ module.exports = class EcIdentityManager {
|
|
|
537
531
|
}
|
|
538
532
|
}
|
|
539
533
|
return Promise.all(promises).then((signatures) => {
|
|
540
|
-
d.signatureSha256 = signatures.filter(
|
|
541
|
-
if (d.signatureSha256
|
|
534
|
+
d.signatureSha256 = signatures.filter(Boolean);
|
|
535
|
+
if (d.signatureSha256?.length == 0) {
|
|
542
536
|
delete d["signatureSha256"];
|
|
543
537
|
delete d["signature"];
|
|
544
538
|
}
|
|
@@ -552,12 +546,12 @@ module.exports = class EcIdentityManager {
|
|
|
552
546
|
searchString += " OR ";
|
|
553
547
|
}
|
|
554
548
|
searchString +=
|
|
555
|
-
|
|
549
|
+
String.raw`\*reader:"` +
|
|
556
550
|
this.ids[i].ppk.toPk().toPem() +
|
|
557
551
|
'"';
|
|
558
552
|
searchString += " OR ";
|
|
559
553
|
searchString +=
|
|
560
|
-
|
|
554
|
+
String.raw`\*owner:"` +
|
|
561
555
|
this.ids[i].ppk.toPk().toPem() +
|
|
562
556
|
'"';
|
|
563
557
|
}
|
|
@@ -566,8 +560,8 @@ module.exports = class EcIdentityManager {
|
|
|
566
560
|
getMyPks() {
|
|
567
561
|
let pks = [];
|
|
568
562
|
if (this.ids == null) return pks;
|
|
569
|
-
for (
|
|
570
|
-
pks.push(
|
|
563
|
+
for (const id of this.ids)
|
|
564
|
+
pks.push(id.ppk.toPk());
|
|
571
565
|
return pks;
|
|
572
566
|
}
|
|
573
567
|
};
|
|
@@ -91,15 +91,16 @@ module.exports = class EcRekeyRequest extends EcRemoteLinkedData {
|
|
|
91
91
|
*/
|
|
92
92
|
async verify() {
|
|
93
93
|
if (!await super.verify()) return false;
|
|
94
|
+
//Compare to true: the browser worker resolves to an {error} object, not false, when a signature is malformed.
|
|
94
95
|
return (await EcRsaOaepAsyncWorker.verifySha256(
|
|
95
96
|
EcPk.fromPem(this.rekeyPk),
|
|
96
97
|
this.toSignableRekeyJson(),
|
|
97
98
|
this.rekeySignature
|
|
98
|
-
) || (await EcRsaOaepAsyncWorker.verify(
|
|
99
|
+
)) === true || (await EcRsaOaepAsyncWorker.verify(
|
|
99
100
|
EcPk.fromPem(this.rekeyPk),
|
|
100
101
|
this.toSignableRekeyJson(),
|
|
101
102
|
this.rekeySignature
|
|
102
|
-
))
|
|
103
|
+
)) === true;
|
|
103
104
|
}
|
|
104
105
|
async addRekeyRequestToForwardingTable() {
|
|
105
106
|
if (!(await this.verify())) return;
|