@twin.org/blob-storage-service 0.0.1-next.8 → 0.0.1-next.9

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.
@@ -1,10 +1,10 @@
1
- import { Guards, ComponentFactory, Is, Converter, GeneralError, Validation, Urn, NotFoundError } from '@twin.org/core';
1
+ import { StringHelper, Guards, ComponentFactory, Is, Converter, GeneralError, Validation, ObjectHelper, Urn, NotFoundError } from '@twin.org/core';
2
2
  import { HttpStatusCode, HeaderTypes, MimeTypes, MimeTypeHelper } from '@twin.org/web';
3
3
  import { BlobStorageConnectorFactory } from '@twin.org/blob-storage-models';
4
4
  import { JsonLdHelper } from '@twin.org/data-json-ld';
5
+ import { ComparisonOperator, EntitySchemaHelper, LogicalOperator, property, entity, EntitySchemaFactory } from '@twin.org/entity';
5
6
  import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
6
7
  import { VaultConnectorFactory, VaultEncryptionType } from '@twin.org/vault-models';
7
- import { property, entity, EntitySchemaFactory, EntitySchemaHelper } from '@twin.org/entity';
8
8
 
9
9
  /**
10
10
  * The source used when communicating about these routes.
@@ -23,13 +23,19 @@ const tagsBlobStorage = [
23
23
  * The REST routes for blob storage.
24
24
  * @param baseRouteName Prefix to prepend to the paths.
25
25
  * @param componentName The name of the component to use in the routes stored in the ComponentFactory.
26
+ * @param options Additional options for the routes.
27
+ * @param options.typeName Optional type name to use in the routes, defaults to Blob Storage.
28
+ * @param options.tagName Optional name to use in OpenAPI spec for tag.
26
29
  * @returns The generated routes.
27
30
  */
28
- function generateRestRoutesBlobStorage(baseRouteName, componentName) {
31
+ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
32
+ const typeName = options?.typeName ?? "Blob Storage";
33
+ const lowerName = typeName.toLowerCase();
34
+ const camelTypeName = StringHelper.camelCase(typeName);
29
35
  const blobStorageCreateRoute = {
30
- operationId: "blobStorageCreate",
31
- summary: "Create a blob in to storage",
32
- tag: tagsBlobStorage[0].name,
36
+ operationId: `${camelTypeName}Create`,
37
+ summary: `Create an entry in ${lowerName}`,
38
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
33
39
  method: "POST",
34
40
  path: `${baseRouteName}/`,
35
41
  handler: async (httpRequestContext, request) => blobStorageCreate(httpRequestContext, componentName, request),
@@ -37,7 +43,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
37
43
  type: "IBlobStorageCreateRequest",
38
44
  examples: [
39
45
  {
40
- id: "blobStorageCreateExample",
46
+ id: `${camelTypeName}CreateRequestExample`,
41
47
  request: {
42
48
  body: {
43
49
  blob: "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw==",
@@ -56,7 +62,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
56
62
  type: "ICreatedResponse",
57
63
  examples: [
58
64
  {
59
- id: "blobStorageCreateResponseExample",
65
+ id: `${camelTypeName}CreateResponseExample`,
60
66
  response: {
61
67
  statusCode: HttpStatusCode.created,
62
68
  headers: {
@@ -69,9 +75,9 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
69
75
  ]
70
76
  };
71
77
  const blobStorageGetRoute = {
72
- operationId: "blobStorageGet",
73
- summary: "Get the blob metadata from storage",
74
- tag: tagsBlobStorage[0].name,
78
+ operationId: `${camelTypeName}Get`,
79
+ summary: `Get the metadata for an item from ${lowerName}`,
80
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
75
81
  method: "GET",
76
82
  path: `${baseRouteName}/:id`,
77
83
  handler: async (httpRequestContext, request) => blobStorageGet(httpRequestContext, componentName, request),
@@ -79,7 +85,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
79
85
  type: "IBlobStorageGetRequest",
80
86
  examples: [
81
87
  {
82
- id: "blobStorageGetRequestExample",
88
+ id: `${camelTypeName}GetRequestExample`,
83
89
  request: {
84
90
  pathParams: {
85
91
  id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
@@ -96,7 +102,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
96
102
  type: "IBlobStorageGetResponse",
97
103
  examples: [
98
104
  {
99
- id: "blobStorageGetResponseExample",
105
+ id: `${camelTypeName}GetResponseExample`,
100
106
  response: {
101
107
  body: {
102
108
  metadata: {
@@ -116,9 +122,9 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
116
122
  ]
117
123
  };
118
124
  const blobStorageGetContentRoute = {
119
- operationId: "blobStorageGetContent",
120
- summary: "Get the blob from storage",
121
- tag: tagsBlobStorage[0].name,
125
+ operationId: `${camelTypeName}GetContent`,
126
+ summary: `Get the content for an item in ${lowerName}`,
127
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
122
128
  method: "GET",
123
129
  path: `${baseRouteName}/:id/content`,
124
130
  handler: async (httpRequestContext, request) => blobStorageGetContent(httpRequestContext, componentName, request),
@@ -126,7 +132,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
126
132
  type: "IBlobStorageGetRequest",
127
133
  examples: [
128
134
  {
129
- id: "blobStorageGetContentRequestExample",
135
+ id: `${camelTypeName}GetContentRequestExample`,
130
136
  request: {
131
137
  pathParams: {
132
138
  id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
@@ -145,7 +151,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
145
151
  mimeType: MimeTypes.OctetStream,
146
152
  examples: [
147
153
  {
148
- id: "blobStorageGetContentResponseExample",
154
+ id: `${camelTypeName}GetContentResponseExample`,
149
155
  description: `The content of the blob, which will be a specific mime type if one can be detected from the content (or set as mimeType in the metadata), or defaults to ${MimeTypes.OctetStream}.`,
150
156
  response: {
151
157
  body: new Uint8Array()
@@ -159,9 +165,9 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
159
165
  ]
160
166
  };
161
167
  const blobStorageUpdateRoute = {
162
- operationId: "blobStorageUpdate",
163
- summary: "Update a blob metadata in storage",
164
- tag: tagsBlobStorage[0].name,
168
+ operationId: `${camelTypeName}Update`,
169
+ summary: `Update the metadata for an item in ${lowerName}`,
170
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
165
171
  method: "PUT",
166
172
  path: `${baseRouteName}/:id`,
167
173
  handler: async (httpRequestContext, request) => blobStorageUpdate(httpRequestContext, componentName, request),
@@ -169,7 +175,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
169
175
  type: "IBlobStorageUpdateRequest",
170
176
  examples: [
171
177
  {
172
- id: "blobStorageUpdateExample",
178
+ id: `${camelTypeName}UpdateRequestExample`,
173
179
  request: {
174
180
  pathParams: {
175
181
  id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
@@ -192,9 +198,9 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
192
198
  ]
193
199
  };
194
200
  const blobStorageRemoveRoute = {
195
- operationId: "blobStorageRemove",
196
- summary: "Remove the blob from storage",
197
- tag: tagsBlobStorage[0].name,
201
+ operationId: `${camelTypeName}Remove`,
202
+ summary: `Remove an item from ${lowerName}`,
203
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
198
204
  method: "DELETE",
199
205
  path: `${baseRouteName}/:id`,
200
206
  handler: async (httpRequestContext, request) => blobStorageRemove(httpRequestContext, componentName, request),
@@ -202,7 +208,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
202
208
  type: "IBlobStorageRemoveRequest",
203
209
  examples: [
204
210
  {
205
- id: "blobStorageRemoveRequestExample",
211
+ id: `${camelTypeName}RemoveRequestExample`,
206
212
  request: {
207
213
  pathParams: {
208
214
  id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
@@ -260,7 +266,7 @@ async function blobStorageGet(httpRequestContext, componentName, request) {
260
266
  Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
261
267
  Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
262
268
  const component = ComponentFactory.get(componentName);
263
- const result = await component.get(request.pathParams.id, request.query?.includeContent ?? false, httpRequestContext.nodeIdentity);
269
+ const result = await component.get(request.pathParams.id, request.query?.includeContent ?? false, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
264
270
  return {
265
271
  body: result
266
272
  };
@@ -277,7 +283,7 @@ async function blobStorageGetContent(httpRequestContext, componentName, request)
277
283
  Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
278
284
  Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
279
285
  const component = ComponentFactory.get(componentName);
280
- const result = await component.get(request.pathParams.id, true, httpRequestContext.nodeIdentity);
286
+ const result = await component.get(request.pathParams.id, true, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
281
287
  const mimeType = result?.mimeType ?? MimeTypes.OctetStream;
282
288
  let filename = request.query?.filename;
283
289
  if (!Is.stringValue(filename)) {
@@ -304,7 +310,7 @@ async function blobStorageUpdate(httpRequestContext, componentName, request) {
304
310
  Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
305
311
  Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
306
312
  const component = ComponentFactory.get(componentName);
307
- await component.update(request.pathParams.id, request.body.mimeType, request.body.extension, request.body.metadata);
313
+ await component.update(request.pathParams.id, request.body.mimeType, request.body.extension, request.body.metadata, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
308
314
  return {
309
315
  statusCode: HttpStatusCode.noContent
310
316
  };
@@ -321,7 +327,7 @@ async function blobStorageRemove(httpRequestContext, componentName, request) {
321
327
  Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
322
328
  Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
323
329
  const component = ComponentFactory.get(componentName);
324
- await component.remove(request.pathParams.id);
330
+ await component.remove(request.pathParams.id, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
325
331
  return {
326
332
  statusCode: HttpStatusCode.noContent
327
333
  };
@@ -362,6 +368,16 @@ class BlobStorageService {
362
368
  * @internal
363
369
  */
364
370
  _vaultKeyId;
371
+ /**
372
+ * Include the node identity when performing storage operations, defaults to true.
373
+ * @internal
374
+ */
375
+ _includeNodeIdentity;
376
+ /**
377
+ * Include the user identity when performing storage operations, defaults to true.
378
+ * @internal
379
+ */
380
+ _includeUserIdentity;
365
381
  /**
366
382
  * Create a new instance of BlobStorageService.
367
383
  * @param options The dependencies for the service.
@@ -380,6 +396,8 @@ class BlobStorageService {
380
396
  }
381
397
  this._defaultNamespace = options?.config?.defaultNamespace ?? names[0];
382
398
  this._vaultKeyId = options?.config?.vaultKeyId ?? "blob-storage";
399
+ this._includeNodeIdentity = options?.config?.includeNodeIdentity ?? true;
400
+ this._includeUserIdentity = options?.config?.includeUserIdentity ?? true;
383
401
  }
384
402
  /**
385
403
  * Create the blob with some metadata.
@@ -388,12 +406,16 @@ class BlobStorageService {
388
406
  * @param extension Extension for the blob, will be detected if left undefined.
389
407
  * @param metadata Data for the custom metadata as JSON-LD.
390
408
  * @param namespace The namespace to use for storing, defaults to component configured namespace.
391
- * @param nodeIdentity The node identity which controls the vault key.
409
+ * @param userIdentity The user identity to use with storage operations.
410
+ * @param nodeIdentity The node identity to use with storage operations.
392
411
  * @returns The id of the stored blob in urn format.
393
412
  */
394
- async create(blob, mimeType, extension, metadata, namespace, nodeIdentity) {
413
+ async create(blob, mimeType, extension, metadata, namespace, userIdentity, nodeIdentity) {
395
414
  Guards.stringBase64(this.CLASS_NAME, "blob", blob);
396
- if (this._vaultConnector) {
415
+ if (this._includeUserIdentity) {
416
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
417
+ }
418
+ if (this._includeNodeIdentity || Is.notEmpty(this._vaultConnector)) {
397
419
  Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
398
420
  }
399
421
  try {
@@ -421,12 +443,23 @@ class BlobStorageService {
421
443
  }
422
444
  // Set the blob in the storage connector, which may now be encrypted
423
445
  const blobId = await blobStorageConnector.set(storeBlob);
424
- await this._metadataEntityStorage.set({
446
+ // Now store the metadata in entity storage
447
+ const blobMetadata = {
425
448
  id: blobId,
426
449
  mimeType,
427
450
  extension,
428
451
  metadata
429
- });
452
+ };
453
+ const conditions = [];
454
+ if (this._includeUserIdentity) {
455
+ ObjectHelper.propertySet(blobMetadata, "userIdentity", userIdentity);
456
+ conditions.push({ property: "userIdentity", value: userIdentity });
457
+ }
458
+ if (this._includeNodeIdentity) {
459
+ ObjectHelper.propertySet(blobMetadata, "nodeIdentity", nodeIdentity);
460
+ conditions.push({ property: "nodeIdentity", value: nodeIdentity });
461
+ }
462
+ await this._metadataEntityStorage.set(blobMetadata, conditions);
430
463
  return blobId;
431
464
  }
432
465
  catch (error) {
@@ -437,18 +470,32 @@ class BlobStorageService {
437
470
  * Get the blob and metadata.
438
471
  * @param id The id of the blob to get in urn format.
439
472
  * @param includeContent Include the content, or just get the metadata.
440
- * @param nodeIdentity The node identity which controls the vault key.
473
+ * @param userIdentity The user identity to use with storage operations.
474
+ * @param nodeIdentity The node identity to use with storage operations.
441
475
  * @returns The metadata and data for the blob if it can be found.
442
476
  * @throws Not found error if the blob cannot be found.
443
477
  */
444
- async get(id, includeContent, nodeIdentity) {
478
+ async get(id, includeContent, userIdentity, nodeIdentity) {
445
479
  Urn.guard(this.CLASS_NAME, "id", id);
446
- if (this._vaultConnector && includeContent) {
480
+ const conditions = [];
481
+ if (this._includeUserIdentity) {
482
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
483
+ conditions.push({
484
+ property: "userIdentity",
485
+ comparison: ComparisonOperator.Equals,
486
+ value: userIdentity
487
+ });
488
+ }
489
+ if (this._includeNodeIdentity || (Is.notEmpty(this._vaultConnector) && includeContent)) {
447
490
  Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
491
+ conditions.push({
492
+ property: "nodeIdentity",
493
+ comparison: ComparisonOperator.Equals,
494
+ value: nodeIdentity
495
+ });
448
496
  }
449
497
  try {
450
- // Get the metadata
451
- const blobMetadata = await this._metadataEntityStorage.get(id);
498
+ const blobMetadata = await this.internalGet(id, userIdentity, nodeIdentity);
452
499
  let returnBlob;
453
500
  if (includeContent) {
454
501
  const blobStorageConnector = this.getConnector(id);
@@ -478,11 +525,19 @@ class BlobStorageService {
478
525
  * @param mimeType Mime type for the blob, will be detected if left undefined.
479
526
  * @param extension Extension for the blob, will be detected if left undefined.
480
527
  * @param metadata Data for the custom metadata as JSON-LD.
528
+ * @param userIdentity The user identity to use with storage operations.
529
+ * @param nodeIdentity The node identity to use with storage operations.
481
530
  * @returns Nothing.
482
531
  * @throws Not found error if the blob cannot be found.
483
532
  */
484
- async update(id, mimeType, extension, metadata) {
533
+ async update(id, mimeType, extension, metadata, userIdentity, nodeIdentity) {
485
534
  Urn.guard(this.CLASS_NAME, "id", id);
535
+ if (this._includeUserIdentity) {
536
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
537
+ }
538
+ if (this._includeNodeIdentity || Is.notEmpty(this._vaultConnector)) {
539
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
540
+ }
486
541
  try {
487
542
  const blobMetadata = await this._metadataEntityStorage.get(id);
488
543
  if (Is.undefined(blobMetadata)) {
@@ -493,12 +548,23 @@ class BlobStorageService {
493
548
  await JsonLdHelper.validate(metadata, validationFailures);
494
549
  Validation.asValidationError(this.CLASS_NAME, "metadata", validationFailures);
495
550
  }
496
- await this._metadataEntityStorage.set({
551
+ // Now store the metadata in entity storage
552
+ const updatedBlobMetadata = {
497
553
  id: blobMetadata.id,
498
554
  mimeType: mimeType ?? blobMetadata.mimeType,
499
555
  extension: extension ?? blobMetadata.extension,
500
556
  metadata: metadata ?? blobMetadata.metadata
501
- });
557
+ };
558
+ const conditions = [];
559
+ if (this._includeUserIdentity) {
560
+ ObjectHelper.propertySet(updatedBlobMetadata, "userIdentity", userIdentity);
561
+ conditions.push({ property: "userIdentity", value: userIdentity });
562
+ }
563
+ if (this._includeNodeIdentity) {
564
+ ObjectHelper.propertySet(updatedBlobMetadata, "nodeIdentity", nodeIdentity);
565
+ conditions.push({ property: "nodeIdentity", value: nodeIdentity });
566
+ }
567
+ await this._metadataEntityStorage.set(updatedBlobMetadata, conditions);
502
568
  }
503
569
  catch (error) {
504
570
  throw new GeneralError(this.CLASS_NAME, "updateFailed", undefined, error);
@@ -507,17 +573,32 @@ class BlobStorageService {
507
573
  /**
508
574
  * Remove the blob.
509
575
  * @param id The id of the blob to remove in urn format.
576
+ * @param userIdentity The user identity to use with storage operations.
577
+ * @param nodeIdentity The node identity to use with storage operations.
510
578
  * @returns Nothing.
511
579
  */
512
- async remove(id) {
580
+ async remove(id, userIdentity, nodeIdentity) {
513
581
  Urn.guard(this.CLASS_NAME, "id", id);
582
+ if (this._includeUserIdentity) {
583
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
584
+ }
585
+ if (this._includeNodeIdentity || Is.notEmpty(this._vaultConnector)) {
586
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
587
+ }
514
588
  try {
515
589
  const blobStorageConnector = this.getConnector(id);
590
+ const conditions = [];
591
+ if (this._includeUserIdentity) {
592
+ conditions.push({ property: "userIdentity", value: userIdentity });
593
+ }
594
+ if (this._includeNodeIdentity) {
595
+ conditions.push({ property: "nodeIdentity", value: nodeIdentity });
596
+ }
597
+ await this._metadataEntityStorage.remove(id, conditions);
516
598
  const removed = await blobStorageConnector.remove(id);
517
599
  if (!removed) {
518
600
  throw new NotFoundError(this.CLASS_NAME, "blobNotFound", id);
519
601
  }
520
- await this._metadataEntityStorage.remove(id);
521
602
  }
522
603
  catch (error) {
523
604
  throw new GeneralError(this.CLASS_NAME, "removeFailed", undefined, error);
@@ -539,6 +620,58 @@ class BlobStorageService {
539
620
  }
540
621
  return BlobStorageConnectorFactory.get(idUri.namespaceMethod());
541
622
  }
623
+ /**
624
+ * Get an entity.
625
+ * @param id The id of the entity to get, or the index value if secondaryIndex is set.
626
+ * @param secondaryIndex Get the item using a secondary index.
627
+ * @param userIdentity The user identity to use with storage operations.
628
+ * @param nodeIdentity The node identity to use with storage operations.
629
+ * @returns The object if it can be found or throws.
630
+ * @internal
631
+ */
632
+ async internalGet(id, userIdentity, nodeIdentity) {
633
+ const conditions = [];
634
+ if (this._includeUserIdentity) {
635
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
636
+ conditions.push({
637
+ property: "userIdentity",
638
+ comparison: ComparisonOperator.Equals,
639
+ value: userIdentity
640
+ });
641
+ }
642
+ if (this._includeNodeIdentity) {
643
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
644
+ conditions.push({
645
+ property: "nodeIdentity",
646
+ comparison: ComparisonOperator.Equals,
647
+ value: nodeIdentity
648
+ });
649
+ }
650
+ let entity;
651
+ if (conditions.length === 0) {
652
+ entity = await this._metadataEntityStorage.get(id);
653
+ }
654
+ else {
655
+ const schema = this._metadataEntityStorage.getSchema();
656
+ const primaryKey = EntitySchemaHelper.getPrimaryKey(schema);
657
+ conditions.unshift({
658
+ property: primaryKey.property,
659
+ comparison: ComparisonOperator.Equals,
660
+ value: id
661
+ });
662
+ const results = await this._metadataEntityStorage.query({
663
+ conditions,
664
+ logicalOperator: LogicalOperator.And
665
+ }, undefined, undefined, undefined, 1);
666
+ entity = results.entities[0];
667
+ }
668
+ if (Is.empty(entity)) {
669
+ throw new NotFoundError(this.CLASS_NAME, "entityNotFound", id);
670
+ }
671
+ ObjectHelper.propertyDelete(entity, "nodeIdentity");
672
+ ObjectHelper.propertyDelete(entity, "userIdentity");
673
+ return entity;
674
+ }
542
675
  }
543
676
 
544
677
  /**
@@ -561,6 +694,14 @@ let BlobMetadata = class BlobMetadata {
561
694
  * The metadata for the blob as JSON-LD.
562
695
  */
563
696
  metadata;
697
+ /**
698
+ * The user identity that created the blob.
699
+ */
700
+ userIdentity;
701
+ /**
702
+ * The node identity that created the blob.
703
+ */
704
+ nodeIdentity;
564
705
  };
565
706
  __decorate([
566
707
  property({ type: "string", isPrimary: true }),
@@ -578,14 +719,27 @@ __decorate([
578
719
  property({ type: "object", itemTypeRef: "IJsonLdNodeObject" }),
579
720
  __metadata("design:type", Object)
580
721
  ], BlobMetadata.prototype, "metadata", void 0);
722
+ __decorate([
723
+ property({ type: "string" }),
724
+ __metadata("design:type", String)
725
+ ], BlobMetadata.prototype, "userIdentity", void 0);
726
+ __decorate([
727
+ property({ type: "string" }),
728
+ __metadata("design:type", String)
729
+ ], BlobMetadata.prototype, "nodeIdentity", void 0);
581
730
  BlobMetadata = __decorate([
582
731
  entity()
583
732
  ], BlobMetadata);
584
733
 
734
+ /**
735
+ * These are dummy entry points for the blob storage service.
736
+ * In reality your application would create its own entry points based on the
737
+ * blob types it wants to store, using a custom defaultBaseRoute.
738
+ */
585
739
  const restEntryPoints = [
586
740
  {
587
- name: "blobStorage",
588
- defaultBaseRoute: "blob",
741
+ name: "blob-storage",
742
+ defaultBaseRoute: "blob-storage",
589
743
  tags: tagsBlobStorage,
590
744
  generateRoutes: generateRestRoutesBlobStorage
591
745
  }
@@ -8,9 +8,15 @@ export declare const tagsBlobStorage: ITag[];
8
8
  * The REST routes for blob storage.
9
9
  * @param baseRouteName Prefix to prepend to the paths.
10
10
  * @param componentName The name of the component to use in the routes stored in the ComponentFactory.
11
+ * @param options Additional options for the routes.
12
+ * @param options.typeName Optional type name to use in the routes, defaults to Blob Storage.
13
+ * @param options.tagName Optional name to use in OpenAPI spec for tag.
11
14
  * @returns The generated routes.
12
15
  */
13
- export declare function generateRestRoutesBlobStorage(baseRouteName: string, componentName: string): IRestRoute[];
16
+ export declare function generateRestRoutesBlobStorage(baseRouteName: string, componentName: string, options?: {
17
+ typeName?: string;
18
+ tagName?: string;
19
+ }): IRestRoute[];
14
20
  /**
15
21
  * Create a blob in storage.
16
22
  * @param httpRequestContext The request context for the API.
@@ -32,19 +32,21 @@ export declare class BlobStorageService implements IBlobStorageComponent {
32
32
  * @param extension Extension for the blob, will be detected if left undefined.
33
33
  * @param metadata Data for the custom metadata as JSON-LD.
34
34
  * @param namespace The namespace to use for storing, defaults to component configured namespace.
35
- * @param nodeIdentity The node identity which controls the vault key.
35
+ * @param userIdentity The user identity to use with storage operations.
36
+ * @param nodeIdentity The node identity to use with storage operations.
36
37
  * @returns The id of the stored blob in urn format.
37
38
  */
38
- create(blob: string, mimeType?: string, extension?: string, metadata?: IJsonLdNodeObject, namespace?: string, nodeIdentity?: string): Promise<string>;
39
+ create(blob: string, mimeType?: string, extension?: string, metadata?: IJsonLdNodeObject, namespace?: string, userIdentity?: string, nodeIdentity?: string): Promise<string>;
39
40
  /**
40
41
  * Get the blob and metadata.
41
42
  * @param id The id of the blob to get in urn format.
42
43
  * @param includeContent Include the content, or just get the metadata.
43
- * @param nodeIdentity The node identity which controls the vault key.
44
+ * @param userIdentity The user identity to use with storage operations.
45
+ * @param nodeIdentity The node identity to use with storage operations.
44
46
  * @returns The metadata and data for the blob if it can be found.
45
47
  * @throws Not found error if the blob cannot be found.
46
48
  */
47
- get(id: string, includeContent: boolean, nodeIdentity?: string): Promise<{
49
+ get(id: string, includeContent: boolean, userIdentity?: string, nodeIdentity?: string): Promise<{
48
50
  blob?: string;
49
51
  mimeType?: string;
50
52
  extension?: string;
@@ -56,14 +58,18 @@ export declare class BlobStorageService implements IBlobStorageComponent {
56
58
  * @param mimeType Mime type for the blob, will be detected if left undefined.
57
59
  * @param extension Extension for the blob, will be detected if left undefined.
58
60
  * @param metadata Data for the custom metadata as JSON-LD.
61
+ * @param userIdentity The user identity to use with storage operations.
62
+ * @param nodeIdentity The node identity to use with storage operations.
59
63
  * @returns Nothing.
60
64
  * @throws Not found error if the blob cannot be found.
61
65
  */
62
- update(id: string, mimeType?: string, extension?: string, metadata?: IJsonLdNodeObject): Promise<void>;
66
+ update(id: string, mimeType?: string, extension?: string, metadata?: IJsonLdNodeObject, userIdentity?: string, nodeIdentity?: string): Promise<void>;
63
67
  /**
64
68
  * Remove the blob.
65
69
  * @param id The id of the blob to remove in urn format.
70
+ * @param userIdentity The user identity to use with storage operations.
71
+ * @param nodeIdentity The node identity to use with storage operations.
66
72
  * @returns Nothing.
67
73
  */
68
- remove(id: string): Promise<void>;
74
+ remove(id: string, userIdentity?: string, nodeIdentity?: string): Promise<void>;
69
75
  }
@@ -19,4 +19,12 @@ export declare class BlobMetadata {
19
19
  * The metadata for the blob as JSON-LD.
20
20
  */
21
21
  metadata?: IJsonLdNodeObject;
22
+ /**
23
+ * The user identity that created the blob.
24
+ */
25
+ userIdentity?: string;
26
+ /**
27
+ * The node identity that created the blob.
28
+ */
29
+ nodeIdentity?: string;
22
30
  }
@@ -12,4 +12,12 @@ export interface IBlobStorageServiceConfig {
12
12
  * Defaults to the first entry in the factory if not provided.
13
13
  */
14
14
  defaultNamespace?: string;
15
+ /**
16
+ * Include the node identity when performing storage operations, defaults to true.
17
+ */
18
+ includeNodeIdentity?: boolean;
19
+ /**
20
+ * Include the user identity when performing storage operations, defaults to true.
21
+ */
22
+ includeUserIdentity?: boolean;
15
23
  }
@@ -1,2 +1,7 @@
1
1
  import type { IRestRouteEntryPoint } from "@twin.org/api-models";
2
+ /**
3
+ * These are dummy entry points for the blob storage service.
4
+ * In reality your application would create its own entry points based on the
5
+ * blob types it wants to store, using a custom defaultBaseRoute.
6
+ */
2
7
  export declare const restEntryPoints: IRestRouteEntryPoint[];
package/docs/changelog.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # @twin.org/blob-storage-service - Changelog
2
2
 
3
- ## v0.0.1-next.8
3
+ ## v0.0.1-next.9
4
4
 
5
5
  - Initial Release