@twin.org/federated-catalogue-service 0.0.2-next.4 → 0.0.2-next.6
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 +195 -101
- package/dist/esm/index.mjs +195 -101
- 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 +5 -0
- package/dist/types/federatedCatalogueService.d.ts +13 -58
- package/dist/types/verification/complianceCredentialVerificationService.d.ts +2 -2
- package/docs/changelog.md +34 -0
- package/docs/open-api/spec.json +65 -77
- 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 +8 -0
- 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 }),
|
|
@@ -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
|
|
@@ -1531,32 +1555,34 @@ class FederatedCatalogueService {
|
|
|
1531
1555
|
* @returns The Id of the Participant (DID usually).
|
|
1532
1556
|
*/
|
|
1533
1557
|
async registerComplianceCredential(credentialJwt) {
|
|
1534
|
-
core.Guards.string(
|
|
1558
|
+
core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
|
|
1535
1559
|
// This will raise exceptions as it has been coded reusing code from Gaia-X
|
|
1536
1560
|
const complianceCredential = await this.decodeJwt(credentialJwt);
|
|
1537
1561
|
const result = await this._complianceCredentialVerifier.verify(complianceCredential);
|
|
1538
1562
|
if (!result.verified) {
|
|
1539
1563
|
this._logging?.log({
|
|
1540
1564
|
level: "error",
|
|
1541
|
-
source:
|
|
1565
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1542
1566
|
ts: Date.now(),
|
|
1543
1567
|
message: "complianceCredentialNotVerified",
|
|
1544
1568
|
data: { result }
|
|
1545
1569
|
});
|
|
1546
|
-
throw new core.UnprocessableError(
|
|
1570
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
|
|
1547
1571
|
reason: result.verificationFailureReason
|
|
1548
1572
|
});
|
|
1549
1573
|
}
|
|
1550
1574
|
const targetCredential = result.credentials.find(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.LegalPerson);
|
|
1551
1575
|
if (core.Is.undefined(targetCredential)) {
|
|
1552
|
-
throw new core.UnprocessableError(
|
|
1576
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
|
|
1553
1577
|
}
|
|
1554
|
-
const participantEntry = this.extractParticipantEntry(complianceCredential, targetCredential);
|
|
1578
|
+
const { participantEntry, extraData } = this.extractParticipantEntry(complianceCredential, targetCredential);
|
|
1555
1579
|
const theEntry = core.ObjectHelper.omit(participantEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1556
|
-
|
|
1580
|
+
const extended = theEntry;
|
|
1581
|
+
extended.extraData = extraData;
|
|
1582
|
+
await this._entityStorageParticipants.set(extended);
|
|
1557
1583
|
await this._logging?.log({
|
|
1558
1584
|
level: "info",
|
|
1559
|
-
source:
|
|
1585
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1560
1586
|
ts: Date.now(),
|
|
1561
1587
|
message: "complianceCredentialVerified",
|
|
1562
1588
|
data: {
|
|
@@ -1571,13 +1597,13 @@ class FederatedCatalogueService {
|
|
|
1571
1597
|
* @param id The identity of the participant.
|
|
1572
1598
|
* @param legalRegistrationNumber The legal registration number.
|
|
1573
1599
|
* @param lrnType The legal registration number type (EORI, VATID, GLEIF, KENYA_PIN, etc.)
|
|
1574
|
-
* @param cursor The cursor to request the next
|
|
1575
|
-
* @param
|
|
1600
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
1601
|
+
* @param limit Limit the number of entities to return.
|
|
1576
1602
|
* @returns All the entities for the storage matching the conditions,
|
|
1577
1603
|
* and a cursor which can be used to request more entities.
|
|
1578
1604
|
* @throws NotImplementedError if the implementation does not support retrieval.
|
|
1579
1605
|
*/
|
|
1580
|
-
async queryParticipants(id, legalRegistrationNumber, lrnType, cursor,
|
|
1606
|
+
async queryParticipants(id, legalRegistrationNumber, lrnType, cursor, limit) {
|
|
1581
1607
|
const conditions = [];
|
|
1582
1608
|
if (core.Is.stringValue(id)) {
|
|
1583
1609
|
const condition = {
|
|
@@ -1603,15 +1629,16 @@ class FederatedCatalogueService {
|
|
|
1603
1629
|
};
|
|
1604
1630
|
conditions.push(condition);
|
|
1605
1631
|
}
|
|
1606
|
-
const entries = await this._entityStorageParticipants.query({ conditions }, undefined, undefined, cursor,
|
|
1632
|
+
const entries = await this._entityStorageParticipants.query({ conditions }, undefined, undefined, cursor, limit);
|
|
1607
1633
|
const itemList = entries.entities.map(entry => {
|
|
1608
1634
|
entry.type = standardsGaiaX.GaiaXTypes.LegalPerson;
|
|
1609
1635
|
return entry;
|
|
1610
1636
|
});
|
|
1637
|
+
const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
|
|
1611
1638
|
const result = {
|
|
1612
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
|
|
1639
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
|
|
1613
1640
|
type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
|
|
1614
|
-
itemListElement:
|
|
1641
|
+
itemListElement: finalItemList,
|
|
1615
1642
|
nextItem: entries.cursor
|
|
1616
1643
|
};
|
|
1617
1644
|
return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
|
|
@@ -1624,7 +1651,7 @@ class FederatedCatalogueService {
|
|
|
1624
1651
|
* @throws NotFoundError if not found.
|
|
1625
1652
|
*/
|
|
1626
1653
|
async getEntry(entryType, entryId) {
|
|
1627
|
-
core.Guards.stringValue(
|
|
1654
|
+
core.Guards.stringValue(FederatedCatalogueService.CLASS_NAME, "entryId", entryId);
|
|
1628
1655
|
let itemsAndCursor;
|
|
1629
1656
|
switch (entryType) {
|
|
1630
1657
|
case standardsGaiaX.GaiaXTypes.LegalPerson:
|
|
@@ -1641,17 +1668,19 @@ class FederatedCatalogueService {
|
|
|
1641
1668
|
itemsAndCursor = await this.queryDataResources(entryId);
|
|
1642
1669
|
break;
|
|
1643
1670
|
default:
|
|
1644
|
-
throw new core.GeneralError(
|
|
1671
|
+
throw new core.GeneralError(FederatedCatalogueService.CLASS_NAME, "unknownEntryType", {
|
|
1672
|
+
entryType
|
|
1673
|
+
});
|
|
1645
1674
|
}
|
|
1646
1675
|
if (core.Is.arrayValue(itemsAndCursor?.itemListElement)) {
|
|
1647
1676
|
const entry = {
|
|
1648
1677
|
...itemsAndCursor.itemListElement[0],
|
|
1649
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY
|
|
1678
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY, itemsAndCursor["@context"])
|
|
1650
1679
|
};
|
|
1651
1680
|
const result = await dataJsonLd.JsonLdProcessor.compact(entry, entry["@context"]);
|
|
1652
1681
|
return result;
|
|
1653
1682
|
}
|
|
1654
|
-
throw new core.NotFoundError(
|
|
1683
|
+
throw new core.NotFoundError(FederatedCatalogueService.CLASS_NAME, "entryNotFound", entryId);
|
|
1655
1684
|
}
|
|
1656
1685
|
/**
|
|
1657
1686
|
* Registers a compliance Credential concerning a Data Space Connector.
|
|
@@ -1659,19 +1688,19 @@ class FederatedCatalogueService {
|
|
|
1659
1688
|
* @returns The identifier of the Data Space Connector registered.
|
|
1660
1689
|
*/
|
|
1661
1690
|
async registerDataSpaceConnectorCredential(credentialJwt) {
|
|
1662
|
-
core.Guards.string(
|
|
1691
|
+
core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
|
|
1663
1692
|
// This will raise exceptions as it has been coded reusing code from Gaia-X
|
|
1664
1693
|
const complianceCredential = await this.decodeJwt(credentialJwt);
|
|
1665
1694
|
const result = await this._complianceCredentialVerifier.verify(complianceCredential);
|
|
1666
1695
|
if (!result.verified) {
|
|
1667
1696
|
this._logging?.log({
|
|
1668
1697
|
level: "error",
|
|
1669
|
-
source:
|
|
1698
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1670
1699
|
ts: Date.now(),
|
|
1671
1700
|
message: "complianceCredentialNotVerified",
|
|
1672
1701
|
data: { result }
|
|
1673
1702
|
});
|
|
1674
|
-
throw new core.UnprocessableError(
|
|
1703
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
|
|
1675
1704
|
reason: result.verificationFailureReason
|
|
1676
1705
|
});
|
|
1677
1706
|
}
|
|
@@ -1683,21 +1712,25 @@ class FederatedCatalogueService {
|
|
|
1683
1712
|
});
|
|
1684
1713
|
const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
|
|
1685
1714
|
if (core.Is.undefined(targetCredential)) {
|
|
1686
|
-
throw new core.UnprocessableError(
|
|
1715
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
|
|
1687
1716
|
}
|
|
1688
1717
|
await this.checkParticipantExists(targetCredential.issuer);
|
|
1689
|
-
const dataSpaceConnectorEntry = this.extractDataSpaceConnectorEntry(complianceCredential, result.credentials[0]);
|
|
1718
|
+
const { dataSpaceConnectorEntry, extraData } = this.extractDataSpaceConnectorEntry(complianceCredential, result.credentials[0]);
|
|
1690
1719
|
const theEntry = core.ObjectHelper.omit(dataSpaceConnectorEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1691
|
-
|
|
1720
|
+
const extended = theEntry;
|
|
1721
|
+
extended.extraData = extraData;
|
|
1722
|
+
await this._entityStorageDataSpaceConnectors.set(extended);
|
|
1692
1723
|
for (const dataResourceCredential of dataResourceCredentials) {
|
|
1693
1724
|
await this.checkParticipantExists(dataResourceCredential.issuer);
|
|
1694
|
-
const dataResourceEntry = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
|
|
1695
|
-
const
|
|
1696
|
-
|
|
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);
|
|
1697
1730
|
}
|
|
1698
1731
|
await this._logging?.log({
|
|
1699
1732
|
level: "info",
|
|
1700
|
-
source:
|
|
1733
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1701
1734
|
ts: Date.now(),
|
|
1702
1735
|
message: "complianceCredentialVerified",
|
|
1703
1736
|
data: {
|
|
@@ -1713,36 +1746,38 @@ class FederatedCatalogueService {
|
|
|
1713
1746
|
* @returns The list of Data Resources created.
|
|
1714
1747
|
*/
|
|
1715
1748
|
async registerDataResourceCredential(credentialJwt) {
|
|
1716
|
-
core.Guards.string(
|
|
1749
|
+
core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
|
|
1717
1750
|
const complianceCredential = await this.decodeJwt(credentialJwt);
|
|
1718
1751
|
const result = await this._complianceCredentialVerifier.verify(complianceCredential);
|
|
1719
1752
|
if (!result.verified) {
|
|
1720
1753
|
this._logging?.log({
|
|
1721
1754
|
level: "error",
|
|
1722
|
-
source:
|
|
1755
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1723
1756
|
ts: Date.now(),
|
|
1724
1757
|
message: "complianceCredentialNotVerified",
|
|
1725
1758
|
data: { result }
|
|
1726
1759
|
});
|
|
1727
|
-
throw new core.UnprocessableError(
|
|
1760
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
|
|
1728
1761
|
reason: result.verificationFailureReason
|
|
1729
1762
|
});
|
|
1730
1763
|
}
|
|
1731
1764
|
const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
|
|
1732
1765
|
if (dataResourceCredentials.length === 0) {
|
|
1733
|
-
throw new core.UnprocessableError(
|
|
1766
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
|
|
1734
1767
|
}
|
|
1735
1768
|
const dataResourceIds = [];
|
|
1736
1769
|
for (const dataResourceCredential of dataResourceCredentials) {
|
|
1737
1770
|
await this.checkParticipantExists(dataResourceCredential.issuer);
|
|
1738
|
-
const dataResourceEntry = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
|
|
1771
|
+
const { dataResourceEntry, extraData } = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
|
|
1739
1772
|
const theEntry = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1740
|
-
|
|
1773
|
+
const extended = theEntry;
|
|
1774
|
+
extended.extraData = extraData;
|
|
1775
|
+
await this._entityStorageDataResources.set(extended);
|
|
1741
1776
|
dataResourceIds.push(dataResourceEntry.id);
|
|
1742
1777
|
}
|
|
1743
1778
|
await this._logging?.log({
|
|
1744
1779
|
level: "info",
|
|
1745
|
-
source:
|
|
1780
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1746
1781
|
ts: Date.now(),
|
|
1747
1782
|
message: "complianceCredentialVerified",
|
|
1748
1783
|
data: {
|
|
@@ -1756,13 +1791,13 @@ class FederatedCatalogueService {
|
|
|
1756
1791
|
* Query the federated catalogue.
|
|
1757
1792
|
* @param id The identity of the participant.
|
|
1758
1793
|
* @param maintainer The DS Connector maintainer.
|
|
1759
|
-
* @param cursor The cursor to request the next
|
|
1760
|
-
* @param
|
|
1794
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
1795
|
+
* @param limit Limit the number of entities to return.
|
|
1761
1796
|
* @returns All the entities for the storage matching the conditions,
|
|
1762
1797
|
* and a cursor which can be used to request more entities.
|
|
1763
1798
|
* @throws NotImplementedError if the implementation does not support retrieval.
|
|
1764
1799
|
*/
|
|
1765
|
-
async queryDataSpaceConnectors(id, maintainer, cursor,
|
|
1800
|
+
async queryDataSpaceConnectors(id, maintainer, cursor, limit) {
|
|
1766
1801
|
const conditions = [];
|
|
1767
1802
|
if (core.Is.stringValue(id)) {
|
|
1768
1803
|
const condition = {
|
|
@@ -1780,7 +1815,7 @@ class FederatedCatalogueService {
|
|
|
1780
1815
|
};
|
|
1781
1816
|
conditions.push(condition);
|
|
1782
1817
|
}
|
|
1783
|
-
const entries = await this._entityStorageDataSpaceConnectors.query({ conditions }, undefined, undefined, cursor,
|
|
1818
|
+
const entries = await this._entityStorageDataSpaceConnectors.query({ conditions }, undefined, undefined, cursor, limit);
|
|
1784
1819
|
const itemList = entries.entities.map(entry => {
|
|
1785
1820
|
entry.type = [
|
|
1786
1821
|
standardsGaiaX.GaiaXTypes.DataExchangeComponent,
|
|
@@ -1788,10 +1823,11 @@ class FederatedCatalogueService {
|
|
|
1788
1823
|
];
|
|
1789
1824
|
return entry;
|
|
1790
1825
|
});
|
|
1826
|
+
const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
|
|
1791
1827
|
const result = {
|
|
1792
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
|
|
1828
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
|
|
1793
1829
|
type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
|
|
1794
|
-
itemListElement:
|
|
1830
|
+
itemListElement: finalItemList,
|
|
1795
1831
|
nextItem: entries.cursor
|
|
1796
1832
|
};
|
|
1797
1833
|
return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
|
|
@@ -1802,44 +1838,48 @@ class FederatedCatalogueService {
|
|
|
1802
1838
|
* @returns Nothing.
|
|
1803
1839
|
*/
|
|
1804
1840
|
async registerServiceOfferingCredential(credentialJwt) {
|
|
1805
|
-
core.Guards.string(
|
|
1841
|
+
core.Guards.string(FederatedCatalogueService.CLASS_NAME, "credentialJwt", credentialJwt);
|
|
1806
1842
|
// This will raise exceptions as it has been coded reusing code from Gaia-X
|
|
1807
1843
|
const sdComplianceCredential = await this.decodeJwt(credentialJwt);
|
|
1808
1844
|
const result = await this._complianceCredentialVerifier.verify(sdComplianceCredential);
|
|
1809
1845
|
if (!result.verified) {
|
|
1810
1846
|
this._logging?.log({
|
|
1811
1847
|
level: "error",
|
|
1812
|
-
source:
|
|
1848
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1813
1849
|
ts: Date.now(),
|
|
1814
1850
|
message: "complianceCredentialNotVerified",
|
|
1815
1851
|
data: { result }
|
|
1816
1852
|
});
|
|
1817
|
-
throw new core.UnprocessableError(
|
|
1853
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "complianceCredentialNotVerified", {
|
|
1818
1854
|
reason: result.verificationFailureReason
|
|
1819
1855
|
});
|
|
1820
1856
|
}
|
|
1821
1857
|
const serviceOfferingCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.ServiceOffering);
|
|
1822
1858
|
const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
|
|
1823
1859
|
if (serviceOfferingCredentials.length === 0) {
|
|
1824
|
-
throw new core.UnprocessableError(
|
|
1860
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "noEvidence");
|
|
1825
1861
|
}
|
|
1826
1862
|
const serviceOfferingIds = [];
|
|
1827
1863
|
for (const serviceOfferingCredential of serviceOfferingCredentials) {
|
|
1828
1864
|
const serviceIssuer = serviceOfferingCredential.issuer;
|
|
1829
1865
|
await this.checkParticipantExists(serviceIssuer);
|
|
1830
|
-
const serviceOfferingEntry = this.extractServiceOfferingEntry(sdComplianceCredential, serviceOfferingCredential);
|
|
1866
|
+
const { serviceOfferingEntry, extraData } = this.extractServiceOfferingEntry(sdComplianceCredential, serviceOfferingCredential);
|
|
1831
1867
|
const theEntry = core.ObjectHelper.omit(serviceOfferingEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
|
|
1832
|
-
|
|
1868
|
+
const extended = theEntry;
|
|
1869
|
+
extended.extraData = extraData;
|
|
1870
|
+
await this._entityStorageServiceOfferings.set(extended);
|
|
1833
1871
|
serviceOfferingIds.push(serviceOfferingEntry.id);
|
|
1834
1872
|
}
|
|
1835
1873
|
for (const dataResourceCredential of dataResourceCredentials) {
|
|
1836
1874
|
await this.checkParticipantExists(dataResourceCredential.issuer);
|
|
1837
|
-
const dataResourceEntry = this.extractDataResourceEntry(sdComplianceCredential, dataResourceCredential);
|
|
1838
|
-
|
|
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);
|
|
1839
1879
|
}
|
|
1840
1880
|
await this._logging?.log({
|
|
1841
1881
|
level: "info",
|
|
1842
|
-
source:
|
|
1882
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
1843
1883
|
ts: Date.now(),
|
|
1844
1884
|
message: "complianceCredentialVerified",
|
|
1845
1885
|
data: {
|
|
@@ -1853,13 +1893,13 @@ class FederatedCatalogueService {
|
|
|
1853
1893
|
* Query the federated catalogue.
|
|
1854
1894
|
* @param id Service Id.
|
|
1855
1895
|
* @param providedBy The identity of the participant.
|
|
1856
|
-
* @param cursor The cursor to request the next
|
|
1857
|
-
* @param
|
|
1896
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
1897
|
+
* @param limit Limit the number of entities to return.
|
|
1858
1898
|
* @returns All the entities for the storage matching the conditions,
|
|
1859
1899
|
* and a cursor which can be used to request more entities.
|
|
1860
1900
|
* @throws NotImplementedError if the implementation does not support retrieval.
|
|
1861
1901
|
*/
|
|
1862
|
-
async queryServiceOfferings(id, providedBy, cursor,
|
|
1902
|
+
async queryServiceOfferings(id, providedBy, cursor, limit) {
|
|
1863
1903
|
const conditions = [];
|
|
1864
1904
|
if (core.Is.stringValue(providedBy)) {
|
|
1865
1905
|
const condition = {
|
|
@@ -1877,15 +1917,16 @@ class FederatedCatalogueService {
|
|
|
1877
1917
|
};
|
|
1878
1918
|
conditions.push(condition);
|
|
1879
1919
|
}
|
|
1880
|
-
const entries = await this._entityStorageServiceOfferings.query({ conditions }, undefined, undefined, cursor,
|
|
1920
|
+
const entries = await this._entityStorageServiceOfferings.query({ conditions }, undefined, undefined, cursor, limit);
|
|
1881
1921
|
const itemList = entries.entities.map(entry => {
|
|
1882
1922
|
entry.type = standardsGaiaX.GaiaXTypes.ServiceOffering;
|
|
1883
1923
|
return entry;
|
|
1884
1924
|
});
|
|
1925
|
+
const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
|
|
1885
1926
|
const result = {
|
|
1886
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
|
|
1927
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
|
|
1887
1928
|
type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
|
|
1888
|
-
itemListElement:
|
|
1929
|
+
itemListElement: finalItemList,
|
|
1889
1930
|
nextItem: entries.cursor
|
|
1890
1931
|
};
|
|
1891
1932
|
return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
|
|
@@ -1894,13 +1935,13 @@ class FederatedCatalogueService {
|
|
|
1894
1935
|
* Query the federated catalogue.
|
|
1895
1936
|
* @param id The identity of the DataResource.
|
|
1896
1937
|
* @param producedBy The identity of the participant.
|
|
1897
|
-
* @param cursor The cursor to request the next
|
|
1898
|
-
* @param
|
|
1938
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
1939
|
+
* @param limit Limit the number of entities to return.
|
|
1899
1940
|
* @returns All the entities for the storage matching the conditions,
|
|
1900
1941
|
* and a cursor which can be used to request more entities.
|
|
1901
1942
|
* @throws NotImplementedError if the implementation does not support retrieval.
|
|
1902
1943
|
*/
|
|
1903
|
-
async queryDataResources(id, producedBy, cursor,
|
|
1944
|
+
async queryDataResources(id, producedBy, cursor, limit) {
|
|
1904
1945
|
const conditions = [];
|
|
1905
1946
|
if (core.Is.stringValue(producedBy)) {
|
|
1906
1947
|
const condition = {
|
|
@@ -1918,23 +1959,44 @@ class FederatedCatalogueService {
|
|
|
1918
1959
|
};
|
|
1919
1960
|
conditions.push(condition);
|
|
1920
1961
|
}
|
|
1921
|
-
const entries = await this._entityStorageDataResources.query({ conditions }, undefined, undefined, cursor,
|
|
1962
|
+
const entries = await this._entityStorageDataResources.query({ conditions }, undefined, undefined, cursor, limit);
|
|
1922
1963
|
const itemList = entries.entities.map(entry => {
|
|
1923
1964
|
entry.type = standardsGaiaX.GaiaXTypes.DataResource;
|
|
1924
1965
|
return entry;
|
|
1925
1966
|
});
|
|
1967
|
+
const { finalItemList, extraDataLdContext } = this.normalizeExtraData(itemList);
|
|
1926
1968
|
const result = {
|
|
1927
|
-
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
|
|
1969
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts(federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST, extraDataLdContext),
|
|
1928
1970
|
type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
|
|
1929
|
-
itemListElement:
|
|
1971
|
+
itemListElement: finalItemList,
|
|
1930
1972
|
nextItem: entries.cursor
|
|
1931
1973
|
};
|
|
1932
1974
|
return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
|
|
1933
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
|
+
}
|
|
1934
1995
|
/**
|
|
1935
1996
|
* Decodes the JWT.
|
|
1936
1997
|
* @param jwt JWT.
|
|
1937
1998
|
* @returns Decoded.
|
|
1999
|
+
* @internal
|
|
1938
2000
|
*/
|
|
1939
2001
|
async decodeJwt(jwt) {
|
|
1940
2002
|
const { payload } = await identityModels.VerificationHelper.verifyJwt(this._resolver, jwt);
|
|
@@ -1944,6 +2006,7 @@ class FederatedCatalogueService {
|
|
|
1944
2006
|
* Returns the trusted Issuer id.
|
|
1945
2007
|
* @param complianceCredential The compliance credential.
|
|
1946
2008
|
* @returns The trusted issuer.
|
|
2009
|
+
* @internal
|
|
1947
2010
|
*/
|
|
1948
2011
|
getTrustedIssuerId(complianceCredential) {
|
|
1949
2012
|
const trustedIssuerId = core.Is.object(complianceCredential.issuer)
|
|
@@ -1956,16 +2019,18 @@ class FederatedCatalogueService {
|
|
|
1956
2019
|
* @param complianceCredential Compliance credential
|
|
1957
2020
|
* @param participantCredential The Participant credential extracted.
|
|
1958
2021
|
* @returns Participant Entry to be saved on the Database.
|
|
2022
|
+
* @internal
|
|
1959
2023
|
*/
|
|
1960
2024
|
extractParticipantEntry(complianceCredential, participantCredential) {
|
|
1961
2025
|
const participantData = participantCredential.credentialSubject;
|
|
1962
|
-
core.Guards.objectValue(
|
|
2026
|
+
core.Guards.objectValue(FederatedCatalogueService.CLASS_NAME, "participantData", participantData);
|
|
1963
2027
|
const evidences = [];
|
|
1964
2028
|
for (const evidence of complianceCredential.evidence) {
|
|
1965
2029
|
evidences.push(evidence.id);
|
|
1966
2030
|
}
|
|
2031
|
+
const { data, extraData } = this.extractExtraData(participantData, entity.EntitySchemaFactory.get("ParticipantEntry"));
|
|
1967
2032
|
const result = {
|
|
1968
|
-
...
|
|
2033
|
+
...data,
|
|
1969
2034
|
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
|
|
1970
2035
|
issuer: this.getTrustedIssuerId(complianceCredential),
|
|
1971
2036
|
validFrom: complianceCredential.validFrom,
|
|
@@ -1973,18 +2038,20 @@ class FederatedCatalogueService {
|
|
|
1973
2038
|
dateCreated: new Date().toISOString(),
|
|
1974
2039
|
evidence: evidences
|
|
1975
2040
|
};
|
|
1976
|
-
return result;
|
|
2041
|
+
return { participantEntry: result, extraData };
|
|
1977
2042
|
}
|
|
1978
2043
|
/**
|
|
1979
2044
|
* Extracts Data Space Connector description entry from the credentials.
|
|
1980
2045
|
* @param complianceCredential Compliance Credential.
|
|
1981
2046
|
* @param dataSpaceConnectorCredential Evidence Credential.
|
|
1982
2047
|
* @returns Service Description Entry to be saved on the Database.
|
|
2048
|
+
* @internal
|
|
1983
2049
|
*/
|
|
1984
2050
|
extractDataSpaceConnectorEntry(complianceCredential, dataSpaceConnectorCredential) {
|
|
1985
2051
|
const credentialData = dataSpaceConnectorCredential.credentialSubject;
|
|
1986
|
-
core.Guards.objectValue(
|
|
1987
|
-
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;
|
|
1988
2055
|
const result = {
|
|
1989
2056
|
...deStructuredData,
|
|
1990
2057
|
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
|
|
@@ -1995,18 +2062,20 @@ class FederatedCatalogueService {
|
|
|
1995
2062
|
dateCreated: new Date().toISOString(),
|
|
1996
2063
|
evidence: [dataSpaceConnectorCredential.id]
|
|
1997
2064
|
};
|
|
1998
|
-
return result;
|
|
2065
|
+
return { dataSpaceConnectorEntry: result, extraData };
|
|
1999
2066
|
}
|
|
2000
2067
|
/**
|
|
2001
2068
|
* Extracts service offering entry from the credentials.
|
|
2002
2069
|
* @param complianceCredential The Compliance Credential.
|
|
2003
2070
|
* @param serviceOfferingCredential Service Offering credential (evidence).
|
|
2004
2071
|
* @returns Service Offering Entry to be saved on the Database.
|
|
2072
|
+
* @internal
|
|
2005
2073
|
*/
|
|
2006
2074
|
extractServiceOfferingEntry(complianceCredential, serviceOfferingCredential) {
|
|
2007
2075
|
const credentialData = serviceOfferingCredential.credentialSubject;
|
|
2008
|
-
core.Guards.objectValue(
|
|
2009
|
-
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;
|
|
2010
2079
|
const result = {
|
|
2011
2080
|
...deStructuredData,
|
|
2012
2081
|
"@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
|
|
@@ -2019,18 +2088,20 @@ class FederatedCatalogueService {
|
|
|
2019
2088
|
evidence: [serviceOfferingCredential.id],
|
|
2020
2089
|
servicePolicy: core.ArrayHelper.fromObjectOrArray(servicePolicy)
|
|
2021
2090
|
};
|
|
2022
|
-
return result;
|
|
2091
|
+
return { serviceOfferingEntry: result, extraData };
|
|
2023
2092
|
}
|
|
2024
2093
|
/**
|
|
2025
2094
|
* Extracts data resource entry from the credentials.
|
|
2026
2095
|
* @param complianceCredential The Compliance Credential.
|
|
2027
2096
|
* @param dataResourceCredential Data Resource credential.
|
|
2028
2097
|
* @returns DataResource Entry to be saved on the Database.
|
|
2098
|
+
* @internal
|
|
2029
2099
|
*/
|
|
2030
2100
|
extractDataResourceEntry(complianceCredential, dataResourceCredential) {
|
|
2031
2101
|
const credentialData = dataResourceCredential.credentialSubject;
|
|
2032
|
-
core.Guards.objectValue(
|
|
2033
|
-
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;
|
|
2034
2105
|
let producedByValue = producedBy;
|
|
2035
2106
|
if (core.Is.object(producedByValue)) {
|
|
2036
2107
|
producedByValue = producedByValue.id;
|
|
@@ -2052,27 +2123,50 @@ class FederatedCatalogueService {
|
|
|
2052
2123
|
evidence: [dataResourceCredential.id],
|
|
2053
2124
|
resourcePolicy: core.ArrayHelper.fromObjectOrArray(resourcePolicy)
|
|
2054
2125
|
};
|
|
2055
|
-
return result;
|
|
2126
|
+
return { dataResourceEntry: result, extraData };
|
|
2056
2127
|
}
|
|
2057
2128
|
/**
|
|
2058
2129
|
* Checks whether the Participant exists.
|
|
2059
2130
|
* @param participantId The Participant identifier
|
|
2131
|
+
* @internal
|
|
2060
2132
|
*/
|
|
2061
2133
|
async checkParticipantExists(participantId) {
|
|
2062
2134
|
const participantData = await this._entityStorageParticipants.get(participantId);
|
|
2063
2135
|
if (!participantData) {
|
|
2064
2136
|
this._logging?.log({
|
|
2065
2137
|
level: "error",
|
|
2066
|
-
source:
|
|
2138
|
+
source: FederatedCatalogueService.CLASS_NAME,
|
|
2067
2139
|
ts: Date.now(),
|
|
2068
2140
|
message: "providerIsNotParticipant",
|
|
2069
2141
|
data: { providedBy: participantId }
|
|
2070
2142
|
});
|
|
2071
|
-
throw new core.UnprocessableError(
|
|
2143
|
+
throw new core.UnprocessableError(FederatedCatalogueService.CLASS_NAME, "providerIsNotParticipant", {
|
|
2072
2144
|
providedBy: participantId
|
|
2073
2145
|
});
|
|
2074
2146
|
}
|
|
2075
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
|
+
}
|
|
2076
2170
|
}
|
|
2077
2171
|
|
|
2078
2172
|
const restEntryPoints = [
|