@twin.org/blob-storage-service 0.0.1-next.33 → 0.0.1-next.35
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/dist/cjs/index.cjs +61 -20
- package/dist/esm/index.mjs +62 -21
- package/dist/types/blobStorageService.d.ts +18 -4
- package/dist/types/entities/blobStorageEntry.d.ts +4 -0
- package/dist/types/models/IBlobStorageServiceConfig.d.ts +1 -2
- package/dist/types/models/IBlobStorageServiceConstructorOptions.d.ts +1 -1
- package/docs/changelog.md +32 -0
- package/docs/open-api/spec.json +64 -1101
- package/docs/reference/classes/BlobStorageEntry.md +8 -0
- package/docs/reference/classes/BlobStorageService.md +36 -4
- package/docs/reference/interfaces/IBlobStorageServiceConfig.md +1 -7
- package/docs/reference/interfaces/IBlobStorageServiceConstructorOptions.md +1 -1
- package/locales/en.json +2 -1
- package/package.json +2 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -98,7 +98,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
98
98
|
id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
|
|
99
99
|
},
|
|
100
100
|
query: {
|
|
101
|
-
includeContent: true
|
|
101
|
+
includeContent: "true"
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -188,7 +188,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
188
188
|
id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
|
|
189
189
|
},
|
|
190
190
|
query: {
|
|
191
|
-
download: true,
|
|
191
|
+
download: "true",
|
|
192
192
|
filename: "my-file.pdf"
|
|
193
193
|
}
|
|
194
194
|
}
|
|
@@ -277,7 +277,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
277
277
|
]
|
|
278
278
|
};
|
|
279
279
|
const blobStorageListRoute = {
|
|
280
|
-
operationId: `${camelTypeName}
|
|
280
|
+
operationId: `${camelTypeName}Query`,
|
|
281
281
|
summary: `Query the items from ${lowerName}`,
|
|
282
282
|
tag: options?.tagName ?? tagsBlobStorage[0].name,
|
|
283
283
|
method: "GET",
|
|
@@ -400,7 +400,11 @@ async function blobStorageCreate(httpRequestContext, componentName, request) {
|
|
|
400
400
|
core.Guards.object(ROUTES_SOURCE, "request.body", request.body);
|
|
401
401
|
core.Guards.stringBase64(ROUTES_SOURCE, "request.body.blob", request.body.blob);
|
|
402
402
|
const component = core.ComponentFactory.get(componentName);
|
|
403
|
-
const id = await component.create(request.body.blob, request.body.encodingFormat, request.body.fileExtension, request.body.metadata,
|
|
403
|
+
const id = await component.create(request.body.blob, request.body.encodingFormat, request.body.fileExtension, request.body.metadata, {
|
|
404
|
+
disableEncryption: request.body.disableEncryption,
|
|
405
|
+
overrideVaultKeyId: request.body.overrideVaultKeyId,
|
|
406
|
+
namespace: request.body.namespace
|
|
407
|
+
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
404
408
|
return {
|
|
405
409
|
statusCode: web.HttpStatusCode.created,
|
|
406
410
|
headers: {
|
|
@@ -421,7 +425,11 @@ async function blobStorageGet(httpRequestContext, componentName, request) {
|
|
|
421
425
|
core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
422
426
|
const mimeType = request.headers?.[web.HeaderTypes.Accept] === web.MimeTypes.JsonLd ? "jsonld" : "json";
|
|
423
427
|
const component = core.ComponentFactory.get(componentName);
|
|
424
|
-
const result = await component.get(request.pathParams.id,
|
|
428
|
+
const result = await component.get(request.pathParams.id, {
|
|
429
|
+
includeContent: core.Coerce.boolean(request.query?.includeContent),
|
|
430
|
+
disableDecryption: core.Coerce.boolean(request.query?.disableDecryption),
|
|
431
|
+
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
432
|
+
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
425
433
|
return {
|
|
426
434
|
headers: {
|
|
427
435
|
[web.HeaderTypes.ContentType]: mimeType === "json" ? web.MimeTypes.Json : web.MimeTypes.JsonLd
|
|
@@ -441,7 +449,11 @@ async function blobStorageGetContent(httpRequestContext, componentName, request)
|
|
|
441
449
|
core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
442
450
|
core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
443
451
|
const component = core.ComponentFactory.get(componentName);
|
|
444
|
-
const result = await component.get(request.pathParams.id,
|
|
452
|
+
const result = await component.get(request.pathParams.id, {
|
|
453
|
+
includeContent: true,
|
|
454
|
+
disableDecryption: core.Coerce.boolean(request.query?.disableDecryption),
|
|
455
|
+
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
456
|
+
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
445
457
|
const encodingFormat = result?.encodingFormat ?? web.MimeTypes.OctetStream;
|
|
446
458
|
let filename = request.query?.filename;
|
|
447
459
|
if (!core.Is.stringValue(filename)) {
|
|
@@ -566,10 +578,10 @@ class BlobStorageService {
|
|
|
566
578
|
}
|
|
567
579
|
this._entryEntityStorage = entityStorageModels.EntityStorageConnectorFactory.get(options?.entryEntityStorageType ?? "blob-storage-entry");
|
|
568
580
|
if (core.Is.stringValue(options?.vaultConnectorType)) {
|
|
569
|
-
this._vaultConnector = vaultModels.VaultConnectorFactory.
|
|
581
|
+
this._vaultConnector = vaultModels.VaultConnectorFactory.get(options.vaultConnectorType);
|
|
570
582
|
}
|
|
571
583
|
this._defaultNamespace = options?.config?.defaultNamespace ?? names[0];
|
|
572
|
-
this._vaultKeyId = options?.config?.vaultKeyId
|
|
584
|
+
this._vaultKeyId = options?.config?.vaultKeyId;
|
|
573
585
|
this._includeNodeIdentity = options?.config?.includeNodeIdentity ?? true;
|
|
574
586
|
this._includeUserIdentity = options?.config?.includeUserIdentity ?? true;
|
|
575
587
|
standardsSchemaOrg.SchemaOrgDataTypes.registerRedirects();
|
|
@@ -580,21 +592,27 @@ class BlobStorageService {
|
|
|
580
592
|
* @param encodingFormat Mime type for the blob, will be detected if left undefined.
|
|
581
593
|
* @param fileExtension Extension for the blob, will be detected if left undefined.
|
|
582
594
|
* @param metadata Data for the custom metadata as JSON-LD.
|
|
583
|
-
* @param
|
|
595
|
+
* @param options Optional options for the creation of the blob.
|
|
596
|
+
* @param options.disableEncryption Disables encryption if enabled by default.
|
|
597
|
+
* @param options.overrideVaultKeyId Use a different vault key id for encryption, if not provided the default vault key id will be used.
|
|
598
|
+
* @param options.namespace The namespace to use for storing, defaults to component configured namespace.
|
|
584
599
|
* @param userIdentity The user identity to use with storage operations.
|
|
585
600
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
586
601
|
* @returns The id of the stored blob in urn format.
|
|
587
602
|
*/
|
|
588
|
-
async create(blob, encodingFormat, fileExtension, metadata,
|
|
603
|
+
async create(blob, encodingFormat, fileExtension, metadata, options, userIdentity, nodeIdentity) {
|
|
589
604
|
core.Guards.stringBase64(this.CLASS_NAME, "blob", blob);
|
|
590
605
|
if (this._includeUserIdentity) {
|
|
591
606
|
core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
592
607
|
}
|
|
593
|
-
|
|
608
|
+
const disableEncryption = options?.disableEncryption ?? false;
|
|
609
|
+
const vaultKeyId = options?.overrideVaultKeyId ?? this._vaultKeyId;
|
|
610
|
+
const encryptionEnabled = !disableEncryption && core.Is.stringValue(vaultKeyId);
|
|
611
|
+
if (this._includeNodeIdentity || encryptionEnabled) {
|
|
594
612
|
core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
595
613
|
}
|
|
596
614
|
try {
|
|
597
|
-
const connectorNamespace = namespace ?? this._defaultNamespace;
|
|
615
|
+
const connectorNamespace = options?.namespace ?? this._defaultNamespace;
|
|
598
616
|
const blobStorageConnector = blobStorageModels.BlobStorageConnectorFactory.get(connectorNamespace);
|
|
599
617
|
// Convert the base64 data into bytes
|
|
600
618
|
let storeBlob = core.Converter.base64ToBytes(blob);
|
|
@@ -615,8 +633,11 @@ class BlobStorageService {
|
|
|
615
633
|
}
|
|
616
634
|
const blobHash = `sha256:${core.Converter.bytesToBase64(crypto.Sha256.sum256(storeBlob))}`;
|
|
617
635
|
// If we have a vault connector then encrypt the data.
|
|
618
|
-
if (
|
|
619
|
-
|
|
636
|
+
if (encryptionEnabled) {
|
|
637
|
+
if (core.Is.empty(this._vaultConnector)) {
|
|
638
|
+
throw new core.GeneralError(this.CLASS_NAME, "vaultConnectorNotConfigured");
|
|
639
|
+
}
|
|
640
|
+
storeBlob = await this._vaultConnector.encrypt(`${nodeIdentity}/${vaultKeyId}`, vaultModels.VaultEncryptionType.ChaCha20Poly1305, storeBlob);
|
|
620
641
|
}
|
|
621
642
|
// Set the blob in the storage connector, which may now be encrypted
|
|
622
643
|
const blobId = await blobStorageConnector.set(storeBlob);
|
|
@@ -628,7 +649,8 @@ class BlobStorageService {
|
|
|
628
649
|
blobHash,
|
|
629
650
|
encodingFormat,
|
|
630
651
|
fileExtension,
|
|
631
|
-
metadata
|
|
652
|
+
metadata,
|
|
653
|
+
isEncrypted: encryptionEnabled
|
|
632
654
|
};
|
|
633
655
|
const conditions = [];
|
|
634
656
|
if (this._includeUserIdentity) {
|
|
@@ -649,14 +671,21 @@ class BlobStorageService {
|
|
|
649
671
|
/**
|
|
650
672
|
* Get the blob entry.
|
|
651
673
|
* @param id The id of the blob to get in urn format.
|
|
652
|
-
* @param
|
|
674
|
+
* @param options Optional options for the retrieval of the blob.
|
|
675
|
+
* @param options.includeContent Include the content, or just get the metadata.
|
|
676
|
+
* @param options.disableDecryption Disables decryption if enabled by default.
|
|
677
|
+
* @param options.overrideVaultKeyId Use a different vault key id for decryption, if not provided the default vault key id will be used.
|
|
653
678
|
* @param userIdentity The user identity to use with storage operations.
|
|
654
679
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
655
680
|
* @returns The entry and data for the blob if it can be found.
|
|
656
681
|
* @throws Not found error if the blob cannot be found.
|
|
657
682
|
*/
|
|
658
|
-
async get(id,
|
|
683
|
+
async get(id, options, userIdentity, nodeIdentity) {
|
|
659
684
|
core.Urn.guard(this.CLASS_NAME, "id", id);
|
|
685
|
+
const includeContent = options?.includeContent ?? false;
|
|
686
|
+
const disableEncryption = options?.disableDecryption ?? false;
|
|
687
|
+
const vaultKeyId = options?.overrideVaultKeyId ?? this._vaultKeyId;
|
|
688
|
+
const decryptionEnabled = !disableEncryption && core.Is.stringValue(vaultKeyId);
|
|
660
689
|
const conditions = [];
|
|
661
690
|
if (this._includeUserIdentity) {
|
|
662
691
|
core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
@@ -684,8 +713,11 @@ class BlobStorageService {
|
|
|
684
713
|
throw new core.NotFoundError(this.CLASS_NAME, "blobNotFound", id);
|
|
685
714
|
}
|
|
686
715
|
// If we have a vault connector then decrypt the data.
|
|
687
|
-
if (
|
|
688
|
-
|
|
716
|
+
if (decryptionEnabled) {
|
|
717
|
+
if (core.Is.empty(this._vaultConnector)) {
|
|
718
|
+
throw new core.GeneralError(this.CLASS_NAME, "vaultConnectorNotConfigured");
|
|
719
|
+
}
|
|
720
|
+
returnBlob = await this._vaultConnector.decrypt(`${nodeIdentity}/${vaultKeyId}`, vaultModels.VaultEncryptionType.ChaCha20Poly1305, returnBlob);
|
|
689
721
|
}
|
|
690
722
|
}
|
|
691
723
|
const jsonLd = this.entryToJsonLd(blobEntry, returnBlob);
|
|
@@ -733,7 +765,8 @@ class BlobStorageService {
|
|
|
733
765
|
blobHash: blobEntry.blobHash,
|
|
734
766
|
encodingFormat: encodingFormat ?? blobEntry.encodingFormat,
|
|
735
767
|
fileExtension: fileExtension ?? blobEntry.fileExtension,
|
|
736
|
-
metadata: metadata ?? blobEntry.metadata
|
|
768
|
+
metadata: metadata ?? blobEntry.metadata,
|
|
769
|
+
isEncrypted: blobEntry.isEncrypted
|
|
737
770
|
};
|
|
738
771
|
const conditions = [];
|
|
739
772
|
if (this._includeUserIdentity) {
|
|
@@ -984,6 +1017,10 @@ exports.BlobStorageEntry = class BlobStorageEntry {
|
|
|
984
1017
|
* The metadata for the blob as JSON-LD.
|
|
985
1018
|
*/
|
|
986
1019
|
metadata;
|
|
1020
|
+
/**
|
|
1021
|
+
* Is the entry encrypted.
|
|
1022
|
+
*/
|
|
1023
|
+
isEncrypted;
|
|
987
1024
|
/**
|
|
988
1025
|
* The user identity that created the blob.
|
|
989
1026
|
*/
|
|
@@ -1030,6 +1067,10 @@ __decorate([
|
|
|
1030
1067
|
entity.property({ type: "object", itemTypeRef: "IJsonLdNodeObject", optional: true }),
|
|
1031
1068
|
__metadata("design:type", Object)
|
|
1032
1069
|
], exports.BlobStorageEntry.prototype, "metadata", void 0);
|
|
1070
|
+
__decorate([
|
|
1071
|
+
entity.property({ type: "boolean" }),
|
|
1072
|
+
__metadata("design:type", Boolean)
|
|
1073
|
+
], exports.BlobStorageEntry.prototype, "isEncrypted", void 0);
|
|
1033
1074
|
__decorate([
|
|
1034
1075
|
entity.property({ type: "string", optional: true }),
|
|
1035
1076
|
__metadata("design:type", String)
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HttpParameterHelper } from '@twin.org/api-models';
|
|
2
2
|
import { BlobStorageTypes, BlobStorageContexts, BlobStorageConnectorFactory } from '@twin.org/blob-storage-models';
|
|
3
|
-
import { StringHelper, Guards, ComponentFactory, Is, Converter,
|
|
3
|
+
import { StringHelper, Guards, ComponentFactory, Coerce, Is, Converter, GeneralError, Validation, ObjectHelper, Urn, NotFoundError } from '@twin.org/core';
|
|
4
4
|
import { SchemaOrgContexts, SchemaOrgTypes, SchemaOrgDataTypes } from '@twin.org/standards-schema-org';
|
|
5
5
|
import { HttpStatusCode, HeaderTypes, MimeTypes, MimeTypeHelper } from '@twin.org/web';
|
|
6
6
|
import { Sha256 } from '@twin.org/crypto';
|
|
@@ -96,7 +96,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
96
96
|
id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
|
|
97
97
|
},
|
|
98
98
|
query: {
|
|
99
|
-
includeContent: true
|
|
99
|
+
includeContent: "true"
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
}
|
|
@@ -186,7 +186,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
186
186
|
id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
|
|
187
187
|
},
|
|
188
188
|
query: {
|
|
189
|
-
download: true,
|
|
189
|
+
download: "true",
|
|
190
190
|
filename: "my-file.pdf"
|
|
191
191
|
}
|
|
192
192
|
}
|
|
@@ -275,7 +275,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
275
275
|
]
|
|
276
276
|
};
|
|
277
277
|
const blobStorageListRoute = {
|
|
278
|
-
operationId: `${camelTypeName}
|
|
278
|
+
operationId: `${camelTypeName}Query`,
|
|
279
279
|
summary: `Query the items from ${lowerName}`,
|
|
280
280
|
tag: options?.tagName ?? tagsBlobStorage[0].name,
|
|
281
281
|
method: "GET",
|
|
@@ -398,7 +398,11 @@ async function blobStorageCreate(httpRequestContext, componentName, request) {
|
|
|
398
398
|
Guards.object(ROUTES_SOURCE, "request.body", request.body);
|
|
399
399
|
Guards.stringBase64(ROUTES_SOURCE, "request.body.blob", request.body.blob);
|
|
400
400
|
const component = ComponentFactory.get(componentName);
|
|
401
|
-
const id = await component.create(request.body.blob, request.body.encodingFormat, request.body.fileExtension, request.body.metadata,
|
|
401
|
+
const id = await component.create(request.body.blob, request.body.encodingFormat, request.body.fileExtension, request.body.metadata, {
|
|
402
|
+
disableEncryption: request.body.disableEncryption,
|
|
403
|
+
overrideVaultKeyId: request.body.overrideVaultKeyId,
|
|
404
|
+
namespace: request.body.namespace
|
|
405
|
+
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
402
406
|
return {
|
|
403
407
|
statusCode: HttpStatusCode.created,
|
|
404
408
|
headers: {
|
|
@@ -419,7 +423,11 @@ async function blobStorageGet(httpRequestContext, componentName, request) {
|
|
|
419
423
|
Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
420
424
|
const mimeType = request.headers?.[HeaderTypes.Accept] === MimeTypes.JsonLd ? "jsonld" : "json";
|
|
421
425
|
const component = ComponentFactory.get(componentName);
|
|
422
|
-
const result = await component.get(request.pathParams.id,
|
|
426
|
+
const result = await component.get(request.pathParams.id, {
|
|
427
|
+
includeContent: Coerce.boolean(request.query?.includeContent),
|
|
428
|
+
disableDecryption: Coerce.boolean(request.query?.disableDecryption),
|
|
429
|
+
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
430
|
+
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
423
431
|
return {
|
|
424
432
|
headers: {
|
|
425
433
|
[HeaderTypes.ContentType]: mimeType === "json" ? MimeTypes.Json : MimeTypes.JsonLd
|
|
@@ -439,7 +447,11 @@ async function blobStorageGetContent(httpRequestContext, componentName, request)
|
|
|
439
447
|
Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
440
448
|
Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
441
449
|
const component = ComponentFactory.get(componentName);
|
|
442
|
-
const result = await component.get(request.pathParams.id,
|
|
450
|
+
const result = await component.get(request.pathParams.id, {
|
|
451
|
+
includeContent: true,
|
|
452
|
+
disableDecryption: Coerce.boolean(request.query?.disableDecryption),
|
|
453
|
+
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
454
|
+
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
443
455
|
const encodingFormat = result?.encodingFormat ?? MimeTypes.OctetStream;
|
|
444
456
|
let filename = request.query?.filename;
|
|
445
457
|
if (!Is.stringValue(filename)) {
|
|
@@ -564,10 +576,10 @@ class BlobStorageService {
|
|
|
564
576
|
}
|
|
565
577
|
this._entryEntityStorage = EntityStorageConnectorFactory.get(options?.entryEntityStorageType ?? "blob-storage-entry");
|
|
566
578
|
if (Is.stringValue(options?.vaultConnectorType)) {
|
|
567
|
-
this._vaultConnector = VaultConnectorFactory.
|
|
579
|
+
this._vaultConnector = VaultConnectorFactory.get(options.vaultConnectorType);
|
|
568
580
|
}
|
|
569
581
|
this._defaultNamespace = options?.config?.defaultNamespace ?? names[0];
|
|
570
|
-
this._vaultKeyId = options?.config?.vaultKeyId
|
|
582
|
+
this._vaultKeyId = options?.config?.vaultKeyId;
|
|
571
583
|
this._includeNodeIdentity = options?.config?.includeNodeIdentity ?? true;
|
|
572
584
|
this._includeUserIdentity = options?.config?.includeUserIdentity ?? true;
|
|
573
585
|
SchemaOrgDataTypes.registerRedirects();
|
|
@@ -578,21 +590,27 @@ class BlobStorageService {
|
|
|
578
590
|
* @param encodingFormat Mime type for the blob, will be detected if left undefined.
|
|
579
591
|
* @param fileExtension Extension for the blob, will be detected if left undefined.
|
|
580
592
|
* @param metadata Data for the custom metadata as JSON-LD.
|
|
581
|
-
* @param
|
|
593
|
+
* @param options Optional options for the creation of the blob.
|
|
594
|
+
* @param options.disableEncryption Disables encryption if enabled by default.
|
|
595
|
+
* @param options.overrideVaultKeyId Use a different vault key id for encryption, if not provided the default vault key id will be used.
|
|
596
|
+
* @param options.namespace The namespace to use for storing, defaults to component configured namespace.
|
|
582
597
|
* @param userIdentity The user identity to use with storage operations.
|
|
583
598
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
584
599
|
* @returns The id of the stored blob in urn format.
|
|
585
600
|
*/
|
|
586
|
-
async create(blob, encodingFormat, fileExtension, metadata,
|
|
601
|
+
async create(blob, encodingFormat, fileExtension, metadata, options, userIdentity, nodeIdentity) {
|
|
587
602
|
Guards.stringBase64(this.CLASS_NAME, "blob", blob);
|
|
588
603
|
if (this._includeUserIdentity) {
|
|
589
604
|
Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
590
605
|
}
|
|
591
|
-
|
|
606
|
+
const disableEncryption = options?.disableEncryption ?? false;
|
|
607
|
+
const vaultKeyId = options?.overrideVaultKeyId ?? this._vaultKeyId;
|
|
608
|
+
const encryptionEnabled = !disableEncryption && Is.stringValue(vaultKeyId);
|
|
609
|
+
if (this._includeNodeIdentity || encryptionEnabled) {
|
|
592
610
|
Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
593
611
|
}
|
|
594
612
|
try {
|
|
595
|
-
const connectorNamespace = namespace ?? this._defaultNamespace;
|
|
613
|
+
const connectorNamespace = options?.namespace ?? this._defaultNamespace;
|
|
596
614
|
const blobStorageConnector = BlobStorageConnectorFactory.get(connectorNamespace);
|
|
597
615
|
// Convert the base64 data into bytes
|
|
598
616
|
let storeBlob = Converter.base64ToBytes(blob);
|
|
@@ -613,8 +631,11 @@ class BlobStorageService {
|
|
|
613
631
|
}
|
|
614
632
|
const blobHash = `sha256:${Converter.bytesToBase64(Sha256.sum256(storeBlob))}`;
|
|
615
633
|
// If we have a vault connector then encrypt the data.
|
|
616
|
-
if (
|
|
617
|
-
|
|
634
|
+
if (encryptionEnabled) {
|
|
635
|
+
if (Is.empty(this._vaultConnector)) {
|
|
636
|
+
throw new GeneralError(this.CLASS_NAME, "vaultConnectorNotConfigured");
|
|
637
|
+
}
|
|
638
|
+
storeBlob = await this._vaultConnector.encrypt(`${nodeIdentity}/${vaultKeyId}`, VaultEncryptionType.ChaCha20Poly1305, storeBlob);
|
|
618
639
|
}
|
|
619
640
|
// Set the blob in the storage connector, which may now be encrypted
|
|
620
641
|
const blobId = await blobStorageConnector.set(storeBlob);
|
|
@@ -626,7 +647,8 @@ class BlobStorageService {
|
|
|
626
647
|
blobHash,
|
|
627
648
|
encodingFormat,
|
|
628
649
|
fileExtension,
|
|
629
|
-
metadata
|
|
650
|
+
metadata,
|
|
651
|
+
isEncrypted: encryptionEnabled
|
|
630
652
|
};
|
|
631
653
|
const conditions = [];
|
|
632
654
|
if (this._includeUserIdentity) {
|
|
@@ -647,14 +669,21 @@ class BlobStorageService {
|
|
|
647
669
|
/**
|
|
648
670
|
* Get the blob entry.
|
|
649
671
|
* @param id The id of the blob to get in urn format.
|
|
650
|
-
* @param
|
|
672
|
+
* @param options Optional options for the retrieval of the blob.
|
|
673
|
+
* @param options.includeContent Include the content, or just get the metadata.
|
|
674
|
+
* @param options.disableDecryption Disables decryption if enabled by default.
|
|
675
|
+
* @param options.overrideVaultKeyId Use a different vault key id for decryption, if not provided the default vault key id will be used.
|
|
651
676
|
* @param userIdentity The user identity to use with storage operations.
|
|
652
677
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
653
678
|
* @returns The entry and data for the blob if it can be found.
|
|
654
679
|
* @throws Not found error if the blob cannot be found.
|
|
655
680
|
*/
|
|
656
|
-
async get(id,
|
|
681
|
+
async get(id, options, userIdentity, nodeIdentity) {
|
|
657
682
|
Urn.guard(this.CLASS_NAME, "id", id);
|
|
683
|
+
const includeContent = options?.includeContent ?? false;
|
|
684
|
+
const disableEncryption = options?.disableDecryption ?? false;
|
|
685
|
+
const vaultKeyId = options?.overrideVaultKeyId ?? this._vaultKeyId;
|
|
686
|
+
const decryptionEnabled = !disableEncryption && Is.stringValue(vaultKeyId);
|
|
658
687
|
const conditions = [];
|
|
659
688
|
if (this._includeUserIdentity) {
|
|
660
689
|
Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
@@ -682,8 +711,11 @@ class BlobStorageService {
|
|
|
682
711
|
throw new NotFoundError(this.CLASS_NAME, "blobNotFound", id);
|
|
683
712
|
}
|
|
684
713
|
// If we have a vault connector then decrypt the data.
|
|
685
|
-
if (
|
|
686
|
-
|
|
714
|
+
if (decryptionEnabled) {
|
|
715
|
+
if (Is.empty(this._vaultConnector)) {
|
|
716
|
+
throw new GeneralError(this.CLASS_NAME, "vaultConnectorNotConfigured");
|
|
717
|
+
}
|
|
718
|
+
returnBlob = await this._vaultConnector.decrypt(`${nodeIdentity}/${vaultKeyId}`, VaultEncryptionType.ChaCha20Poly1305, returnBlob);
|
|
687
719
|
}
|
|
688
720
|
}
|
|
689
721
|
const jsonLd = this.entryToJsonLd(blobEntry, returnBlob);
|
|
@@ -731,7 +763,8 @@ class BlobStorageService {
|
|
|
731
763
|
blobHash: blobEntry.blobHash,
|
|
732
764
|
encodingFormat: encodingFormat ?? blobEntry.encodingFormat,
|
|
733
765
|
fileExtension: fileExtension ?? blobEntry.fileExtension,
|
|
734
|
-
metadata: metadata ?? blobEntry.metadata
|
|
766
|
+
metadata: metadata ?? blobEntry.metadata,
|
|
767
|
+
isEncrypted: blobEntry.isEncrypted
|
|
735
768
|
};
|
|
736
769
|
const conditions = [];
|
|
737
770
|
if (this._includeUserIdentity) {
|
|
@@ -982,6 +1015,10 @@ let BlobStorageEntry = class BlobStorageEntry {
|
|
|
982
1015
|
* The metadata for the blob as JSON-LD.
|
|
983
1016
|
*/
|
|
984
1017
|
metadata;
|
|
1018
|
+
/**
|
|
1019
|
+
* Is the entry encrypted.
|
|
1020
|
+
*/
|
|
1021
|
+
isEncrypted;
|
|
985
1022
|
/**
|
|
986
1023
|
* The user identity that created the blob.
|
|
987
1024
|
*/
|
|
@@ -1028,6 +1065,10 @@ __decorate([
|
|
|
1028
1065
|
property({ type: "object", itemTypeRef: "IJsonLdNodeObject", optional: true }),
|
|
1029
1066
|
__metadata("design:type", Object)
|
|
1030
1067
|
], BlobStorageEntry.prototype, "metadata", void 0);
|
|
1068
|
+
__decorate([
|
|
1069
|
+
property({ type: "boolean" }),
|
|
1070
|
+
__metadata("design:type", Boolean)
|
|
1071
|
+
], BlobStorageEntry.prototype, "isEncrypted", void 0);
|
|
1031
1072
|
__decorate([
|
|
1032
1073
|
property({ type: "string", optional: true }),
|
|
1033
1074
|
__metadata("design:type", String)
|
|
@@ -25,22 +25,36 @@ export declare class BlobStorageService implements IBlobStorageComponent {
|
|
|
25
25
|
* @param encodingFormat Mime type for the blob, will be detected if left undefined.
|
|
26
26
|
* @param fileExtension Extension for the blob, will be detected if left undefined.
|
|
27
27
|
* @param metadata Data for the custom metadata as JSON-LD.
|
|
28
|
-
* @param
|
|
28
|
+
* @param options Optional options for the creation of the blob.
|
|
29
|
+
* @param options.disableEncryption Disables encryption if enabled by default.
|
|
30
|
+
* @param options.overrideVaultKeyId Use a different vault key id for encryption, if not provided the default vault key id will be used.
|
|
31
|
+
* @param options.namespace The namespace to use for storing, defaults to component configured namespace.
|
|
29
32
|
* @param userIdentity The user identity to use with storage operations.
|
|
30
33
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
31
34
|
* @returns The id of the stored blob in urn format.
|
|
32
35
|
*/
|
|
33
|
-
create(blob: string, encodingFormat?: string, fileExtension?: string, metadata?: IJsonLdNodeObject,
|
|
36
|
+
create(blob: string, encodingFormat?: string, fileExtension?: string, metadata?: IJsonLdNodeObject, options?: {
|
|
37
|
+
disableEncryption?: boolean;
|
|
38
|
+
overrideVaultKeyId?: string;
|
|
39
|
+
namespace?: string;
|
|
40
|
+
}, userIdentity?: string, nodeIdentity?: string): Promise<string>;
|
|
34
41
|
/**
|
|
35
42
|
* Get the blob entry.
|
|
36
43
|
* @param id The id of the blob to get in urn format.
|
|
37
|
-
* @param
|
|
44
|
+
* @param options Optional options for the retrieval of the blob.
|
|
45
|
+
* @param options.includeContent Include the content, or just get the metadata.
|
|
46
|
+
* @param options.disableDecryption Disables decryption if enabled by default.
|
|
47
|
+
* @param options.overrideVaultKeyId Use a different vault key id for decryption, if not provided the default vault key id will be used.
|
|
38
48
|
* @param userIdentity The user identity to use with storage operations.
|
|
39
49
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
40
50
|
* @returns The entry and data for the blob if it can be found.
|
|
41
51
|
* @throws Not found error if the blob cannot be found.
|
|
42
52
|
*/
|
|
43
|
-
get(id: string,
|
|
53
|
+
get(id: string, options?: {
|
|
54
|
+
includeContent?: boolean;
|
|
55
|
+
disableDecryption?: boolean;
|
|
56
|
+
overrideVaultKeyId?: string;
|
|
57
|
+
}, userIdentity?: string, nodeIdentity?: string): Promise<IBlobStorageEntry>;
|
|
44
58
|
/**
|
|
45
59
|
* Update the blob with metadata.
|
|
46
60
|
* @param id The id of the blob entry to update.
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export interface IBlobStorageServiceConfig {
|
|
5
5
|
/**
|
|
6
|
-
* The name of the vault key to use for encryption if
|
|
7
|
-
* @default blob-storage.
|
|
6
|
+
* The name of the vault key to use for encryption, if not configured no encryption will happen.
|
|
8
7
|
*/
|
|
9
8
|
vaultKeyId?: string;
|
|
10
9
|
/**
|
|
@@ -9,7 +9,7 @@ export interface IBlobStorageServiceConstructorOptions {
|
|
|
9
9
|
*/
|
|
10
10
|
entryEntityStorageType?: string;
|
|
11
11
|
/**
|
|
12
|
-
* The type of the vault connector for encryption
|
|
12
|
+
* The type of the vault connector for encryption.
|
|
13
13
|
*/
|
|
14
14
|
vaultConnectorType?: string;
|
|
15
15
|
/**
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @twin.org/blob-storage-service - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.1-next.35](https://github.com/twinfoundation/blob-storage/compare/blob-storage-service-v0.0.1-next.34...blob-storage-service-v0.0.1-next.35) (2025-06-17)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* additional encryption options on per item basis ([4b95a65](https://github.com/twinfoundation/blob-storage/commit/4b95a656d19e3b571cea905e36f29b679b13e1e8))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/blob-storage-models bumped from 0.0.1-next.34 to 0.0.1-next.35
|
|
16
|
+
* devDependencies
|
|
17
|
+
* @twin.org/blob-storage-connector-memory bumped from 0.0.1-next.34 to 0.0.1-next.35
|
|
18
|
+
|
|
19
|
+
## [0.0.1-next.34](https://github.com/twinfoundation/blob-storage/compare/blob-storage-service-v0.0.1-next.33...blob-storage-service-v0.0.1-next.34) (2025-06-12)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* update dependencies ([56f0094](https://github.com/twinfoundation/blob-storage/commit/56f0094b68d8bd22864cd899ac1b61d95540f719))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Dependencies
|
|
28
|
+
|
|
29
|
+
* The following workspace dependencies were updated
|
|
30
|
+
* dependencies
|
|
31
|
+
* @twin.org/blob-storage-models bumped from 0.0.1-next.33 to 0.0.1-next.34
|
|
32
|
+
* devDependencies
|
|
33
|
+
* @twin.org/blob-storage-connector-memory bumped from 0.0.1-next.33 to 0.0.1-next.34
|
|
34
|
+
|
|
3
35
|
## [0.0.1-next.33](https://github.com/twinfoundation/blob-storage/compare/blob-storage-service-v0.0.1-next.32...blob-storage-service-v0.0.1-next.33) (2025-06-03)
|
|
4
36
|
|
|
5
37
|
|