@twin.org/federated-catalogue-service 0.0.2-next.3 → 0.0.2-next.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +200 -108
- package/dist/esm/index.mjs +201 -109
- package/dist/types/entities/dataResourceEntry.d.ts +5 -0
- package/dist/types/entities/dataSpaceConnectorEntry.d.ts +5 -0
- package/dist/types/entities/participantEntry.d.ts +5 -0
- package/dist/types/entities/serviceOfferingEntry.d.ts +6 -1
- package/dist/types/federatedCatalogueService.d.ts +13 -58
- package/dist/types/verification/complianceCredentialVerificationService.d.ts +2 -2
- package/docs/changelog.md +35 -0
- package/docs/open-api/spec.json +651 -1398
- package/docs/reference/classes/DataResourceEntry.md +8 -0
- package/docs/reference/classes/DataSpaceConnectorEntry.md +8 -0
- package/docs/reference/classes/FederatedCatalogueService.md +17 -21
- package/docs/reference/classes/ParticipantEntry.md +8 -0
- package/docs/reference/classes/ServiceOfferingEntry.md +10 -2
- package/locales/en.json +9 -5
- package/package.json +18 -3
package/dist/cjs/index.cjs
CHANGED
|
@@ -12,8 +12,6 @@ var identityModels = require('@twin.org/identity-models');
|
|
|
12
12
|
var crypto = require('@twin.org/crypto');
|
|
13
13
|
var standardsW3cDid = require('@twin.org/standards-w3c-did');
|
|
14
14
|
|
|
15
|
-
// Copyright 2024 IOTA Stiftung.
|
|
16
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
17
15
|
/**
|
|
18
16
|
* Data Resource Entry.
|
|
19
17
|
*/
|
|
@@ -71,6 +69,10 @@ exports.DataResourceEntry = class DataResourceEntry {
|
|
|
71
69
|
* Evidences
|
|
72
70
|
*/
|
|
73
71
|
evidence;
|
|
72
|
+
/**
|
|
73
|
+
* Extended data of a Data Resource entry.
|
|
74
|
+
*/
|
|
75
|
+
extraData;
|
|
74
76
|
};
|
|
75
77
|
__decorate([
|
|
76
78
|
entity.property({ type: "string", isPrimary: true }),
|
|
@@ -124,12 +126,14 @@ __decorate([
|
|
|
124
126
|
entity.property({ type: "array" }),
|
|
125
127
|
__metadata("design:type", Array)
|
|
126
128
|
], exports.DataResourceEntry.prototype, "evidence", void 0);
|
|
129
|
+
__decorate([
|
|
130
|
+
entity.property({ type: "object", optional: true }),
|
|
131
|
+
__metadata("design:type", Object)
|
|
132
|
+
], exports.DataResourceEntry.prototype, "extraData", void 0);
|
|
127
133
|
exports.DataResourceEntry = __decorate([
|
|
128
134
|
entity.entity()
|
|
129
135
|
], exports.DataResourceEntry);
|
|
130
136
|
|
|
131
|
-
// Copyright 2024 IOTA Stiftung.
|
|
132
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
133
137
|
/**
|
|
134
138
|
* Data Space Connector Entry.
|
|
135
139
|
*/
|
|
@@ -194,6 +198,10 @@ exports.DataSpaceConnectorEntry = class DataSpaceConnectorEntry {
|
|
|
194
198
|
* Evidences
|
|
195
199
|
*/
|
|
196
200
|
evidence;
|
|
201
|
+
/**
|
|
202
|
+
* Extended data of a DS Connector entry.
|
|
203
|
+
*/
|
|
204
|
+
extraData;
|
|
197
205
|
};
|
|
198
206
|
__decorate([
|
|
199
207
|
entity.property({ type: "string", isPrimary: true }),
|
|
@@ -255,12 +263,14 @@ __decorate([
|
|
|
255
263
|
entity.property({ type: "array" }),
|
|
256
264
|
__metadata("design:type", Array)
|
|
257
265
|
], exports.DataSpaceConnectorEntry.prototype, "evidence", void 0);
|
|
266
|
+
__decorate([
|
|
267
|
+
entity.property({ type: "object", optional: true }),
|
|
268
|
+
__metadata("design:type", Object)
|
|
269
|
+
], exports.DataSpaceConnectorEntry.prototype, "extraData", void 0);
|
|
258
270
|
exports.DataSpaceConnectorEntry = __decorate([
|
|
259
271
|
entity.entity()
|
|
260
272
|
], exports.DataSpaceConnectorEntry);
|
|
261
273
|
|
|
262
|
-
// Copyright 2024 IOTA Stiftung.
|
|
263
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
264
274
|
/**
|
|
265
275
|
* Participant entry.
|
|
266
276
|
*/
|
|
@@ -301,6 +311,10 @@ exports.ParticipantEntry = class ParticipantEntry {
|
|
|
301
311
|
* Evidences
|
|
302
312
|
*/
|
|
303
313
|
evidence;
|
|
314
|
+
/**
|
|
315
|
+
* Extended data of a Participant entry.
|
|
316
|
+
*/
|
|
317
|
+
extraData;
|
|
304
318
|
};
|
|
305
319
|
__decorate([
|
|
306
320
|
entity.property({ type: "string", isPrimary: true }),
|
|
@@ -338,12 +352,14 @@ __decorate([
|
|
|
338
352
|
entity.property({ type: "array" }),
|
|
339
353
|
__metadata("design:type", Array)
|
|
340
354
|
], exports.ParticipantEntry.prototype, "evidence", void 0);
|
|
355
|
+
__decorate([
|
|
356
|
+
entity.property({ type: "object", optional: true }),
|
|
357
|
+
__metadata("design:type", Object)
|
|
358
|
+
], exports.ParticipantEntry.prototype, "extraData", void 0);
|
|
341
359
|
exports.ParticipantEntry = __decorate([
|
|
342
360
|
entity.entity()
|
|
343
361
|
], exports.ParticipantEntry);
|
|
344
362
|
|
|
345
|
-
// Copyright 2024 IOTA Stiftung.
|
|
346
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
347
363
|
/**
|
|
348
364
|
* Service Offering Entry.
|
|
349
365
|
*/
|
|
@@ -396,6 +412,10 @@ exports.ServiceOfferingEntry = class ServiceOfferingEntry {
|
|
|
396
412
|
* Evidences
|
|
397
413
|
*/
|
|
398
414
|
evidence;
|
|
415
|
+
/**
|
|
416
|
+
* Extended data of a Service Offering entry.
|
|
417
|
+
*/
|
|
418
|
+
extraData;
|
|
399
419
|
};
|
|
400
420
|
__decorate([
|
|
401
421
|
entity.property({ type: "string", isPrimary: true }),
|
|
@@ -418,7 +438,7 @@ __decorate([
|
|
|
418
438
|
__metadata("design:type", String)
|
|
419
439
|
], exports.ServiceOfferingEntry.prototype, "providedBy", void 0);
|
|
420
440
|
__decorate([
|
|
421
|
-
entity.property({ type: "object" }),
|
|
441
|
+
entity.property({ type: "object", optional: true }),
|
|
422
442
|
__metadata("design:type", Object)
|
|
423
443
|
], exports.ServiceOfferingEntry.prototype, "endpoint", void 0);
|
|
424
444
|
__decorate([
|
|
@@ -445,6 +465,10 @@ __decorate([
|
|
|
445
465
|
entity.property({ type: "array" }),
|
|
446
466
|
__metadata("design:type", Array)
|
|
447
467
|
], exports.ServiceOfferingEntry.prototype, "evidence", void 0);
|
|
468
|
+
__decorate([
|
|
469
|
+
entity.property({ type: "object", optional: true }),
|
|
470
|
+
__metadata("design:type", Object)
|
|
471
|
+
], exports.ServiceOfferingEntry.prototype, "extraData", void 0);
|
|
448
472
|
exports.ServiceOfferingEntry = __decorate([
|
|
449
473
|
entity.entity()
|
|
450
474
|
], exports.ServiceOfferingEntry);
|
|
@@ -1047,7 +1071,7 @@ async function complianceCredentialPresentation(baseRouteName, httpRequestContex
|
|
|
1047
1071
|
*/
|
|
1048
1072
|
async function participantList(httpRequestContext, factoryServiceName, request) {
|
|
1049
1073
|
const service = core.ComponentFactory.get(factoryServiceName);
|
|
1050
|
-
const itemsAndCursor = await service.queryParticipants(request?.query?.id, request?.query?.registrationNumber, request?.query?.lrnType, request?.query?.cursor, core.Coerce.integer(request?.query?.
|
|
1074
|
+
const itemsAndCursor = await service.queryParticipants(request?.query?.id, request?.query?.registrationNumber, request?.query?.lrnType, request?.query?.cursor, core.Coerce.integer(request?.query?.limit));
|
|
1051
1075
|
return {
|
|
1052
1076
|
body: itemsAndCursor
|
|
1053
1077
|
};
|
|
@@ -1101,7 +1125,7 @@ async function serviceOfferingCredentialPresentation(baseRouteName, httpRequestC
|
|
|
1101
1125
|
*/
|
|
1102
1126
|
async function serviceOfferingList(httpRequestContext, factoryServiceName, request) {
|
|
1103
1127
|
const service = core.ComponentFactory.get(factoryServiceName);
|
|
1104
|
-
const itemsAndCursor = await service.queryServiceOfferings(request?.query?.id, request?.query?.providedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.
|
|
1128
|
+
const itemsAndCursor = await service.queryServiceOfferings(request?.query?.id, request?.query?.providedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.limit));
|
|
1105
1129
|
return {
|
|
1106
1130
|
body: itemsAndCursor
|
|
1107
1131
|
};
|
|
@@ -1155,7 +1179,7 @@ async function dataResourceCredentialPresentation(baseRouteName, httpRequestCont
|
|
|
1155
1179
|
*/
|
|
1156
1180
|
async function dataResourceList(httpRequestContext, factoryServiceName, request) {
|
|
1157
1181
|
const service = core.ComponentFactory.get(factoryServiceName);
|
|
1158
|
-
const itemsAndCursor = await service.queryDataResources(request?.query?.id, request?.query?.producedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.
|
|
1182
|
+
const itemsAndCursor = await service.queryDataResources(request?.query?.id, request?.query?.producedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.limit));
|
|
1159
1183
|
return {
|
|
1160
1184
|
body: itemsAndCursor
|
|
1161
1185
|
};
|
|
@@ -1206,7 +1230,7 @@ async function dataSpaceConnectorCredentialPresentation(baseRouteName, httpReque
|
|
|
1206
1230
|
*/
|
|
1207
1231
|
async function dataSpaceConnectorList(httpRequestContext, factoryServiceName, request) {
|
|
1208
1232
|
const service = core.ComponentFactory.get(factoryServiceName);
|
|
1209
|
-
const itemsAndCursor = await service.queryDataSpaceConnectors(request?.query?.id, request?.query?.maintainedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.
|
|
1233
|
+
const itemsAndCursor = await service.queryDataSpaceConnectors(request?.query?.id, request?.query?.maintainedBy, request?.query?.cursor, core.Coerce.integer(request?.query?.limit));
|
|
1210
1234
|
return {
|
|
1211
1235
|
body: itemsAndCursor
|
|
1212
1236
|
};
|
|
@@ -1234,9 +1258,9 @@ async function dataSpaceConnectorGet(httpRequestContext, factoryServiceName, req
|
|
|
1234
1258
|
*/
|
|
1235
1259
|
class ComplianceCredentialVerificationService {
|
|
1236
1260
|
/**
|
|
1237
|
-
*
|
|
1261
|
+
* Runtime name for the class.
|
|
1238
1262
|
*/
|
|
1239
|
-
CLASS_NAME = "ComplianceCredentialVerificationService";
|
|
1263
|
+
static CLASS_NAME = "ComplianceCredentialVerificationService";
|
|
1240
1264
|
/**
|
|
1241
1265
|
* Resolver component.
|
|
1242
1266
|
* @internal
|
|
@@ -1367,10 +1391,10 @@ class ComplianceCredentialVerificationService {
|
|
|
1367
1391
|
*/
|
|
1368
1392
|
async verifyEvidence(evidence) {
|
|
1369
1393
|
// The credential associated to the evidence has to be retrieved, then verified
|
|
1370
|
-
core.Guards.object(
|
|
1394
|
+
core.Guards.object(ComplianceCredentialVerificationService.CLASS_NAME, "IComplianceEvidence", evidence);
|
|
1371
1395
|
const credentialUrl = evidence.id;
|
|
1372
1396
|
this._logger?.log({
|
|
1373
|
-
source:
|
|
1397
|
+
source: ComplianceCredentialVerificationService.CLASS_NAME,
|
|
1374
1398
|
level: "info",
|
|
1375
1399
|
message: "verifyingEvidenceCredential",
|
|
1376
1400
|
ts: Date.now(),
|
|
@@ -1378,10 +1402,10 @@ class ComplianceCredentialVerificationService {
|
|
|
1378
1402
|
credentialUrl
|
|
1379
1403
|
}
|
|
1380
1404
|
});
|
|
1381
|
-
const credentialResponse = await web.FetchHelper.fetch(
|
|
1405
|
+
const credentialResponse = await web.FetchHelper.fetch(ComplianceCredentialVerificationService.CLASS_NAME, credentialUrl, "GET", undefined, { cacheTtlMs: this._subResourceCacheTtlMs });
|
|
1382
1406
|
if (!credentialResponse.ok) {
|
|
1383
1407
|
this._logger?.log({
|
|
1384
|
-
source:
|
|
1408
|
+
source: ComplianceCredentialVerificationService.CLASS_NAME,
|
|
1385
1409
|
level: "error",
|
|
1386
1410
|
message: "credentialCannotBeRetrieved",
|
|
1387
1411
|
ts: Date.now(),
|
|
@@ -1412,7 +1436,7 @@ class ComplianceCredentialVerificationService {
|
|
|
1412
1436
|
hashToCheck = core.Converter.bytesToBase64(crypto.Sha512.sum512(core.Converter.utf8ToBytes(canonicalized)));
|
|
1413
1437
|
}
|
|
1414
1438
|
else {
|
|
1415
|
-
throw new core.UnprocessableError(
|
|
1439
|
+
throw new core.UnprocessableError(ComplianceCredentialVerificationService.CLASS_NAME, "unknownHashingAlgorithm", { hashingAlg });
|
|
1416
1440
|
}
|
|
1417
1441
|
if (hashToCheck !== hash) {
|
|
1418
1442
|
return {
|
|
@@ -1422,7 +1446,7 @@ class ComplianceCredentialVerificationService {
|
|
|
1422
1446
|
}
|
|
1423
1447
|
const { id } = identityModels.DocumentHelper.parseId(proof.verificationMethod);
|
|
1424
1448
|
const documentId = theCredential.issuer ?? id;
|
|
1425
|
-
core.Guards.stringValue(
|
|
1449
|
+
core.Guards.stringValue(ComplianceCredentialVerificationService.CLASS_NAME, "documentId", documentId);
|
|
1426
1450
|
let verified = false;
|
|
1427
1451
|
try {
|
|
1428
1452
|
const document = await this._resolver.identityResolve(documentId);
|
|
@@ -1431,7 +1455,7 @@ class ComplianceCredentialVerificationService {
|
|
|
1431
1455
|
}
|
|
1432
1456
|
catch (error) {
|
|
1433
1457
|
this._logger?.log({
|
|
1434
|
-
source:
|
|
1458
|
+
source: ComplianceCredentialVerificationService.CLASS_NAME,
|
|
1435
1459
|
level: "error",
|
|
1436
1460
|
message: "credentialVerificationError",
|
|
1437
1461
|
ts: Date.now(),
|
|
@@ -1446,7 +1470,7 @@ class ComplianceCredentialVerificationService {
|
|
|
1446
1470
|
};
|
|
1447
1471
|
}
|
|
1448
1472
|
this._logger?.log({
|
|
1449
|
-
source:
|
|
1473
|
+
source: ComplianceCredentialVerificationService.CLASS_NAME,
|
|
1450
1474
|
level: "info",
|
|
1451
1475
|
message: "credentialEvidenceVerified",
|
|
1452
1476
|
ts: Date.now(),
|
|
@@ -1467,15 +1491,15 @@ class ComplianceCredentialVerificationService {
|
|
|
1467
1491
|
* Service for performing logging operations to a connector.
|
|
1468
1492
|
*/
|
|
1469
1493
|
class FederatedCatalogueService {
|
|
1494
|
+
/**
|
|
1495
|
+
* Runtime name for the class.
|
|
1496
|
+
*/
|
|
1497
|
+
static CLASS_NAME = "FederatedCatalogueService";
|
|
1470
1498
|
/**
|
|
1471
1499
|
* Fields to skip when persisting entries to the Catalogue
|
|
1472
1500
|
* @internal
|
|
1473
1501
|
*/
|
|
1474
1502
|
static _FIELDS_TO_SKIP = ["@context", "type"];
|
|
1475
|
-
/**
|
|
1476
|
-
* Runtime name for the class.
|
|
1477
|
-
*/
|
|
1478
|
-
CLASS_NAME = "FederatedCatalogueService";
|
|
1479
1503
|
/**
|
|
1480
1504
|
* The identity resolver used to dereference DIDs.
|
|
1481
1505
|
* @internal
|
|
@@ -1517,12 +1541,10 @@ class FederatedCatalogueService {
|
|
|
1517
1541
|
*/
|
|
1518
1542
|
constructor(options) {
|
|
1519
1543
|
this._logging = core.ComponentFactory.getIfExists(options?.loggingComponentType ?? "logging");
|
|
1520
|
-
this._entityStorageParticipants = entityStorageModels.EntityStorageConnectorFactory.get(options.participantEntityStorageType ??
|
|
1521
|
-
this._entityStorageServiceOfferings = entityStorageModels.EntityStorageConnectorFactory.get(options.serviceOfferingEntityStorageType ??
|
|
1522
|
-
|
|
1523
|
-
this.
|
|
1524
|
-
this._entityStorageDataSpaceConnectors = entityStorageModels.EntityStorageConnectorFactory.get(options.dataSpaceConnectorStorageType ??
|
|
1525
|
-
core.StringHelper.kebabCase("DataSpaceConnectorEntry"));
|
|
1544
|
+
this._entityStorageParticipants = entityStorageModels.EntityStorageConnectorFactory.get(options.participantEntityStorageType ?? "participant-entry");
|
|
1545
|
+
this._entityStorageServiceOfferings = entityStorageModels.EntityStorageConnectorFactory.get(options.serviceOfferingEntityStorageType ?? "service-offering-entry");
|
|
1546
|
+
this._entityStorageDataResources = entityStorageModels.EntityStorageConnectorFactory.get(options.dataResourceEntityStorageType ?? "data-resource-entry");
|
|
1547
|
+
this._entityStorageDataSpaceConnectors = entityStorageModels.EntityStorageConnectorFactory.get(options.dataSpaceConnectorStorageType ?? "data-space-connector-entry");
|
|
1526
1548
|
this._resolver = core.ComponentFactory.get(options.identityResolverComponentType ?? "identity-resolver");
|
|
1527
1549
|
this._complianceCredentialVerifier = new ComplianceCredentialVerificationService(options.config.clearingHouseApproverList, this._resolver, options.config.subResourceCacheTtlMs, this._logging);
|
|
1528
1550
|
standardsSchemaOrg.SchemaOrgDataTypes.registerRedirects();
|
|
@@ -1533,32 +1555,34 @@ class FederatedCatalogueService {
|
|
|
1533
1555
|
* @returns The Id of the Participant (DID usually).
|
|
1534
1556
|
*/
|
|
1535
1557
|
async registerComplianceCredential(credentialJwt) {
|
|
1536
|
-
core.Guards.string(
|
|
1558
|
+
core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
|
|
1537
1559
|
// This will raise exceptions as it has been coded reusing code from Gaia-X
|
|
1538
1560
|
const complianceCredential = await this.decodeJwt(credentialJwt);
|
|
1539
1561
|
const result = await this._complianceCredentialVerifier.verify(complianceCredential);
|
|
1540
1562
|
if (!result.verified) {
|
|
1541
1563
|
this._logging?.log({
|
|
1542
1564
|
level: "error",
|
|
1543
|
-
source:
|
|
1565
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1544
1566
|
ts: Date.now(),
|
|
1545
1567
|
message: "complianceCredentialNotVerified",
|
|
1546
1568
|
data: { result }
|
|
1547
1569
|
});
|
|
1548
|
-
throw new core.UnprocessableError(
|
|
1570
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
|
|
1549
1571
|
reason: result.verificationFailureReason
|
|
1550
1572
|
});
|
|
1551
1573
|
}
|
|
1552
1574
|
const targetCredential = result.credentials.find(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.LegalPerson);
|
|
1553
1575
|
if (core.Is.undefined(targetCredential)) {
|
|
1554
|
-
throw new core.UnprocessableError(
|
|
1576
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
|
|
1555
1577
|
}
|
|
1556
|
-
const participantEntry = this.extractParticipantEntry(complianceCredential, targetCredential);
|
|
1578
|
+
const { participantEntry, extraData } = this.extractParticipantEntry(complianceCredential, targetCredential);
|
|
1557
1579
|
const theEntry = core.ObjectHelper.omit(participantEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1558
|
-
|
|
1580
|
+
const extended = theEntry;
|
|
1581
|
+
extended.extraData = extraData;
|
|
1582
|
+
await this._entityStorageParticipants.set(extended);
|
|
1559
1583
|
await this._logging?.log({
|
|
1560
1584
|
level: "info",
|
|
1561
|
-
source:
|
|
1585
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1562
1586
|
ts: Date.now(),
|
|
1563
1587
|
message: "complianceCredentialVerified",
|
|
1564
1588
|
data: {
|
|
@@ -1573,13 +1597,13 @@ class FederatedCatalogueService {
|
|
|
1573
1597
|
* @param id The identity of the participant.
|
|
1574
1598
|
* @param legalRegistrationNumber The legal registration number.
|
|
1575
1599
|
* @param lrnType The legal registration number type (EORI, VATID, GLEIF, KENYA_PIN, etc.)
|
|
1576
|
-
* @param cursor The cursor to request the next
|
|
1577
|
-
* @param
|
|
1600
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
1601
|
+
* @param limit Limit the number of entities to return.
|
|
1578
1602
|
* @returns All the entities for the storage matching the conditions,
|
|
1579
1603
|
* and a cursor which can be used to request more entities.
|
|
1580
1604
|
* @throws NotImplementedError if the implementation does not support retrieval.
|
|
1581
1605
|
*/
|
|
1582
|
-
async queryParticipants(id, legalRegistrationNumber, lrnType, cursor,
|
|
1606
|
+
async queryParticipants(id, legalRegistrationNumber, lrnType, cursor, limit) {
|
|
1583
1607
|
const conditions = [];
|
|
1584
1608
|
if (core.Is.stringValue(id)) {
|
|
1585
1609
|
const condition = {
|
|
@@ -1605,15 +1629,16 @@ class FederatedCatalogueService {
|
|
|
1605
1629
|
};
|
|
1606
1630
|
conditions.push(condition);
|
|
1607
1631
|
}
|
|
1608
|
-
const entries = await this._entityStorageParticipants.query({ conditions }, undefined, undefined, cursor,
|
|
1632
|
+
const entries = await this._entityStorageParticipants.query({ conditions }, undefined, undefined, cursor, limit);
|
|
1609
1633
|
const itemList = entries.entities.map(entry => {
|
|
1610
1634
|
entry.type = standardsGaiaX.GaiaXTypes.LegalPerson;
|
|
1611
1635
|
return entry;
|
|
1612
1636
|
});
|
|
1637
|
+
const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
|
|
1613
1638
|
const result = {
|
|
1614
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
|
|
1639
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
|
|
1615
1640
|
type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
|
|
1616
|
-
itemListElement:
|
|
1641
|
+
itemListElement: finalItemList,
|
|
1617
1642
|
nextItem: entries.cursor
|
|
1618
1643
|
};
|
|
1619
1644
|
return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
|
|
@@ -1626,7 +1651,7 @@ class FederatedCatalogueService {
|
|
|
1626
1651
|
* @throws NotFoundError if not found.
|
|
1627
1652
|
*/
|
|
1628
1653
|
async getEntry(entryType, entryId) {
|
|
1629
|
-
core.Guards.stringValue(
|
|
1654
|
+
core.Guards.stringValue(FederatedCatalogueService.CLASS_NAME, "entryId", entryId);
|
|
1630
1655
|
let itemsAndCursor;
|
|
1631
1656
|
switch (entryType) {
|
|
1632
1657
|
case standardsGaiaX.GaiaXTypes.LegalPerson:
|
|
@@ -1643,17 +1668,19 @@ class FederatedCatalogueService {
|
|
|
1643
1668
|
itemsAndCursor = await this.queryDataResources(entryId);
|
|
1644
1669
|
break;
|
|
1645
1670
|
default:
|
|
1646
|
-
throw new core.GeneralError(
|
|
1671
|
+
throw new core.GeneralError(FederatedCatalogueService.CLASS_NAME, "unknownEntryType", {
|
|
1672
|
+
entryType
|
|
1673
|
+
});
|
|
1647
1674
|
}
|
|
1648
1675
|
if (core.Is.arrayValue(itemsAndCursor?.itemListElement)) {
|
|
1649
1676
|
const entry = {
|
|
1650
1677
|
...itemsAndCursor.itemListElement[0],
|
|
1651
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY
|
|
1678
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY, itemsAndCursor["@context"])
|
|
1652
1679
|
};
|
|
1653
1680
|
const result = await dataJsonLd.JsonLdProcessor.compact(entry, entry["@context"]);
|
|
1654
1681
|
return result;
|
|
1655
1682
|
}
|
|
1656
|
-
throw new core.NotFoundError(
|
|
1683
|
+
throw new core.NotFoundError(FederatedCatalogueService.CLASS_NAME, "entryNotFound", entryId);
|
|
1657
1684
|
}
|
|
1658
1685
|
/**
|
|
1659
1686
|
* Registers a compliance Credential concerning a Data Space Connector.
|
|
@@ -1661,19 +1688,19 @@ class FederatedCatalogueService {
|
|
|
1661
1688
|
* @returns The identifier of the Data Space Connector registered.
|
|
1662
1689
|
*/
|
|
1663
1690
|
async registerDataSpaceConnectorCredential(credentialJwt) {
|
|
1664
|
-
core.Guards.string(
|
|
1691
|
+
core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
|
|
1665
1692
|
// This will raise exceptions as it has been coded reusing code from Gaia-X
|
|
1666
1693
|
const complianceCredential = await this.decodeJwt(credentialJwt);
|
|
1667
1694
|
const result = await this._complianceCredentialVerifier.verify(complianceCredential);
|
|
1668
1695
|
if (!result.verified) {
|
|
1669
1696
|
this._logging?.log({
|
|
1670
1697
|
level: "error",
|
|
1671
|
-
source:
|
|
1698
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1672
1699
|
ts: Date.now(),
|
|
1673
1700
|
message: "complianceCredentialNotVerified",
|
|
1674
1701
|
data: { result }
|
|
1675
1702
|
});
|
|
1676
|
-
throw new core.UnprocessableError(
|
|
1703
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
|
|
1677
1704
|
reason: result.verificationFailureReason
|
|
1678
1705
|
});
|
|
1679
1706
|
}
|
|
@@ -1685,21 +1712,25 @@ class FederatedCatalogueService {
|
|
|
1685
1712
|
});
|
|
1686
1713
|
const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
|
|
1687
1714
|
if (core.Is.undefined(targetCredential)) {
|
|
1688
|
-
throw new core.UnprocessableError(
|
|
1715
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
|
|
1689
1716
|
}
|
|
1690
1717
|
await this.checkParticipantExists(targetCredential.issuer);
|
|
1691
|
-
const dataSpaceConnectorEntry = this.extractDataSpaceConnectorEntry(complianceCredential, result.credentials[0]);
|
|
1718
|
+
const { dataSpaceConnectorEntry, extraData } = this.extractDataSpaceConnectorEntry(complianceCredential, result.credentials[0]);
|
|
1692
1719
|
const theEntry = core.ObjectHelper.omit(dataSpaceConnectorEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1693
|
-
|
|
1720
|
+
const extended = theEntry;
|
|
1721
|
+
extended.extraData = extraData;
|
|
1722
|
+
await this._entityStorageDataSpaceConnectors.set(extended);
|
|
1694
1723
|
for (const dataResourceCredential of dataResourceCredentials) {
|
|
1695
1724
|
await this.checkParticipantExists(dataResourceCredential.issuer);
|
|
1696
|
-
const dataResourceEntry = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
|
|
1697
|
-
const
|
|
1698
|
-
|
|
1725
|
+
const { dataResourceEntry, extraData: extraDataResourceData } = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
|
|
1726
|
+
const finalDataResourceEntry = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1727
|
+
const extendedDataResourceEntry = finalDataResourceEntry;
|
|
1728
|
+
extendedDataResourceEntry.extraData = extraDataResourceData;
|
|
1729
|
+
await this._entityStorageDataResources.set(extendedDataResourceEntry);
|
|
1699
1730
|
}
|
|
1700
1731
|
await this._logging?.log({
|
|
1701
1732
|
level: "info",
|
|
1702
|
-
source:
|
|
1733
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1703
1734
|
ts: Date.now(),
|
|
1704
1735
|
message: "complianceCredentialVerified",
|
|
1705
1736
|
data: {
|
|
@@ -1715,36 +1746,38 @@ class FederatedCatalogueService {
|
|
|
1715
1746
|
* @returns The list of Data Resources created.
|
|
1716
1747
|
*/
|
|
1717
1748
|
async registerDataResourceCredential(credentialJwt) {
|
|
1718
|
-
core.Guards.string(
|
|
1749
|
+
core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
|
|
1719
1750
|
const complianceCredential = await this.decodeJwt(credentialJwt);
|
|
1720
1751
|
const result = await this._complianceCredentialVerifier.verify(complianceCredential);
|
|
1721
1752
|
if (!result.verified) {
|
|
1722
1753
|
this._logging?.log({
|
|
1723
1754
|
level: "error",
|
|
1724
|
-
source:
|
|
1755
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1725
1756
|
ts: Date.now(),
|
|
1726
1757
|
message: "complianceCredentialNotVerified",
|
|
1727
1758
|
data: { result }
|
|
1728
1759
|
});
|
|
1729
|
-
throw new core.UnprocessableError(
|
|
1760
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
|
|
1730
1761
|
reason: result.verificationFailureReason
|
|
1731
1762
|
});
|
|
1732
1763
|
}
|
|
1733
1764
|
const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
|
|
1734
1765
|
if (dataResourceCredentials.length === 0) {
|
|
1735
|
-
throw new core.UnprocessableError(
|
|
1766
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
|
|
1736
1767
|
}
|
|
1737
1768
|
const dataResourceIds = [];
|
|
1738
1769
|
for (const dataResourceCredential of dataResourceCredentials) {
|
|
1739
1770
|
await this.checkParticipantExists(dataResourceCredential.issuer);
|
|
1740
|
-
const dataResourceEntry = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
|
|
1771
|
+
const { dataResourceEntry, extraData } = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
|
|
1741
1772
|
const theEntry = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1742
|
-
|
|
1773
|
+
const extended = theEntry;
|
|
1774
|
+
extended.extraData = extraData;
|
|
1775
|
+
await this._entityStorageDataResources.set(extended);
|
|
1743
1776
|
dataResourceIds.push(dataResourceEntry.id);
|
|
1744
1777
|
}
|
|
1745
1778
|
await this._logging?.log({
|
|
1746
1779
|
level: "info",
|
|
1747
|
-
source:
|
|
1780
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1748
1781
|
ts: Date.now(),
|
|
1749
1782
|
message: "complianceCredentialVerified",
|
|
1750
1783
|
data: {
|
|
@@ -1758,13 +1791,13 @@ class FederatedCatalogueService {
|
|
|
1758
1791
|
* Query the federated catalogue.
|
|
1759
1792
|
* @param id The identity of the participant.
|
|
1760
1793
|
* @param maintainer The DS Connector maintainer.
|
|
1761
|
-
* @param cursor The cursor to request the next
|
|
1762
|
-
* @param
|
|
1794
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
1795
|
+
* @param limit Limit the number of entities to return.
|
|
1763
1796
|
* @returns All the entities for the storage matching the conditions,
|
|
1764
1797
|
* and a cursor which can be used to request more entities.
|
|
1765
1798
|
* @throws NotImplementedError if the implementation does not support retrieval.
|
|
1766
1799
|
*/
|
|
1767
|
-
async queryDataSpaceConnectors(id, maintainer, cursor,
|
|
1800
|
+
async queryDataSpaceConnectors(id, maintainer, cursor, limit) {
|
|
1768
1801
|
const conditions = [];
|
|
1769
1802
|
if (core.Is.stringValue(id)) {
|
|
1770
1803
|
const condition = {
|
|
@@ -1782,7 +1815,7 @@ class FederatedCatalogueService {
|
|
|
1782
1815
|
};
|
|
1783
1816
|
conditions.push(condition);
|
|
1784
1817
|
}
|
|
1785
|
-
const entries = await this._entityStorageDataSpaceConnectors.query({ conditions }, undefined, undefined, cursor,
|
|
1818
|
+
const entries = await this._entityStorageDataSpaceConnectors.query({ conditions }, undefined, undefined, cursor, limit);
|
|
1786
1819
|
const itemList = entries.entities.map(entry => {
|
|
1787
1820
|
entry.type = [
|
|
1788
1821
|
standardsGaiaX.GaiaXTypes.DataExchangeComponent,
|
|
@@ -1790,10 +1823,11 @@ class FederatedCatalogueService {
|
|
|
1790
1823
|
];
|
|
1791
1824
|
return entry;
|
|
1792
1825
|
});
|
|
1826
|
+
const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
|
|
1793
1827
|
const result = {
|
|
1794
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
|
|
1828
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
|
|
1795
1829
|
type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
|
|
1796
|
-
itemListElement:
|
|
1830
|
+
itemListElement: finalItemList,
|
|
1797
1831
|
nextItem: entries.cursor
|
|
1798
1832
|
};
|
|
1799
1833
|
return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
|
|
@@ -1804,44 +1838,48 @@ class FederatedCatalogueService {
|
|
|
1804
1838
|
* @returns Nothing.
|
|
1805
1839
|
*/
|
|
1806
1840
|
async registerServiceOfferingCredential(credentialJwt) {
|
|
1807
|
-
core.Guards.string(
|
|
1841
|
+
core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
|
|
1808
1842
|
// This will raise exceptions as it has been coded reusing code from Gaia-X
|
|
1809
1843
|
const sdComplianceCredential = await this.decodeJwt(credentialJwt);
|
|
1810
1844
|
const result = await this._complianceCredentialVerifier.verify(sdComplianceCredential);
|
|
1811
1845
|
if (!result.verified) {
|
|
1812
1846
|
this._logging?.log({
|
|
1813
1847
|
level: "error",
|
|
1814
|
-
source:
|
|
1848
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1815
1849
|
ts: Date.now(),
|
|
1816
1850
|
message: "complianceCredentialNotVerified",
|
|
1817
1851
|
data: { result }
|
|
1818
1852
|
});
|
|
1819
|
-
throw new core.UnprocessableError(
|
|
1853
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
|
|
1820
1854
|
reason: result.verificationFailureReason
|
|
1821
1855
|
});
|
|
1822
1856
|
}
|
|
1823
1857
|
const serviceOfferingCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.ServiceOffering);
|
|
1824
1858
|
const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
|
|
1825
1859
|
if (serviceOfferingCredentials.length === 0) {
|
|
1826
|
-
throw new core.UnprocessableError(
|
|
1860
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
|
|
1827
1861
|
}
|
|
1828
1862
|
const serviceOfferingIds = [];
|
|
1829
1863
|
for (const serviceOfferingCredential of serviceOfferingCredentials) {
|
|
1830
1864
|
const serviceIssuer = serviceOfferingCredential.issuer;
|
|
1831
1865
|
await this.checkParticipantExists(serviceIssuer);
|
|
1832
|
-
const serviceOfferingEntry = this.extractServiceOfferingEntry(sdComplianceCredential, serviceOfferingCredential);
|
|
1866
|
+
const { serviceOfferingEntry, extraData } = this.extractServiceOfferingEntry(sdComplianceCredential, serviceOfferingCredential);
|
|
1833
1867
|
const theEntry = core.ObjectHelper.omit(serviceOfferingEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1834
|
-
|
|
1868
|
+
const extended = theEntry;
|
|
1869
|
+
extended.extraData = extraData;
|
|
1870
|
+
await this._entityStorageServiceOfferings.set(extended);
|
|
1835
1871
|
serviceOfferingIds.push(serviceOfferingEntry.id);
|
|
1836
1872
|
}
|
|
1837
1873
|
for (const dataResourceCredential of dataResourceCredentials) {
|
|
1838
1874
|
await this.checkParticipantExists(dataResourceCredential.issuer);
|
|
1839
|
-
const dataResourceEntry = this.extractDataResourceEntry(sdComplianceCredential, dataResourceCredential);
|
|
1840
|
-
|
|
1875
|
+
const { dataResourceEntry, extraData } = this.extractDataResourceEntry(sdComplianceCredential, dataResourceCredential);
|
|
1876
|
+
const extended = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1877
|
+
extended.extraData = extraData;
|
|
1878
|
+
await this._entityStorageDataResources.set(extended);
|
|
1841
1879
|
}
|
|
1842
1880
|
await this._logging?.log({
|
|
1843
1881
|
level: "info",
|
|
1844
|
-
source:
|
|
1882
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1845
1883
|
ts: Date.now(),
|
|
1846
1884
|
message: "complianceCredentialVerified",
|
|
1847
1885
|
data: {
|
|
@@ -1855,13 +1893,13 @@ class FederatedCatalogueService {
|
|
|
1855
1893
|
* Query the federated catalogue.
|
|
1856
1894
|
* @param id Service Id.
|
|
1857
1895
|
* @param providedBy The identity of the participant.
|
|
1858
|
-
* @param cursor The cursor to request the next
|
|
1859
|
-
* @param
|
|
1896
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
1897
|
+
* @param limit Limit the number of entities to return.
|
|
1860
1898
|
* @returns All the entities for the storage matching the conditions,
|
|
1861
1899
|
* and a cursor which can be used to request more entities.
|
|
1862
1900
|
* @throws NotImplementedError if the implementation does not support retrieval.
|
|
1863
1901
|
*/
|
|
1864
|
-
async queryServiceOfferings(id, providedBy, cursor,
|
|
1902
|
+
async queryServiceOfferings(id, providedBy, cursor, limit) {
|
|
1865
1903
|
const conditions = [];
|
|
1866
1904
|
if (core.Is.stringValue(providedBy)) {
|
|
1867
1905
|
const condition = {
|
|
@@ -1879,15 +1917,16 @@ class FederatedCatalogueService {
|
|
|
1879
1917
|
};
|
|
1880
1918
|
conditions.push(condition);
|
|
1881
1919
|
}
|
|
1882
|
-
const entries = await this._entityStorageServiceOfferings.query({ conditions }, undefined, undefined, cursor,
|
|
1920
|
+
const entries = await this._entityStorageServiceOfferings.query({ conditions }, undefined, undefined, cursor, limit);
|
|
1883
1921
|
const itemList = entries.entities.map(entry => {
|
|
1884
1922
|
entry.type = standardsGaiaX.GaiaXTypes.ServiceOffering;
|
|
1885
1923
|
return entry;
|
|
1886
1924
|
});
|
|
1925
|
+
const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
|
|
1887
1926
|
const result = {
|
|
1888
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
|
|
1927
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
|
|
1889
1928
|
type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
|
|
1890
|
-
itemListElement:
|
|
1929
|
+
itemListElement: finalItemList,
|
|
1891
1930
|
nextItem: entries.cursor
|
|
1892
1931
|
};
|
|
1893
1932
|
return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
|
|
@@ -1896,13 +1935,13 @@ class FederatedCatalogueService {
|
|
|
1896
1935
|
* Query the federated catalogue.
|
|
1897
1936
|
* @param id The identity of the DataResource.
|
|
1898
1937
|
* @param producedBy The identity of the participant.
|
|
1899
|
-
* @param cursor The cursor to request the next
|
|
1900
|
-
* @param
|
|
1938
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
1939
|
+
* @param limit Limit the number of entities to return.
|
|
1901
1940
|
* @returns All the entities for the storage matching the conditions,
|
|
1902
1941
|
* and a cursor which can be used to request more entities.
|
|
1903
1942
|
* @throws NotImplementedError if the implementation does not support retrieval.
|
|
1904
1943
|
*/
|
|
1905
|
-
async queryDataResources(id, producedBy, cursor,
|
|
1944
|
+
async queryDataResources(id, producedBy, cursor, limit) {
|
|
1906
1945
|
const conditions = [];
|
|
1907
1946
|
if (core.Is.stringValue(producedBy)) {
|
|
1908
1947
|
const condition = {
|
|
@@ -1920,23 +1959,44 @@ class FederatedCatalogueService {
|
|
|
1920
1959
|
};
|
|
1921
1960
|
conditions.push(condition);
|
|
1922
1961
|
}
|
|
1923
|
-
const entries = await this._entityStorageDataResources.query({ conditions }, undefined, undefined, cursor,
|
|
1962
|
+
const entries = await this._entityStorageDataResources.query({ conditions }, undefined, undefined, cursor, limit);
|
|
1924
1963
|
const itemList = entries.entities.map(entry => {
|
|
1925
1964
|
entry.type = standardsGaiaX.GaiaXTypes.DataResource;
|
|
1926
1965
|
return entry;
|
|
1927
1966
|
});
|
|
1967
|
+
const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
|
|
1928
1968
|
const result = {
|
|
1929
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
|
|
1969
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
|
|
1930
1970
|
type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
|
|
1931
|
-
itemListElement:
|
|
1971
|
+
itemListElement: finalItemList,
|
|
1932
1972
|
nextItem: entries.cursor
|
|
1933
1973
|
};
|
|
1934
1974
|
return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
|
|
1935
1975
|
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Normalizes the extra data adding it to each entry.
|
|
1978
|
+
* @param itemList The item list.
|
|
1979
|
+
* @returns the final item list plus the additional LD Context
|
|
1980
|
+
* @internal
|
|
1981
|
+
*/
|
|
1982
|
+
normalizeExtraData(itemList) {
|
|
1983
|
+
let extraDataLdContext;
|
|
1984
|
+
const finalItemList = itemList.map(entry => {
|
|
1985
|
+
const extraData = core.ObjectHelper.extractProperty(entry, "extraData", true);
|
|
1986
|
+
if (!core.Is.undefined(extraData?.["@context"])) {
|
|
1987
|
+
const ldContext = extraData["@context"];
|
|
1988
|
+
extraDataLdContext = dataJsonLd.JsonLdProcessor.combineContexts(extraDataLdContext, ldContext);
|
|
1989
|
+
return core.ObjectHelper.merge(entry, extraData);
|
|
1990
|
+
}
|
|
1991
|
+
return entry;
|
|
1992
|
+
});
|
|
1993
|
+
return { finalItemList, extraDataLdContext };
|
|
1994
|
+
}
|
|
1936
1995
|
/**
|
|
1937
1996
|
* Decodes the JWT.
|
|
1938
1997
|
* @param jwt JWT.
|
|
1939
1998
|
* @returns Decoded.
|
|
1999
|
+
* @internal
|
|
1940
2000
|
*/
|
|
1941
2001
|
async decodeJwt(jwt) {
|
|
1942
2002
|
const { payload } = await identityModels.VerificationHelper.verifyJwt(this._resolver, jwt);
|
|
@@ -1946,6 +2006,7 @@ class FederatedCatalogueService {
|
|
|
1946
2006
|
* Returns the trusted Issuer id.
|
|
1947
2007
|
* @param complianceCredential The compliance credential.
|
|
1948
2008
|
* @returns The trusted issuer.
|
|
2009
|
+
* @internal
|
|
1949
2010
|
*/
|
|
1950
2011
|
getTrustedIssuerId(complianceCredential) {
|
|
1951
2012
|
const trustedIssuerId = core.Is.object(complianceCredential.issuer)
|
|
@@ -1958,16 +2019,18 @@ class FederatedCatalogueService {
|
|
|
1958
2019
|
* @param complianceCredential Compliance credential
|
|
1959
2020
|
* @param participantCredential The Participant credential extracted.
|
|
1960
2021
|
* @returns Participant Entry to be saved on the Database.
|
|
2022
|
+
* @internal
|
|
1961
2023
|
*/
|
|
1962
2024
|
extractParticipantEntry(complianceCredential, participantCredential) {
|
|
1963
2025
|
const participantData = participantCredential.credentialSubject;
|
|
1964
|
-
core.Guards.objectValue(
|
|
2026
|
+
core.Guards.objectValue(FederatedCatalogueService.CLASS_NAME, "participantData", participantData);
|
|
1965
2027
|
const evidences = [];
|
|
1966
2028
|
for (const evidence of complianceCredential.evidence) {
|
|
1967
2029
|
evidences.push(evidence.id);
|
|
1968
2030
|
}
|
|
2031
|
+
const { data, extraData } = this.extractExtraData(participantData, entity.EntitySchemaFactory.get("ParticipantEntry"));
|
|
1969
2032
|
const result = {
|
|
1970
|
-
...
|
|
2033
|
+
...data,
|
|
1971
2034
|
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
|
|
1972
2035
|
issuer: this.getTrustedIssuerId(complianceCredential),
|
|
1973
2036
|
validFrom: complianceCredential.validFrom,
|
|
@@ -1975,18 +2038,20 @@ class FederatedCatalogueService {
|
|
|
1975
2038
|
dateCreated: new Date().toISOString(),
|
|
1976
2039
|
evidence: evidences
|
|
1977
2040
|
};
|
|
1978
|
-
return result;
|
|
2041
|
+
return { participantEntry: result, extraData };
|
|
1979
2042
|
}
|
|
1980
2043
|
/**
|
|
1981
2044
|
* Extracts Data Space Connector description entry from the credentials.
|
|
1982
2045
|
* @param complianceCredential Compliance Credential.
|
|
1983
2046
|
* @param dataSpaceConnectorCredential Evidence Credential.
|
|
1984
2047
|
* @returns Service Description Entry to be saved on the Database.
|
|
2048
|
+
* @internal
|
|
1985
2049
|
*/
|
|
1986
2050
|
extractDataSpaceConnectorEntry(complianceCredential, dataSpaceConnectorCredential) {
|
|
1987
2051
|
const credentialData = dataSpaceConnectorCredential.credentialSubject;
|
|
1988
|
-
core.Guards.objectValue(
|
|
1989
|
-
const {
|
|
2052
|
+
core.Guards.objectValue(FederatedCatalogueService.CLASS_NAME, "credentialData", credentialData);
|
|
2053
|
+
const { extraData, data } = this.extractExtraData(credentialData, entity.EntitySchemaFactory.get("DataSpaceConnectorEntry"));
|
|
2054
|
+
const { offeredResource, ...deStructuredData } = data;
|
|
1990
2055
|
const result = {
|
|
1991
2056
|
...deStructuredData,
|
|
1992
2057
|
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
|
|
@@ -1997,18 +2062,20 @@ class FederatedCatalogueService {
|
|
|
1997
2062
|
dateCreated: new Date().toISOString(),
|
|
1998
2063
|
evidence: [dataSpaceConnectorCredential.id]
|
|
1999
2064
|
};
|
|
2000
|
-
return result;
|
|
2065
|
+
return { dataSpaceConnectorEntry: result, extraData };
|
|
2001
2066
|
}
|
|
2002
2067
|
/**
|
|
2003
2068
|
* Extracts service offering entry from the credentials.
|
|
2004
2069
|
* @param complianceCredential The Compliance Credential.
|
|
2005
2070
|
* @param serviceOfferingCredential Service Offering credential (evidence).
|
|
2006
2071
|
* @returns Service Offering Entry to be saved on the Database.
|
|
2072
|
+
* @internal
|
|
2007
2073
|
*/
|
|
2008
2074
|
extractServiceOfferingEntry(complianceCredential, serviceOfferingCredential) {
|
|
2009
2075
|
const credentialData = serviceOfferingCredential.credentialSubject;
|
|
2010
|
-
core.Guards.objectValue(
|
|
2011
|
-
const {
|
|
2076
|
+
core.Guards.objectValue(FederatedCatalogueService.CLASS_NAME, "credentialData", credentialData);
|
|
2077
|
+
const { data, extraData } = this.extractExtraData(credentialData, entity.EntitySchemaFactory.get("ServiceOfferingEntry"));
|
|
2078
|
+
const { providedBy, aggregationOfResources, servicePolicy, ...deStructuredData } = data;
|
|
2012
2079
|
const result = {
|
|
2013
2080
|
...deStructuredData,
|
|
2014
2081
|
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
|
|
@@ -2021,18 +2088,20 @@ class FederatedCatalogueService {
|
|
|
2021
2088
|
evidence: [serviceOfferingCredential.id],
|
|
2022
2089
|
servicePolicy: core.ArrayHelper.fromObjectOrArray(servicePolicy)
|
|
2023
2090
|
};
|
|
2024
|
-
return result;
|
|
2091
|
+
return { serviceOfferingEntry: result, extraData };
|
|
2025
2092
|
}
|
|
2026
2093
|
/**
|
|
2027
2094
|
* Extracts data resource entry from the credentials.
|
|
2028
2095
|
* @param complianceCredential The Compliance Credential.
|
|
2029
2096
|
* @param dataResourceCredential Data Resource credential.
|
|
2030
2097
|
* @returns DataResource Entry to be saved on the Database.
|
|
2098
|
+
* @internal
|
|
2031
2099
|
*/
|
|
2032
2100
|
extractDataResourceEntry(complianceCredential, dataResourceCredential) {
|
|
2033
2101
|
const credentialData = dataResourceCredential.credentialSubject;
|
|
2034
|
-
core.Guards.objectValue(
|
|
2035
|
-
const {
|
|
2102
|
+
core.Guards.objectValue(FederatedCatalogueService.CLASS_NAME, "credentialData", credentialData);
|
|
2103
|
+
const { data, extraData } = this.extractExtraData(credentialData, entity.EntitySchemaFactory.get("DataResourceEntry"));
|
|
2104
|
+
const { producedBy, copyrightOwnedBy, exposedThrough, resourcePolicy, ...deStructuredData } = data;
|
|
2036
2105
|
let producedByValue = producedBy;
|
|
2037
2106
|
if (core.Is.object(producedByValue)) {
|
|
2038
2107
|
producedByValue = producedByValue.id;
|
|
@@ -2054,27 +2123,50 @@ class FederatedCatalogueService {
|
|
|
2054
2123
|
evidence: [dataResourceCredential.id],
|
|
2055
2124
|
resourcePolicy: core.ArrayHelper.fromObjectOrArray(resourcePolicy)
|
|
2056
2125
|
};
|
|
2057
|
-
return result;
|
|
2126
|
+
return { dataResourceEntry: result, extraData };
|
|
2058
2127
|
}
|
|
2059
2128
|
/**
|
|
2060
2129
|
* Checks whether the Participant exists.
|
|
2061
2130
|
* @param participantId The Participant identifier
|
|
2131
|
+
* @internal
|
|
2062
2132
|
*/
|
|
2063
2133
|
async checkParticipantExists(participantId) {
|
|
2064
2134
|
const participantData = await this._entityStorageParticipants.get(participantId);
|
|
2065
2135
|
if (!participantData) {
|
|
2066
2136
|
this._logging?.log({
|
|
2067
2137
|
level: "error",
|
|
2068
|
-
source:
|
|
2138
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
2069
2139
|
ts: Date.now(),
|
|
2070
2140
|
message: "providerIsNotParticipant",
|
|
2071
2141
|
data: { providedBy: participantId }
|
|
2072
2142
|
});
|
|
2073
|
-
throw new core.UnprocessableError(
|
|
2143
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "providerIsNotParticipant", {
|
|
2074
2144
|
providedBy: participantId
|
|
2075
2145
|
});
|
|
2076
2146
|
}
|
|
2077
2147
|
}
|
|
2148
|
+
/**
|
|
2149
|
+
* Extracts extra data from an object.
|
|
2150
|
+
* @param originalData The original data to extract from
|
|
2151
|
+
* @param schema The entity storage that is used to store
|
|
2152
|
+
* @returns The extraData and the data.
|
|
2153
|
+
* @internal
|
|
2154
|
+
*/
|
|
2155
|
+
extractExtraData(originalData, schema) {
|
|
2156
|
+
const entityProperties = schema.properties ?? [];
|
|
2157
|
+
// Type and @context is also an extra known property
|
|
2158
|
+
const knownProperties = entityProperties.map(property => property.property).concat(["type", "@context"]);
|
|
2159
|
+
const splitObjects = core.ObjectHelper.split(originalData, knownProperties);
|
|
2160
|
+
return {
|
|
2161
|
+
data: splitObjects.picked,
|
|
2162
|
+
extraData: core.Is.objectValue(splitObjects.omitted)
|
|
2163
|
+
? {
|
|
2164
|
+
"@context": originalData["@context"],
|
|
2165
|
+
...splitObjects.omitted
|
|
2166
|
+
}
|
|
2167
|
+
: undefined
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2078
2170
|
}
|
|
2079
2171
|
|
|
2080
2172
|
const restEntryPoints = [
|