@twin.org/federated-catalogue-service 0.0.1-next.3

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.
Files changed (46) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +21 -0
  3. package/dist/cjs/index.cjs +2149 -0
  4. package/dist/esm/index.mjs +2131 -0
  5. package/dist/types/entities/dataResourceEntry.d.ts +59 -0
  6. package/dist/types/entities/dataSpaceConnectorEntry.d.ts +66 -0
  7. package/dist/types/entities/participantEntry.d.ts +42 -0
  8. package/dist/types/entities/serviceOfferingEntry.d.ts +55 -0
  9. package/dist/types/federatedCatalogueRoutes.d.ts +113 -0
  10. package/dist/types/federatedCatalogueService.d.ts +138 -0
  11. package/dist/types/index.d.ts +10 -0
  12. package/dist/types/models/IFederatedCatalogueConfig.d.ts +15 -0
  13. package/dist/types/models/IFederatedCatalogueConstructorOptions.d.ts +38 -0
  14. package/dist/types/restEntryPoints.d.ts +2 -0
  15. package/dist/types/schema.d.ts +4 -0
  16. package/dist/types/verification/complianceCredentialVerificationService.d.ts +32 -0
  17. package/docs/changelog.md +40 -0
  18. package/docs/examples.md +1 -0
  19. package/docs/open-api/spec.json +5345 -0
  20. package/docs/overview.md +21 -0
  21. package/docs/reference/classes/DataResourceEntry.md +118 -0
  22. package/docs/reference/classes/DataSpaceConnectorEntry.md +133 -0
  23. package/docs/reference/classes/FederatedCatalogueService.md +381 -0
  24. package/docs/reference/classes/ParticipantEntry.md +85 -0
  25. package/docs/reference/classes/ServiceOfferingEntry.md +109 -0
  26. package/docs/reference/functions/complianceCredentialPresentation.md +37 -0
  27. package/docs/reference/functions/dataResourceCredentialPresentation.md +37 -0
  28. package/docs/reference/functions/dataResourceGet.md +31 -0
  29. package/docs/reference/functions/dataResourceList.md +31 -0
  30. package/docs/reference/functions/dataSpaceConnectorCredentialPresentation.md +37 -0
  31. package/docs/reference/functions/dataSpaceConnectorGet.md +31 -0
  32. package/docs/reference/functions/dataSpaceConnectorList.md +31 -0
  33. package/docs/reference/functions/generateRestRoutesFederatedCatalogue.md +25 -0
  34. package/docs/reference/functions/initSchema.md +9 -0
  35. package/docs/reference/functions/participantGet.md +31 -0
  36. package/docs/reference/functions/participantList.md +31 -0
  37. package/docs/reference/functions/serviceOfferingCredentialPresentation.md +37 -0
  38. package/docs/reference/functions/serviceOfferingGet.md +31 -0
  39. package/docs/reference/functions/serviceOfferingList.md +31 -0
  40. package/docs/reference/index.md +36 -0
  41. package/docs/reference/interfaces/IFederatedCatalogueConfig.md +21 -0
  42. package/docs/reference/interfaces/IFederatedCatalogueConstructorOptions.md +83 -0
  43. package/docs/reference/variables/restEntryPoints.md +3 -0
  44. package/docs/reference/variables/tagsFederatedCatalogue.md +5 -0
  45. package/locales/en.json +21 -0
  46. package/package.json +52 -0
@@ -0,0 +1,2149 @@
1
+ 'use strict';
2
+
3
+ var core = require('@twin.org/core');
4
+ var federatedCatalogueModels = require('@twin.org/federated-catalogue-models');
5
+ var standardsGaiaX = require('@twin.org/standards-gaia-x');
6
+ var standardsSchemaOrg = require('@twin.org/standards-schema-org');
7
+ var web = require('@twin.org/web');
8
+ var dataJsonLd = require('@twin.org/data-json-ld');
9
+ var entity = require('@twin.org/entity');
10
+ var entityStorageModels = require('@twin.org/entity-storage-models');
11
+ var identityModels = require('@twin.org/identity-models');
12
+ var loggingModels = require('@twin.org/logging-models');
13
+ var crypto = require('@twin.org/crypto');
14
+ var standardsW3cDid = require('@twin.org/standards-w3c-did');
15
+
16
+ /**
17
+ * The source used when communicating about these routes.
18
+ */
19
+ const ROUTES_SOURCE = "federatedCatalogueRoutes";
20
+ /**
21
+ * Participants route.
22
+ */
23
+ const PARTICIPANTS_ROUTE = "participants";
24
+ /**
25
+ * Service offering route.
26
+ */
27
+ const SERVICE_OFFERING_ROUTE = "service-offerings";
28
+ /**
29
+ * Data Resource route.
30
+ */
31
+ const DATA_RESOURCE_ROUTE = "data-resources";
32
+ /**
33
+ * Data Space Connector route.
34
+ */
35
+ const DATA_SPACE_CONNECTOR_ROUTE = "data-space-connectors";
36
+ /**
37
+ * The tag to associate with the routes.
38
+ */
39
+ const tagsFederatedCatalogue = [
40
+ {
41
+ name: "Federated Catalogue",
42
+ description: "Endpoints to access a Federated Catalogue."
43
+ }
44
+ ];
45
+ /**
46
+ * The REST routes for Federated Catalogue.
47
+ * @param baseRouteName Prefix to prepend to the paths.
48
+ * @param factoryServiceName The name of the service to use in the routes store in the ServiceFactory.
49
+ * @returns The generated routes.
50
+ */
51
+ function generateRestRoutesFederatedCatalogue(baseRouteName, factoryServiceName) {
52
+ const createParticipantRoute = {
53
+ operationId: "compliancePresentationRequest",
54
+ summary: "Present a Compliance Credential",
55
+ tag: tagsFederatedCatalogue[0].name,
56
+ method: "POST",
57
+ path: `${baseRouteName}/participant-credentials`,
58
+ handler: async (httpRequestContext, request) => complianceCredentialPresentation(baseRouteName, httpRequestContext, factoryServiceName, request),
59
+ requestType: {
60
+ mimeType: web.MimeTypes.Jwt,
61
+ type: "ICompliancePresentationRequest",
62
+ examples: [
63
+ {
64
+ id: "compliancePresentationRequestExample",
65
+ request: {
66
+ body: "ey..."
67
+ }
68
+ }
69
+ ]
70
+ },
71
+ responseType: [
72
+ {
73
+ type: "ICreatedResponse"
74
+ },
75
+ { type: "IUnprocessableEntityResponse" }
76
+ ]
77
+ };
78
+ const createServiceOfferingRoute = {
79
+ operationId: "serviceOfferingPresentationRequest",
80
+ summary: "Present a Service Offering Credential",
81
+ tag: tagsFederatedCatalogue[0].name,
82
+ method: "POST",
83
+ path: `${baseRouteName}/service-offering-credentials`,
84
+ handler: async (httpRequestContext, request) => serviceOfferingCredentialPresentation(baseRouteName, httpRequestContext, factoryServiceName, request),
85
+ requestType: {
86
+ mimeType: web.MimeTypes.Jwt,
87
+ type: "ICompliancePresentationRequest",
88
+ examples: [
89
+ {
90
+ id: "serviceOfferingPresentationRequestExample",
91
+ request: {
92
+ body: "ey..."
93
+ }
94
+ }
95
+ ]
96
+ },
97
+ responseType: [
98
+ {
99
+ type: "ICreatedResponse"
100
+ },
101
+ { type: "IUnprocessableEntityResponse" }
102
+ ]
103
+ };
104
+ const createDataSpaceConnectorRoute = {
105
+ operationId: "dataSpaceConnectorPresentationRequest",
106
+ summary: "Present a Data Space Connector Credential",
107
+ tag: tagsFederatedCatalogue[0].name,
108
+ method: "POST",
109
+ path: `${baseRouteName}/data-space-connector-credentials`,
110
+ handler: async (httpRequestContext, request) => dataSpaceConnectorCredentialPresentation(baseRouteName, httpRequestContext, factoryServiceName, request),
111
+ requestType: {
112
+ mimeType: web.MimeTypes.Jwt,
113
+ type: "ICompliancePresentationRequest",
114
+ examples: [
115
+ {
116
+ id: "dataSpaceConnectorPresentationRequestExample",
117
+ request: {
118
+ body: "ey..."
119
+ }
120
+ }
121
+ ]
122
+ },
123
+ responseType: [
124
+ {
125
+ type: "ICreatedResponse"
126
+ },
127
+ { type: "IUnprocessableEntityResponse" }
128
+ ]
129
+ };
130
+ const createDataResourceRoute = {
131
+ operationId: "dataResourcePresentationRequest",
132
+ summary: "Present a Data Resource Credential",
133
+ tag: tagsFederatedCatalogue[0].name,
134
+ method: "POST",
135
+ path: `${baseRouteName}/data-resource-credentials`,
136
+ handler: async (httpRequestContext, request) => dataResourceCredentialPresentation(baseRouteName, httpRequestContext, factoryServiceName, request),
137
+ requestType: {
138
+ mimeType: web.MimeTypes.Jwt,
139
+ type: "ICompliancePresentationRequest",
140
+ examples: [
141
+ {
142
+ id: "dataResourcePresentationRequestExample",
143
+ request: {
144
+ body: "ey..."
145
+ }
146
+ }
147
+ ]
148
+ },
149
+ responseType: [
150
+ {
151
+ type: "ICreatedResponse"
152
+ },
153
+ { type: "IUnprocessableEntityResponse" }
154
+ ]
155
+ };
156
+ const participantEntryExample = {
157
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
158
+ id: "did:iota:xxx",
159
+ type: standardsGaiaX.GaiaXTypes.Participant,
160
+ registrationNumber: {
161
+ type: standardsGaiaX.GaiaXTypes.LocalRegistrationNumber,
162
+ local: "P1234567"
163
+ },
164
+ legalName: "A Inc.",
165
+ issuer: "did:iota:zzz",
166
+ legalAddress: {
167
+ type: standardsGaiaX.GaiaXTypes.Address,
168
+ countryCode: "KE"
169
+ },
170
+ validFrom: "2024-08-01T12:00:00Z",
171
+ validUntil: "2025-08-01T12:00:00Z",
172
+ dateCreated: "2024-08-02T13:45:00Z",
173
+ evidence: ["https://credentials.example.org/1234567"]
174
+ };
175
+ const listParticipantsRoute = {
176
+ operationId: "federatedCatalogueListParticipants",
177
+ summary: "Get a list of the participant entries",
178
+ tag: tagsFederatedCatalogue[0].name,
179
+ method: "GET",
180
+ path: `${baseRouteName}/${PARTICIPANTS_ROUTE}`,
181
+ handler: async (httpRequestContext, request) => participantList(httpRequestContext, factoryServiceName, request),
182
+ requestType: {
183
+ type: "IParticipantListRequest",
184
+ examples: [
185
+ {
186
+ id: "participantListRequestExample",
187
+ request: {
188
+ query: {
189
+ registrationNumber: "abc"
190
+ }
191
+ }
192
+ }
193
+ ]
194
+ },
195
+ responseType: [
196
+ {
197
+ type: "IParticipantListResponse",
198
+ examples: [
199
+ {
200
+ id: "participantListResponseExample",
201
+ response: {
202
+ body: {
203
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
204
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
205
+ itemListElement: [
206
+ {
207
+ ...participantEntryExample
208
+ }
209
+ ]
210
+ }
211
+ }
212
+ }
213
+ ]
214
+ }
215
+ ]
216
+ };
217
+ const getParticipantRoute = {
218
+ operationId: "federatedCatalogueGetParticipant",
219
+ summary: "Get a participant",
220
+ tag: tagsFederatedCatalogue[0].name,
221
+ method: "GET",
222
+ path: `${baseRouteName}/${PARTICIPANTS_ROUTE}/:id`,
223
+ handler: async (httpRequestContext, request) => participantGet(httpRequestContext, factoryServiceName, request),
224
+ requestType: {
225
+ type: "ICatalogueEntryGetRequest",
226
+ examples: [
227
+ {
228
+ id: "participantGetRequestExample",
229
+ request: {
230
+ pathParams: {
231
+ id: "did:iota:123456"
232
+ }
233
+ }
234
+ }
235
+ ]
236
+ },
237
+ responseType: [
238
+ {
239
+ type: "IParticipantGetResponse",
240
+ examples: [
241
+ {
242
+ id: "participantGetResponseExample",
243
+ response: {
244
+ body: { ...participantEntryExample }
245
+ }
246
+ }
247
+ ]
248
+ }
249
+ ]
250
+ };
251
+ const servicePolicyExample = {
252
+ "@context": [
253
+ "https://www.w3.org/ns/odrl.jsonld",
254
+ {
255
+ twin: "https://schema.twindev.org/odrl/",
256
+ jsonPathSelector: "twin:jsonPathSelector"
257
+ }
258
+ ],
259
+ "@type": "Agreement",
260
+ uid: "http://example.com/policy:1010",
261
+ assigner: "did:iota:testnet:0x1a7bded4d22dc54722435d624e4323e10fcbc570cd57462eabbf3a5ab2ced24f",
262
+ assignee: "did:iota:testnet:0x119adb64d01d3b0fa0d308c67db90ab1c6e0df6aebe5b7e0250783f57cd10c21",
263
+ permission: [
264
+ {
265
+ target: {
266
+ type: "https://vocabulary.uncefact.org/Document",
267
+ refinement: {
268
+ leftOperand: {
269
+ "@id": "https://w3id.org/twin/odrl/propertyValue",
270
+ jsonPathSelector: ".documentTypeCode"
271
+ },
272
+ operator: "eq",
273
+ rightOperand: "https://vocabulary.uncefact.org/DocumentCodeList#331"
274
+ }
275
+ },
276
+ action: "extract"
277
+ }
278
+ ]
279
+ };
280
+ const serviceOfferingEntryExample = {
281
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
282
+ id: "http://example.org/is123456",
283
+ name: "Service 1",
284
+ type: standardsGaiaX.GaiaXTypes.ServiceOffering,
285
+ servicePolicy: [servicePolicyExample],
286
+ endpoint: {
287
+ type: standardsGaiaX.GaiaXTypes.Endpoint,
288
+ endpointURL: "https://endpoint.example.org/api"
289
+ },
290
+ issuer: "did:iota:7890",
291
+ providedBy: "did:iota:1234567",
292
+ validFrom: "2024-08-01T12:00:00Z",
293
+ validUntil: "2025-08-01T12:00:00Z",
294
+ dateCreated: "2024-08-02T13:45:00Z",
295
+ evidence: ["https://credentials.example.org/1234567"]
296
+ };
297
+ const listServicesRoute = {
298
+ operationId: "federatedCatalogueListServices",
299
+ summary: "Get a list of the service entries",
300
+ tag: tagsFederatedCatalogue[0].name,
301
+ method: "GET",
302
+ path: `${baseRouteName}/${SERVICE_OFFERING_ROUTE}`,
303
+ handler: async (httpRequestContext, request) => serviceOfferingList(httpRequestContext, factoryServiceName, request),
304
+ requestType: {
305
+ type: "IServiceOfferingListRequest",
306
+ examples: [
307
+ {
308
+ id: "serviceOfferingListRequestExample",
309
+ request: {
310
+ query: {
311
+ providedBy: "did:iota:1234"
312
+ }
313
+ }
314
+ }
315
+ ]
316
+ },
317
+ responseType: [
318
+ {
319
+ type: "IServiceOfferingListResponse",
320
+ examples: [
321
+ {
322
+ id: "serviceOfferingListResponseExample",
323
+ response: {
324
+ body: {
325
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
326
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
327
+ itemListElement: [
328
+ {
329
+ ...serviceOfferingEntryExample
330
+ }
331
+ ]
332
+ }
333
+ }
334
+ }
335
+ ]
336
+ }
337
+ ]
338
+ };
339
+ const getServiceRoute = {
340
+ operationId: "federatedCatalogueGetService",
341
+ summary: "Get a Service Offering entry",
342
+ tag: tagsFederatedCatalogue[0].name,
343
+ method: "GET",
344
+ path: `${baseRouteName}/${SERVICE_OFFERING_ROUTE}/:id`,
345
+ handler: async (httpRequestContext, request) => serviceOfferingGet(httpRequestContext, factoryServiceName, request),
346
+ requestType: {
347
+ type: "ICatalogueEntryGetRequest",
348
+ examples: [
349
+ {
350
+ id: "serviceOfferingGetRequestExample",
351
+ request: {
352
+ pathParams: {
353
+ id: "https://my-services.example.org/service1"
354
+ }
355
+ }
356
+ }
357
+ ]
358
+ },
359
+ responseType: [
360
+ {
361
+ type: "IServiceOfferingGetResponse",
362
+ examples: [
363
+ {
364
+ id: "serviceOfferingGetResponseExample",
365
+ response: {
366
+ body: {
367
+ ...serviceOfferingEntryExample
368
+ }
369
+ }
370
+ }
371
+ ]
372
+ }
373
+ ]
374
+ };
375
+ const resourcePolicyExample = {
376
+ "@context": ["https://www.w3.org/ns/odrl.jsonld"],
377
+ "@type": "Offer",
378
+ uid: "http://example.com/policy:1010",
379
+ assigner: "did:iota:testnet:0x1a7bded4d22dc54722435d624e4323e10fcbc570cd57462eabbf3a5ab2ced24f",
380
+ permission: [
381
+ {
382
+ target: {
383
+ type: "https://vocabulary.uncefact.org/Document"
384
+ },
385
+ action: "extract"
386
+ }
387
+ ]
388
+ };
389
+ const dataResourceEntryExample = {
390
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
391
+ id: "http://example.org/is123456",
392
+ name: "Data Resource 1",
393
+ type: "DataResource",
394
+ copyrightOwnedBy: "did:iota:1234",
395
+ license: "http://licenses.example.org/12345",
396
+ resourcePolicy: [resourcePolicyExample],
397
+ exposedThrough: "https://ds-connectors.example.org/ds1",
398
+ producedBy: "did:iota:1234567",
399
+ issuer: "did:iota:987654",
400
+ validFrom: "2024-08-01T12:00:00Z",
401
+ validUntil: "2025-08-01T12:00:00Z",
402
+ dateCreated: "2024-08-02T13:45:00Z",
403
+ evidence: ["https://credentials.example.org/1234567"]
404
+ };
405
+ const listDataResourcesRoute = {
406
+ operationId: "federatedCatalogueListResources",
407
+ summary: "Get a list of the data resource entries",
408
+ tag: tagsFederatedCatalogue[0].name,
409
+ method: "GET",
410
+ path: `${baseRouteName}/${DATA_RESOURCE_ROUTE}`,
411
+ handler: async (httpRequestContext, request) => dataResourceList(httpRequestContext, factoryServiceName, request),
412
+ requestType: {
413
+ type: "IDataResourceListRequest",
414
+ examples: [
415
+ {
416
+ id: "dataResourceListRequestExample",
417
+ request: {
418
+ query: {
419
+ producedBy: "did:iota:1234"
420
+ }
421
+ }
422
+ }
423
+ ]
424
+ },
425
+ responseType: [
426
+ {
427
+ type: "IDataResourceListResponse",
428
+ examples: [
429
+ {
430
+ id: "dataResourceListResponseExample",
431
+ response: {
432
+ body: {
433
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
434
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
435
+ itemListElement: [
436
+ {
437
+ ...dataResourceEntryExample
438
+ }
439
+ ]
440
+ }
441
+ }
442
+ }
443
+ ]
444
+ }
445
+ ]
446
+ };
447
+ const getDataResourceRoute = {
448
+ operationId: "federatedCatalogueGetDataResource",
449
+ summary: "Get a Data Resource entry",
450
+ tag: tagsFederatedCatalogue[0].name,
451
+ method: "GET",
452
+ path: `${baseRouteName}/${DATA_RESOURCE_ROUTE}/:id`,
453
+ handler: async (httpRequestContext, request) => dataResourceGet(httpRequestContext, factoryServiceName, request),
454
+ requestType: {
455
+ type: "IDataResourceListRequest",
456
+ examples: [
457
+ {
458
+ id: "dataResourceListRequestExample",
459
+ request: {
460
+ pathParams: {
461
+ id: "https://data-resources.example.org/drs1"
462
+ }
463
+ }
464
+ }
465
+ ]
466
+ },
467
+ responseType: [
468
+ {
469
+ type: "IDataResourceGetResponse",
470
+ examples: [
471
+ {
472
+ id: "dataResourceGetResponseExample",
473
+ response: {
474
+ body: {
475
+ ...dataResourceEntryExample
476
+ }
477
+ }
478
+ }
479
+ ]
480
+ }
481
+ ]
482
+ };
483
+ const dataSpaceConnectorEntryExample = {
484
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
485
+ id: "https://my-ds-connectors.example.org/ds-connector-ABCD",
486
+ type: [standardsGaiaX.GaiaXTypes.DataExchangeComponent, federatedCatalogueModels.FederatedCatalogueTypes.DataSpaceConnector],
487
+ identity: "did:iota:testnet:123456",
488
+ defaultEndpoint: {
489
+ type: standardsGaiaX.GaiaXTypes.Endpoint,
490
+ endpointURL: "https://my-twin-node.example.org:9000/twin-ds-connector"
491
+ },
492
+ subscriptionActivityEndpoint: {
493
+ type: standardsGaiaX.GaiaXTypes.Endpoint,
494
+ endpointURL: "/subscriptions"
495
+ },
496
+ pushActivityEndpoint: {
497
+ type: standardsGaiaX.GaiaXTypes.Endpoint,
498
+ endpointURL: "/notify"
499
+ },
500
+ pullDataEndpoint: {
501
+ type: standardsGaiaX.GaiaXTypes.Endpoint,
502
+ endpointURL: "/data"
503
+ },
504
+ maintainer: "did:iota:99999",
505
+ offeredResource: ["https://my-data-resource.example.org"],
506
+ issuer: "did:iota:987654",
507
+ validFrom: "2024-08-01T12:00:00Z",
508
+ validUntil: "2025-08-01T12:00:00Z",
509
+ dateCreated: "2024-08-02T13:45:00Z",
510
+ evidence: ["https://credentials.example.org/1234567"]
511
+ };
512
+ const listDataSpaceConnectorsRoute = {
513
+ operationId: "federatedCatalogueListDataSpaceConnectors",
514
+ summary: "Get a list of the Data Space connectors entries",
515
+ tag: tagsFederatedCatalogue[0].name,
516
+ method: "GET",
517
+ path: `${baseRouteName}/${DATA_SPACE_CONNECTOR_ROUTE}`,
518
+ handler: async (httpRequestContext, request) => dataSpaceConnectorList(httpRequestContext, factoryServiceName, request),
519
+ requestType: {
520
+ type: "IDataSpaceConnectorListRequest",
521
+ examples: [
522
+ {
523
+ id: "dataSpaceConnectorListRequestExample",
524
+ request: {
525
+ query: {
526
+ maintainedBy: "did:iota:1234"
527
+ }
528
+ }
529
+ }
530
+ ]
531
+ },
532
+ responseType: [
533
+ {
534
+ type: "IDataSpaceConnectorListResponse",
535
+ examples: [
536
+ {
537
+ id: "dataSpaceConnectorListResponseExample",
538
+ response: {
539
+ body: {
540
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
541
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
542
+ itemListElement: [
543
+ {
544
+ ...dataSpaceConnectorEntryExample
545
+ }
546
+ ]
547
+ }
548
+ }
549
+ }
550
+ ]
551
+ }
552
+ ]
553
+ };
554
+ const getDataSpaceConnectorRoute = {
555
+ operationId: "federatedCatalogueGetDataSpaceConnector",
556
+ summary: "Get a Data Space Connector entry",
557
+ tag: tagsFederatedCatalogue[0].name,
558
+ method: "GET",
559
+ path: `${baseRouteName}/${DATA_SPACE_CONNECTOR_ROUTE}/:id`,
560
+ handler: async (httpRequestContext, request) => dataSpaceConnectorGet(httpRequestContext, factoryServiceName, request),
561
+ requestType: {
562
+ type: "ICatalogueEntryGetRequest",
563
+ examples: [
564
+ {
565
+ id: "dataSpaceConnectorGetRequestExample",
566
+ request: {
567
+ pathParams: {
568
+ id: "https://ds-connectors.example.org/ds1"
569
+ }
570
+ }
571
+ }
572
+ ]
573
+ },
574
+ responseType: [
575
+ {
576
+ type: "IDataSpaceConnectorGetResponse",
577
+ examples: [
578
+ {
579
+ id: "dataSpaceConnectorGetResponseExample",
580
+ response: {
581
+ body: {
582
+ ...dataSpaceConnectorEntryExample
583
+ }
584
+ }
585
+ }
586
+ ]
587
+ }
588
+ ]
589
+ };
590
+ return [
591
+ createParticipantRoute,
592
+ createServiceOfferingRoute,
593
+ createDataResourceRoute,
594
+ createDataSpaceConnectorRoute,
595
+ listParticipantsRoute,
596
+ getParticipantRoute,
597
+ listServicesRoute,
598
+ getServiceRoute,
599
+ listDataResourcesRoute,
600
+ getDataResourceRoute,
601
+ listDataSpaceConnectorsRoute,
602
+ getDataSpaceConnectorRoute
603
+ ];
604
+ }
605
+ /**
606
+ * Register a new participant.
607
+ * @param baseRouteName The base route name.
608
+ * @param httpRequestContext The request context for the API.
609
+ * @param factoryServiceName The name of the service to use in the routes.
610
+ * @param request The request.
611
+ * @returns The response object with additional http response properties.
612
+ */
613
+ async function complianceCredentialPresentation(baseRouteName, httpRequestContext, factoryServiceName, request) {
614
+ core.Guards.object(ROUTES_SOURCE, "request", request);
615
+ core.Guards.stringValue(ROUTES_SOURCE, "request.body", request.body);
616
+ const service = core.ComponentFactory.get(factoryServiceName);
617
+ const participantId = await service.registerComplianceCredential(request.body);
618
+ const searchParams = new URLSearchParams();
619
+ searchParams.append(federatedCatalogueModels.FederatedCatalogueTypes.Id, participantId);
620
+ return {
621
+ headers: {
622
+ location: `${baseRouteName}/${PARTICIPANTS_ROUTE}?${searchParams.toString()}`
623
+ },
624
+ statusCode: web.HttpStatusCode.created
625
+ };
626
+ }
627
+ /**
628
+ * Get a list of the participant entries.
629
+ * @param httpRequestContext The request context for the API.
630
+ * @param factoryServiceName The name of the service to use in the routes.
631
+ * @param request The request.
632
+ * @returns The response object with additional http response properties.
633
+ */
634
+ async function participantList(httpRequestContext, factoryServiceName, request) {
635
+ const service = core.ComponentFactory.get(factoryServiceName);
636
+ const itemsAndCursor = await service.queryParticipants(request?.query?.id, request?.query?.registrationNumber, request?.query?.lrnType, request?.query?.cursor, core.Coerce.number(request?.query?.pageSize));
637
+ return {
638
+ body: {
639
+ ...itemsAndCursor
640
+ }
641
+ };
642
+ }
643
+ /**
644
+ * Get a Participant entry.
645
+ * @param httpRequestContext The request context for the API.
646
+ * @param factoryServiceName The name of the service to use in the routes.
647
+ * @param request The request.
648
+ * @returns The response object with additional http response properties.
649
+ */
650
+ async function participantGet(httpRequestContext, factoryServiceName, request) {
651
+ const service = core.ComponentFactory.get(factoryServiceName);
652
+ const id = request?.pathParams.id;
653
+ core.Guards.stringValue(ROUTES_SOURCE, "id", id);
654
+ return {
655
+ body: (await service.getEntry(standardsGaiaX.GaiaXTypes.Participant, id))
656
+ };
657
+ }
658
+ /**
659
+ * Register a new service offering.
660
+ * @param baseRouteName The base route used.
661
+ * @param httpRequestContext The request context for the API.
662
+ * @param factoryServiceName The name of the service to use in the routes.
663
+ * @param request The request.
664
+ * @returns The response object with additional http response properties.
665
+ */
666
+ async function serviceOfferingCredentialPresentation(baseRouteName, httpRequestContext, factoryServiceName, request) {
667
+ core.Guards.object(ROUTES_SOURCE, "request", request);
668
+ core.Guards.stringValue(ROUTES_SOURCE, "request.body", request.body);
669
+ const service = core.ComponentFactory.get(factoryServiceName);
670
+ const serviceOfferingsCreated = await service.registerServiceOfferingCredential(request.body);
671
+ // Prepare the Ids to be returned
672
+ const searchParams = new URLSearchParams();
673
+ for (const serviceOffering of serviceOfferingsCreated) {
674
+ searchParams.append(federatedCatalogueModels.FederatedCatalogueTypes.Id, serviceOffering);
675
+ }
676
+ return {
677
+ headers: {
678
+ location: `${baseRouteName}/${SERVICE_OFFERING_ROUTE}?${searchParams.toString()}`
679
+ },
680
+ statusCode: web.HttpStatusCode.created
681
+ };
682
+ }
683
+ /**
684
+ * Get a list of the service offering entries.
685
+ * @param httpRequestContext The request context for the API.
686
+ * @param factoryServiceName The name of the service to use in the routes.
687
+ * @param request The request.
688
+ * @returns The response object with additional http response properties.
689
+ */
690
+ async function serviceOfferingList(httpRequestContext, factoryServiceName, request) {
691
+ const service = core.ComponentFactory.get(factoryServiceName);
692
+ const itemsAndCursor = await service.queryServiceOfferings(request?.query.id, request?.query.providedBy, request?.query.cursor, core.Coerce.number(request?.query?.pageSize));
693
+ return {
694
+ body: {
695
+ ...itemsAndCursor
696
+ }
697
+ };
698
+ }
699
+ /**
700
+ * Get a Service Offering entry.
701
+ * @param httpRequestContext The request context for the API.
702
+ * @param factoryServiceName The name of the service to use in the routes.
703
+ * @param request The request.
704
+ * @returns The response object with additional http response properties.
705
+ */
706
+ async function serviceOfferingGet(httpRequestContext, factoryServiceName, request) {
707
+ const service = core.ComponentFactory.get(factoryServiceName);
708
+ const id = request?.pathParams.id;
709
+ core.Guards.stringValue(ROUTES_SOURCE, "id", id);
710
+ return {
711
+ body: (await service.getEntry(standardsGaiaX.GaiaXTypes.ServiceOffering, id))
712
+ };
713
+ }
714
+ /**
715
+ * Register a new data resource.
716
+ * @param baseRouteName The base route name.
717
+ * @param httpRequestContext The request context for the API.
718
+ * @param factoryServiceName The name of the service to use in the routes.
719
+ * @param request The request.
720
+ * @returns The response object with additional http response properties.
721
+ */
722
+ async function dataResourceCredentialPresentation(baseRouteName, httpRequestContext, factoryServiceName, request) {
723
+ core.Guards.object(ROUTES_SOURCE, "request", request);
724
+ core.Guards.stringValue(ROUTES_SOURCE, "request.body", request.body);
725
+ const service = core.ComponentFactory.get(factoryServiceName);
726
+ const dataResourcesCreated = await service.registerDataResourceCredential(request.body);
727
+ // Prepare the Ids to be returned
728
+ const searchParams = new URLSearchParams();
729
+ for (const dataResource of dataResourcesCreated) {
730
+ searchParams.append(federatedCatalogueModels.FederatedCatalogueTypes.Id, dataResource);
731
+ }
732
+ return {
733
+ headers: {
734
+ location: `${baseRouteName}/${DATA_RESOURCE_ROUTE}?${searchParams.toString()}`
735
+ },
736
+ statusCode: web.HttpStatusCode.created
737
+ };
738
+ }
739
+ /**
740
+ * Get a list of the data resource entries.
741
+ * @param httpRequestContext The request context for the API.
742
+ * @param factoryServiceName The name of the service to use in the routes.
743
+ * @param request The request.
744
+ * @returns The response object with additional http response properties.
745
+ */
746
+ async function dataResourceList(httpRequestContext, factoryServiceName, request) {
747
+ const service = core.ComponentFactory.get(factoryServiceName);
748
+ const itemsAndCursor = await service.queryDataResources(request?.query.id, request?.query.producedBy, request?.query.cursor, core.Coerce.number(request?.query?.pageSize));
749
+ return {
750
+ body: {
751
+ ...itemsAndCursor
752
+ }
753
+ };
754
+ }
755
+ /**
756
+ * Get a Data Resource entry.
757
+ * @param httpRequestContext The request context for the API.
758
+ * @param factoryServiceName The name of the service to use in the routes.
759
+ * @param request The request.
760
+ * @returns The response object with additional http response properties.
761
+ */
762
+ async function dataResourceGet(httpRequestContext, factoryServiceName, request) {
763
+ const service = core.ComponentFactory.get(factoryServiceName);
764
+ const id = request?.pathParams.id;
765
+ core.Guards.stringValue(ROUTES_SOURCE, "id", id);
766
+ return {
767
+ body: (await service.getEntry(standardsGaiaX.GaiaXTypes.DataResource, id))
768
+ };
769
+ }
770
+ /**
771
+ * Register a new data space connector.
772
+ * @param baseRouteName the base route name.
773
+ * @param httpRequestContext The request context for the API.
774
+ * @param factoryServiceName The name of the service to use in the routes.
775
+ * @param request The request.
776
+ * @returns The response object with additional http response properties.
777
+ */
778
+ async function dataSpaceConnectorCredentialPresentation(baseRouteName, httpRequestContext, factoryServiceName, request) {
779
+ core.Guards.object(ROUTES_SOURCE, "request", request);
780
+ core.Guards.stringValue(ROUTES_SOURCE, "request.body", request.body);
781
+ const service = core.ComponentFactory.get(factoryServiceName);
782
+ const dataSpaceConnectorId = await service.registerDataSpaceConnectorCredential(request.body);
783
+ const searchParams = new URLSearchParams();
784
+ searchParams.append("id", dataSpaceConnectorId);
785
+ return {
786
+ headers: {
787
+ location: `${baseRouteName}/${DATA_SPACE_CONNECTOR_ROUTE}?${searchParams.toString()}`
788
+ },
789
+ statusCode: web.HttpStatusCode.created
790
+ };
791
+ }
792
+ /**
793
+ * Get a list of the data space connector entries.
794
+ * @param httpRequestContext The request context for the API.
795
+ * @param factoryServiceName The name of the service to use in the routes.
796
+ * @param request The request.
797
+ * @returns The response object with additional http response properties.
798
+ */
799
+ async function dataSpaceConnectorList(httpRequestContext, factoryServiceName, request) {
800
+ const service = core.ComponentFactory.get(factoryServiceName);
801
+ const itemsAndCursor = await service.queryDataSpaceConnectors(request?.query.id, request?.query.maintainedBy, request?.query.cursor, core.Coerce.number(request?.query?.pageSize));
802
+ return {
803
+ body: {
804
+ ...itemsAndCursor
805
+ }
806
+ };
807
+ }
808
+ /**
809
+ * Get a Data Space Connector entry.
810
+ * @param httpRequestContext The request context for the API.
811
+ * @param factoryServiceName The name of the service to use in the routes.
812
+ * @param request The request.
813
+ * @returns The response object with additional http response properties.
814
+ */
815
+ async function dataSpaceConnectorGet(httpRequestContext, factoryServiceName, request) {
816
+ const service = core.ComponentFactory.get(factoryServiceName);
817
+ const id = request?.pathParams.id;
818
+ core.Guards.stringValue(ROUTES_SOURCE, "id", id);
819
+ return {
820
+ body: (await service.getEntry(standardsGaiaX.GaiaXTypes.DataExchangeComponent, id))
821
+ };
822
+ }
823
+
824
+ // Copyright 2024 IOTA Stiftung.
825
+ // SPDX-License-Identifier: Apache-2.0.
826
+ /**
827
+ * Compliance Credential Verification Service.
828
+ */
829
+ class ComplianceCredentialVerificationService {
830
+ /**
831
+ * Class name
832
+ */
833
+ CLASS_NAME = "ComplianceCredentialVerificationService";
834
+ /**
835
+ * Resolver component.
836
+ * @internal
837
+ */
838
+ _resolver;
839
+ /**
840
+ * Resolver component.
841
+ * @internal
842
+ */
843
+ _subResourceCacheTtlMs;
844
+ /**
845
+ * Logging Component.
846
+ * @internal
847
+ */
848
+ _logger;
849
+ /**
850
+ * List of clearing houses tha are approvers.
851
+ * @internal
852
+ */
853
+ _clearingHouseApproverList;
854
+ /**
855
+ * Constructor.
856
+ * @param clearingHouseApproverList The list of clearing house identities approved.
857
+ * @param resolver The resolver used for DID.
858
+ * @param subResourceCacheTtlMs The time to live (in ms) of sub-resource objects in the cache. undefined means no cache. 0 means live in cache forever.
859
+ * @param logger The Logger Component.
860
+ */
861
+ constructor(clearingHouseApproverList, resolver, subResourceCacheTtlMs, logger) {
862
+ this._clearingHouseApproverList = clearingHouseApproverList;
863
+ this._resolver = resolver;
864
+ this._subResourceCacheTtlMs = subResourceCacheTtlMs;
865
+ this._logger = logger;
866
+ }
867
+ /**
868
+ * Verifies a Compliance Credential.
869
+ * @param credential The Credential to be verified
870
+ * @returns The Verification Result.
871
+ */
872
+ async verify(credential) {
873
+ if (!core.Is.arrayValue(credential.type) ||
874
+ !credential.type.includes(federatedCatalogueModels.FederatedCatalogueTypes.ComplianceCredential)) {
875
+ return {
876
+ verified: false,
877
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.InvalidCredentialType,
878
+ credentials: []
879
+ };
880
+ }
881
+ const issuer = core.Is.string(credential.issuer)
882
+ ? credential.issuer
883
+ : core.Coerce.object(credential.issuer)?.id;
884
+ if (core.Is.undefined(issuer)) {
885
+ return {
886
+ verified: false,
887
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.InvalidIssuer,
888
+ credentials: []
889
+ };
890
+ }
891
+ if (!this._clearingHouseApproverList.includes(issuer)) {
892
+ return {
893
+ verified: false,
894
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.InvalidIssuer,
895
+ credentials: []
896
+ };
897
+ }
898
+ const validFrom = credential.validFrom;
899
+ const validFromDate = core.Coerce.dateTime(validFrom);
900
+ if (core.Is.undefined(validFromDate) || validFromDate.getTime() > Date.now()) {
901
+ return {
902
+ verified: false,
903
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.NotValidYet,
904
+ credentials: []
905
+ };
906
+ }
907
+ const validUntilDate = core.Coerce.dateTime(credential.validUntil);
908
+ if (core.Is.undefined(validUntilDate)) {
909
+ return {
910
+ verified: false,
911
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.NoValidityEndPeriod,
912
+ credentials: []
913
+ };
914
+ }
915
+ if (validUntilDate.getTime() <= Date.now()) {
916
+ return {
917
+ verified: false,
918
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.Expired,
919
+ credentials: []
920
+ };
921
+ }
922
+ const subject = credential.credentialSubject;
923
+ if (!subject) {
924
+ return {
925
+ verified: false,
926
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.MissingSubject,
927
+ credentials: []
928
+ };
929
+ }
930
+ const evidences = core.Is.array(credential.evidence) ? credential.evidence : [credential.evidence];
931
+ if (evidences.length === 0) {
932
+ return {
933
+ verified: false,
934
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.MissingEvidences,
935
+ credentials: []
936
+ };
937
+ }
938
+ const finalResult = {
939
+ verified: true,
940
+ credentials: []
941
+ };
942
+ for (const evidence of evidences) {
943
+ const verResult = await this.verifyEvidence(evidence);
944
+ if (!verResult.verified) {
945
+ return {
946
+ verified: false,
947
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.EvidenceCannotBeVerified,
948
+ evidenceVerificationResult: verResult,
949
+ credentials: [],
950
+ evidenceFailedToVerify: [evidence.id]
951
+ };
952
+ }
953
+ finalResult.credentials.push(verResult.credential);
954
+ }
955
+ return finalResult;
956
+ }
957
+ /**
958
+ * Verifies the evidence supplied as part of a Compliance Credential.
959
+ * @param evidence The compliance evidence
960
+ * @returns The verification result with the original credentials that served as evidence
961
+ */
962
+ async verifyEvidence(evidence) {
963
+ // The credential associated to the evidence has to be retrieved, then verified
964
+ core.Guards.object(this.CLASS_NAME, "IComplianceEvidence", evidence);
965
+ const credentialUrl = evidence.id;
966
+ this._logger?.log({
967
+ source: this.CLASS_NAME,
968
+ level: "info",
969
+ message: "verifyingEvidenceCredential",
970
+ ts: Date.now(),
971
+ data: {
972
+ credentialUrl
973
+ }
974
+ });
975
+ const credentialResponse = await web.FetchHelper.fetch(this.CLASS_NAME, credentialUrl, "GET", undefined, { cacheTtlMs: this._subResourceCacheTtlMs });
976
+ if (!credentialResponse.ok) {
977
+ this._logger?.log({
978
+ source: this.CLASS_NAME,
979
+ level: "error",
980
+ message: "credentialCannotBeRetrieved",
981
+ ts: Date.now(),
982
+ data: {
983
+ credentialUrl,
984
+ statusCode: credentialResponse.status
985
+ }
986
+ });
987
+ return {
988
+ verified: false,
989
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.EvidenceCannotBeRetrieved
990
+ };
991
+ }
992
+ const originalCredential = await credentialResponse.json();
993
+ const theCredential = core.ObjectHelper.clone(originalCredential);
994
+ const proof = theCredential.proof;
995
+ // The proof is not taken into account to calculate the hash
996
+ delete theCredential.proof;
997
+ // Checking the hash
998
+ const canonicalized = core.JsonHelper.canonicalize(theCredential);
999
+ const hashingDetails = evidence.digestSRI;
1000
+ const [hashingAlg, hash] = hashingDetails.split("-");
1001
+ let hashToCheck = "";
1002
+ if (hashingAlg === "sha256") {
1003
+ hashToCheck = core.Converter.bytesToBase64(crypto.Sha256.sum256(core.Converter.utf8ToBytes(canonicalized)));
1004
+ }
1005
+ else if (hashingAlg === "sha512") {
1006
+ hashToCheck = core.Converter.bytesToBase64(crypto.Sha512.sum512(core.Converter.utf8ToBytes(canonicalized)));
1007
+ }
1008
+ else {
1009
+ throw new core.UnprocessableError(this.CLASS_NAME, "unknownHashingAlgorithm", { hashingAlg });
1010
+ }
1011
+ if (hashToCheck !== hash) {
1012
+ return {
1013
+ verified: false,
1014
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.IntegrityCheckFailed
1015
+ };
1016
+ }
1017
+ const { id } = identityModels.DocumentHelper.parseId(proof.verificationMethod);
1018
+ const documentId = theCredential.issuer ?? id;
1019
+ core.Guards.stringValue(this.CLASS_NAME, "documentId", documentId);
1020
+ let verified = false;
1021
+ try {
1022
+ const document = await this._resolver.identityResolve(documentId);
1023
+ const jwk = identityModels.DocumentHelper.getJwk(document, proof.verificationMethod);
1024
+ verified = await standardsW3cDid.ProofHelper.verifyProof(theCredential, proof, jwk);
1025
+ }
1026
+ catch (error) {
1027
+ this._logger?.log({
1028
+ source: this.CLASS_NAME,
1029
+ level: "error",
1030
+ message: "credentialVerificationError",
1031
+ ts: Date.now(),
1032
+ error: error,
1033
+ data: {
1034
+ credentialUrl
1035
+ }
1036
+ });
1037
+ return {
1038
+ verified,
1039
+ verificationFailureReason: federatedCatalogueModels.VerificationFailureReasons.GeneralVerificationError
1040
+ };
1041
+ }
1042
+ this._logger?.log({
1043
+ source: this.CLASS_NAME,
1044
+ level: "info",
1045
+ message: "credentialEvidenceVerified",
1046
+ ts: Date.now(),
1047
+ data: {
1048
+ credentialUrl
1049
+ }
1050
+ });
1051
+ return {
1052
+ verified: true,
1053
+ credential: originalCredential
1054
+ };
1055
+ }
1056
+ }
1057
+
1058
+ // Copyright 2024 IOTA Stiftung.
1059
+ // SPDX-License-Identifier: Apache-2.0.
1060
+ /**
1061
+ * Service for performing logging operations to a connector.
1062
+ */
1063
+ class FederatedCatalogueService {
1064
+ /**
1065
+ * Fields to skip when persisting entries to the Catalogue
1066
+ * @internal
1067
+ */
1068
+ static _FIELDS_TO_SKIP = ["@context", "type"];
1069
+ /**
1070
+ * Runtime name for the class.
1071
+ */
1072
+ CLASS_NAME = "FederatedCatalogueService";
1073
+ /**
1074
+ * The identity resolver used to dereference DIDs.
1075
+ * @internal
1076
+ */
1077
+ _resolver;
1078
+ /**
1079
+ * Logging service.
1080
+ * @internal
1081
+ */
1082
+ _loggingService;
1083
+ /**
1084
+ * Storage service for participants.
1085
+ * @internal
1086
+ */
1087
+ _entityStorageParticipants;
1088
+ /**
1089
+ * Storage service for service offering.
1090
+ * @internal
1091
+ */
1092
+ _entityStorageServiceOfferings;
1093
+ /**
1094
+ * Storage service for data resources.
1095
+ * @internal
1096
+ */
1097
+ _entityStorageDataResources;
1098
+ /**
1099
+ * Storage service for data resources.
1100
+ * @internal
1101
+ */
1102
+ _entityStorageDataSpaceConnectors;
1103
+ /**
1104
+ * Compliance Credential Verifier service.
1105
+ * @internal
1106
+ */
1107
+ _complianceCredentialVerifier;
1108
+ /**
1109
+ * Create a new instance of FederatedCatalogue service.
1110
+ * @param options The options for the connector.
1111
+ */
1112
+ constructor(options) {
1113
+ this._loggingService = loggingModels.LoggingConnectorFactory.getIfExists(options?.loggingConnectorType ?? "logging");
1114
+ this._entityStorageParticipants = entityStorageModels.EntityStorageConnectorFactory.get(options.participantEntityStorageType ?? core.StringHelper.kebabCase("ParticipantEntry"));
1115
+ this._entityStorageServiceOfferings = entityStorageModels.EntityStorageConnectorFactory.get(options.serviceOfferingEntityStorageType ??
1116
+ core.StringHelper.kebabCase("ServiceOfferingEntry"));
1117
+ this._entityStorageDataResources = entityStorageModels.EntityStorageConnectorFactory.get(options.dataResourceEntityStorageType ?? core.StringHelper.kebabCase("DataResourceEntry"));
1118
+ this._entityStorageDataSpaceConnectors = entityStorageModels.EntityStorageConnectorFactory.get(options.dataSpaceConnectorStorageType ??
1119
+ core.StringHelper.kebabCase("DataSpaceConnectorEntry"));
1120
+ this._resolver = core.ComponentFactory.get(options.identityResolverComponentType ?? "identity-resolver");
1121
+ this._complianceCredentialVerifier = new ComplianceCredentialVerificationService(options.config.clearingHouseApproverList, this._resolver, options.config.subResourceCacheTtlMs, this._loggingService);
1122
+ standardsSchemaOrg.SchemaOrgDataTypes.registerRedirects();
1123
+ }
1124
+ /**
1125
+ * Registers a Participant's compliance Credential.
1126
+ * @param credentialJwt The credential (wrapped into a presentation) as JWT.
1127
+ * @returns The Id of the Participant (DID usually).
1128
+ */
1129
+ async registerComplianceCredential(credentialJwt) {
1130
+ core.Guards.string(this.CLASS_NAME, "credentialJwt", credentialJwt);
1131
+ // This will raise exceptions as it has been coded reusing code from Gaia-X
1132
+ const complianceCredential = await this.decodeJwt(credentialJwt);
1133
+ const result = await this._complianceCredentialVerifier.verify(complianceCredential);
1134
+ if (!result.verified) {
1135
+ this._loggingService?.log({
1136
+ level: "error",
1137
+ source: this.CLASS_NAME,
1138
+ ts: Date.now(),
1139
+ message: "complianceCredentialNotVerified",
1140
+ data: { result }
1141
+ });
1142
+ throw new core.UnprocessableError(this.CLASS_NAME, "complianceCredentialNotVerified", {
1143
+ reason: result.verificationFailureReason
1144
+ });
1145
+ }
1146
+ const targetCredential = result.credentials.find(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.Participant);
1147
+ if (core.Is.undefined(targetCredential)) {
1148
+ throw new core.UnprocessableError(this.CLASS_NAME, "noEvidence");
1149
+ }
1150
+ const participantEntry = this.extractParticipantEntry(complianceCredential, targetCredential);
1151
+ const theEntry = core.ObjectHelper.omit(participantEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1152
+ await this._entityStorageParticipants.set(theEntry);
1153
+ await this._loggingService?.log({
1154
+ level: "info",
1155
+ source: this.CLASS_NAME,
1156
+ ts: Date.now(),
1157
+ message: "complianceCredentialVerified",
1158
+ data: {
1159
+ participantId: complianceCredential.credentialSubject?.id,
1160
+ trustedIssuer: complianceCredential.issuer
1161
+ }
1162
+ });
1163
+ return participantEntry.id;
1164
+ }
1165
+ /**
1166
+ * Query the federated catalogue.
1167
+ * @param id The identity of the participant.
1168
+ * @param legalRegistrationNumber The legal registration number.
1169
+ * @param lrnType The legal registration number type (EORI, VATID, GLEIF, KENYA_PIN, etc.)
1170
+ * @param cursor The cursor to request the next page of entities.
1171
+ * @param pageSize The maximum number of entities in a page.
1172
+ * @returns All the entities for the storage matching the conditions,
1173
+ * and a cursor which can be used to request more entities.
1174
+ * @throws NotImplementedError if the implementation does not support retrieval.
1175
+ */
1176
+ async queryParticipants(id, legalRegistrationNumber, lrnType, cursor, pageSize) {
1177
+ const conditions = [];
1178
+ if (core.Is.stringValue(id)) {
1179
+ const condition = {
1180
+ property: "id",
1181
+ value: id,
1182
+ comparison: entity.ComparisonOperator.Equals
1183
+ };
1184
+ conditions.push(condition);
1185
+ }
1186
+ if (core.Is.stringValue(lrnType)) {
1187
+ const condition = {
1188
+ property: "lrnType",
1189
+ value: lrnType,
1190
+ comparison: entity.ComparisonOperator.Equals
1191
+ };
1192
+ conditions.push(condition);
1193
+ }
1194
+ if (core.Is.stringValue(legalRegistrationNumber)) {
1195
+ const condition = {
1196
+ property: "registrationNumber",
1197
+ value: legalRegistrationNumber,
1198
+ comparison: entity.ComparisonOperator.Equals
1199
+ };
1200
+ conditions.push(condition);
1201
+ }
1202
+ const entries = await this._entityStorageParticipants.query({ conditions }, undefined, undefined, cursor, pageSize);
1203
+ const itemList = entries.entities.map(entry => {
1204
+ entry.type = standardsGaiaX.GaiaXTypes.Participant;
1205
+ return entry;
1206
+ });
1207
+ const result = {
1208
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
1209
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
1210
+ itemListElement: itemList,
1211
+ nextItem: entries.cursor
1212
+ };
1213
+ return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
1214
+ }
1215
+ /**
1216
+ * Returns a Federated Catalogue entry.
1217
+ * @param entryType The type of entry.
1218
+ * @param entryId The entry's id.
1219
+ * @returns Catalogue Entry
1220
+ * @throws NotFoundError if not found.
1221
+ */
1222
+ async getEntry(entryType, entryId) {
1223
+ core.Guards.stringValue(this.CLASS_NAME, "entryId", entryId);
1224
+ let itemsAndCursor;
1225
+ switch (entryType) {
1226
+ case standardsGaiaX.GaiaXTypes.Participant:
1227
+ itemsAndCursor = await this.queryParticipants(entryId);
1228
+ break;
1229
+ case standardsGaiaX.GaiaXTypes.DataExchangeComponent:
1230
+ case federatedCatalogueModels.FederatedCatalogueTypes.DataSpaceConnector:
1231
+ itemsAndCursor = await this.queryDataSpaceConnectors(entryId);
1232
+ break;
1233
+ case standardsGaiaX.GaiaXTypes.ServiceOffering:
1234
+ itemsAndCursor = await this.queryServiceOfferings(entryId);
1235
+ break;
1236
+ case standardsGaiaX.GaiaXTypes.DataResource:
1237
+ itemsAndCursor = await this.queryDataResources(entryId);
1238
+ break;
1239
+ default:
1240
+ throw new core.GeneralError(this.CLASS_NAME, "unknownEntryType", { entryType });
1241
+ }
1242
+ if (core.Is.arrayValue(itemsAndCursor?.itemListElement)) {
1243
+ const entry = {
1244
+ ...itemsAndCursor.itemListElement[0],
1245
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY
1246
+ };
1247
+ const result = await dataJsonLd.JsonLdProcessor.compact(entry, entry["@context"]);
1248
+ return result;
1249
+ }
1250
+ throw new core.NotFoundError(this.CLASS_NAME, "entryNotFound", entryId);
1251
+ }
1252
+ /**
1253
+ * Registers a compliance Credential concerning a Data Space Connector.
1254
+ * @param credentialJwt The credential (wrapped into a presentation) as JWT.
1255
+ * @returns The identifier of the Data Space Connector registered.
1256
+ */
1257
+ async registerDataSpaceConnectorCredential(credentialJwt) {
1258
+ core.Guards.string(this.CLASS_NAME, "credentialJwt", credentialJwt);
1259
+ // This will raise exceptions as it has been coded reusing code from Gaia-X
1260
+ const complianceCredential = await this.decodeJwt(credentialJwt);
1261
+ const result = await this._complianceCredentialVerifier.verify(complianceCredential);
1262
+ if (!result.verified) {
1263
+ this._loggingService?.log({
1264
+ level: "error",
1265
+ source: this.CLASS_NAME,
1266
+ ts: Date.now(),
1267
+ message: "complianceCredentialNotVerified",
1268
+ data: { result }
1269
+ });
1270
+ throw new core.UnprocessableError(this.CLASS_NAME, "complianceCredentialNotVerified", {
1271
+ reason: result.verificationFailureReason
1272
+ });
1273
+ }
1274
+ const targetCredential = result.credentials.find(credential => {
1275
+ if (core.Is.array(credential.credentialSubject.type)) {
1276
+ return credential.credentialSubject.type.includes(federatedCatalogueModels.FederatedCatalogueTypes.DataSpaceConnector);
1277
+ }
1278
+ return credential.credentialSubject.type === federatedCatalogueModels.FederatedCatalogueTypes.DataSpaceConnector;
1279
+ });
1280
+ const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
1281
+ if (core.Is.undefined(targetCredential)) {
1282
+ throw new core.UnprocessableError(this.CLASS_NAME, "noEvidence");
1283
+ }
1284
+ await this.checkParticipantExists(targetCredential.issuer);
1285
+ const dataSpaceConnectorEntry = this.extractDataSpaceConnectorEntry(complianceCredential, result.credentials[0]);
1286
+ const theEntry = core.ObjectHelper.omit(dataSpaceConnectorEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1287
+ await this._entityStorageDataSpaceConnectors.set(theEntry);
1288
+ for (const dataResourceCredential of dataResourceCredentials) {
1289
+ await this.checkParticipantExists(dataResourceCredential.issuer);
1290
+ const dataResourceEntry = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
1291
+ const drEntry = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1292
+ await this._entityStorageDataResources.set(drEntry);
1293
+ }
1294
+ await this._loggingService?.log({
1295
+ level: "info",
1296
+ source: this.CLASS_NAME,
1297
+ ts: Date.now(),
1298
+ message: "complianceCredentialVerified",
1299
+ data: {
1300
+ dataSpaceConnectorId: complianceCredential.credentialSubject?.id,
1301
+ trustedIssuer: complianceCredential.issuer
1302
+ }
1303
+ });
1304
+ return dataSpaceConnectorEntry.id;
1305
+ }
1306
+ /**
1307
+ * Registers a data resource Credential concerning a Data Space Connector.
1308
+ * @param credentialJwt The credential (wrapped into a presentation) as JWT.
1309
+ * @returns The list of Data Resources created.
1310
+ */
1311
+ async registerDataResourceCredential(credentialJwt) {
1312
+ core.Guards.string(this.CLASS_NAME, "credentialJwt", credentialJwt);
1313
+ // This will raise exceptions as it has been coded reusing code from Gaia-X
1314
+ const complianceCredential = await this.decodeJwt(credentialJwt);
1315
+ const result = await this._complianceCredentialVerifier.verify(complianceCredential);
1316
+ if (!result.verified) {
1317
+ this._loggingService?.log({
1318
+ level: "error",
1319
+ source: this.CLASS_NAME,
1320
+ ts: Date.now(),
1321
+ message: "complianceCredentialNotVerified",
1322
+ data: { result }
1323
+ });
1324
+ throw new core.UnprocessableError(this.CLASS_NAME, "complianceCredentialNotVerified", {
1325
+ reason: result.verificationFailureReason
1326
+ });
1327
+ }
1328
+ const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
1329
+ if (dataResourceCredentials.length === 0) {
1330
+ throw new core.UnprocessableError(this.CLASS_NAME, "noEvidence");
1331
+ }
1332
+ const dataResourceIds = [];
1333
+ for (const dataResourceCredential of dataResourceCredentials) {
1334
+ await this.checkParticipantExists(dataResourceCredential.issuer);
1335
+ const dataResourceEntry = this.extractDataResourceEntry(complianceCredential, dataResourceCredential);
1336
+ const theEntry = core.ObjectHelper.omit(dataResourceEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1337
+ await this._entityStorageDataResources.set(theEntry);
1338
+ dataResourceIds.push(dataResourceEntry.id);
1339
+ }
1340
+ await this._loggingService?.log({
1341
+ level: "info",
1342
+ source: this.CLASS_NAME,
1343
+ ts: Date.now(),
1344
+ message: "complianceCredentialVerified",
1345
+ data: {
1346
+ dataResourceIds,
1347
+ trustedIssuer: complianceCredential.issuer
1348
+ }
1349
+ });
1350
+ return dataResourceIds;
1351
+ }
1352
+ /**
1353
+ * Query the federated catalogue.
1354
+ * @param id The identity of the participant.
1355
+ * @param maintainer The DS Connector maintainer.
1356
+ * @param cursor The cursor to request the next page of entities.
1357
+ * @param pageSize The maximum number of entities in a page.
1358
+ * @returns All the entities for the storage matching the conditions,
1359
+ * and a cursor which can be used to request more entities.
1360
+ * @throws NotImplementedError if the implementation does not support retrieval.
1361
+ */
1362
+ async queryDataSpaceConnectors(id, maintainer, cursor, pageSize) {
1363
+ const conditions = [];
1364
+ if (core.Is.stringValue(id)) {
1365
+ const condition = {
1366
+ property: "id",
1367
+ value: id,
1368
+ comparison: entity.ComparisonOperator.Equals
1369
+ };
1370
+ conditions.push(condition);
1371
+ }
1372
+ if (core.Is.stringValue(maintainer)) {
1373
+ const condition = {
1374
+ property: "maintainer",
1375
+ value: maintainer,
1376
+ comparison: entity.ComparisonOperator.Equals
1377
+ };
1378
+ conditions.push(condition);
1379
+ }
1380
+ const entries = await this._entityStorageDataSpaceConnectors.query({ conditions }, undefined, undefined, cursor, pageSize);
1381
+ const itemList = entries.entities.map(entry => {
1382
+ entry.type = [
1383
+ standardsGaiaX.GaiaXTypes.DataExchangeComponent,
1384
+ federatedCatalogueModels.FederatedCatalogueTypes.DataSpaceConnector
1385
+ ];
1386
+ return entry;
1387
+ });
1388
+ const result = {
1389
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
1390
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
1391
+ itemListElement: itemList,
1392
+ nextItem: entries.cursor
1393
+ };
1394
+ return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
1395
+ }
1396
+ /**
1397
+ * Registers a Service Offering Credential.
1398
+ * @param credentialJwt The credential (wrapped into a presentation) as JWT.
1399
+ * @returns Nothing.
1400
+ */
1401
+ async registerServiceOfferingCredential(credentialJwt) {
1402
+ core.Guards.string(this.CLASS_NAME, "credentialJwt", credentialJwt);
1403
+ // This will raise exceptions as it has been coded reusing code from Gaia-X
1404
+ const sdComplianceCredential = await this.decodeJwt(credentialJwt);
1405
+ const result = await this._complianceCredentialVerifier.verify(sdComplianceCredential);
1406
+ if (!result.verified) {
1407
+ this._loggingService?.log({
1408
+ level: "error",
1409
+ source: this.CLASS_NAME,
1410
+ ts: Date.now(),
1411
+ message: "complianceCredentialNotVerified",
1412
+ data: { result }
1413
+ });
1414
+ throw new core.UnprocessableError(this.CLASS_NAME, "complianceCredentialNotVerified", {
1415
+ reason: result.verificationFailureReason
1416
+ });
1417
+ }
1418
+ const serviceOfferingCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.ServiceOffering);
1419
+ const dataResourceCredentials = result.credentials.filter(credential => credential.credentialSubject.type === standardsGaiaX.GaiaXTypes.DataResource);
1420
+ if (serviceOfferingCredentials.length === 0) {
1421
+ throw new core.UnprocessableError(this.CLASS_NAME, "noEvidence");
1422
+ }
1423
+ const serviceOfferingIds = [];
1424
+ for (const serviceOfferingCredential of serviceOfferingCredentials) {
1425
+ const serviceIssuer = serviceOfferingCredential.issuer;
1426
+ await this.checkParticipantExists(serviceIssuer);
1427
+ const serviceOfferingEntry = this.extractServiceOfferingEntry(sdComplianceCredential, serviceOfferingCredential);
1428
+ const theEntry = core.ObjectHelper.omit(serviceOfferingEntry, FederatedCatalogueService._FIELDS_TO_SKIP);
1429
+ await this._entityStorageServiceOfferings.set(theEntry);
1430
+ serviceOfferingIds.push(serviceOfferingEntry.id);
1431
+ }
1432
+ for (const dataResourceCredential of dataResourceCredentials) {
1433
+ await this.checkParticipantExists(dataResourceCredential.issuer);
1434
+ const dataResourceEntry = this.extractDataResourceEntry(sdComplianceCredential, dataResourceCredential);
1435
+ await this._entityStorageDataResources.set(dataResourceEntry);
1436
+ }
1437
+ await this._loggingService?.log({
1438
+ level: "info",
1439
+ source: this.CLASS_NAME,
1440
+ ts: Date.now(),
1441
+ message: "complianceCredentialVerified",
1442
+ data: {
1443
+ serviceOfferingIds,
1444
+ trustedIssuer: sdComplianceCredential.issuer
1445
+ }
1446
+ });
1447
+ return serviceOfferingIds;
1448
+ }
1449
+ /**
1450
+ * Query the federated catalogue.
1451
+ * @param id Service Id.
1452
+ * @param providedBy The identity of the participant.
1453
+ * @param cursor The cursor to request the next page of entities.
1454
+ * @param pageSize The maximum number of entities in a page.
1455
+ * @returns All the entities for the storage matching the conditions,
1456
+ * and a cursor which can be used to request more entities.
1457
+ * @throws NotImplementedError if the implementation does not support retrieval.
1458
+ */
1459
+ async queryServiceOfferings(id, providedBy, cursor, pageSize) {
1460
+ const conditions = [];
1461
+ if (core.Is.stringValue(providedBy)) {
1462
+ const condition = {
1463
+ property: "providedBy",
1464
+ value: providedBy,
1465
+ comparison: entity.ComparisonOperator.Equals
1466
+ };
1467
+ conditions.push(condition);
1468
+ }
1469
+ if (core.Is.stringValue(id)) {
1470
+ const condition = {
1471
+ property: "id",
1472
+ value: id,
1473
+ comparison: entity.ComparisonOperator.Equals
1474
+ };
1475
+ conditions.push(condition);
1476
+ }
1477
+ const entries = await this._entityStorageServiceOfferings.query({ conditions }, undefined, undefined, cursor, pageSize);
1478
+ const itemList = entries.entities.map(entry => {
1479
+ entry.type = standardsGaiaX.GaiaXTypes.ServiceOffering;
1480
+ return entry;
1481
+ });
1482
+ const result = {
1483
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
1484
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
1485
+ itemListElement: itemList,
1486
+ nextItem: entries.cursor
1487
+ };
1488
+ return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
1489
+ }
1490
+ /**
1491
+ * Query the federated catalogue.
1492
+ * @param id The identity of the DataResource.
1493
+ * @param producedBy The identity of the participant.
1494
+ * @param cursor The cursor to request the next page of entities.
1495
+ * @param pageSize The maximum number of entities in a page.
1496
+ * @returns All the entities for the storage matching the conditions,
1497
+ * and a cursor which can be used to request more entities.
1498
+ * @throws NotImplementedError if the implementation does not support retrieval.
1499
+ */
1500
+ async queryDataResources(id, producedBy, cursor, pageSize) {
1501
+ const conditions = [];
1502
+ if (core.Is.stringValue(producedBy)) {
1503
+ const condition = {
1504
+ property: "producedBy",
1505
+ value: producedBy,
1506
+ comparison: entity.ComparisonOperator.Equals
1507
+ };
1508
+ conditions.push(condition);
1509
+ }
1510
+ if (core.Is.stringValue(id)) {
1511
+ const condition = {
1512
+ property: "id",
1513
+ value: id,
1514
+ comparison: entity.ComparisonOperator.Equals
1515
+ };
1516
+ conditions.push(condition);
1517
+ }
1518
+ const entries = await this._entityStorageDataResources.query({ conditions }, undefined, undefined, cursor, pageSize);
1519
+ const itemList = entries.entities.map(entry => {
1520
+ entry.type = standardsGaiaX.GaiaXTypes.DataResource;
1521
+ return entry;
1522
+ });
1523
+ const result = {
1524
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY_LIST,
1525
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
1526
+ itemListElement: itemList,
1527
+ nextItem: entries.cursor
1528
+ };
1529
+ return dataJsonLd.JsonLdProcessor.compact(result, result["@context"]);
1530
+ }
1531
+ /**
1532
+ * Decodes the JWT.
1533
+ * @param jwt JWT.
1534
+ * @returns Decoded.
1535
+ */
1536
+ async decodeJwt(jwt) {
1537
+ const { payload } = await identityModels.VerificationHelper.verifyJwt(this._resolver, jwt);
1538
+ return payload;
1539
+ }
1540
+ /**
1541
+ * Returns the trusted Issuer id.
1542
+ * @param complianceCredential The compliance credential.
1543
+ * @returns The trusted issuer.
1544
+ */
1545
+ getTrustedIssuerId(complianceCredential) {
1546
+ const trustedIssuerId = core.Is.object(complianceCredential.issuer)
1547
+ ? complianceCredential.issuer.id
1548
+ : complianceCredential.issuer;
1549
+ return trustedIssuerId;
1550
+ }
1551
+ /**
1552
+ * Extracts participant entry from the credentials.
1553
+ * @param complianceCredential Compliance credential
1554
+ * @param participantCredential The Participant credential extracted.
1555
+ * @returns Participant Entry to be saved on the Database.
1556
+ */
1557
+ extractParticipantEntry(complianceCredential, participantCredential) {
1558
+ const participantData = participantCredential.credentialSubject;
1559
+ core.Guards.objectValue(this.CLASS_NAME, "participantData", participantData);
1560
+ const evidences = [];
1561
+ for (const evidence of complianceCredential.evidence) {
1562
+ evidences.push(evidence.id);
1563
+ }
1564
+ const result = {
1565
+ ...participantData,
1566
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
1567
+ issuer: this.getTrustedIssuerId(complianceCredential),
1568
+ validFrom: complianceCredential.validFrom,
1569
+ validUntil: complianceCredential.validUntil,
1570
+ dateCreated: new Date().toISOString(),
1571
+ evidence: evidences
1572
+ };
1573
+ return result;
1574
+ }
1575
+ /**
1576
+ * Extracts Data Space Connector description entry from the credentials.
1577
+ * @param complianceCredential Compliance Credential.
1578
+ * @param dataSpaceConnectorCredential Evidence Credential.
1579
+ * @returns Service Description Entry to be saved on the Database.
1580
+ */
1581
+ extractDataSpaceConnectorEntry(complianceCredential, dataSpaceConnectorCredential) {
1582
+ const credentialData = dataSpaceConnectorCredential.credentialSubject;
1583
+ core.Guards.objectValue(this.CLASS_NAME, "credentialData", credentialData);
1584
+ const { offeredResource, ...deStructuredData } = credentialData;
1585
+ const result = {
1586
+ ...deStructuredData,
1587
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
1588
+ offeredResource: Object.keys(offeredResource),
1589
+ issuer: this.getTrustedIssuerId(complianceCredential),
1590
+ validFrom: complianceCredential.validFrom,
1591
+ validUntil: complianceCredential.validUntil,
1592
+ dateCreated: new Date().toISOString(),
1593
+ evidence: [dataSpaceConnectorCredential.id]
1594
+ };
1595
+ return result;
1596
+ }
1597
+ /**
1598
+ * Extracts service offering entry from the credentials.
1599
+ * @param complianceCredential The Compliance Credential.
1600
+ * @param serviceOfferingCredential Service Offering credential (evidence).
1601
+ * @returns Service Offering Entry to be saved on the Database.
1602
+ */
1603
+ extractServiceOfferingEntry(complianceCredential, serviceOfferingCredential) {
1604
+ const credentialData = serviceOfferingCredential.credentialSubject;
1605
+ core.Guards.objectValue(this.CLASS_NAME, "credentialData", credentialData);
1606
+ const { providedBy, aggregationOfResources, servicePolicy, ...deStructuredData } = credentialData;
1607
+ const result = {
1608
+ ...deStructuredData,
1609
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
1610
+ providedBy: core.Is.string(providedBy) ? providedBy : providedBy.id,
1611
+ aggregationOfResources: aggregationOfResources,
1612
+ issuer: this.getTrustedIssuerId(complianceCredential),
1613
+ validFrom: complianceCredential.validFrom,
1614
+ validUntil: complianceCredential.validUntil,
1615
+ dateCreated: new Date().toISOString(),
1616
+ evidence: [serviceOfferingCredential.id],
1617
+ servicePolicy: core.ArrayHelper.fromObjectOrArray(servicePolicy)
1618
+ };
1619
+ return result;
1620
+ }
1621
+ /**
1622
+ * Extracts data resource entry from the credentials.
1623
+ * @param complianceCredential The Compliance Credential.
1624
+ * @param dataResourceCredential Data Resource credential.
1625
+ * @returns DataResource Entry to be saved on the Database.
1626
+ */
1627
+ extractDataResourceEntry(complianceCredential, dataResourceCredential) {
1628
+ const credentialData = dataResourceCredential.credentialSubject;
1629
+ core.Guards.objectValue(this.CLASS_NAME, "credentialData", credentialData);
1630
+ const { producedBy, copyrightOwnedBy, exposedThrough, resourcePolicy, ...deStructuredData } = credentialData;
1631
+ let producedByValue = producedBy;
1632
+ if (core.Is.object(producedByValue)) {
1633
+ producedByValue = producedByValue.id;
1634
+ }
1635
+ let copyrightOwnedByValue = copyrightOwnedBy;
1636
+ if (core.Is.object(copyrightOwnedByValue)) {
1637
+ copyrightOwnedByValue = copyrightOwnedByValue.id;
1638
+ }
1639
+ const result = {
1640
+ ...deStructuredData,
1641
+ "@context": federatedCatalogueModels.FederatedCatalogueContextInstances.DEFAULT_LD_CONTEXT_ENTRY,
1642
+ issuer: this.getTrustedIssuerId(complianceCredential),
1643
+ producedBy: producedByValue,
1644
+ copyrightOwnedBy: copyrightOwnedByValue,
1645
+ exposedThrough: exposedThrough,
1646
+ validFrom: complianceCredential.validFrom,
1647
+ validUntil: complianceCredential.validUntil,
1648
+ dateCreated: new Date().toISOString(),
1649
+ evidence: [dataResourceCredential.id],
1650
+ resourcePolicy: core.ArrayHelper.fromObjectOrArray(resourcePolicy)
1651
+ };
1652
+ return result;
1653
+ }
1654
+ /**
1655
+ * Checks whether the Participant exists.
1656
+ * @param participantId The Participant identifier
1657
+ */
1658
+ async checkParticipantExists(participantId) {
1659
+ const participantData = await this._entityStorageParticipants.get(participantId);
1660
+ if (!participantData) {
1661
+ this._loggingService?.log({
1662
+ level: "error",
1663
+ source: this.CLASS_NAME,
1664
+ ts: Date.now(),
1665
+ message: "providerIsNotParticipant",
1666
+ data: { providedBy: participantId }
1667
+ });
1668
+ throw new core.UnprocessableError(this.CLASS_NAME, "providerIsNotParticipant", {
1669
+ providedBy: participantId
1670
+ });
1671
+ }
1672
+ }
1673
+ }
1674
+
1675
+ const restEntryPoints = [
1676
+ {
1677
+ name: "federated-catalogue",
1678
+ defaultBaseRoute: "federated-catalogue",
1679
+ tags: tagsFederatedCatalogue,
1680
+ generateRoutes: generateRestRoutesFederatedCatalogue
1681
+ }
1682
+ ];
1683
+
1684
+ // Copyright 2024 IOTA Stiftung.
1685
+ // SPDX-License-Identifier: Apache-2.0.
1686
+ /**
1687
+ * Data Resource Entry.
1688
+ */
1689
+ exports.DataResourceEntry = class DataResourceEntry {
1690
+ /**
1691
+ * The Id.
1692
+ */
1693
+ id;
1694
+ /**
1695
+ * The trusted issuer of the compliance credential
1696
+ */
1697
+ issuer;
1698
+ /**
1699
+ * The name.
1700
+ */
1701
+ name;
1702
+ /**
1703
+ * The description.
1704
+ */
1705
+ description;
1706
+ /**
1707
+ * The Id of the producer of the data described by this Data Resource.
1708
+ */
1709
+ producedBy;
1710
+ /**
1711
+ * The copyright owner
1712
+ */
1713
+ copyrightOwnedBy;
1714
+ /**
1715
+ * The license
1716
+ */
1717
+ license;
1718
+ /**
1719
+ * The data exchange component used to expose the Data Resource.
1720
+ * Only a URL pointing to the resource is stored
1721
+ */
1722
+ exposedThrough;
1723
+ /**
1724
+ * The Data Resource policy
1725
+ */
1726
+ resourcePolicy;
1727
+ /**
1728
+ * Valid from
1729
+ */
1730
+ validFrom;
1731
+ /**
1732
+ * Valid to
1733
+ */
1734
+ validUntil;
1735
+ /**
1736
+ * Date created
1737
+ */
1738
+ dateCreated;
1739
+ /**
1740
+ * Evidences
1741
+ */
1742
+ evidence;
1743
+ };
1744
+ __decorate([
1745
+ entity.property({ type: "string", isPrimary: true }),
1746
+ __metadata("design:type", String)
1747
+ ], exports.DataResourceEntry.prototype, "id", void 0);
1748
+ __decorate([
1749
+ entity.property({ type: "string" }),
1750
+ __metadata("design:type", String)
1751
+ ], exports.DataResourceEntry.prototype, "issuer", void 0);
1752
+ __decorate([
1753
+ entity.property({ type: "string" }),
1754
+ __metadata("design:type", String)
1755
+ ], exports.DataResourceEntry.prototype, "name", void 0);
1756
+ __decorate([
1757
+ entity.property({ type: "string", optional: true }),
1758
+ __metadata("design:type", String)
1759
+ ], exports.DataResourceEntry.prototype, "description", void 0);
1760
+ __decorate([
1761
+ entity.property({ type: "string", isSecondary: true }),
1762
+ __metadata("design:type", String)
1763
+ ], exports.DataResourceEntry.prototype, "producedBy", void 0);
1764
+ __decorate([
1765
+ entity.property({ type: "string" }),
1766
+ __metadata("design:type", String)
1767
+ ], exports.DataResourceEntry.prototype, "copyrightOwnedBy", void 0);
1768
+ __decorate([
1769
+ entity.property({ type: "string" }),
1770
+ __metadata("design:type", String)
1771
+ ], exports.DataResourceEntry.prototype, "license", void 0);
1772
+ __decorate([
1773
+ entity.property({ type: "string" }),
1774
+ __metadata("design:type", String)
1775
+ ], exports.DataResourceEntry.prototype, "exposedThrough", void 0);
1776
+ __decorate([
1777
+ entity.property({ type: "array" }),
1778
+ __metadata("design:type", Array)
1779
+ ], exports.DataResourceEntry.prototype, "resourcePolicy", void 0);
1780
+ __decorate([
1781
+ entity.property({ type: "string", format: "date-time" }),
1782
+ __metadata("design:type", String)
1783
+ ], exports.DataResourceEntry.prototype, "validFrom", void 0);
1784
+ __decorate([
1785
+ entity.property({ type: "string", format: "date-time" }),
1786
+ __metadata("design:type", String)
1787
+ ], exports.DataResourceEntry.prototype, "validUntil", void 0);
1788
+ __decorate([
1789
+ entity.property({ type: "string", format: "date-time", sortDirection: entity.SortDirection.Descending }),
1790
+ __metadata("design:type", String)
1791
+ ], exports.DataResourceEntry.prototype, "dateCreated", void 0);
1792
+ __decorate([
1793
+ entity.property({ type: "array" }),
1794
+ __metadata("design:type", Array)
1795
+ ], exports.DataResourceEntry.prototype, "evidence", void 0);
1796
+ exports.DataResourceEntry = __decorate([
1797
+ entity.entity()
1798
+ ], exports.DataResourceEntry);
1799
+
1800
+ // Copyright 2024 IOTA Stiftung.
1801
+ // SPDX-License-Identifier: Apache-2.0.
1802
+ /**
1803
+ * Data Space Connector Entry.
1804
+ */
1805
+ exports.DataSpaceConnectorEntry = class DataSpaceConnectorEntry {
1806
+ /**
1807
+ * The Id.
1808
+ */
1809
+ id;
1810
+ /**
1811
+ * The trusted issuer of the compliance credential.
1812
+ */
1813
+ issuer;
1814
+ /**
1815
+ * The name.
1816
+ */
1817
+ name;
1818
+ /**
1819
+ * The description.
1820
+ */
1821
+ description;
1822
+ /**
1823
+ * The identity of the Data Space Connector
1824
+ */
1825
+ identity;
1826
+ /**
1827
+ * Who maintains the Data Space Connector
1828
+ */
1829
+ maintainer;
1830
+ /**
1831
+ * The default endpoint
1832
+ */
1833
+ defaultEndpoint;
1834
+ /**
1835
+ * The activity push endpoint
1836
+ */
1837
+ pushActivityEndpoint;
1838
+ /**
1839
+ * The activity subscribe endpoint
1840
+ */
1841
+ subscriptionActivityEndpoint;
1842
+ /**
1843
+ * The pull data endpoint
1844
+ */
1845
+ pullDataEndpoint;
1846
+ /**
1847
+ * The pull data endpoint
1848
+ */
1849
+ offeredResource;
1850
+ /**
1851
+ * Valid from
1852
+ */
1853
+ validFrom;
1854
+ /**
1855
+ * Valid to
1856
+ */
1857
+ validUntil;
1858
+ /**
1859
+ * Date created
1860
+ */
1861
+ dateCreated;
1862
+ /**
1863
+ * Evidences
1864
+ */
1865
+ evidence;
1866
+ };
1867
+ __decorate([
1868
+ entity.property({ type: "string", isPrimary: true }),
1869
+ __metadata("design:type", String)
1870
+ ], exports.DataSpaceConnectorEntry.prototype, "id", void 0);
1871
+ __decorate([
1872
+ entity.property({ type: "string" }),
1873
+ __metadata("design:type", String)
1874
+ ], exports.DataSpaceConnectorEntry.prototype, "issuer", void 0);
1875
+ __decorate([
1876
+ entity.property({ type: "string", optional: true }),
1877
+ __metadata("design:type", String)
1878
+ ], exports.DataSpaceConnectorEntry.prototype, "name", void 0);
1879
+ __decorate([
1880
+ entity.property({ type: "string", optional: true }),
1881
+ __metadata("design:type", String)
1882
+ ], exports.DataSpaceConnectorEntry.prototype, "description", void 0);
1883
+ __decorate([
1884
+ entity.property({ type: "string" }),
1885
+ __metadata("design:type", String)
1886
+ ], exports.DataSpaceConnectorEntry.prototype, "identity", void 0);
1887
+ __decorate([
1888
+ entity.property({ type: "string", isSecondary: true }),
1889
+ __metadata("design:type", String)
1890
+ ], exports.DataSpaceConnectorEntry.prototype, "maintainer", void 0);
1891
+ __decorate([
1892
+ entity.property({ type: "object" }),
1893
+ __metadata("design:type", Object)
1894
+ ], exports.DataSpaceConnectorEntry.prototype, "defaultEndpoint", void 0);
1895
+ __decorate([
1896
+ entity.property({ type: "object" }),
1897
+ __metadata("design:type", Object)
1898
+ ], exports.DataSpaceConnectorEntry.prototype, "pushActivityEndpoint", void 0);
1899
+ __decorate([
1900
+ entity.property({ type: "object", optional: true }),
1901
+ __metadata("design:type", Object)
1902
+ ], exports.DataSpaceConnectorEntry.prototype, "subscriptionActivityEndpoint", void 0);
1903
+ __decorate([
1904
+ entity.property({ type: "object" }),
1905
+ __metadata("design:type", Object)
1906
+ ], exports.DataSpaceConnectorEntry.prototype, "pullDataEndpoint", void 0);
1907
+ __decorate([
1908
+ entity.property({ type: "array" }),
1909
+ __metadata("design:type", Array)
1910
+ ], exports.DataSpaceConnectorEntry.prototype, "offeredResource", void 0);
1911
+ __decorate([
1912
+ entity.property({ type: "string", format: "date-time" }),
1913
+ __metadata("design:type", String)
1914
+ ], exports.DataSpaceConnectorEntry.prototype, "validFrom", void 0);
1915
+ __decorate([
1916
+ entity.property({ type: "string", format: "date-time" }),
1917
+ __metadata("design:type", String)
1918
+ ], exports.DataSpaceConnectorEntry.prototype, "validUntil", void 0);
1919
+ __decorate([
1920
+ entity.property({ type: "string", format: "date-time", sortDirection: entity.SortDirection.Descending }),
1921
+ __metadata("design:type", String)
1922
+ ], exports.DataSpaceConnectorEntry.prototype, "dateCreated", void 0);
1923
+ __decorate([
1924
+ entity.property({ type: "array" }),
1925
+ __metadata("design:type", Array)
1926
+ ], exports.DataSpaceConnectorEntry.prototype, "evidence", void 0);
1927
+ exports.DataSpaceConnectorEntry = __decorate([
1928
+ entity.entity()
1929
+ ], exports.DataSpaceConnectorEntry);
1930
+
1931
+ // Copyright 2024 IOTA Stiftung.
1932
+ // SPDX-License-Identifier: Apache-2.0.
1933
+ /**
1934
+ * Participant entry.
1935
+ */
1936
+ exports.ParticipantEntry = class ParticipantEntry {
1937
+ /**
1938
+ * The participant Id.
1939
+ */
1940
+ id;
1941
+ /**
1942
+ * The trusted issuer of the compliance credential
1943
+ */
1944
+ issuer;
1945
+ /**
1946
+ * The legal registration number.
1947
+ */
1948
+ registrationNumber;
1949
+ /**
1950
+ * The legal name.
1951
+ */
1952
+ legalName;
1953
+ /**
1954
+ * Address
1955
+ */
1956
+ legalAddress;
1957
+ /**
1958
+ * Valid from
1959
+ */
1960
+ validFrom;
1961
+ /**
1962
+ * Valid to
1963
+ */
1964
+ validUntil;
1965
+ /**
1966
+ * Date created
1967
+ */
1968
+ dateCreated;
1969
+ /**
1970
+ * Evidences
1971
+ */
1972
+ evidence;
1973
+ };
1974
+ __decorate([
1975
+ entity.property({ type: "string", isPrimary: true }),
1976
+ __metadata("design:type", String)
1977
+ ], exports.ParticipantEntry.prototype, "id", void 0);
1978
+ __decorate([
1979
+ entity.property({ type: "string" }),
1980
+ __metadata("design:type", String)
1981
+ ], exports.ParticipantEntry.prototype, "issuer", void 0);
1982
+ __decorate([
1983
+ entity.property({ type: "object", isSecondary: true }),
1984
+ __metadata("design:type", Object)
1985
+ ], exports.ParticipantEntry.prototype, "registrationNumber", void 0);
1986
+ __decorate([
1987
+ entity.property({ type: "string", isSecondary: true }),
1988
+ __metadata("design:type", String)
1989
+ ], exports.ParticipantEntry.prototype, "legalName", void 0);
1990
+ __decorate([
1991
+ entity.property({ type: "object" }),
1992
+ __metadata("design:type", Object)
1993
+ ], exports.ParticipantEntry.prototype, "legalAddress", void 0);
1994
+ __decorate([
1995
+ entity.property({ type: "string", format: "date-time" }),
1996
+ __metadata("design:type", String)
1997
+ ], exports.ParticipantEntry.prototype, "validFrom", void 0);
1998
+ __decorate([
1999
+ entity.property({ type: "string", format: "date-time" }),
2000
+ __metadata("design:type", String)
2001
+ ], exports.ParticipantEntry.prototype, "validUntil", void 0);
2002
+ __decorate([
2003
+ entity.property({ type: "string", format: "date-time", sortDirection: entity.SortDirection.Descending }),
2004
+ __metadata("design:type", String)
2005
+ ], exports.ParticipantEntry.prototype, "dateCreated", void 0);
2006
+ __decorate([
2007
+ entity.property({ type: "array" }),
2008
+ __metadata("design:type", Array)
2009
+ ], exports.ParticipantEntry.prototype, "evidence", void 0);
2010
+ exports.ParticipantEntry = __decorate([
2011
+ entity.entity()
2012
+ ], exports.ParticipantEntry);
2013
+
2014
+ // Copyright 2024 IOTA Stiftung.
2015
+ // SPDX-License-Identifier: Apache-2.0.
2016
+ /**
2017
+ * Service Offering Entry.
2018
+ */
2019
+ exports.ServiceOfferingEntry = class ServiceOfferingEntry {
2020
+ /**
2021
+ * The service Id.
2022
+ */
2023
+ id;
2024
+ /**
2025
+ * The trusted issuer of the compliance credential associated with
2026
+ */
2027
+ issuer;
2028
+ /**
2029
+ * The service name.
2030
+ */
2031
+ name;
2032
+ /**
2033
+ * The service description.
2034
+ */
2035
+ description;
2036
+ /**
2037
+ * The provider Id
2038
+ */
2039
+ providedBy;
2040
+ /**
2041
+ * The REST endpoint
2042
+ */
2043
+ endpoint;
2044
+ /**
2045
+ * The policy
2046
+ */
2047
+ servicePolicy;
2048
+ /**
2049
+ * Resources aggregated
2050
+ */
2051
+ aggregationOfResources;
2052
+ /**
2053
+ * Valid from
2054
+ */
2055
+ validFrom;
2056
+ /**
2057
+ * Valid to
2058
+ */
2059
+ validUntil;
2060
+ /**
2061
+ * Date created
2062
+ */
2063
+ dateCreated;
2064
+ /**
2065
+ * Evidences
2066
+ */
2067
+ evidence;
2068
+ };
2069
+ __decorate([
2070
+ entity.property({ type: "string", isPrimary: true }),
2071
+ __metadata("design:type", String)
2072
+ ], exports.ServiceOfferingEntry.prototype, "id", void 0);
2073
+ __decorate([
2074
+ entity.property({ type: "string" }),
2075
+ __metadata("design:type", String)
2076
+ ], exports.ServiceOfferingEntry.prototype, "issuer", void 0);
2077
+ __decorate([
2078
+ entity.property({ type: "string" }),
2079
+ __metadata("design:type", String)
2080
+ ], exports.ServiceOfferingEntry.prototype, "name", void 0);
2081
+ __decorate([
2082
+ entity.property({ type: "string", optional: true }),
2083
+ __metadata("design:type", String)
2084
+ ], exports.ServiceOfferingEntry.prototype, "description", void 0);
2085
+ __decorate([
2086
+ entity.property({ type: "string", isSecondary: true }),
2087
+ __metadata("design:type", String)
2088
+ ], exports.ServiceOfferingEntry.prototype, "providedBy", void 0);
2089
+ __decorate([
2090
+ entity.property({ type: "object" }),
2091
+ __metadata("design:type", Object)
2092
+ ], exports.ServiceOfferingEntry.prototype, "endpoint", void 0);
2093
+ __decorate([
2094
+ entity.property({ type: "array" }),
2095
+ __metadata("design:type", Array)
2096
+ ], exports.ServiceOfferingEntry.prototype, "servicePolicy", void 0);
2097
+ __decorate([
2098
+ entity.property({ type: "array", optional: true }),
2099
+ __metadata("design:type", Array)
2100
+ ], exports.ServiceOfferingEntry.prototype, "aggregationOfResources", void 0);
2101
+ __decorate([
2102
+ entity.property({ type: "string", format: "date-time" }),
2103
+ __metadata("design:type", String)
2104
+ ], exports.ServiceOfferingEntry.prototype, "validFrom", void 0);
2105
+ __decorate([
2106
+ entity.property({ type: "string", format: "date-time" }),
2107
+ __metadata("design:type", String)
2108
+ ], exports.ServiceOfferingEntry.prototype, "validUntil", void 0);
2109
+ __decorate([
2110
+ entity.property({ type: "string", format: "date-time", sortDirection: entity.SortDirection.Descending }),
2111
+ __metadata("design:type", String)
2112
+ ], exports.ServiceOfferingEntry.prototype, "dateCreated", void 0);
2113
+ __decorate([
2114
+ entity.property({ type: "array" }),
2115
+ __metadata("design:type", Array)
2116
+ ], exports.ServiceOfferingEntry.prototype, "evidence", void 0);
2117
+ exports.ServiceOfferingEntry = __decorate([
2118
+ entity.entity()
2119
+ ], exports.ServiceOfferingEntry);
2120
+
2121
+ // Copyright 2024 IOTA Stiftung.
2122
+ // SPDX-License-Identifier: Apache-2.0.
2123
+ /**
2124
+ * Inits schemas.
2125
+ */
2126
+ function initSchema() {
2127
+ entity.EntitySchemaFactory.register("ParticipantEntry", () => entity.EntitySchemaHelper.getSchema(exports.ParticipantEntry));
2128
+ entity.EntitySchemaFactory.register("DataResourceEntry", () => entity.EntitySchemaHelper.getSchema(exports.DataResourceEntry));
2129
+ entity.EntitySchemaFactory.register("ServiceOfferingEntry", () => entity.EntitySchemaHelper.getSchema(exports.ServiceOfferingEntry));
2130
+ entity.EntitySchemaFactory.register("DataSpaceConnectorEntry", () => entity.EntitySchemaHelper.getSchema(exports.DataSpaceConnectorEntry));
2131
+ }
2132
+
2133
+ exports.FederatedCatalogueService = FederatedCatalogueService;
2134
+ exports.complianceCredentialPresentation = complianceCredentialPresentation;
2135
+ exports.dataResourceCredentialPresentation = dataResourceCredentialPresentation;
2136
+ exports.dataResourceGet = dataResourceGet;
2137
+ exports.dataResourceList = dataResourceList;
2138
+ exports.dataSpaceConnectorCredentialPresentation = dataSpaceConnectorCredentialPresentation;
2139
+ exports.dataSpaceConnectorGet = dataSpaceConnectorGet;
2140
+ exports.dataSpaceConnectorList = dataSpaceConnectorList;
2141
+ exports.generateRestRoutesFederatedCatalogue = generateRestRoutesFederatedCatalogue;
2142
+ exports.initSchema = initSchema;
2143
+ exports.participantGet = participantGet;
2144
+ exports.participantList = participantList;
2145
+ exports.restEntryPoints = restEntryPoints;
2146
+ exports.serviceOfferingCredentialPresentation = serviceOfferingCredentialPresentation;
2147
+ exports.serviceOfferingGet = serviceOfferingGet;
2148
+ exports.serviceOfferingList = serviceOfferingList;
2149
+ exports.tagsFederatedCatalogue = tagsFederatedCatalogue;