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

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