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