@twin.org/auditable-item-graph-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.
- package/LICENSE +201 -0
- package/README.md +21 -0
- package/dist/cjs/index.cjs +1606 -0
- package/dist/esm/index.mjs +1596 -0
- package/dist/types/auditableItemGraphRoutes.d.ts +45 -0
- package/dist/types/auditableItemGraphService.d.ts +123 -0
- package/dist/types/entities/auditableItemGraphAlias.d.ts +30 -0
- package/dist/types/entities/auditableItemGraphChangeset.d.ts +30 -0
- package/dist/types/entities/auditableItemGraphEdge.d.ts +30 -0
- package/dist/types/entities/auditableItemGraphPatch.d.ts +21 -0
- package/dist/types/entities/auditableItemGraphResource.d.ts +26 -0
- package/dist/types/entities/auditableItemGraphVertex.d.ts +45 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/models/IAuditableItemGraphServiceConfig.d.ts +5 -0
- package/dist/types/models/IAuditableItemGraphServiceContext.d.ts +17 -0
- package/dist/types/restEntryPoints.d.ts +2 -0
- package/dist/types/schema.d.ts +4 -0
- package/docs/changelog.md +5 -0
- package/docs/examples.md +1 -0
- package/docs/open-api/spec.json +1032 -0
- package/docs/reference/classes/AuditableItemGraphAlias.md +61 -0
- package/docs/reference/classes/AuditableItemGraphChangeset.md +61 -0
- package/docs/reference/classes/AuditableItemGraphEdge.md +61 -0
- package/docs/reference/classes/AuditableItemGraphPatch.md +45 -0
- package/docs/reference/classes/AuditableItemGraphResource.md +53 -0
- package/docs/reference/classes/AuditableItemGraphService.md +289 -0
- package/docs/reference/classes/AuditableItemGraphVertex.md +85 -0
- package/docs/reference/functions/auditableItemGraphCreate.md +25 -0
- package/docs/reference/functions/auditableItemGraphGet.md +25 -0
- package/docs/reference/functions/auditableItemGraphList.md +25 -0
- package/docs/reference/functions/auditableItemGraphUpdate.md +25 -0
- package/docs/reference/functions/generateRestRoutesAuditableItemGraph.md +21 -0
- package/docs/reference/functions/initSchema.md +9 -0
- package/docs/reference/index.md +29 -0
- package/docs/reference/interfaces/IAuditableItemGraphServiceConfig.md +3 -0
- package/docs/reference/variables/restEntryPoints.md +3 -0
- package/docs/reference/variables/tagsAuditableItemGraph.md +5 -0
- package/locales/en.json +19 -0
- package/package.json +51 -0
|
@@ -0,0 +1,1596 @@
|
|
|
1
|
+
import { AuditableItemGraphTypes, VerifyDepth } from '@twin.org/auditable-item-graph-models';
|
|
2
|
+
import { Guards, ComponentFactory, StringHelper, Is, Validation, Converter, RandomHelper, ObjectHelper, Urn, GeneralError, NotFoundError, JsonHelper } from '@twin.org/core';
|
|
3
|
+
import { SchemaOrgTypes, SchemaOrgDataTypes } from '@twin.org/data-schema-org';
|
|
4
|
+
import { HttpStatusCode, HeaderTypes, MimeTypes } from '@twin.org/web';
|
|
5
|
+
import { JsonLdHelper, JsonLdProcessor, JsonLdTypes } from '@twin.org/data-json-ld';
|
|
6
|
+
import { ComparisonOperator, SortDirection, LogicalOperator, property, entity, EntitySchemaFactory, EntitySchemaHelper } from '@twin.org/entity';
|
|
7
|
+
import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
|
|
8
|
+
import { ImmutableProofTypes, ImmutableProofFailure } from '@twin.org/immutable-proof-models';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The source used when communicating about these routes.
|
|
12
|
+
*/
|
|
13
|
+
const ROUTES_SOURCE = "auditableItemGraphRoutes";
|
|
14
|
+
/**
|
|
15
|
+
* The tag to associate with the routes.
|
|
16
|
+
*/
|
|
17
|
+
const tagsAuditableItemGraph = [
|
|
18
|
+
{
|
|
19
|
+
name: "Auditable Item Graph",
|
|
20
|
+
description: "Endpoints which are modelled to access an auditable item graph contract."
|
|
21
|
+
}
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* The REST routes for auditable item graph.
|
|
25
|
+
* @param baseRouteName Prefix to prepend to the paths.
|
|
26
|
+
* @param componentName The name of the component to use in the routes stored in the ComponentFactory.
|
|
27
|
+
* @returns The generated routes.
|
|
28
|
+
*/
|
|
29
|
+
function generateRestRoutesAuditableItemGraph(baseRouteName, componentName) {
|
|
30
|
+
const createRoute = {
|
|
31
|
+
operationId: "auditableItemGraphCreate",
|
|
32
|
+
summary: "Create a new graph vertex",
|
|
33
|
+
tag: tagsAuditableItemGraph[0].name,
|
|
34
|
+
method: "POST",
|
|
35
|
+
path: `${baseRouteName}/`,
|
|
36
|
+
handler: async (httpRequestContext, request) => auditableItemGraphCreate(httpRequestContext, componentName, request),
|
|
37
|
+
requestType: {
|
|
38
|
+
type: "IAuditableItemGraphCreateRequest",
|
|
39
|
+
examples: [
|
|
40
|
+
{
|
|
41
|
+
id: "auditableItemGraphCreateRequestExample",
|
|
42
|
+
request: {
|
|
43
|
+
body: {
|
|
44
|
+
vertexObject: {
|
|
45
|
+
"@context": "http://schema.org/",
|
|
46
|
+
"@type": "Note",
|
|
47
|
+
content: "This is a simple note"
|
|
48
|
+
},
|
|
49
|
+
aliases: [
|
|
50
|
+
{
|
|
51
|
+
id: "bar456",
|
|
52
|
+
aliasObject: {
|
|
53
|
+
"@context": "http://schema.org/",
|
|
54
|
+
"@type": "Note",
|
|
55
|
+
content: "This is a simple note"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "foo321",
|
|
60
|
+
aliasObject: {
|
|
61
|
+
"@context": "http://schema.org/",
|
|
62
|
+
"@type": "Note",
|
|
63
|
+
content: "This is a simple note"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
resources: [
|
|
68
|
+
{
|
|
69
|
+
id: "resource1",
|
|
70
|
+
resourceObject: {
|
|
71
|
+
"@context": "http://schema.org/",
|
|
72
|
+
"@type": "Note",
|
|
73
|
+
content: "This is a simple note"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: "resource2",
|
|
78
|
+
resourceObject: {
|
|
79
|
+
"@context": "http://schema.org/",
|
|
80
|
+
"@type": "Note",
|
|
81
|
+
content: "This is a simple note"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
edges: [
|
|
86
|
+
{
|
|
87
|
+
id: "edge1",
|
|
88
|
+
edgeRelationship: "frenemy",
|
|
89
|
+
edgeObject: {
|
|
90
|
+
"@context": "http://schema.org/",
|
|
91
|
+
"@type": "Note",
|
|
92
|
+
content: "This is a simple note"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: "edge2",
|
|
97
|
+
edgeRelationship: "end",
|
|
98
|
+
edgeObject: {
|
|
99
|
+
"@context": "http://schema.org/",
|
|
100
|
+
"@type": "Note",
|
|
101
|
+
content: "This is a simple note"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
responseType: [
|
|
111
|
+
{
|
|
112
|
+
type: "ICreatedResponse",
|
|
113
|
+
examples: [
|
|
114
|
+
{
|
|
115
|
+
id: "auditableItemGraphCreateResponseExample",
|
|
116
|
+
description: "The response when a new graph vertex is created.",
|
|
117
|
+
response: {
|
|
118
|
+
statusCode: HttpStatusCode.created,
|
|
119
|
+
headers: {
|
|
120
|
+
[HeaderTypes.Location]: "aig:1234567890"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
};
|
|
128
|
+
const getRoute = {
|
|
129
|
+
operationId: "auditableItemGraphGet",
|
|
130
|
+
summary: "Get a graph vertex",
|
|
131
|
+
tag: tagsAuditableItemGraph[0].name,
|
|
132
|
+
method: "GET",
|
|
133
|
+
path: `${baseRouteName}/:id`,
|
|
134
|
+
handler: async (httpRequestContext, request) => auditableItemGraphGet(httpRequestContext, componentName, request),
|
|
135
|
+
requestType: {
|
|
136
|
+
type: "IAuditableItemGraphGetRequest",
|
|
137
|
+
examples: [
|
|
138
|
+
{
|
|
139
|
+
id: "auditableItemGraphGetRequestExample",
|
|
140
|
+
request: {
|
|
141
|
+
headers: {
|
|
142
|
+
[HeaderTypes.Accept]: MimeTypes.Json
|
|
143
|
+
},
|
|
144
|
+
pathParams: {
|
|
145
|
+
id: "aig:1234567890"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
},
|
|
151
|
+
responseType: [
|
|
152
|
+
{
|
|
153
|
+
type: "IAuditableItemGraphGetResponse",
|
|
154
|
+
examples: [
|
|
155
|
+
{
|
|
156
|
+
id: "auditableItemGraphGetResponseExample",
|
|
157
|
+
response: {
|
|
158
|
+
body: {
|
|
159
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
160
|
+
type: AuditableItemGraphTypes.Vertex,
|
|
161
|
+
id: "aig:1234567890",
|
|
162
|
+
dateCreated: "2024-08-22T11:55:16.271Z",
|
|
163
|
+
dateModified: "2024-08-22T11:55:16.271Z",
|
|
164
|
+
vertexObject: {
|
|
165
|
+
"@context": "http://schema.org/",
|
|
166
|
+
"@type": "Note",
|
|
167
|
+
content: "This is a simple note"
|
|
168
|
+
},
|
|
169
|
+
aliases: [
|
|
170
|
+
{
|
|
171
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
172
|
+
type: AuditableItemGraphTypes.Alias,
|
|
173
|
+
id: "tst:1234567890",
|
|
174
|
+
dateCreated: "2024-08-22T11:55:16.271Z"
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
type: "IAuditableItemGraphGetResponse",
|
|
184
|
+
mimeType: MimeTypes.JsonLd,
|
|
185
|
+
examples: [
|
|
186
|
+
{
|
|
187
|
+
id: "auditableItemGraphJsonLdGetResponseExample",
|
|
188
|
+
response: {
|
|
189
|
+
headers: {
|
|
190
|
+
[HeaderTypes.ContentType]: MimeTypes.JsonLd
|
|
191
|
+
},
|
|
192
|
+
body: {
|
|
193
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
194
|
+
type: AuditableItemGraphTypes.Vertex,
|
|
195
|
+
id: "aig:1234567890",
|
|
196
|
+
dateCreated: "2024-08-22T11:55:16.271Z",
|
|
197
|
+
dateModified: "2024-08-22T11:55:16.271Z",
|
|
198
|
+
vertexObject: {
|
|
199
|
+
"@context": "http://schema.org/",
|
|
200
|
+
"@type": "Note",
|
|
201
|
+
content: "This is a simple note"
|
|
202
|
+
},
|
|
203
|
+
aliases: [
|
|
204
|
+
{
|
|
205
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
206
|
+
type: AuditableItemGraphTypes.Alias,
|
|
207
|
+
dateCreated: "2024-08-22T11:55:16.271Z",
|
|
208
|
+
id: "tst:1234567890"
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
]
|
|
217
|
+
};
|
|
218
|
+
const updateRoute = {
|
|
219
|
+
operationId: "auditableItemGraphUpdate",
|
|
220
|
+
summary: "Update a graph vertex",
|
|
221
|
+
tag: tagsAuditableItemGraph[0].name,
|
|
222
|
+
method: "PUT",
|
|
223
|
+
path: `${baseRouteName}/:id`,
|
|
224
|
+
handler: async (httpRequestContext, request) => auditableItemGraphUpdate(httpRequestContext, componentName, request),
|
|
225
|
+
requestType: {
|
|
226
|
+
type: "IAuditableItemGraphUpdateRequest",
|
|
227
|
+
examples: [
|
|
228
|
+
{
|
|
229
|
+
id: "auditableItemGraphUpdateRequestExample",
|
|
230
|
+
request: {
|
|
231
|
+
pathParams: {
|
|
232
|
+
id: "aig:1234567890"
|
|
233
|
+
},
|
|
234
|
+
body: {
|
|
235
|
+
vertexObject: {
|
|
236
|
+
"@context": "http://schema.org/",
|
|
237
|
+
"@type": "Note",
|
|
238
|
+
content: "This is a simple note"
|
|
239
|
+
},
|
|
240
|
+
aliases: [
|
|
241
|
+
{
|
|
242
|
+
id: "bar456",
|
|
243
|
+
aliasObject: {
|
|
244
|
+
"@context": "http://schema.org/",
|
|
245
|
+
"@type": "Note",
|
|
246
|
+
content: "This is a simple note"
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
id: "foo321",
|
|
251
|
+
aliasObject: {
|
|
252
|
+
"@context": "http://schema.org/",
|
|
253
|
+
"@type": "Note",
|
|
254
|
+
content: "This is a simple note"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
],
|
|
258
|
+
resources: [
|
|
259
|
+
{
|
|
260
|
+
id: "resource1",
|
|
261
|
+
resourceObject: {
|
|
262
|
+
"@context": "http://schema.org/",
|
|
263
|
+
"@type": "Note",
|
|
264
|
+
content: "This is a simple note"
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
id: "resource2",
|
|
269
|
+
resourceObject: {
|
|
270
|
+
"@context": "http://schema.org/",
|
|
271
|
+
"@type": "Note",
|
|
272
|
+
content: "This is a simple note"
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
],
|
|
276
|
+
edges: [
|
|
277
|
+
{
|
|
278
|
+
id: "edge1",
|
|
279
|
+
edgeRelationship: "frenemy",
|
|
280
|
+
edgeObject: {
|
|
281
|
+
"@context": "http://schema.org/",
|
|
282
|
+
"@type": "Note",
|
|
283
|
+
content: "This is a simple note"
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: "edge2",
|
|
288
|
+
edgeRelationship: "end",
|
|
289
|
+
edgeObject: {
|
|
290
|
+
"@context": "http://schema.org/",
|
|
291
|
+
"@type": "Note",
|
|
292
|
+
content: "This is a simple note"
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
]
|
|
300
|
+
},
|
|
301
|
+
responseType: [
|
|
302
|
+
{
|
|
303
|
+
type: "INoContentResponse"
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
};
|
|
307
|
+
const listRoute = {
|
|
308
|
+
operationId: "auditableItemGraphList",
|
|
309
|
+
summary: "Query graph vertices by id or alias",
|
|
310
|
+
tag: tagsAuditableItemGraph[0].name,
|
|
311
|
+
method: "GET",
|
|
312
|
+
path: `${baseRouteName}/`,
|
|
313
|
+
handler: async (httpRequestContext, request) => auditableItemGraphList(httpRequestContext, componentName, request),
|
|
314
|
+
requestType: {
|
|
315
|
+
type: "IAuditableItemGraphListRequest",
|
|
316
|
+
examples: [
|
|
317
|
+
{
|
|
318
|
+
id: "IAuditableItemGraphListAllRequest",
|
|
319
|
+
request: {}
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
id: "IAuditableItemGraphListIdRequest",
|
|
323
|
+
request: {
|
|
324
|
+
query: {
|
|
325
|
+
id: "1234567890"
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
]
|
|
330
|
+
},
|
|
331
|
+
responseType: [
|
|
332
|
+
{
|
|
333
|
+
type: "IAuditableItemGraphListResponse",
|
|
334
|
+
examples: [
|
|
335
|
+
{
|
|
336
|
+
id: "auditableItemGraphListResponseExample",
|
|
337
|
+
response: {
|
|
338
|
+
body: {
|
|
339
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
340
|
+
type: AuditableItemGraphTypes.VertexList,
|
|
341
|
+
vertices: [
|
|
342
|
+
{
|
|
343
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
344
|
+
type: AuditableItemGraphTypes.Vertex,
|
|
345
|
+
id: "0101010101010101010101010101010101010101010101010101010101010101",
|
|
346
|
+
dateCreated: "2024-08-22T11:55:16.271Z",
|
|
347
|
+
aliases: [
|
|
348
|
+
{
|
|
349
|
+
"@context": [
|
|
350
|
+
AuditableItemGraphTypes.ContextRoot,
|
|
351
|
+
SchemaOrgTypes.ContextRoot
|
|
352
|
+
],
|
|
353
|
+
type: AuditableItemGraphTypes.Alias,
|
|
354
|
+
id: "foo4",
|
|
355
|
+
dateCreated: "2024-08-22T11:55:16.271Z"
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
],
|
|
360
|
+
cursor: "1"
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
]
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
type: "IAuditableItemGraphListResponse",
|
|
368
|
+
mimeType: MimeTypes.JsonLd,
|
|
369
|
+
examples: [
|
|
370
|
+
{
|
|
371
|
+
id: "auditableItemGraphJsonLdListResponseExample",
|
|
372
|
+
response: {
|
|
373
|
+
headers: {
|
|
374
|
+
[HeaderTypes.ContentType]: MimeTypes.JsonLd
|
|
375
|
+
},
|
|
376
|
+
body: {
|
|
377
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
378
|
+
type: AuditableItemGraphTypes.VertexList,
|
|
379
|
+
vertices: [
|
|
380
|
+
{
|
|
381
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
382
|
+
type: AuditableItemGraphTypes.Vertex,
|
|
383
|
+
id: "0101010101010101010101010101010101010101010101010101010101010101",
|
|
384
|
+
dateCreated: "2024-08-22T11:55:16.271Z",
|
|
385
|
+
aliases: [
|
|
386
|
+
{
|
|
387
|
+
"@context": [
|
|
388
|
+
AuditableItemGraphTypes.ContextRoot,
|
|
389
|
+
SchemaOrgTypes.ContextRoot
|
|
390
|
+
],
|
|
391
|
+
type: AuditableItemGraphTypes.Alias,
|
|
392
|
+
id: "foo4",
|
|
393
|
+
dateCreated: "2024-08-22T11:55:16.271Z"
|
|
394
|
+
}
|
|
395
|
+
]
|
|
396
|
+
}
|
|
397
|
+
],
|
|
398
|
+
cursor: "1"
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
]
|
|
403
|
+
}
|
|
404
|
+
]
|
|
405
|
+
};
|
|
406
|
+
return [createRoute, getRoute, updateRoute, listRoute];
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Create the graph vertex.
|
|
410
|
+
* @param httpRequestContext The request context for the API.
|
|
411
|
+
* @param componentName The name of the component to use in the routes.
|
|
412
|
+
* @param request The request.
|
|
413
|
+
* @returns The response object with additional http response properties.
|
|
414
|
+
*/
|
|
415
|
+
async function auditableItemGraphCreate(httpRequestContext, componentName, request) {
|
|
416
|
+
Guards.object(ROUTES_SOURCE, "request", request);
|
|
417
|
+
const component = ComponentFactory.get(componentName);
|
|
418
|
+
const id = await component.create(request.body?.vertexObject, request.body?.aliases, request.body?.resources, request.body?.edges, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
419
|
+
return {
|
|
420
|
+
statusCode: HttpStatusCode.created,
|
|
421
|
+
headers: {
|
|
422
|
+
[HeaderTypes.Location]: id
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Get the graph vertex.
|
|
428
|
+
* @param httpRequestContext The request context for the API.
|
|
429
|
+
* @param componentName The name of the component to use in the routes.
|
|
430
|
+
* @param request The request.
|
|
431
|
+
* @returns The response object with additional http response properties.
|
|
432
|
+
*/
|
|
433
|
+
async function auditableItemGraphGet(httpRequestContext, componentName, request) {
|
|
434
|
+
Guards.object(ROUTES_SOURCE, "request", request);
|
|
435
|
+
Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
436
|
+
Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
437
|
+
const mimeType = request.headers?.[HeaderTypes.Accept] === MimeTypes.JsonLd ? "jsonld" : "json";
|
|
438
|
+
const component = ComponentFactory.get(componentName);
|
|
439
|
+
const result = await component.get(request.pathParams.id, {
|
|
440
|
+
includeDeleted: request.query?.includeDeleted,
|
|
441
|
+
includeChangesets: request.query?.includeChangesets,
|
|
442
|
+
verifySignatureDepth: request.query?.verifySignatureDepth
|
|
443
|
+
});
|
|
444
|
+
return {
|
|
445
|
+
headers: {
|
|
446
|
+
[HeaderTypes.ContentType]: mimeType === "json" ? MimeTypes.Json : MimeTypes.JsonLd
|
|
447
|
+
},
|
|
448
|
+
body: result
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Update the graph vertex.
|
|
453
|
+
* @param httpRequestContext The request context for the API.
|
|
454
|
+
* @param componentName The name of the component to use in the routes.
|
|
455
|
+
* @param request The request.
|
|
456
|
+
* @returns The response object with additional http response properties.
|
|
457
|
+
*/
|
|
458
|
+
async function auditableItemGraphUpdate(httpRequestContext, componentName, request) {
|
|
459
|
+
Guards.object(ROUTES_SOURCE, "request", request);
|
|
460
|
+
Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
461
|
+
Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
462
|
+
const component = ComponentFactory.get(componentName);
|
|
463
|
+
await component.update(request.pathParams.id, request.body?.vertexObject, request.body?.aliases, request.body?.resources, request.body?.edges, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
464
|
+
return {
|
|
465
|
+
statusCode: HttpStatusCode.noContent
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Query the graph vertices.
|
|
470
|
+
* @param httpRequestContext The request context for the API.
|
|
471
|
+
* @param componentName The name of the component to use in the routes.
|
|
472
|
+
* @param request The request.
|
|
473
|
+
* @returns The response object with additional http response properties.
|
|
474
|
+
*/
|
|
475
|
+
async function auditableItemGraphList(httpRequestContext, componentName, request) {
|
|
476
|
+
Guards.object(ROUTES_SOURCE, "request", request);
|
|
477
|
+
Guards.object(ROUTES_SOURCE, "request.query", request.query);
|
|
478
|
+
const mimeType = request.headers?.[HeaderTypes.Accept] === MimeTypes.JsonLd ? "jsonld" : "json";
|
|
479
|
+
const component = ComponentFactory.get(componentName);
|
|
480
|
+
const result = await component.query({
|
|
481
|
+
id: request.query?.id,
|
|
482
|
+
idMode: request.query?.idMode
|
|
483
|
+
}, request.query?.orderBy, request.query?.orderByDirection, request.query?.properties?.split(","), request.query?.cursor, request.query?.pageSize);
|
|
484
|
+
return {
|
|
485
|
+
headers: {
|
|
486
|
+
[HeaderTypes.ContentType]: mimeType === "json" ? MimeTypes.Json : MimeTypes.JsonLd
|
|
487
|
+
},
|
|
488
|
+
body: result
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Copyright 2024 IOTA Stiftung.
|
|
493
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
494
|
+
/**
|
|
495
|
+
* Class for performing auditable item graph operations.
|
|
496
|
+
*/
|
|
497
|
+
class AuditableItemGraphService {
|
|
498
|
+
/**
|
|
499
|
+
* The namespace for the service.
|
|
500
|
+
*/
|
|
501
|
+
static NAMESPACE = "aig";
|
|
502
|
+
/**
|
|
503
|
+
* The namespace for the service changeset.
|
|
504
|
+
*/
|
|
505
|
+
static NAMESPACE_CHANGESET = "changeset";
|
|
506
|
+
/**
|
|
507
|
+
* The keys to pick when creating the proof for the stream.
|
|
508
|
+
*/
|
|
509
|
+
static _PROOF_KEYS_CHANGESET = [
|
|
510
|
+
"id",
|
|
511
|
+
"vertexId",
|
|
512
|
+
"userIdentity",
|
|
513
|
+
"dateCreated",
|
|
514
|
+
"patches"
|
|
515
|
+
];
|
|
516
|
+
/**
|
|
517
|
+
* Runtime name for the class.
|
|
518
|
+
*/
|
|
519
|
+
CLASS_NAME = "AuditableItemGraphService";
|
|
520
|
+
/**
|
|
521
|
+
* The immutable proof component.
|
|
522
|
+
* @internal
|
|
523
|
+
*/
|
|
524
|
+
_immutableProofComponent;
|
|
525
|
+
/**
|
|
526
|
+
* The entity storage for vertices.
|
|
527
|
+
* @internal
|
|
528
|
+
*/
|
|
529
|
+
_vertexStorage;
|
|
530
|
+
/**
|
|
531
|
+
* The entity storage for changesets.
|
|
532
|
+
* @internal
|
|
533
|
+
*/
|
|
534
|
+
_changesetStorage;
|
|
535
|
+
/**
|
|
536
|
+
* Create a new instance of AuditableItemGraphService.
|
|
537
|
+
* @param options The dependencies for the auditable item graph connector.
|
|
538
|
+
* @param options.config The configuration for the connector.
|
|
539
|
+
* @param options.immutableProofComponentType The immutable proof component type, defaults to "immutable-proof".
|
|
540
|
+
* @param options.vertexEntityStorageType The entity storage for vertices, defaults to "auditable-item-graph-vertex".
|
|
541
|
+
* @param options.changesetEntityStorageType The entity storage for changesets, defaults to "auditable-item-graph-changeset".
|
|
542
|
+
*/
|
|
543
|
+
constructor(options) {
|
|
544
|
+
this._immutableProofComponent = ComponentFactory.get(options?.immutableProofComponentType ?? "immutable-proof");
|
|
545
|
+
this._vertexStorage = EntityStorageConnectorFactory.get(options?.vertexEntityStorageType ?? StringHelper.kebabCase("AuditableItemGraphVertex"));
|
|
546
|
+
this._changesetStorage = EntityStorageConnectorFactory.get(options?.changesetEntityStorageType ??
|
|
547
|
+
StringHelper.kebabCase("AuditableItemGraphChangeset"));
|
|
548
|
+
SchemaOrgDataTypes.registerRedirects();
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Create a new graph vertex.
|
|
552
|
+
* @param vertexObject The object for the vertex as JSON-LD.
|
|
553
|
+
* @param aliases Alternative aliases that can be used to identify the vertex.
|
|
554
|
+
* @param resources The resources attached to the vertex.
|
|
555
|
+
* @param edges The edges connected to the vertex.
|
|
556
|
+
* @param userIdentity The identity to create the auditable item graph operation with.
|
|
557
|
+
* @param nodeIdentity The node identity to include in the auditable item graph.
|
|
558
|
+
* @returns The id of the new graph item.
|
|
559
|
+
*/
|
|
560
|
+
async create(vertexObject, aliases, resources, edges, userIdentity, nodeIdentity) {
|
|
561
|
+
Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
562
|
+
Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
563
|
+
try {
|
|
564
|
+
if (Is.object(vertexObject)) {
|
|
565
|
+
const validationFailures = [];
|
|
566
|
+
await JsonLdHelper.validate(vertexObject, validationFailures);
|
|
567
|
+
Validation.asValidationError(this.CLASS_NAME, "vertexObject", validationFailures);
|
|
568
|
+
}
|
|
569
|
+
const id = Converter.bytesToHex(RandomHelper.generate(32), false);
|
|
570
|
+
const context = {
|
|
571
|
+
now: new Date(Date.now()).toISOString(),
|
|
572
|
+
userIdentity,
|
|
573
|
+
nodeIdentity
|
|
574
|
+
};
|
|
575
|
+
const vertex = {
|
|
576
|
+
id,
|
|
577
|
+
nodeIdentity,
|
|
578
|
+
dateCreated: context.now,
|
|
579
|
+
dateModified: context.now
|
|
580
|
+
};
|
|
581
|
+
const originalEntity = ObjectHelper.clone(vertex);
|
|
582
|
+
vertex.vertexObject = vertexObject;
|
|
583
|
+
await this.updateAliasList(context, vertex, aliases);
|
|
584
|
+
await this.updateResourceList(context, vertex, resources);
|
|
585
|
+
await this.updateEdgeList(context, vertex, edges);
|
|
586
|
+
delete originalEntity.aliasIndex;
|
|
587
|
+
await this.addChangeset(context, originalEntity, vertex, true);
|
|
588
|
+
await this._vertexStorage.set({
|
|
589
|
+
...vertex,
|
|
590
|
+
aliasIndex: vertex.aliases
|
|
591
|
+
?.map(a => a.id)
|
|
592
|
+
.join("||")
|
|
593
|
+
.toLowerCase()
|
|
594
|
+
});
|
|
595
|
+
return new Urn(AuditableItemGraphService.NAMESPACE, id).toString();
|
|
596
|
+
}
|
|
597
|
+
catch (error) {
|
|
598
|
+
throw new GeneralError(this.CLASS_NAME, "createFailed", undefined, error);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Get a graph vertex.
|
|
603
|
+
* @param id The id of the vertex to get.
|
|
604
|
+
* @returns The vertex if found.
|
|
605
|
+
* @param options Additional options for the get operation.
|
|
606
|
+
* @param options.includeDeleted Whether to include deleted/updated aliases, resource, edges, defaults to false.
|
|
607
|
+
* @param options.includeChangesets Whether to include the changesets of the vertex, defaults to false.
|
|
608
|
+
* @param options.verifySignatureDepth How many signatures to verify, defaults to "none".
|
|
609
|
+
* @throws NotFoundError if the vertex is not found.
|
|
610
|
+
*/
|
|
611
|
+
async get(id, options) {
|
|
612
|
+
Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
613
|
+
const urnParsed = Urn.fromValidString(id);
|
|
614
|
+
if (urnParsed.namespaceIdentifier() !== AuditableItemGraphService.NAMESPACE) {
|
|
615
|
+
throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
|
|
616
|
+
namespace: AuditableItemGraphService.NAMESPACE,
|
|
617
|
+
id
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
try {
|
|
621
|
+
const vertexId = urnParsed.namespaceSpecific(0);
|
|
622
|
+
const vertexEntity = await this._vertexStorage.get(vertexId);
|
|
623
|
+
if (Is.empty(vertexEntity)) {
|
|
624
|
+
throw new NotFoundError(this.CLASS_NAME, "vertexNotFound", id);
|
|
625
|
+
}
|
|
626
|
+
const vertexModel = this.vertexEntityToJsonLd(vertexEntity);
|
|
627
|
+
const includeChangesets = options?.includeChangesets ?? false;
|
|
628
|
+
const verifySignatureDepth = options?.verifySignatureDepth ?? "none";
|
|
629
|
+
let verified;
|
|
630
|
+
let changesets;
|
|
631
|
+
if (verifySignatureDepth === VerifyDepth.Current ||
|
|
632
|
+
verifySignatureDepth === VerifyDepth.All ||
|
|
633
|
+
includeChangesets) {
|
|
634
|
+
const verifyResult = await this.verifyChangesets(vertexModel, verifySignatureDepth);
|
|
635
|
+
verified = verifyResult.verified;
|
|
636
|
+
changesets = verifyResult.changesets;
|
|
637
|
+
}
|
|
638
|
+
if (!(options?.includeDeleted ?? false)) {
|
|
639
|
+
if (Is.arrayValue(vertexModel.aliases)) {
|
|
640
|
+
vertexModel.aliases = vertexModel.aliases.filter(a => Is.undefined(a.dateDeleted));
|
|
641
|
+
if (vertexModel.aliases.length === 0) {
|
|
642
|
+
delete vertexModel.aliases;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
if (Is.arrayValue(vertexModel.resources)) {
|
|
646
|
+
vertexModel.resources = vertexModel.resources.filter(r => Is.undefined(r.dateDeleted));
|
|
647
|
+
if (vertexModel.resources.length === 0) {
|
|
648
|
+
delete vertexModel.resources;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
if (Is.arrayValue(vertexModel.edges)) {
|
|
652
|
+
vertexModel.edges = vertexModel.edges.filter(r => Is.undefined(r.dateDeleted));
|
|
653
|
+
if (vertexModel.edges.length === 0) {
|
|
654
|
+
delete vertexModel.edges;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
if (includeChangesets) {
|
|
659
|
+
vertexModel.changesets = changesets;
|
|
660
|
+
}
|
|
661
|
+
if (verifySignatureDepth !== VerifyDepth.None) {
|
|
662
|
+
vertexModel.verified = verified;
|
|
663
|
+
}
|
|
664
|
+
const compacted = await JsonLdProcessor.compact(vertexModel, vertexModel["@context"]);
|
|
665
|
+
return compacted;
|
|
666
|
+
}
|
|
667
|
+
catch (error) {
|
|
668
|
+
throw new GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Update a graph vertex.
|
|
673
|
+
* @param id The id of the vertex to update.
|
|
674
|
+
* @param vertexObject The object for the vertex.
|
|
675
|
+
* @param aliases Alternative aliases that can be used to identify the vertex.
|
|
676
|
+
* @param resources The resources attached to the vertex.
|
|
677
|
+
* @param edges The edges connected to the vertex.
|
|
678
|
+
* @param userIdentity The identity to create the auditable item graph operation with.
|
|
679
|
+
* @param nodeIdentity The node identity to include in the auditable item graph.
|
|
680
|
+
* @returns Nothing.
|
|
681
|
+
*/
|
|
682
|
+
async update(id, vertexObject, aliases, resources, edges, userIdentity, nodeIdentity) {
|
|
683
|
+
Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
684
|
+
Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
685
|
+
Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
686
|
+
const urnParsed = Urn.fromValidString(id);
|
|
687
|
+
if (urnParsed.namespaceIdentifier() !== AuditableItemGraphService.NAMESPACE) {
|
|
688
|
+
throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
|
|
689
|
+
namespace: AuditableItemGraphService.NAMESPACE,
|
|
690
|
+
id
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
try {
|
|
694
|
+
const vertexId = urnParsed.namespaceSpecific(0);
|
|
695
|
+
const vertexEntity = await this._vertexStorage.get(vertexId);
|
|
696
|
+
if (Is.empty(vertexEntity)) {
|
|
697
|
+
throw new NotFoundError(this.CLASS_NAME, "vertexNotFound", id);
|
|
698
|
+
}
|
|
699
|
+
if (Is.object(vertexObject)) {
|
|
700
|
+
const validationFailures = [];
|
|
701
|
+
await JsonLdHelper.validate(vertexObject, validationFailures);
|
|
702
|
+
Validation.asValidationError(this.CLASS_NAME, "vertexObject", validationFailures);
|
|
703
|
+
}
|
|
704
|
+
const context = {
|
|
705
|
+
now: new Date(Date.now()).toISOString(),
|
|
706
|
+
userIdentity,
|
|
707
|
+
nodeIdentity
|
|
708
|
+
};
|
|
709
|
+
delete vertexEntity.aliasIndex;
|
|
710
|
+
const originalEntity = ObjectHelper.clone(vertexEntity);
|
|
711
|
+
const newEntity = ObjectHelper.clone(vertexEntity);
|
|
712
|
+
newEntity.vertexObject = vertexObject;
|
|
713
|
+
await this.updateAliasList(context, newEntity, aliases);
|
|
714
|
+
await this.updateResourceList(context, newEntity, resources);
|
|
715
|
+
await this.updateEdgeList(context, newEntity, edges);
|
|
716
|
+
const changes = await this.addChangeset(context, originalEntity, newEntity, false);
|
|
717
|
+
if (changes) {
|
|
718
|
+
newEntity.dateModified = context.now;
|
|
719
|
+
await this._vertexStorage.set({
|
|
720
|
+
...newEntity,
|
|
721
|
+
aliasIndex: newEntity.aliases
|
|
722
|
+
?.map(a => a.id)
|
|
723
|
+
.join("||")
|
|
724
|
+
.toLowerCase()
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
catch (error) {
|
|
729
|
+
throw new GeneralError(this.CLASS_NAME, "updateFailed", undefined, error);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Remove the immutable storage for an item.
|
|
734
|
+
* @param id The id of the vertex to get.
|
|
735
|
+
* @param nodeIdentity The node identity to use for vault operations.
|
|
736
|
+
* @returns Nothing.
|
|
737
|
+
* @throws NotFoundError if the vertex is not found.
|
|
738
|
+
*/
|
|
739
|
+
async removeImmutable(id, nodeIdentity) {
|
|
740
|
+
Guards.stringValue(this.CLASS_NAME, "id", id);
|
|
741
|
+
Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
742
|
+
const urnParsed = Urn.fromValidString(id);
|
|
743
|
+
if (urnParsed.namespaceIdentifier() !== AuditableItemGraphService.NAMESPACE) {
|
|
744
|
+
throw new GeneralError(this.CLASS_NAME, "namespaceMismatch", {
|
|
745
|
+
namespace: AuditableItemGraphService.NAMESPACE,
|
|
746
|
+
id
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
try {
|
|
750
|
+
const vertexId = urnParsed.namespaceSpecific(0);
|
|
751
|
+
const vertexEntity = await this._vertexStorage.get(vertexId);
|
|
752
|
+
if (Is.empty(vertexEntity)) {
|
|
753
|
+
throw new NotFoundError(this.CLASS_NAME, "vertexNotFound", id);
|
|
754
|
+
}
|
|
755
|
+
let changesetsResult;
|
|
756
|
+
do {
|
|
757
|
+
changesetsResult = await this._changesetStorage.query({
|
|
758
|
+
property: "vertexId",
|
|
759
|
+
value: vertexId,
|
|
760
|
+
comparison: ComparisonOperator.Equals
|
|
761
|
+
}, [
|
|
762
|
+
{
|
|
763
|
+
property: "dateCreated",
|
|
764
|
+
sortDirection: SortDirection.Ascending
|
|
765
|
+
}
|
|
766
|
+
], undefined, changesetsResult?.cursor);
|
|
767
|
+
for (const changeset of changesetsResult.entities) {
|
|
768
|
+
if (Is.stringValue(changeset.proofId)) {
|
|
769
|
+
await this._immutableProofComponent.removeImmutable(changeset.proofId, nodeIdentity);
|
|
770
|
+
delete changeset.proofId;
|
|
771
|
+
await this._changesetStorage.set(changeset);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
} while (Is.stringValue(changesetsResult.cursor));
|
|
775
|
+
}
|
|
776
|
+
catch (error) {
|
|
777
|
+
throw new GeneralError(this.CLASS_NAME, "removeImmutableFailed", undefined, error);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Query the graph for vertices.
|
|
782
|
+
* @param options The query options.
|
|
783
|
+
* @param options.id The optional id to look for.
|
|
784
|
+
* @param options.idMode Look in id, alias or both, defaults to both.
|
|
785
|
+
* @param orderBy The order for the results, defaults to created.
|
|
786
|
+
* @param orderByDirection The direction for the order, defaults to desc.
|
|
787
|
+
* @param properties The properties to return, if not provided defaults to id, created, aliases and object.
|
|
788
|
+
* @param cursor The cursor to request the next page of entities.
|
|
789
|
+
* @param pageSize The maximum number of entities in a page.
|
|
790
|
+
* @returns The entities, which can be partial if a limited keys list was provided.
|
|
791
|
+
*/
|
|
792
|
+
async query(options, orderBy, orderByDirection, properties, cursor, pageSize) {
|
|
793
|
+
try {
|
|
794
|
+
const propertiesToReturn = properties ?? [
|
|
795
|
+
"id",
|
|
796
|
+
"dateCreated",
|
|
797
|
+
"dateModified",
|
|
798
|
+
"aliases",
|
|
799
|
+
"vertexObject"
|
|
800
|
+
];
|
|
801
|
+
const conditions = [];
|
|
802
|
+
const orderProperty = orderBy ?? "dateCreated";
|
|
803
|
+
const orderDirection = orderByDirection ?? SortDirection.Descending;
|
|
804
|
+
const idOrAlias = options?.id;
|
|
805
|
+
if (Is.stringValue(idOrAlias)) {
|
|
806
|
+
const idMode = options?.idMode ?? "both";
|
|
807
|
+
if (idMode === "id" || idMode === "both") {
|
|
808
|
+
conditions.push({
|
|
809
|
+
property: "id",
|
|
810
|
+
comparison: ComparisonOperator.Includes,
|
|
811
|
+
value: idOrAlias
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
if (idMode === "alias" || idMode === "both") {
|
|
815
|
+
conditions.push({
|
|
816
|
+
property: "aliasIndex",
|
|
817
|
+
comparison: ComparisonOperator.Includes,
|
|
818
|
+
value: idOrAlias.toLowerCase()
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
if (!propertiesToReturn.includes("id")) {
|
|
823
|
+
propertiesToReturn.unshift("id");
|
|
824
|
+
}
|
|
825
|
+
const results = await this._vertexStorage.query(conditions.length > 0
|
|
826
|
+
? {
|
|
827
|
+
conditions,
|
|
828
|
+
logicalOperator: LogicalOperator.Or
|
|
829
|
+
}
|
|
830
|
+
: undefined, [
|
|
831
|
+
{
|
|
832
|
+
property: orderProperty,
|
|
833
|
+
sortDirection: orderDirection
|
|
834
|
+
}
|
|
835
|
+
], propertiesToReturn, cursor, pageSize);
|
|
836
|
+
const models = results.entities.map(e => this.vertexEntityToJsonLd(e));
|
|
837
|
+
const vertexList = {
|
|
838
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
839
|
+
type: AuditableItemGraphTypes.VertexList,
|
|
840
|
+
vertices: models,
|
|
841
|
+
cursor: results.cursor
|
|
842
|
+
};
|
|
843
|
+
const compacted = await JsonLdProcessor.compact(vertexList, vertexList["@context"]);
|
|
844
|
+
return compacted;
|
|
845
|
+
}
|
|
846
|
+
catch (error) {
|
|
847
|
+
throw new GeneralError(this.CLASS_NAME, "queryingFailed", undefined, error);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* Map the vertex entity to JSON-LD.
|
|
852
|
+
* @param vertexEntity The vertex entity.
|
|
853
|
+
* @returns The model.
|
|
854
|
+
* @internal
|
|
855
|
+
*/
|
|
856
|
+
vertexEntityToJsonLd(vertexEntity) {
|
|
857
|
+
const model = {
|
|
858
|
+
"@context": [
|
|
859
|
+
AuditableItemGraphTypes.ContextRoot,
|
|
860
|
+
ImmutableProofTypes.ContextRoot,
|
|
861
|
+
SchemaOrgTypes.ContextRoot
|
|
862
|
+
],
|
|
863
|
+
type: AuditableItemGraphTypes.Vertex,
|
|
864
|
+
id: vertexEntity.id,
|
|
865
|
+
dateCreated: vertexEntity.dateCreated,
|
|
866
|
+
dateModified: vertexEntity.dateModified,
|
|
867
|
+
nodeIdentity: vertexEntity.nodeIdentity,
|
|
868
|
+
vertexObject: vertexEntity.vertexObject
|
|
869
|
+
};
|
|
870
|
+
if (Is.arrayValue(vertexEntity.aliases)) {
|
|
871
|
+
model.aliases ??= [];
|
|
872
|
+
for (const aliasEntity of vertexEntity.aliases) {
|
|
873
|
+
const aliasModel = {
|
|
874
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
875
|
+
type: AuditableItemGraphTypes.Alias,
|
|
876
|
+
id: aliasEntity.id,
|
|
877
|
+
aliasFormat: aliasEntity.aliasFormat,
|
|
878
|
+
dateCreated: aliasEntity.dateCreated,
|
|
879
|
+
dateModified: aliasEntity.dateModified,
|
|
880
|
+
dateDeleted: aliasEntity.dateDeleted,
|
|
881
|
+
aliasObject: aliasEntity.aliasObject
|
|
882
|
+
};
|
|
883
|
+
model.aliases.push(aliasModel);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
if (Is.arrayValue(vertexEntity.resources)) {
|
|
887
|
+
model.resources ??= [];
|
|
888
|
+
for (const resourceEntity of vertexEntity.resources) {
|
|
889
|
+
const resourceModel = {
|
|
890
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
891
|
+
type: AuditableItemGraphTypes.Resource,
|
|
892
|
+
id: resourceEntity.id,
|
|
893
|
+
dateCreated: resourceEntity.dateCreated,
|
|
894
|
+
dateModified: resourceEntity.dateModified,
|
|
895
|
+
dateDeleted: resourceEntity.dateDeleted,
|
|
896
|
+
resourceObject: resourceEntity.resourceObject
|
|
897
|
+
};
|
|
898
|
+
model.resources.push(resourceModel);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
if (Is.arrayValue(vertexEntity.edges)) {
|
|
902
|
+
model.edges ??= [];
|
|
903
|
+
for (const edgeEntity of vertexEntity.edges) {
|
|
904
|
+
const edgeModel = {
|
|
905
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
906
|
+
type: AuditableItemGraphTypes.Edge,
|
|
907
|
+
id: edgeEntity.id,
|
|
908
|
+
dateCreated: edgeEntity.dateCreated,
|
|
909
|
+
dateModified: edgeEntity.dateModified,
|
|
910
|
+
dateDeleted: edgeEntity.dateDeleted,
|
|
911
|
+
edgeRelationship: edgeEntity.edgeRelationship,
|
|
912
|
+
edgeObject: edgeEntity.edgeObject
|
|
913
|
+
};
|
|
914
|
+
model.edges.push(edgeModel);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
return model;
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Map the changeset entity to a JSON-LD.
|
|
921
|
+
* @param changesetEntity The changeset entity.
|
|
922
|
+
* @returns The model.
|
|
923
|
+
* @internal
|
|
924
|
+
*/
|
|
925
|
+
changesetEntityToJsonLd(changesetEntity) {
|
|
926
|
+
const model = {
|
|
927
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
928
|
+
type: AuditableItemGraphTypes.Changeset,
|
|
929
|
+
id: changesetEntity.id,
|
|
930
|
+
dateCreated: changesetEntity.dateCreated,
|
|
931
|
+
userIdentity: changesetEntity.userIdentity,
|
|
932
|
+
patches: changesetEntity.patches.map(p => ({
|
|
933
|
+
"@context": [AuditableItemGraphTypes.ContextRoot, SchemaOrgTypes.ContextRoot],
|
|
934
|
+
type: AuditableItemGraphTypes.PatchOperation,
|
|
935
|
+
patchOperation: p.op,
|
|
936
|
+
patchPath: p.path,
|
|
937
|
+
patchFrom: p.from,
|
|
938
|
+
patchValue: p.value
|
|
939
|
+
})),
|
|
940
|
+
proofId: changesetEntity.proofId
|
|
941
|
+
};
|
|
942
|
+
return model;
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Update the aliases of a vertex model.
|
|
946
|
+
* @param context The context for the operation.
|
|
947
|
+
* @param vertex The vertex.
|
|
948
|
+
* @param aliases The aliases to update.
|
|
949
|
+
* @internal
|
|
950
|
+
*/
|
|
951
|
+
async updateAliasList(context, vertex, aliases) {
|
|
952
|
+
const active = vertex.aliases?.filter(a => Is.empty(a.dateDeleted)) ?? [];
|
|
953
|
+
// The active aliases that are not in the update list should be marked as deleted.
|
|
954
|
+
if (Is.arrayValue(active)) {
|
|
955
|
+
for (const alias of active) {
|
|
956
|
+
if (!aliases?.find(a => a.id === alias.id)) {
|
|
957
|
+
alias.dateDeleted = context.now;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
if (Is.arrayValue(aliases)) {
|
|
962
|
+
for (const alias of aliases) {
|
|
963
|
+
await this.updateAlias(context, vertex, alias);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Update an alias in the vertex.
|
|
969
|
+
* @param context The context for the operation.
|
|
970
|
+
* @param vertex The vertex.
|
|
971
|
+
* @param alias The alias.
|
|
972
|
+
* @internal
|
|
973
|
+
*/
|
|
974
|
+
async updateAlias(context, vertex, alias) {
|
|
975
|
+
Guards.object(this.CLASS_NAME, "alias", alias);
|
|
976
|
+
Guards.stringValue(this.CLASS_NAME, "alias.id", alias.id);
|
|
977
|
+
if (Is.object(alias.aliasObject)) {
|
|
978
|
+
const validationFailures = [];
|
|
979
|
+
await JsonLdHelper.validate(alias.aliasObject, validationFailures);
|
|
980
|
+
Validation.asValidationError(this.CLASS_NAME, "alias.aliasObject", validationFailures);
|
|
981
|
+
}
|
|
982
|
+
// Try to find an existing alias with the same id.
|
|
983
|
+
const existing = vertex.aliases?.find(a => a.id === alias.id);
|
|
984
|
+
if (Is.empty(existing) || !Is.empty(existing?.dateDeleted)) {
|
|
985
|
+
// Did not find a matching item, or found one which is deleted.
|
|
986
|
+
vertex.aliases ??= [];
|
|
987
|
+
const model = {
|
|
988
|
+
id: alias.id,
|
|
989
|
+
aliasFormat: alias.aliasFormat,
|
|
990
|
+
dateCreated: context.now,
|
|
991
|
+
aliasObject: alias.aliasObject
|
|
992
|
+
};
|
|
993
|
+
vertex.aliases.push(model);
|
|
994
|
+
}
|
|
995
|
+
else if (existing.aliasFormat !== alias.aliasFormat ||
|
|
996
|
+
!ObjectHelper.equal(existing.aliasObject, alias.aliasObject, false)) {
|
|
997
|
+
// Existing alias found, update the aliasObject.
|
|
998
|
+
existing.dateModified = context.now;
|
|
999
|
+
existing.aliasFormat = alias.aliasFormat;
|
|
1000
|
+
existing.aliasObject = alias.aliasObject;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Update the resources of a vertex.
|
|
1005
|
+
* @param context The context for the operation.
|
|
1006
|
+
* @param vertex The vertex.
|
|
1007
|
+
* @param resources The resources to update.
|
|
1008
|
+
* @internal
|
|
1009
|
+
*/
|
|
1010
|
+
async updateResourceList(context, vertex, resources) {
|
|
1011
|
+
const active = vertex.resources?.filter(r => Is.empty(r.dateDeleted)) ?? [];
|
|
1012
|
+
// The active resources that are not in the update list should be marked as deleted.
|
|
1013
|
+
if (Is.arrayValue(active)) {
|
|
1014
|
+
for (const resource of active) {
|
|
1015
|
+
if (!resources?.find(a => a.id === resource.id)) {
|
|
1016
|
+
resource.dateDeleted = context.now;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
if (Is.arrayValue(resources)) {
|
|
1021
|
+
for (const resource of resources) {
|
|
1022
|
+
await this.updateResource(context, vertex, resource);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
/**
|
|
1027
|
+
* Add a resource to the vertex.
|
|
1028
|
+
* @param context The context for the operation.
|
|
1029
|
+
* @param vertex The vertex.
|
|
1030
|
+
* @param resource The resource.
|
|
1031
|
+
* @internal
|
|
1032
|
+
*/
|
|
1033
|
+
async updateResource(context, vertex, resource) {
|
|
1034
|
+
Guards.object(this.CLASS_NAME, "resource", resource);
|
|
1035
|
+
Guards.stringValue(this.CLASS_NAME, "resource.id", resource.id);
|
|
1036
|
+
if (Is.object(resource.resourceObject)) {
|
|
1037
|
+
const validationFailures = [];
|
|
1038
|
+
await JsonLdHelper.validate(resource.resourceObject, validationFailures);
|
|
1039
|
+
Validation.asValidationError(this.CLASS_NAME, "resource.resourceObject", validationFailures);
|
|
1040
|
+
}
|
|
1041
|
+
// Try to find an existing resource with the same id.
|
|
1042
|
+
const existing = vertex.resources?.find(r => r.id === resource.id);
|
|
1043
|
+
if (Is.empty(existing) || !Is.empty(existing?.dateDeleted)) {
|
|
1044
|
+
// Did not find a matching item, or found one which is deleted.
|
|
1045
|
+
vertex.resources ??= [];
|
|
1046
|
+
const model = {
|
|
1047
|
+
id: resource.id,
|
|
1048
|
+
dateCreated: context.now,
|
|
1049
|
+
resourceObject: resource.resourceObject
|
|
1050
|
+
};
|
|
1051
|
+
vertex.resources.push(model);
|
|
1052
|
+
}
|
|
1053
|
+
else if (!ObjectHelper.equal(existing.resourceObject, resource.resourceObject, false)) {
|
|
1054
|
+
// Existing resource found, update the resourceObject.
|
|
1055
|
+
existing.dateModified = context.now;
|
|
1056
|
+
existing.resourceObject = resource.resourceObject;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Update the edges of a vertex.
|
|
1061
|
+
* @param context The context for the operation.
|
|
1062
|
+
* @param vertex The vertex.
|
|
1063
|
+
* @param edges The edges to update.
|
|
1064
|
+
* @internal
|
|
1065
|
+
*/
|
|
1066
|
+
async updateEdgeList(context, vertex, edges) {
|
|
1067
|
+
const active = vertex.edges?.filter(e => Is.empty(e.dateDeleted)) ?? [];
|
|
1068
|
+
// The active edges that are not in the update list should be marked as deleted.
|
|
1069
|
+
if (Is.arrayValue(active)) {
|
|
1070
|
+
for (const edge of active) {
|
|
1071
|
+
if (!edges?.find(a => a.id === edge.id)) {
|
|
1072
|
+
edge.dateDeleted = context.now;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
if (Is.arrayValue(edges)) {
|
|
1077
|
+
for (const edge of edges) {
|
|
1078
|
+
await this.updateEdge(context, vertex, edge);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Add an edge to the vertex.
|
|
1084
|
+
* @param context The context for the operation.
|
|
1085
|
+
* @param vertex The vertex.
|
|
1086
|
+
* @param edge The edge.
|
|
1087
|
+
* @internal
|
|
1088
|
+
*/
|
|
1089
|
+
async updateEdge(context, vertex, edge) {
|
|
1090
|
+
Guards.object(this.CLASS_NAME, "edge", edge);
|
|
1091
|
+
Guards.stringValue(this.CLASS_NAME, "edge.id", edge.id);
|
|
1092
|
+
Guards.stringValue(this.CLASS_NAME, "edge.edgeRelationship", edge.edgeRelationship);
|
|
1093
|
+
if (Is.object(edge.edgeObject)) {
|
|
1094
|
+
const validationFailures = [];
|
|
1095
|
+
await JsonLdHelper.validate(edge.edgeObject, validationFailures);
|
|
1096
|
+
Validation.asValidationError(this.CLASS_NAME, "edge.edgeObject", validationFailures);
|
|
1097
|
+
}
|
|
1098
|
+
// Try to find an existing edge with the same id.
|
|
1099
|
+
const existing = vertex.edges?.find(r => r.id === edge.id);
|
|
1100
|
+
if (Is.empty(existing) || !Is.empty(existing?.dateDeleted)) {
|
|
1101
|
+
// Did not find a matching item, or found one which is deleted.
|
|
1102
|
+
vertex.edges ??= [];
|
|
1103
|
+
const model = {
|
|
1104
|
+
id: edge.id,
|
|
1105
|
+
dateCreated: context.now,
|
|
1106
|
+
edgeObject: edge.edgeObject,
|
|
1107
|
+
edgeRelationship: edge.edgeRelationship
|
|
1108
|
+
};
|
|
1109
|
+
vertex.edges.push(model);
|
|
1110
|
+
}
|
|
1111
|
+
else if (existing.edgeRelationship !== edge.edgeRelationship ||
|
|
1112
|
+
!ObjectHelper.equal(existing.edgeObject, edge.edgeObject, false)) {
|
|
1113
|
+
// Existing resource found, update the edgeObject.
|
|
1114
|
+
existing.dateModified = context.now;
|
|
1115
|
+
existing.edgeRelationship = edge.edgeRelationship;
|
|
1116
|
+
existing.edgeObject = edge.edgeObject;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
/**
|
|
1120
|
+
* Add a changeset to the vertex and generate the associated verifications.
|
|
1121
|
+
* @param context The context for the operation.
|
|
1122
|
+
* @param original The original vertex.
|
|
1123
|
+
* @param updated The updated vertex.
|
|
1124
|
+
* @param isNew Whether this is a new item.
|
|
1125
|
+
* @returns True if there were changes.
|
|
1126
|
+
* @internal
|
|
1127
|
+
*/
|
|
1128
|
+
async addChangeset(context, original, updated, isNew) {
|
|
1129
|
+
const patches = JsonHelper.diff(original, updated);
|
|
1130
|
+
// If there is a diff set or this is the first time the item is created.
|
|
1131
|
+
if (patches.length > 0 || isNew) {
|
|
1132
|
+
const changesetEntity = {
|
|
1133
|
+
id: Converter.bytesToHex(RandomHelper.generate(32), false),
|
|
1134
|
+
vertexId: updated.id,
|
|
1135
|
+
dateCreated: context.now,
|
|
1136
|
+
userIdentity: context.userIdentity,
|
|
1137
|
+
patches,
|
|
1138
|
+
proofId: ""
|
|
1139
|
+
};
|
|
1140
|
+
// Create the JSON-LD object we want to use for the proof
|
|
1141
|
+
// this is a subset of fixed properties from the changeset object.
|
|
1142
|
+
const reducedChangesetJsonLd = await this.changesetEntityToJsonLd({
|
|
1143
|
+
...ObjectHelper.pick(changesetEntity, AuditableItemGraphService._PROOF_KEYS_CHANGESET),
|
|
1144
|
+
id: `${AuditableItemGraphService.NAMESPACE}:${updated.id}:${AuditableItemGraphService.NAMESPACE_CHANGESET}:${changesetEntity.id}`
|
|
1145
|
+
});
|
|
1146
|
+
// Create the proof for the changeset object
|
|
1147
|
+
changesetEntity.proofId = await this._immutableProofComponent.create(reducedChangesetJsonLd, context.userIdentity, context.nodeIdentity);
|
|
1148
|
+
// Link the immutable storage id to the changeset
|
|
1149
|
+
await this._changesetStorage.set(changesetEntity);
|
|
1150
|
+
return true;
|
|
1151
|
+
}
|
|
1152
|
+
return false;
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Verify the changesets of a vertex.
|
|
1156
|
+
* @param nodeIdentity The node identity to verify the changesets with.
|
|
1157
|
+
* @param vertex The vertex to verify.
|
|
1158
|
+
* @param verifySignatureDepth How many signatures to verify.
|
|
1159
|
+
* @internal
|
|
1160
|
+
*/
|
|
1161
|
+
async verifyChangesets(vertex, verifySignatureDepth) {
|
|
1162
|
+
const changesets = [];
|
|
1163
|
+
let changesetsResult;
|
|
1164
|
+
let verified = true;
|
|
1165
|
+
do {
|
|
1166
|
+
changesetsResult = await this._changesetStorage.query({
|
|
1167
|
+
property: "vertexId",
|
|
1168
|
+
value: vertex.id,
|
|
1169
|
+
comparison: ComparisonOperator.Equals
|
|
1170
|
+
}, [
|
|
1171
|
+
{
|
|
1172
|
+
property: "dateCreated",
|
|
1173
|
+
sortDirection: SortDirection.Ascending
|
|
1174
|
+
}
|
|
1175
|
+
], undefined, changesetsResult?.cursor);
|
|
1176
|
+
const storedChangesets = changesetsResult.entities;
|
|
1177
|
+
if (Is.arrayValue(storedChangesets)) {
|
|
1178
|
+
for (let i = 0; i < storedChangesets.length; i++) {
|
|
1179
|
+
const storedChangeset = storedChangesets[i];
|
|
1180
|
+
const storedChangesetJsonLd = this.changesetEntityToJsonLd(storedChangeset);
|
|
1181
|
+
changesets.push(storedChangesetJsonLd);
|
|
1182
|
+
// If we are verifying all signatures
|
|
1183
|
+
// or this is the last changeset (cursor is empty)
|
|
1184
|
+
// and the changeset has a proofId, then verify the proof.
|
|
1185
|
+
if (verifySignatureDepth === VerifyDepth.All ||
|
|
1186
|
+
(verifySignatureDepth === VerifyDepth.Current &&
|
|
1187
|
+
!Is.stringValue(changesetsResult.cursor) &&
|
|
1188
|
+
i === storedChangesets.length - 1)) {
|
|
1189
|
+
if (!Is.stringValue(storedChangeset.proofId)) {
|
|
1190
|
+
verified = false;
|
|
1191
|
+
storedChangesetJsonLd.verification = {
|
|
1192
|
+
"@context": ImmutableProofTypes.ContextRoot,
|
|
1193
|
+
type: ImmutableProofTypes.ImmutableProofVerification,
|
|
1194
|
+
verified: false,
|
|
1195
|
+
failure: ImmutableProofFailure.ProofMissing
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
else {
|
|
1199
|
+
// Create the JSON-LD object we want to use for the proof
|
|
1200
|
+
// this is a subset of fixed properties from the changeset object.
|
|
1201
|
+
const reducedChangesetJsonLd = await this.changesetEntityToJsonLd(ObjectHelper.pick(storedChangeset, AuditableItemGraphService._PROOF_KEYS_CHANGESET));
|
|
1202
|
+
// Verify the proof for the changeset object
|
|
1203
|
+
storedChangesetJsonLd.verification = await this._immutableProofComponent.verify(storedChangeset.proofId, reducedChangesetJsonLd);
|
|
1204
|
+
if (!storedChangesetJsonLd.verification.verified) {
|
|
1205
|
+
verified = false;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
} while (Is.stringValue(changesetsResult.cursor));
|
|
1212
|
+
return {
|
|
1213
|
+
verified,
|
|
1214
|
+
changesets
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
// Copyright 2024 IOTA Stiftung.
|
|
1220
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
1221
|
+
/**
|
|
1222
|
+
* Class describing the auditable item graph alias.
|
|
1223
|
+
*/
|
|
1224
|
+
let AuditableItemGraphAlias = class AuditableItemGraphAlias {
|
|
1225
|
+
/**
|
|
1226
|
+
* The alternative alias for the vertex.
|
|
1227
|
+
*/
|
|
1228
|
+
id;
|
|
1229
|
+
/**
|
|
1230
|
+
* The format of the alias for the vertex.
|
|
1231
|
+
*/
|
|
1232
|
+
aliasFormat;
|
|
1233
|
+
/**
|
|
1234
|
+
* The date/time of when the alias was created.
|
|
1235
|
+
*/
|
|
1236
|
+
dateCreated;
|
|
1237
|
+
/**
|
|
1238
|
+
* The date/time of when the alias was last modified.
|
|
1239
|
+
*/
|
|
1240
|
+
dateModified;
|
|
1241
|
+
/**
|
|
1242
|
+
* The timestamp of when the alias was deleted, as we never actually remove items.
|
|
1243
|
+
*/
|
|
1244
|
+
dateDeleted;
|
|
1245
|
+
/**
|
|
1246
|
+
* Object to associate with the alias as JSON-LD.
|
|
1247
|
+
*/
|
|
1248
|
+
aliasObject;
|
|
1249
|
+
};
|
|
1250
|
+
__decorate([
|
|
1251
|
+
property({ type: "string" }),
|
|
1252
|
+
__metadata("design:type", String)
|
|
1253
|
+
], AuditableItemGraphAlias.prototype, "id", void 0);
|
|
1254
|
+
__decorate([
|
|
1255
|
+
property({ type: "string" }),
|
|
1256
|
+
__metadata("design:type", String)
|
|
1257
|
+
], AuditableItemGraphAlias.prototype, "aliasFormat", void 0);
|
|
1258
|
+
__decorate([
|
|
1259
|
+
property({ type: "string", format: "date-time" }),
|
|
1260
|
+
__metadata("design:type", String)
|
|
1261
|
+
], AuditableItemGraphAlias.prototype, "dateCreated", void 0);
|
|
1262
|
+
__decorate([
|
|
1263
|
+
property({ type: "string", format: "date-time" }),
|
|
1264
|
+
__metadata("design:type", String)
|
|
1265
|
+
], AuditableItemGraphAlias.prototype, "dateModified", void 0);
|
|
1266
|
+
__decorate([
|
|
1267
|
+
property({ type: "string", format: "date-time" }),
|
|
1268
|
+
__metadata("design:type", String)
|
|
1269
|
+
], AuditableItemGraphAlias.prototype, "dateDeleted", void 0);
|
|
1270
|
+
__decorate([
|
|
1271
|
+
property({ type: "object", itemTypeRef: JsonLdTypes.NodeObject }),
|
|
1272
|
+
__metadata("design:type", Object)
|
|
1273
|
+
], AuditableItemGraphAlias.prototype, "aliasObject", void 0);
|
|
1274
|
+
AuditableItemGraphAlias = __decorate([
|
|
1275
|
+
entity()
|
|
1276
|
+
], AuditableItemGraphAlias);
|
|
1277
|
+
|
|
1278
|
+
// Copyright 2024 IOTA Stiftung.
|
|
1279
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
1280
|
+
/**
|
|
1281
|
+
* Class describing a set of updates to the vertex.
|
|
1282
|
+
*/
|
|
1283
|
+
let AuditableItemGraphChangeset = class AuditableItemGraphChangeset {
|
|
1284
|
+
/**
|
|
1285
|
+
* The id of the changeset.
|
|
1286
|
+
*/
|
|
1287
|
+
id;
|
|
1288
|
+
/**
|
|
1289
|
+
* The vertex the changeset belongs to.
|
|
1290
|
+
*/
|
|
1291
|
+
vertexId;
|
|
1292
|
+
/**
|
|
1293
|
+
* The date/time of when the changeset was created.
|
|
1294
|
+
*/
|
|
1295
|
+
dateCreated;
|
|
1296
|
+
/**
|
|
1297
|
+
* The identity of the user who made the changeset.
|
|
1298
|
+
*/
|
|
1299
|
+
userIdentity;
|
|
1300
|
+
/**
|
|
1301
|
+
* The patches in the changeset.
|
|
1302
|
+
*/
|
|
1303
|
+
patches;
|
|
1304
|
+
/**
|
|
1305
|
+
* The immutable proof id which contains the signature for this changeset.
|
|
1306
|
+
*/
|
|
1307
|
+
proofId;
|
|
1308
|
+
};
|
|
1309
|
+
__decorate([
|
|
1310
|
+
property({ type: "string", isPrimary: true }),
|
|
1311
|
+
__metadata("design:type", String)
|
|
1312
|
+
], AuditableItemGraphChangeset.prototype, "id", void 0);
|
|
1313
|
+
__decorate([
|
|
1314
|
+
property({ type: "string", isSecondary: true }),
|
|
1315
|
+
__metadata("design:type", String)
|
|
1316
|
+
], AuditableItemGraphChangeset.prototype, "vertexId", void 0);
|
|
1317
|
+
__decorate([
|
|
1318
|
+
property({ type: "string", format: "date-time", sortDirection: SortDirection.Descending }),
|
|
1319
|
+
__metadata("design:type", String)
|
|
1320
|
+
], AuditableItemGraphChangeset.prototype, "dateCreated", void 0);
|
|
1321
|
+
__decorate([
|
|
1322
|
+
property({ type: "string" }),
|
|
1323
|
+
__metadata("design:type", String)
|
|
1324
|
+
], AuditableItemGraphChangeset.prototype, "userIdentity", void 0);
|
|
1325
|
+
__decorate([
|
|
1326
|
+
property({ type: "array", itemTypeRef: "AuditableItemGraphPatch" }),
|
|
1327
|
+
__metadata("design:type", Array)
|
|
1328
|
+
], AuditableItemGraphChangeset.prototype, "patches", void 0);
|
|
1329
|
+
__decorate([
|
|
1330
|
+
property({ type: "string" }),
|
|
1331
|
+
__metadata("design:type", String)
|
|
1332
|
+
], AuditableItemGraphChangeset.prototype, "proofId", void 0);
|
|
1333
|
+
AuditableItemGraphChangeset = __decorate([
|
|
1334
|
+
entity()
|
|
1335
|
+
], AuditableItemGraphChangeset);
|
|
1336
|
+
|
|
1337
|
+
// Copyright 2024 IOTA Stiftung.
|
|
1338
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
1339
|
+
/**
|
|
1340
|
+
* Class describing the auditable item graph edge.
|
|
1341
|
+
*/
|
|
1342
|
+
let AuditableItemGraphEdge = class AuditableItemGraphEdge {
|
|
1343
|
+
/**
|
|
1344
|
+
* The id of the edge.
|
|
1345
|
+
*/
|
|
1346
|
+
id;
|
|
1347
|
+
/**
|
|
1348
|
+
* The date/time of when the edge was created.
|
|
1349
|
+
*/
|
|
1350
|
+
dateCreated;
|
|
1351
|
+
/**
|
|
1352
|
+
* The date/time of when the edge was last modified.
|
|
1353
|
+
*/
|
|
1354
|
+
dateModified;
|
|
1355
|
+
/**
|
|
1356
|
+
* The timestamp of when the edge was deleted, as we never actually remove items.
|
|
1357
|
+
*/
|
|
1358
|
+
dateDeleted;
|
|
1359
|
+
/**
|
|
1360
|
+
* The relationship between the two vertices.
|
|
1361
|
+
*/
|
|
1362
|
+
edgeRelationship;
|
|
1363
|
+
/**
|
|
1364
|
+
* Object to associate with the edge as JSON-LD.
|
|
1365
|
+
*/
|
|
1366
|
+
edgeObject;
|
|
1367
|
+
};
|
|
1368
|
+
__decorate([
|
|
1369
|
+
property({ type: "string" }),
|
|
1370
|
+
__metadata("design:type", String)
|
|
1371
|
+
], AuditableItemGraphEdge.prototype, "id", void 0);
|
|
1372
|
+
__decorate([
|
|
1373
|
+
property({ type: "string", format: "date-time" }),
|
|
1374
|
+
__metadata("design:type", String)
|
|
1375
|
+
], AuditableItemGraphEdge.prototype, "dateCreated", void 0);
|
|
1376
|
+
__decorate([
|
|
1377
|
+
property({ type: "string", format: "date-time" }),
|
|
1378
|
+
__metadata("design:type", String)
|
|
1379
|
+
], AuditableItemGraphEdge.prototype, "dateModified", void 0);
|
|
1380
|
+
__decorate([
|
|
1381
|
+
property({ type: "string", format: "date-time" }),
|
|
1382
|
+
__metadata("design:type", String)
|
|
1383
|
+
], AuditableItemGraphEdge.prototype, "dateDeleted", void 0);
|
|
1384
|
+
__decorate([
|
|
1385
|
+
property({ type: "string" }),
|
|
1386
|
+
__metadata("design:type", String)
|
|
1387
|
+
], AuditableItemGraphEdge.prototype, "edgeRelationship", void 0);
|
|
1388
|
+
__decorate([
|
|
1389
|
+
property({ type: "object", itemTypeRef: JsonLdTypes.NodeObject }),
|
|
1390
|
+
__metadata("design:type", Object)
|
|
1391
|
+
], AuditableItemGraphEdge.prototype, "edgeObject", void 0);
|
|
1392
|
+
AuditableItemGraphEdge = __decorate([
|
|
1393
|
+
entity()
|
|
1394
|
+
], AuditableItemGraphEdge);
|
|
1395
|
+
|
|
1396
|
+
// Copyright 2024 IOTA Stiftung.
|
|
1397
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
1398
|
+
/**
|
|
1399
|
+
* Class describing the auditable item graph patches.
|
|
1400
|
+
*/
|
|
1401
|
+
let AuditableItemGraphPatch = class AuditableItemGraphPatch {
|
|
1402
|
+
/**
|
|
1403
|
+
* The operation for the patch.
|
|
1404
|
+
*/
|
|
1405
|
+
op;
|
|
1406
|
+
/**
|
|
1407
|
+
* The path for the patch.
|
|
1408
|
+
*/
|
|
1409
|
+
path;
|
|
1410
|
+
/**
|
|
1411
|
+
* The from for the patch.
|
|
1412
|
+
*/
|
|
1413
|
+
from;
|
|
1414
|
+
/**
|
|
1415
|
+
* The value for the patch.
|
|
1416
|
+
*/
|
|
1417
|
+
value;
|
|
1418
|
+
};
|
|
1419
|
+
__decorate([
|
|
1420
|
+
property({ type: "string" }),
|
|
1421
|
+
__metadata("design:type", String)
|
|
1422
|
+
], AuditableItemGraphPatch.prototype, "op", void 0);
|
|
1423
|
+
__decorate([
|
|
1424
|
+
property({ type: "string" }),
|
|
1425
|
+
__metadata("design:type", String)
|
|
1426
|
+
], AuditableItemGraphPatch.prototype, "path", void 0);
|
|
1427
|
+
__decorate([
|
|
1428
|
+
property({ type: "string" }),
|
|
1429
|
+
__metadata("design:type", String)
|
|
1430
|
+
], AuditableItemGraphPatch.prototype, "from", void 0);
|
|
1431
|
+
__decorate([
|
|
1432
|
+
property({ type: "object" }),
|
|
1433
|
+
__metadata("design:type", Object)
|
|
1434
|
+
], AuditableItemGraphPatch.prototype, "value", void 0);
|
|
1435
|
+
AuditableItemGraphPatch = __decorate([
|
|
1436
|
+
entity()
|
|
1437
|
+
], AuditableItemGraphPatch);
|
|
1438
|
+
|
|
1439
|
+
// Copyright 2024 IOTA Stiftung.
|
|
1440
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
1441
|
+
/**
|
|
1442
|
+
* Class describing the auditable item graph vertex resource.
|
|
1443
|
+
*/
|
|
1444
|
+
let AuditableItemGraphResource = class AuditableItemGraphResource {
|
|
1445
|
+
/**
|
|
1446
|
+
* The id of the resource.
|
|
1447
|
+
*/
|
|
1448
|
+
id;
|
|
1449
|
+
/**
|
|
1450
|
+
* The date/time of when the resource was created.
|
|
1451
|
+
*/
|
|
1452
|
+
dateCreated;
|
|
1453
|
+
/**
|
|
1454
|
+
* The date/time of when the resource was last modified.
|
|
1455
|
+
*/
|
|
1456
|
+
dateModified;
|
|
1457
|
+
/**
|
|
1458
|
+
* The timestamp of when the resource was deleted, as we never actually remove items.
|
|
1459
|
+
*/
|
|
1460
|
+
dateDeleted;
|
|
1461
|
+
/**
|
|
1462
|
+
* Object to associate with the resource as JSON-LD.
|
|
1463
|
+
*/
|
|
1464
|
+
resourceObject;
|
|
1465
|
+
};
|
|
1466
|
+
__decorate([
|
|
1467
|
+
property({ type: "string", isPrimary: true }),
|
|
1468
|
+
__metadata("design:type", String)
|
|
1469
|
+
], AuditableItemGraphResource.prototype, "id", void 0);
|
|
1470
|
+
__decorate([
|
|
1471
|
+
property({ type: "string", format: "date-time" }),
|
|
1472
|
+
__metadata("design:type", String)
|
|
1473
|
+
], AuditableItemGraphResource.prototype, "dateCreated", void 0);
|
|
1474
|
+
__decorate([
|
|
1475
|
+
property({ type: "string", format: "date-time" }),
|
|
1476
|
+
__metadata("design:type", String)
|
|
1477
|
+
], AuditableItemGraphResource.prototype, "dateModified", void 0);
|
|
1478
|
+
__decorate([
|
|
1479
|
+
property({ type: "string", format: "date-time" }),
|
|
1480
|
+
__metadata("design:type", String)
|
|
1481
|
+
], AuditableItemGraphResource.prototype, "dateDeleted", void 0);
|
|
1482
|
+
__decorate([
|
|
1483
|
+
property({ type: "object", itemTypeRef: JsonLdTypes.NodeObject }),
|
|
1484
|
+
__metadata("design:type", Object)
|
|
1485
|
+
], AuditableItemGraphResource.prototype, "resourceObject", void 0);
|
|
1486
|
+
AuditableItemGraphResource = __decorate([
|
|
1487
|
+
entity()
|
|
1488
|
+
], AuditableItemGraphResource);
|
|
1489
|
+
|
|
1490
|
+
// Copyright 2024 IOTA Stiftung.
|
|
1491
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
1492
|
+
/**
|
|
1493
|
+
* Class describing the auditable item graph vertex.
|
|
1494
|
+
*/
|
|
1495
|
+
let AuditableItemGraphVertex = class AuditableItemGraphVertex {
|
|
1496
|
+
/**
|
|
1497
|
+
* The id of the vertex.
|
|
1498
|
+
*/
|
|
1499
|
+
id;
|
|
1500
|
+
/**
|
|
1501
|
+
* The identity of the node which controls the vertex.
|
|
1502
|
+
*/
|
|
1503
|
+
nodeIdentity;
|
|
1504
|
+
/**
|
|
1505
|
+
* The date/time of when the vertex was created.
|
|
1506
|
+
*/
|
|
1507
|
+
dateCreated;
|
|
1508
|
+
/**
|
|
1509
|
+
* The date/time of when the vertex was last modified.
|
|
1510
|
+
*/
|
|
1511
|
+
dateModified;
|
|
1512
|
+
/**
|
|
1513
|
+
* Combined alias index for the vertex used for querying.
|
|
1514
|
+
*/
|
|
1515
|
+
aliasIndex;
|
|
1516
|
+
/**
|
|
1517
|
+
* Object to associate with the vertex as JSON-LD.
|
|
1518
|
+
*/
|
|
1519
|
+
vertexObject;
|
|
1520
|
+
/**
|
|
1521
|
+
* Alternative aliases that can be used to identify the vertex.
|
|
1522
|
+
*/
|
|
1523
|
+
aliases;
|
|
1524
|
+
/**
|
|
1525
|
+
* The resources attached to the vertex.
|
|
1526
|
+
*/
|
|
1527
|
+
resources;
|
|
1528
|
+
/**
|
|
1529
|
+
* Edges connected to the vertex.
|
|
1530
|
+
*/
|
|
1531
|
+
edges;
|
|
1532
|
+
};
|
|
1533
|
+
__decorate([
|
|
1534
|
+
property({ type: "string", isPrimary: true }),
|
|
1535
|
+
__metadata("design:type", String)
|
|
1536
|
+
], AuditableItemGraphVertex.prototype, "id", void 0);
|
|
1537
|
+
__decorate([
|
|
1538
|
+
property({ type: "string" }),
|
|
1539
|
+
__metadata("design:type", String)
|
|
1540
|
+
], AuditableItemGraphVertex.prototype, "nodeIdentity", void 0);
|
|
1541
|
+
__decorate([
|
|
1542
|
+
property({ type: "string", format: "date-time", sortDirection: SortDirection.Descending }),
|
|
1543
|
+
__metadata("design:type", String)
|
|
1544
|
+
], AuditableItemGraphVertex.prototype, "dateCreated", void 0);
|
|
1545
|
+
__decorate([
|
|
1546
|
+
property({ type: "string", format: "date-time", sortDirection: SortDirection.Descending }),
|
|
1547
|
+
__metadata("design:type", String)
|
|
1548
|
+
], AuditableItemGraphVertex.prototype, "dateModified", void 0);
|
|
1549
|
+
__decorate([
|
|
1550
|
+
property({ type: "string", isSecondary: true }),
|
|
1551
|
+
__metadata("design:type", String)
|
|
1552
|
+
], AuditableItemGraphVertex.prototype, "aliasIndex", void 0);
|
|
1553
|
+
__decorate([
|
|
1554
|
+
property({ type: "object", itemTypeRef: JsonLdTypes.NodeObject }),
|
|
1555
|
+
__metadata("design:type", Object)
|
|
1556
|
+
], AuditableItemGraphVertex.prototype, "vertexObject", void 0);
|
|
1557
|
+
__decorate([
|
|
1558
|
+
property({ type: "array", itemType: "string" }),
|
|
1559
|
+
__metadata("design:type", Array)
|
|
1560
|
+
], AuditableItemGraphVertex.prototype, "aliases", void 0);
|
|
1561
|
+
__decorate([
|
|
1562
|
+
property({ type: "array", itemTypeRef: "AuditableItemGraphResource" }),
|
|
1563
|
+
__metadata("design:type", Array)
|
|
1564
|
+
], AuditableItemGraphVertex.prototype, "resources", void 0);
|
|
1565
|
+
__decorate([
|
|
1566
|
+
property({ type: "array", itemTypeRef: "AuditableItemGraphEdge" }),
|
|
1567
|
+
__metadata("design:type", Array)
|
|
1568
|
+
], AuditableItemGraphVertex.prototype, "edges", void 0);
|
|
1569
|
+
AuditableItemGraphVertex = __decorate([
|
|
1570
|
+
entity()
|
|
1571
|
+
], AuditableItemGraphVertex);
|
|
1572
|
+
|
|
1573
|
+
const restEntryPoints = [
|
|
1574
|
+
{
|
|
1575
|
+
name: "auditable-item-graph",
|
|
1576
|
+
defaultBaseRoute: "auditable-item-graph",
|
|
1577
|
+
tags: tagsAuditableItemGraph,
|
|
1578
|
+
generateRoutes: generateRestRoutesAuditableItemGraph
|
|
1579
|
+
}
|
|
1580
|
+
];
|
|
1581
|
+
|
|
1582
|
+
// Copyright 2024 IOTA Stiftung.
|
|
1583
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
1584
|
+
/**
|
|
1585
|
+
* Initialize the schema for the auditable item graph entity storage connector.
|
|
1586
|
+
*/
|
|
1587
|
+
function initSchema() {
|
|
1588
|
+
EntitySchemaFactory.register("AuditableItemGraphVertex", () => EntitySchemaHelper.getSchema(AuditableItemGraphVertex));
|
|
1589
|
+
EntitySchemaFactory.register("AuditableItemGraphAlias", () => EntitySchemaHelper.getSchema(AuditableItemGraphAlias));
|
|
1590
|
+
EntitySchemaFactory.register("AuditableItemGraphResource", () => EntitySchemaHelper.getSchema(AuditableItemGraphResource));
|
|
1591
|
+
EntitySchemaFactory.register("AuditableItemGraphEdge", () => EntitySchemaHelper.getSchema(AuditableItemGraphEdge));
|
|
1592
|
+
EntitySchemaFactory.register("AuditableItemGraphChangeset", () => EntitySchemaHelper.getSchema(AuditableItemGraphChangeset));
|
|
1593
|
+
EntitySchemaFactory.register("AuditableItemGraphPatch", () => EntitySchemaHelper.getSchema(AuditableItemGraphPatch));
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
export { AuditableItemGraphAlias, AuditableItemGraphChangeset, AuditableItemGraphEdge, AuditableItemGraphPatch, AuditableItemGraphResource, AuditableItemGraphService, AuditableItemGraphVertex, auditableItemGraphCreate, auditableItemGraphGet, auditableItemGraphList, auditableItemGraphUpdate, generateRestRoutesAuditableItemGraph, initSchema, restEntryPoints, tagsAuditableItemGraph };
|