@solidxai/core 0.1.12-beta.8 → 0.1.12-beta.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.
- package/dist/entities/media.entity.d.ts +0 -1
- package/dist/entities/media.entity.d.ts.map +1 -1
- package/dist/entities/media.entity.js +1 -9
- package/dist/entities/media.entity.js.map +1 -1
- package/dist/repository/media.repository.d.ts.map +1 -1
- package/dist/repository/media.repository.js +0 -2
- package/dist/repository/media.repository.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +0 -39
- package/dist/services/media-download-url.service.d.ts +3 -2
- package/dist/services/media-download-url.service.d.ts.map +1 -1
- package/dist/services/media-download-url.service.js +6 -3
- package/dist/services/media-download-url.service.js.map +1 -1
- package/dist/services/media-storage.utils.d.ts +0 -3
- package/dist/services/media-storage.utils.d.ts.map +1 -1
- package/dist/services/media-storage.utils.js +2 -11
- package/dist/services/media-storage.utils.js.map +1 -1
- package/dist/services/media.service.d.ts.map +1 -1
- package/dist/services/media.service.js +3 -5
- package/dist/services/media.service.js.map +1 -1
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.d.ts.map +1 -1
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.js +2 -5
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
- package/dist/services/mediaStorageProviders/file-storage-provider.d.ts.map +1 -1
- package/dist/services/mediaStorageProviders/file-storage-provider.js +2 -5
- package/dist/services/mediaStorageProviders/file-storage-provider.js.map +1 -1
- package/package.json +1 -1
- package/src/entities/media.entity.ts +0 -3
- package/src/repository/media.repository.ts +1 -2
- package/src/seeders/seed-data/solid-core-metadata.json +0 -39
- package/src/services/media-download-url.service.ts +13 -6
- package/src/services/media-storage.utils.ts +6 -15
- package/src/services/media.service.ts +4 -6
- package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +6 -9
- package/src/services/mediaStorageProviders/file-storage-provider.ts +3 -6
|
@@ -4,7 +4,6 @@ import { MediaStorageProviderMetadata } from '../entities/media-storage-provider
|
|
|
4
4
|
import { FieldMetadata } from '../entities/field-metadata.entity';
|
|
5
5
|
export declare class Media extends CommonEntity {
|
|
6
6
|
entityId: number;
|
|
7
|
-
isPublic: boolean;
|
|
8
7
|
relativeUri: string;
|
|
9
8
|
fileSize: number;
|
|
10
9
|
mimeType: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.entity.d.ts","sourceRoot":"","sources":["../../src/entities/media.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAEzD,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,qDAAqD,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAA;AAClE,qBACa,KAAM,SAAQ,YAAY;IAGnC,QAAQ,EAAE,MAAM,CAAC;IAGjB,
|
|
1
|
+
{"version":3,"file":"media.entity.d.ts","sourceRoot":"","sources":["../../src/entities/media.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAEzD,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,qDAAqD,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAA;AAClE,qBACa,KAAM,SAAQ,YAAY;IAGnC,QAAQ,EAAE,MAAM,CAAC;IAGjB,WAAW,EAAE,MAAM,CAAC;IAIpB,QAAQ,EAAE,MAAM,CAAC;IAGjB,QAAQ,EAAE,MAAM,CAAC;IAGjB,gBAAgB,EAAE,MAAM,CAAC;IAKzB,aAAa,EAAE,aAAa,CAAC;IAK7B,4BAA4B,EAAE,4BAA4B,CAAC;IAK3D,aAAa,EAAE,aAAa,CAAC;CAChC"}
|
|
@@ -17,12 +17,8 @@ const model_metadata_entity_1 = require("./model-metadata.entity");
|
|
|
17
17
|
const media_storage_provider_metadata_entity_1 = require("./media-storage-provider-metadata.entity");
|
|
18
18
|
const field_metadata_entity_1 = require("./field-metadata.entity");
|
|
19
19
|
let Media = class Media extends common_entity_1.CommonEntity {
|
|
20
|
-
constructor() {
|
|
21
|
-
super(...arguments);
|
|
22
|
-
this.isPublic = true;
|
|
23
|
-
}
|
|
24
20
|
static _OPENAPI_METADATA_FACTORY() {
|
|
25
|
-
return { entityId: { required: true, type: () => Number },
|
|
21
|
+
return { entityId: { required: true, type: () => Number }, relativeUri: { required: true, type: () => String }, fileSize: { required: true, type: () => Number }, mimeType: { required: true, type: () => String }, originalFileName: { required: true, type: () => String }, modelMetadata: { required: true, type: () => require("./model-metadata.entity").ModelMetadata }, mediaStorageProviderMetadata: { required: true, type: () => require("./media-storage-provider-metadata.entity").MediaStorageProviderMetadata }, fieldMetadata: { required: true, type: () => require("./field-metadata.entity").FieldMetadata } };
|
|
26
22
|
}
|
|
27
23
|
};
|
|
28
24
|
exports.Media = Media;
|
|
@@ -31,10 +27,6 @@ __decorate([
|
|
|
31
27
|
(0, typeorm_1.Column)({ type: "integer" }),
|
|
32
28
|
__metadata("design:type", Number)
|
|
33
29
|
], Media.prototype, "entityId", void 0);
|
|
34
|
-
__decorate([
|
|
35
|
-
(0, typeorm_1.Column)({ name: "is_public", default: true }),
|
|
36
|
-
__metadata("design:type", Boolean)
|
|
37
|
-
], Media.prototype, "isPublic", void 0);
|
|
38
30
|
__decorate([
|
|
39
31
|
(0, typeorm_1.Column)({ type: "varchar", nullable: true }),
|
|
40
32
|
__metadata("design:type", String)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.entity.js","sourceRoot":"","sources":["../../src/entities/media.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,mDAAyD;AACzD,qCAAuE;AACvE,mEAAmE;AACnE,qGAAmG;AACnG,mEAAkE;AAE3D,IAAM,KAAK,GAAX,MAAM,KAAM,SAAQ,4BAAY
|
|
1
|
+
{"version":3,"file":"media.entity.js","sourceRoot":"","sources":["../../src/entities/media.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,mDAAyD;AACzD,qCAAuE;AACvE,mEAAmE;AACnE,qGAAmG;AACnG,mEAAkE;AAE3D,IAAM,KAAK,GAAX,MAAM,KAAM,SAAQ,4BAAY;;;;CAgCtC,CAAA;AAhCY,sBAAK;AAGd;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;uCACX;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;0CACxB;AAIpB;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;uCAC3B;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;uCAC3B;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACnB;AAKzB;IAHC,IAAA,eAAK,GAAE;IACP,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,qCAAa,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACnD,IAAA,oBAAU,GAAE;8BACE,qCAAa;4CAAC;AAK7B;IAHC,IAAA,eAAK,GAAE;IACP,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,qEAA4B,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClE,IAAA,oBAAU,GAAE;8BACiB,qEAA4B;2DAAC;AAK3D;IAHC,IAAA,eAAK,GAAE;IACP,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,qCAAa,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACnD,IAAA,oBAAU,GAAE;8BACE,qCAAa;4CAAC;gBA/BpB,KAAK;IADjB,IAAA,gBAAM,EAAC,UAAU,CAAC;GACN,KAAK,CAgCjB","sourcesContent":["import { CommonEntity } from 'src/entities/common.entity'\nimport { Entity, Column, Index, JoinColumn, ManyToOne } from 'typeorm';\nimport { ModelMetadata } from 'src/entities/model-metadata.entity';\nimport { MediaStorageProviderMetadata } from 'src/entities/media-storage-provider-metadata.entity';\nimport { FieldMetadata } from 'src/entities/field-metadata.entity'\n@Entity(\"ss_media\")\nexport class Media extends CommonEntity {\n @Index()\n @Column({ type: \"integer\" })\n entityId: number;\n\n @Column({ type: \"varchar\", nullable: true })\n relativeUri: string;\n\n @Index()\n @Column({ type: \"integer\", nullable: true })\n fileSize: number;\n\n @Column({ type: \"varchar\", nullable: true })\n mimeType: string;\n\n @Column({ type: \"varchar\", nullable: true })\n originalFileName: string;\n\n @Index()\n @ManyToOne(() => ModelMetadata, { nullable: false })\n @JoinColumn()\n modelMetadata: ModelMetadata;\n\n @Index()\n @ManyToOne(() => MediaStorageProviderMetadata, { nullable: false })\n @JoinColumn()\n mediaStorageProviderMetadata: MediaStorageProviderMetadata;\n\n @Index()\n @ManyToOne(() => FieldMetadata, { nullable: false })\n @JoinColumn()\n fieldMetadata: FieldMetadata;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.repository.d.ts","sourceRoot":"","sources":["../../src/repository/media.repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAM,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,sCAAsC,EAAE,MAAM,8CAA8C,CAAC;AACtG,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"media.repository.d.ts","sourceRoot":"","sources":["../../src/repository/media.repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAM,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,sCAAsC,EAAE,MAAM,8CAA8C,CAAC;AACtG,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,qBACa,eAAgB,SAAQ,mBAAmB,CAAC,KAAK,CAAC;IAEvD,QAAQ,CAAC,UAAU,EAAE,UAAU;IAC/B,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IACrD,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB;IAOvD,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,gCAAgC;gBAZxC,UAAU,EAAE,UAAU,EACtB,qBAAqB,EAAE,qBAAqB,EAC5C,sBAAsB,EAAE,sBAAsB,EAOtC,iBAAiB,EAAE,uBAAuB,EAE1C,iBAAiB,EAAE,uBAAuB,EAC1C,gCAAgC,EAAE,sCAAsC;IAKvF,WAAW,CAAC,SAAS,EAAE,GAAG;IAqB1B,0CAA0C,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,KAAK;IAe7H,4CAA4C,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM;CAexH"}
|
|
@@ -22,7 +22,6 @@ const media_storage_provider_metadata_repository_1 = require("./media-storage-pr
|
|
|
22
22
|
const model_metadata_repository_1 = require("./model-metadata.repository");
|
|
23
23
|
const security_rule_repository_1 = require("./security-rule.repository");
|
|
24
24
|
const solid_base_repository_1 = require("./solid-base.repository");
|
|
25
|
-
const media_storage_utils_1 = require("../services/media-storage.utils");
|
|
26
25
|
let MediaRepository = class MediaRepository extends solid_base_repository_1.SolidBaseRepository {
|
|
27
26
|
constructor(dataSource, requestContextService, securityRuleRepository, fieldMetadataRepo, modelMetadataRepo, mediaStorageProviderMetadataRepo) {
|
|
28
27
|
super(media_entity_1.Media, dataSource, requestContextService, securityRuleRepository);
|
|
@@ -49,7 +48,6 @@ let MediaRepository = class MediaRepository extends solid_base_repository_1.Soli
|
|
|
49
48
|
id: createDto['mediaStorageProviderMetadataId']
|
|
50
49
|
},
|
|
51
50
|
});
|
|
52
|
-
createDto['isPublic'] = (0, media_storage_utils_1.resolveStoredMediaIsPublic)(createDto['isPublic'], createDto['mediaStorageProviderMetadata']);
|
|
53
51
|
const media = this.create(createDto);
|
|
54
52
|
return this.save(media);
|
|
55
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.repository.js","sourceRoot":"","sources":["../../src/repository/media.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAgE;AAChE,2DAAkD;AAClD,iFAA6E;AAC7E,qCAAyC;AACzC,2EAAsE;AACtE,6GAAsG;AACtG,2EAAsE;AACtE,yEAAoE;AACpE,mEAA8D;
|
|
1
|
+
{"version":3,"file":"media.repository.js","sourceRoot":"","sources":["../../src/repository/media.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAgE;AAChE,2DAAkD;AAClD,iFAA6E;AAC7E,qCAAyC;AACzC,2EAAsE;AACtE,6GAAsG;AACtG,2EAAsE;AACtE,yEAAoE;AACpE,mEAA8D;AAGvD,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,2CAA0B;IAC3D,YACa,UAAsB,EACtB,qBAA4C,EAC5C,sBAA8C,EAOtC,iBAA0C,EAE1C,iBAA0C,EAC1C,gCAAwE;QAEzF,KAAK,CAAC,oBAAK,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,CAAC,CAAC;QAd/D,eAAU,GAAV,UAAU,CAAY;QACtB,0BAAqB,GAArB,qBAAqB,CAAuB;QAC5C,2BAAsB,GAAtB,sBAAsB,CAAwB;QAOtC,sBAAiB,GAAjB,iBAAiB,CAAyB;QAE1C,sBAAiB,GAAjB,iBAAiB,CAAyB;QAC1C,qCAAgC,GAAhC,gCAAgC,CAAwC;IAG7F,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,SAAc;QAC5B,SAAS,CAAC,eAAe,CAAC,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC;YAC9D,KAAK,EAAE;gBACH,EAAE,EAAE,SAAS,CAAC,iBAAiB,CAAC;aACnC;SACJ,CAAC,CAAC;QACH,SAAS,CAAC,eAAe,CAAC,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC;YAC9D,KAAK,EAAE;gBACH,EAAE,EAAE,SAAS,CAAC,iBAAiB,CAAC;aACnC;SACJ,CAAC,CAAC;QACH,SAAS,CAAC,8BAA8B,CAAC,GAAG,MAAM,IAAI,CAAC,gCAAgC,CAAC,OAAO,CAAC;YAC5F,KAAK,EAAE;gBACH,EAAE,EAAE,SAAS,CAAC,gCAAgC,CAAC;aAClD;SACJ,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,0CAA0C,CAAC,QAAgB,EAAE,eAAuB,EAAE,eAAuB,EAAE,SAAS,GAAG,EAAE;QAC/H,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC;YACnB,KAAK,EAAE;gBACH,aAAa,EAAE;oBACX,EAAE,EAAE,eAAe;iBACtB;gBACD,aAAa,EAAE;oBACX,EAAE,EAAE,eAAe;iBACtB;gBACD,QAAQ,EAAE,QAAQ;aACrB;YACD,SAAS,EAAE,SAAS;SACvB,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,4CAA4C,CAAC,QAAgB,EAAE,eAAuB,EAAE,eAAuB;QACjH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC;YAC7B,KAAK,EAAE;gBACH,aAAa,EAAE;oBACX,EAAE,EAAE,eAAe;iBACtB;gBACD,aAAa,EAAE;oBACX,EAAE,EAAE,eAAe;iBACtB;gBACD,QAAQ,EAAE,QAAQ;aACrB;SACJ,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;CAEJ,CAAA;AAtEY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;IAaJ,WAAA,IAAA,eAAM,EAAC,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,mDAAuB,CAAC,CAAC,CAAA;qCAV7B,oBAAU;QACC,+CAAqB;QACpB,iDAAsB;QAOnB,mDAAuB;QAEvB,mDAAuB;QACR,mFAAsC;GAdpF,eAAe,CAsE3B","sourcesContent":["import { forwardRef, Inject, Injectable } from '@nestjs/common';\nimport { Media } from 'src/entities/media.entity';\nimport { RequestContextService } from 'src/services/request-context.service';\nimport { DataSource, In } from 'typeorm';\nimport { FieldMetadataRepository } from './field-metadata.repository';\nimport { MediaStorageProviderMetadataRepository } from './media-storage-provider-metadata.repository';\nimport { ModelMetadataRepository } from './model-metadata.repository';\nimport { SecurityRuleRepository } from './security-rule.repository';\nimport { SolidBaseRepository } from './solid-base.repository';\n\n@Injectable()\nexport class MediaRepository extends SolidBaseRepository<Media> {\n constructor(\n readonly dataSource: DataSource,\n readonly requestContextService: RequestContextService,\n readonly securityRuleRepository: SecurityRuleRepository,\n // @InjectRepository(FieldMetadata)\n // private readonly fieldMetadataRepo: Repository<FieldMetadata>,\n // @InjectRepository(ModelMetadata)\n // private readonly modelMetadataRepo: Repository<ModelMetadata>,\n // @InjectRepository(MediaStorageProviderMetadata)\n // private readonly mediaStorageProviderMetadataRepo: Repository<MediaStorageProviderMetadata>,\n private readonly fieldMetadataRepo: FieldMetadataRepository,\n @Inject(forwardRef(() => ModelMetadataRepository))\n private readonly modelMetadataRepo: ModelMetadataRepository,\n private readonly mediaStorageProviderMetadataRepo: MediaStorageProviderMetadataRepository,\n ) {\n super(Media, dataSource, requestContextService, securityRuleRepository);\n }\n\n async createMedia(createDto: any) {\n createDto['fieldMetadata'] = await this.fieldMetadataRepo.findOne({\n where: {\n id: createDto['fieldMetadataId']\n },\n });\n createDto['modelMetadata'] = await this.modelMetadataRepo.findOne({\n where: {\n id: createDto['modelMetadataId']\n },\n });\n createDto['mediaStorageProviderMetadata'] = await this.mediaStorageProviderMetadataRepo.findOne({\n where: {\n id: createDto['mediaStorageProviderMetadataId']\n },\n });\n // delete createDto['isPublic'];\n const media = this.create(createDto);\n return this.save(media);\n }\n\n async findByEntityIdAndFieldIdAndModelMetadataId(entityId: number, fieldMetadataId: number, modelMetadataId: number, relations = {}) {\n return await this.find({\n where: {\n modelMetadata: {\n id: modelMetadataId\n },\n fieldMetadata: {\n id: fieldMetadataId\n },\n entityId: entityId,\n },\n relations: relations,\n });\n }\n\n async deleteByEntityIdAndFieldIdAndModelMetadataId(entityId: number, fieldMetadataId: number, modelMetadataId: number) {\n const entities = await this.find({\n where: {\n modelMetadata: {\n id: modelMetadataId\n },\n fieldMetadata: {\n id: fieldMetadataId\n },\n entityId: entityId,\n }\n });\n return this.remove(entities);\n }\n\n}\n"]}
|
|
@@ -1704,18 +1704,6 @@
|
|
|
1704
1704
|
"columnName": "original_file_name",
|
|
1705
1705
|
"isSystem": true
|
|
1706
1706
|
},
|
|
1707
|
-
{
|
|
1708
|
-
"name": "isPublic",
|
|
1709
|
-
"displayName": "Is Public",
|
|
1710
|
-
"type": "boolean",
|
|
1711
|
-
"required": false,
|
|
1712
|
-
"unique": false,
|
|
1713
|
-
"index": false,
|
|
1714
|
-
"private": false,
|
|
1715
|
-
"encrypt": false,
|
|
1716
|
-
"columnName": "is_public",
|
|
1717
|
-
"isSystem": true
|
|
1718
|
-
},
|
|
1719
1707
|
{
|
|
1720
1708
|
"name": "modelMetadata",
|
|
1721
1709
|
"displayName": "Model Metadata",
|
|
@@ -8789,13 +8777,6 @@
|
|
|
8789
8777
|
"sortable": false
|
|
8790
8778
|
}
|
|
8791
8779
|
},
|
|
8792
|
-
{
|
|
8793
|
-
"type": "field",
|
|
8794
|
-
"attrs": {
|
|
8795
|
-
"name": "isPublic",
|
|
8796
|
-
"sortable": true
|
|
8797
|
-
}
|
|
8798
|
-
},
|
|
8799
8780
|
{
|
|
8800
8781
|
"type": "field",
|
|
8801
8782
|
"attrs": {
|
|
@@ -8891,14 +8872,6 @@
|
|
|
8891
8872
|
"isSearchable": true
|
|
8892
8873
|
}
|
|
8893
8874
|
},
|
|
8894
|
-
{
|
|
8895
|
-
"type": "field",
|
|
8896
|
-
"attrs": {
|
|
8897
|
-
"name": "isPublic",
|
|
8898
|
-
"label": "isPublic",
|
|
8899
|
-
"isSearchable": true
|
|
8900
|
-
}
|
|
8901
|
-
},
|
|
8902
8875
|
{
|
|
8903
8876
|
"type": "field",
|
|
8904
8877
|
"attrs": {
|
|
@@ -8967,12 +8940,6 @@
|
|
|
8967
8940
|
"name": "mediaStorageProviderMetadata"
|
|
8968
8941
|
}
|
|
8969
8942
|
},
|
|
8970
|
-
{
|
|
8971
|
-
"type": "field",
|
|
8972
|
-
"attrs": {
|
|
8973
|
-
"name": "isPublic"
|
|
8974
|
-
}
|
|
8975
|
-
},
|
|
8976
8943
|
{
|
|
8977
8944
|
"type": "field",
|
|
8978
8945
|
"attrs": {
|
|
@@ -14581,12 +14548,6 @@
|
|
|
14581
14548
|
"isPublic": true,
|
|
14582
14549
|
"localPath": "media-files-storage"
|
|
14583
14550
|
},
|
|
14584
|
-
{
|
|
14585
|
-
"name": "private-filesystem",
|
|
14586
|
-
"type": "filesystem",
|
|
14587
|
-
"isPublic": false,
|
|
14588
|
-
"localPath": "media-private-files-storage"
|
|
14589
|
-
},
|
|
14590
14551
|
{
|
|
14591
14552
|
"name": "default-aws-s3",
|
|
14592
14553
|
"type": "aws-s3"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ConfigService } from '@nestjs/config';
|
|
2
1
|
import { JwtService } from '@nestjs/jwt';
|
|
3
2
|
import { MediaStorageProviderMetadata } from '../entities/media-storage-provider-metadata.entity';
|
|
4
|
-
import { S3FileService } from '../services/file';
|
|
5
3
|
import { SettingService } from '../services/setting.service';
|
|
4
|
+
import { ConfigService } from '@nestjs/config';
|
|
5
|
+
import { S3FileService } from './file';
|
|
6
6
|
export declare const MEDIA_DOWNLOAD_TOKEN_AUDIENCE = "media-download";
|
|
7
7
|
export interface MediaDownloadTokenPayload {
|
|
8
8
|
mediaId: number;
|
|
@@ -15,6 +15,7 @@ export declare class MediaDownloadUrlService {
|
|
|
15
15
|
private readonly logger;
|
|
16
16
|
constructor(jwtService: JwtService, s3FileService: S3FileService, settingService: SettingService, configService: ConfigService);
|
|
17
17
|
resolveDownloadUrl(mediaId: number, relativeUri: string, storageProvider?: MediaStorageProviderMetadata): Promise<string>;
|
|
18
|
+
getPrivateUrl(mediaId: number, relativeUri: string, storageProvider?: MediaStorageProviderMetadata): Promise<string>;
|
|
18
19
|
verifyDownloadToken(token: string): Promise<MediaDownloadTokenPayload>;
|
|
19
20
|
private mintDownloadToken;
|
|
20
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-download-url.service.d.ts","sourceRoot":"","sources":["../../src/services/media-download-url.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"media-download-url.service.d.ts","sourceRoot":"","sources":["../../src/services/media-download-url.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,4BAA4B,EAAE,MAAM,qDAAqD,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAG9D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,eAAO,MAAM,6BAA6B,mBAAmB,CAAC;AAG9D,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBACa,uBAAuB;IAIhC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa;IANhC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;gBAGhD,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,aAAa;IAGzC,kBAAkB,CACtB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,4BAA4B,GAC7C,OAAO,CAAC,MAAM,CAAC;IAsBZ,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,4BAA4B,GAAG,OAAO,CAAC,MAAM,CAAC;IAIpH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAO5E,OAAO,CAAC,iBAAiB;CAQ1B"}
|
|
@@ -12,12 +12,12 @@ var MediaDownloadUrlService_1;
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.MediaDownloadUrlService = exports.MEDIA_DOWNLOAD_TOKEN_AUDIENCE = void 0;
|
|
14
14
|
const common_1 = require("@nestjs/common");
|
|
15
|
-
const config_1 = require("@nestjs/config");
|
|
16
15
|
const jwt_1 = require("@nestjs/jwt");
|
|
17
16
|
const create_media_storage_provider_metadata_dto_1 = require("../dtos/create-media-storage-provider-metadata.dto");
|
|
18
|
-
const file_1 = require("./file");
|
|
19
|
-
const media_storage_utils_1 = require("./media-storage.utils");
|
|
20
17
|
const setting_service_1 = require("./setting.service");
|
|
18
|
+
const media_storage_utils_1 = require("./media-storage.utils");
|
|
19
|
+
const config_1 = require("@nestjs/config");
|
|
20
|
+
const file_1 = require("./file");
|
|
21
21
|
exports.MEDIA_DOWNLOAD_TOKEN_AUDIENCE = 'media-download';
|
|
22
22
|
const DEFAULT_SIGNED_URL_EXPIRY_MINUTES = 60;
|
|
23
23
|
let MediaDownloadUrlService = MediaDownloadUrlService_1 = class MediaDownloadUrlService {
|
|
@@ -41,6 +41,9 @@ let MediaDownloadUrlService = MediaDownloadUrlService_1 = class MediaDownloadUrl
|
|
|
41
41
|
const baseUrl = this.settingService.getConfigValue('baseUrl');
|
|
42
42
|
return `${String(baseUrl).replace(/\/+$/, '')}${downloadPath}`;
|
|
43
43
|
}
|
|
44
|
+
async getPrivateUrl(mediaId, relativeUri, storageProvider) {
|
|
45
|
+
return this.resolveDownloadUrl(mediaId, relativeUri, storageProvider);
|
|
46
|
+
}
|
|
44
47
|
async verifyDownloadToken(token) {
|
|
45
48
|
return this.jwtService.verifyAsync(token, {
|
|
46
49
|
secret: this.settingService.getConfigValue('secret'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-download-url.service.js","sourceRoot":"","sources":["../../src/services/media-download-url.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,
|
|
1
|
+
{"version":3,"file":"media-download-url.service.js","sourceRoot":"","sources":["../../src/services/media-download-url.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,qCAAyC;AACzC,mHAA+F;AAE/F,uDAA8D;AAE9D,+DAA6D;AAC7D,2CAA+C;AAC/C,iCAAuC;AAE1B,QAAA,6BAA6B,GAAG,gBAAgB,CAAC;AAC9D,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAOtC,IAAM,uBAAuB,+BAA7B,MAAM,uBAAuB;IAGlC,YACmB,UAAsB,EACtB,aAA4B,EAC5B,cAA8B,EAC9B,aAA4B;QAH5B,eAAU,GAAV,UAAU,CAAY;QACtB,kBAAa,GAAb,aAAa,CAAe;QAC5B,mBAAc,GAAd,cAAc,CAAgB;QAC9B,kBAAa,GAAb,aAAa,CAAe;QAN9B,WAAM,GAAG,IAAI,eAAM,CAAC,yBAAuB,CAAC,IAAI,CAAC,CAAC;IAO/D,CAAC;IAEL,KAAK,CAAC,kBAAkB,CACtB,OAAe,EACf,WAAmB,EACnB,eAA8C;QAE9C,MAAM,aAAa,GAAG,eAAe,EAAE,eAAe,IAAI,iCAAiC,CAAC;QAE1F,IAAK,eAAe,EAAE,IAAiC,KAAK,qEAAwB,CAAC,KAAK,EAAE,CAAC;YAC7F,IAAI,eAAe,EAAE,UAAU,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAC9B,GAAG,eAAe,CAAC,UAAU,IAAI,WAAW,EAAE,EAC9C,EAAE,MAAM,EAAE,IAAA,0CAAoB,EAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,aAAa,GAAG,EAAE,EAAE,CAC5G,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,OAAO,2EAA2E,CAAC,CAAC;QACnH,CAAC;QAKD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACnE,MAAM,YAAY,GAAG,cAAc,OAAO,mBAAmB,KAAK,EAAE,CAAC;QACrE,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAmB,SAAS,CAAC,CAAC;QAChF,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAe,EAAE,WAAmB,EAAE,eAA8C;QACtG,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,KAAa;QACrC,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,CAA4B,KAAK,EAAE;YACnE,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,cAAc,CAAmB,QAAQ,CAAC;YACtE,QAAQ,EAAE,qCAA6B;SACxC,CAAC,CAAC;IACL,CAAC;IAEO,iBAAiB,CAAC,OAAe,EAAE,aAAqB;QAC9D,MAAM,OAAO,GAA8B,EAAE,OAAO,EAAE,CAAC;QACvD,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,EAAE;YACxC,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,cAAc,CAAmB,QAAQ,CAAC;YACtE,QAAQ,EAAE,qCAA6B;YACvC,SAAS,EAAE,aAAa,GAAG,EAAE;SAC9B,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAvDY,0DAAuB;kCAAvB,uBAAuB;IADnC,IAAA,mBAAU,GAAE;qCAKoB,gBAAU;QACP,oBAAa;QACZ,gCAAc;QACf,sBAAa;GAPpC,uBAAuB,CAuDnC","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { JwtService } from '@nestjs/jwt';\nimport { MediaStorageProviderType } from 'src/dtos/create-media-storage-provider-metadata.dto';\nimport { MediaStorageProviderMetadata } from 'src/entities/media-storage-provider-metadata.entity';\nimport { SettingService } from 'src/services/setting.service';\nimport type { SolidCoreSetting } from 'src/services/settings/default-settings-provider.service';\nimport { getEffectiveS3Region } from './media-storage.utils';\nimport { ConfigService } from '@nestjs/config';\nimport { S3FileService } from './file';\n\nexport const MEDIA_DOWNLOAD_TOKEN_AUDIENCE = 'media-download';\nconst DEFAULT_SIGNED_URL_EXPIRY_MINUTES = 60;\n\nexport interface MediaDownloadTokenPayload {\n mediaId: number;\n}\n\n@Injectable()\nexport class MediaDownloadUrlService {\n private readonly logger = new Logger(MediaDownloadUrlService.name);\n\n constructor(\n private readonly jwtService: JwtService,\n private readonly s3FileService: S3FileService,\n private readonly settingService: SettingService,\n private readonly configService: ConfigService,\n ) { }\n\n async resolveDownloadUrl(\n mediaId: number,\n relativeUri: string,\n storageProvider?: MediaStorageProviderMetadata,\n ): Promise<string> {\n const expiryMinutes = storageProvider?.signedUrlExpiry ?? DEFAULT_SIGNED_URL_EXPIRY_MINUTES;\n\n if ((storageProvider?.type as MediaStorageProviderType) === MediaStorageProviderType.AwsS3) {\n if (storageProvider?.bucketName) {\n return this.s3FileService.getUrl(\n `${storageProvider.bucketName}:${relativeUri}`,\n { region: getEffectiveS3Region(this.configService, storageProvider.region), expiresIn: expiryMinutes * 60 },\n );\n }\n this.logger.warn(`Media id ${mediaId}: AwsS3 provider missing bucketName; falling back to app-hosted token URL`);\n }\n // Filesystem (or misconfigured S3) has no native presigned-URL mechanism, so mint our\n // own short-lived token and embed it in the download URL - the token alone authorizes\n // the request (see MediaSignedUrlGuard), so it works in a plain <img src> with no\n // Authorization header needed.\n const token = await this.mintDownloadToken(mediaId, expiryMinutes);\n const downloadPath = `/api/media/${mediaId}/download?token=${token}`;\n const baseUrl = this.settingService.getConfigValue<SolidCoreSetting>('baseUrl');\n return `${String(baseUrl).replace(/\\/+$/, '')}${downloadPath}`;\n }\n\n async getPrivateUrl(mediaId: number, relativeUri: string, storageProvider?: MediaStorageProviderMetadata): Promise<string> {\n return this.resolveDownloadUrl(mediaId, relativeUri, storageProvider);\n }\n\n async verifyDownloadToken(token: string): Promise<MediaDownloadTokenPayload> {\n return this.jwtService.verifyAsync<MediaDownloadTokenPayload>(token, {\n secret: this.settingService.getConfigValue<SolidCoreSetting>('secret'),\n audience: MEDIA_DOWNLOAD_TOKEN_AUDIENCE,\n });\n }\n\n private mintDownloadToken(mediaId: number, expiryMinutes: number): Promise<string> {\n const payload: MediaDownloadTokenPayload = { mediaId };\n return this.jwtService.signAsync(payload, {\n secret: this.settingService.getConfigValue<SolidCoreSetting>('secret'),\n audience: MEDIA_DOWNLOAD_TOKEN_AUDIENCE,\n expiresIn: expiryMinutes * 60,\n });\n }\n}\n"]}
|
|
@@ -2,7 +2,6 @@ import { ConfigService } from '@nestjs/config';
|
|
|
2
2
|
import { FieldMetadata } from '../entities/field-metadata.entity';
|
|
3
3
|
import { MediaStorageProviderMetadata } from '../entities/media-storage-provider-metadata.entity';
|
|
4
4
|
import { SettingService } from '../services/setting.service';
|
|
5
|
-
export declare const DEFAULT_PRIVATE_MEDIA_STORAGE_DIR = "media-private-files-storage";
|
|
6
5
|
export interface MediaRecordCreateInput {
|
|
7
6
|
entityId: number;
|
|
8
7
|
modelMetadataId: number;
|
|
@@ -12,13 +11,11 @@ export interface MediaRecordCreateInput {
|
|
|
12
11
|
mimeType?: string;
|
|
13
12
|
fileSize?: number;
|
|
14
13
|
originalFileName?: string;
|
|
15
|
-
isPublic?: boolean;
|
|
16
14
|
}
|
|
17
15
|
export declare function buildStoredMediaFileName(file: Pick<Express.Multer.File, 'filename' | 'originalname'>): string;
|
|
18
16
|
export declare function buildDiskMediaPath(fileName: string, settingService: Pick<SettingService, 'getConfigValue'>, storageProvider?: Pick<MediaStorageProviderMetadata, 'localPath' | 'isPublic'>): string;
|
|
19
17
|
export declare function getEffectiveS3Region(configService: Pick<ConfigService, 'get'>, providerRegion?: string): string | undefined;
|
|
20
18
|
export declare function resolveMediaIsPublic(storageProvider?: Pick<MediaStorageProviderMetadata, 'isPublic'>): boolean | undefined;
|
|
21
|
-
export declare function resolveStoredMediaIsPublic(currentValue: boolean | undefined, storageProvider?: Pick<MediaStorageProviderMetadata, 'isPublic'>): boolean | undefined;
|
|
22
19
|
export declare function buildMediaRecordCreateInput(entityId: number, mediaFieldMetadata: Pick<FieldMetadata, 'id' | 'model'> & {
|
|
23
20
|
model: {
|
|
24
21
|
id: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-storage.utils.d.ts","sourceRoot":"","sources":["../../src/services/media-storage.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,qDAAqD,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"media-storage.utils.d.ts","sourceRoot":"","sources":["../../src/services/media-storage.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,qDAAqD,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAK9D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,8BAA8B,EAAE,MAAM,CAAC;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAGD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,CAAC,GAAG,MAAM,CAE7G;AAGD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAC,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,EAAC,eAAe,CAAC,EAAE,IAAI,CAAC,4BAA4B,EAAE,WAAW,GAAG,UAAU,CAAC,GAAI,MAAM,CAYlM;AAGD,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE3H;AAGD,wBAAgB,oBAAoB,CAAC,eAAe,CAAC,EAAE,IAAI,CAAC,4BAA4B,EAAE,UAAU,CAAC,GAAG,OAAO,GAAG,SAAS,CAM1H;AAGD,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,kBAAkB,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG;IAAE,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EACnF,eAAe,EAAE,IAAI,CAAC,4BAA4B,EAAE,IAAI,CAAC,EACzD,SAAS,EAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,GAClD,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,UAAU,GAAG,iBAAiB,GAAG,gCAAgC,GAAG,iBAAiB,GAAG,aAAa,CAAC,CAAC,GAC/I,sBAAsB,CAQxB"}
|
|
@@ -33,23 +33,20 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.DEFAULT_PRIVATE_MEDIA_STORAGE_DIR = void 0;
|
|
37
36
|
exports.buildStoredMediaFileName = buildStoredMediaFileName;
|
|
38
37
|
exports.buildDiskMediaPath = buildDiskMediaPath;
|
|
39
38
|
exports.getEffectiveS3Region = getEffectiveS3Region;
|
|
40
39
|
exports.resolveMediaIsPublic = resolveMediaIsPublic;
|
|
41
|
-
exports.resolveStoredMediaIsPublic = resolveStoredMediaIsPublic;
|
|
42
40
|
exports.buildMediaRecordCreateInput = buildMediaRecordCreateInput;
|
|
43
41
|
const path = __importStar(require("path"));
|
|
44
42
|
const default_settings_provider_service_1 = require("./settings/default-settings-provider.service");
|
|
45
|
-
exports.DEFAULT_PRIVATE_MEDIA_STORAGE_DIR = 'media-private-files-storage';
|
|
46
43
|
function buildStoredMediaFileName(file) {
|
|
47
44
|
return `${file.filename}-${file.originalname}`;
|
|
48
45
|
}
|
|
49
46
|
function buildDiskMediaPath(fileName, settingService, storageProvider) {
|
|
50
47
|
const publicBase = settingService.getConfigValue('fileStorageDir') || default_settings_provider_service_1.DEFAULT_MEDIA_FILE_STORAGE_DIR;
|
|
51
|
-
const privateBase =
|
|
52
|
-
const providerBase = storageProvider?.
|
|
48
|
+
const privateBase = `${publicBase}-private`;
|
|
49
|
+
const providerBase = storageProvider?.isPublic === false ? privateBase : publicBase;
|
|
53
50
|
if (path.isAbsolute(fileName) || fileName.startsWith(`${publicBase}/`) || fileName.startsWith(`${privateBase}/`) || (!!storageProvider?.localPath && fileName.startsWith(`${storageProvider.localPath}/`))) {
|
|
54
51
|
return fileName;
|
|
55
52
|
}
|
|
@@ -64,12 +61,6 @@ function resolveMediaIsPublic(storageProvider) {
|
|
|
64
61
|
}
|
|
65
62
|
return storageProvider.isPublic !== false;
|
|
66
63
|
}
|
|
67
|
-
function resolveStoredMediaIsPublic(currentValue, storageProvider) {
|
|
68
|
-
if (typeof currentValue === 'boolean') {
|
|
69
|
-
return currentValue;
|
|
70
|
-
}
|
|
71
|
-
return resolveMediaIsPublic(storageProvider);
|
|
72
|
-
}
|
|
73
64
|
function buildMediaRecordCreateInput(entityId, mediaFieldMetadata, storageProvider, overrides) {
|
|
74
65
|
return {
|
|
75
66
|
entityId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-storage.utils.js","sourceRoot":"","sources":["../../src/services/media-storage.utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"media-storage.utils.js","sourceRoot":"","sources":["../../src/services/media-storage.utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,4DAEC;AAGD,gDAYC;AAGD,oDAEC;AAGD,oDAMC;AAGD,kEAcC;AApED,2CAA6B;AAI7B,oGAAyG;AAgBzG,SAAgB,wBAAwB,CAAC,IAA4D;IACnG,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;AACjD,CAAC;AAGD,SAAgB,kBAAkB,CAAC,QAAgB,EAAC,cAAsD,EAAC,eAA8E;IACvL,MAAM,UAAU,GAAG,cAAc,CAAC,cAAc,CAAmB,gBAAgB,CAAC,IAAI,kEAA8B,CAAC;IACvH,MAAM,WAAW,GAAG,GAAG,UAAU,UAAU,CAAC;IAG5C,MAAM,YAAY,GAAG,eAAe,EAAE,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAA;IAEnF,IAAK,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,WAAW,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,EAAE,SAAS,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,eAAe,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;QAC5M,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,GAAG,YAAY,IAAI,QAAQ,EAAE,CAAC;AACvC,CAAC;AAGD,SAAgB,oBAAoB,CAAC,aAAyC,EAAE,cAAuB;IACrG,OAAO,cAAc,IAAI,aAAa,CAAC,GAAG,CAAS,oBAAoB,CAAC,CAAC;AAC3E,CAAC;AAGD,SAAgB,oBAAoB,CAAC,eAAgE;IACnG,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,eAAe,CAAC,QAAQ,KAAK,KAAK,CAAC;AAC5C,CAAC;AAGD,SAAgB,2BAA2B,CACzC,QAAgB,EAChB,kBAAmF,EACnF,eAAyD,EACzD,SACgJ;IAEhJ,OAAO;QACL,QAAQ;QACR,eAAe,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE;QAC5C,8BAA8B,EAAE,eAAe,CAAC,EAAE;QAClD,eAAe,EAAE,kBAAkB,CAAC,EAAE;QACtC,GAAG,SAAS;KACb,CAAC;AACJ,CAAC","sourcesContent":["import { ConfigService } from '@nestjs/config';\nimport * as path from 'path';\nimport { FieldMetadata } from 'src/entities/field-metadata.entity';\nimport { MediaStorageProviderMetadata } from 'src/entities/media-storage-provider-metadata.entity';\nimport { SettingService } from 'src/services/setting.service';\nimport { DEFAULT_MEDIA_FILE_STORAGE_DIR } from 'src/services/settings/default-settings-provider.service';\nimport type { SolidCoreSetting } from 'src/services/settings/default-settings-provider.service';\n\n\nexport interface MediaRecordCreateInput {\n entityId: number;\n modelMetadataId: number;\n mediaStorageProviderMetadataId: number;\n fieldMetadataId: number;\n relativeUri: string;\n mimeType?: string;\n fileSize?: number;\n originalFileName?: string;\n}\n\n// Builds the stored file name format shared by media storage implementations.\nexport function buildStoredMediaFileName(file: Pick<Express.Multer.File, 'filename' | 'originalname'>): string {\n return `${file.filename}-${file.originalname}`;\n}\n\n// Resolves the on-disk path for a media file based on settings and provider visibility.\nexport function buildDiskMediaPath(fileName: string,settingService: Pick<SettingService, 'getConfigValue'>,storageProvider?: Pick<MediaStorageProviderMetadata, 'localPath' | 'isPublic'>,): string {\n const publicBase = settingService.getConfigValue<SolidCoreSetting>('fileStorageDir') || DEFAULT_MEDIA_FILE_STORAGE_DIR;\n const privateBase = `${publicBase}-private`;\n // const localPath = storageProvider?.localPath;\n // const isUsingLegacyDefaultPath = localPath === publicBase || localPath === privateBase || localPath === privateBase;\n const providerBase = storageProvider?.isPublic === false ? privateBase : publicBase\n\n if ( path.isAbsolute(fileName) || fileName.startsWith(`${publicBase}/`) || fileName.startsWith(`${privateBase}/`) || (!!storageProvider?.localPath && fileName.startsWith(`${storageProvider.localPath}/`))) {\n return fileName;\n }\n\n return `${providerBase}/${fileName}`;\n}\n\n// Returns the S3 region from the provider when present, otherwise falls back to app config.\nexport function getEffectiveS3Region(configService: Pick<ConfigService, 'get'>, providerRegion?: string): string | undefined {\n return providerRegion || configService.get<string>('S3_AWS_REGION_NAME');\n}\n\n// Resolves the effective public/private flag for a media storage provider.\nexport function resolveMediaIsPublic(storageProvider?: Pick<MediaStorageProviderMetadata, 'isPublic'>): boolean | undefined {\n if (!storageProvider) {\n return undefined;\n }\n\n return storageProvider.isPublic !== false;\n}\n\n// Builds the shared media record payload used before saving media metadata to the database.\nexport function buildMediaRecordCreateInput(\n entityId: number,\n mediaFieldMetadata: Pick<FieldMetadata, 'id' | 'model'> & { model: { id: number } },\n storageProvider: Pick<MediaStorageProviderMetadata, 'id'>,\n overrides: Pick<MediaRecordCreateInput, 'relativeUri'>\n & Partial<Omit<MediaRecordCreateInput, 'entityId' | 'modelMetadataId' | 'mediaStorageProviderMetadataId' | 'fieldMetadataId' | 'relativeUri'>>,\n): MediaRecordCreateInput {\n return {\n entityId,\n modelMetadataId: mediaFieldMetadata.model.id,\n mediaStorageProviderMetadataId: storageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id,\n ...overrides,\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.service.d.ts","sourceRoot":"","sources":["../../src/services/media.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAM,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAIlF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAElD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,sCAAsC,EAAE,MAAM,2DAA2D,CAAC;AACnH,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAInF,qBACa,YAAa,SAAQ,WAAW,CAAC,KAAK,CAAC;IAIhD,QAAQ,CAAC,aAAa,EAAE,aAAa;IACrC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACzC,QAAQ,CAAC,aAAa,EAAE,aAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IAExC,QAAQ,CAAC,aAAa,EAAE,aAAa;IAGrC,QAAQ,CAAC,IAAI,EAAE,eAAe;IAQ9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,gCAAgC;IACjD,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,QAAQ,CAAC,SAAS,EAAE,SAAS;IAtB/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;gBAG7C,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EACpB,uBAAuB,EAAE,uBAAuB,EAExD,aAAa,EAAE,aAAa,EAG5B,IAAI,EAAE,eAAe,EAQb,iBAAiB,EAAE,uBAAuB,EAC1C,gCAAgC,EAAE,sCAAsC,EACxE,iBAAiB,EAAE,uBAAuB,EAClD,SAAS,EAAE,SAAS;IAKzB,IAAI,CAAC,cAAc,EAAE,cAAc,EAAE,mBAAmB,GAAE,GAAQ;IAalE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,GAAE,GAAQ,EAAE,mBAAmB,GAAE,GAAQ;IAQlE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,oBAAoB,GAAE,GAAQ;
|
|
1
|
+
{"version":3,"file":"media.service.d.ts","sourceRoot":"","sources":["../../src/services/media.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAM,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAIlF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAElD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,sCAAsC,EAAE,MAAM,2DAA2D,CAAC;AACnH,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AAInF,qBACa,YAAa,SAAQ,WAAW,CAAC,KAAK,CAAC;IAIhD,QAAQ,CAAC,aAAa,EAAE,aAAa;IACrC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACzC,QAAQ,CAAC,aAAa,EAAE,aAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IAExC,QAAQ,CAAC,aAAa,EAAE,aAAa;IAGrC,QAAQ,CAAC,IAAI,EAAE,eAAe;IAQ9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,gCAAgC;IACjD,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,QAAQ,CAAC,SAAS,EAAE,SAAS;IAtB/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;gBAG7C,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EACpB,uBAAuB,EAAE,uBAAuB,EAExD,aAAa,EAAE,aAAa,EAG5B,IAAI,EAAE,eAAe,EAQb,iBAAiB,EAAE,uBAAuB,EAC1C,gCAAgC,EAAE,sCAAsC,EACxE,iBAAiB,EAAE,uBAAuB,EAClD,SAAS,EAAE,SAAS;IAKzB,IAAI,CAAC,cAAc,EAAE,cAAc,EAAE,mBAAmB,GAAE,GAAQ;IAalE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,GAAE,GAAQ,EAAE,mBAAmB,GAAE,GAAQ;IAQlE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,oBAAoB,GAAE,GAAQ;IAkExF,MAAM,CAAC,EAAE,EAAE,MAAM;IAqBjB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA2BhI,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,mBAAmB,GAAE,GAAQ;IAehD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,mBAAmB,GAAE,GAAQ;YAiB/C,oBAAoB;YAMpB,mBAAmB;YAKnB,eAAe;YAsBf,kBAAkB;YA8BlB,2BAA2B;CAgB1C"}
|
|
@@ -145,10 +145,9 @@ let MediaService = MediaService_1 = class MediaService extends crud_service_1.CR
|
|
|
145
145
|
break;
|
|
146
146
|
}
|
|
147
147
|
await this.diskFileService.delete(file.path);
|
|
148
|
-
|
|
148
|
+
delete createDto['isPublic'];
|
|
149
149
|
const media = this.repo.create(createDto);
|
|
150
150
|
const savedMedia = await this.repo.save(media);
|
|
151
|
-
savedMedia.isPublic = (0, media_storage_utils_1.resolveStoredMediaIsPublic)(savedMedia.isPublic, storageProvider);
|
|
152
151
|
savedMedias.push(savedMedia);
|
|
153
152
|
}
|
|
154
153
|
return savedMedias;
|
|
@@ -222,14 +221,13 @@ let MediaService = MediaService_1 = class MediaService extends crud_service_1.CR
|
|
|
222
221
|
}
|
|
223
222
|
async decorateMediaRecord(media) {
|
|
224
223
|
const mediaStorageProvider = await this.resolveMediaStorageProvider(media);
|
|
225
|
-
media.isPublic = (0, media_storage_utils_1.resolveStoredMediaIsPublic)(media.isPublic, mediaStorageProvider);
|
|
226
224
|
media.relativeUri = await this.resolveMediaUrl(media, mediaStorageProvider);
|
|
227
225
|
}
|
|
228
226
|
async resolveMediaUrl(media, mediaStorageProvider) {
|
|
229
227
|
const resolvedMediaStorageProvider = mediaStorageProvider || await this.resolveMediaStorageProvider(media);
|
|
230
|
-
const isPublic = (0, media_storage_utils_1.
|
|
228
|
+
const isPublic = (0, media_storage_utils_1.resolveMediaIsPublic)(resolvedMediaStorageProvider);
|
|
231
229
|
if (isPublic === false) {
|
|
232
|
-
return this.mediaDownloadUrlService.
|
|
230
|
+
return this.mediaDownloadUrlService.getPrivateUrl(media.id, media.relativeUri, resolvedMediaStorageProvider);
|
|
233
231
|
}
|
|
234
232
|
if (resolvedMediaStorageProvider?.type === create_media_storage_provider_metadata_dto_1.MediaStorageProviderType.Filesystem) {
|
|
235
233
|
return this.diskFileService.getUrl((0, media_storage_utils_1.buildDiskMediaPath)(media.relativeUri, this.settingService, resolvedMediaStorageProvider));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media.service.js","sourceRoot":"","sources":["../../src/services/media.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { forwardRef, Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';\nimport { ModuleRef } from \"@nestjs/core\";\nimport { InjectEntityManager } from '@nestjs/typeorm';\nimport { EntityManager, In } from 'typeorm';\nimport * as path from 'path';\nimport { Readable } from 'stream';\n\nimport { ConfigService } from '@nestjs/config';\nimport { CRUDService } from 'src/services/crud.service';\nimport { DiskFileService, S3FileService } from 'src/services/file';\nimport { MediaDownloadUrlService } from 'src/services/media-download-url.service';\n\n\nimport { ERROR_MESSAGES } from 'src/constants/error-messages';\nimport { BasicFilterDto } from 'src/dtos/basic-filters.dto';\nimport { MediaStorageProviderType } from 'src/dtos/create-media-storage-provider-metadata.dto';\nimport { Media } from 'src/entities/media.entity';\nimport { MediaStorageProviderMetadata } from 'src/entities/media-storage-provider-metadata.entity';\nimport { FieldMetadataRepository } from 'src/repository/field-metadata.repository';\nimport { MediaStorageProviderMetadataRepository } from 'src/repository/media-storage-provider-metadata.repository';\nimport { MediaRepository } from 'src/repository/media.repository';\nimport { ModelMetadataRepository } from 'src/repository/model-metadata.repository';\nimport { buildDiskMediaPath, buildStoredMediaFileName, getEffectiveS3Region, resolveStoredMediaIsPublic, } from 'src/services/media-storage.utils';\nimport { getMediaStorageProvider } from \"./mediaStorageProviders\";\n\n@Injectable()\nexport class MediaService extends CRUDService<Media> {\n private readonly logger = new Logger(MediaService.name);\n\n constructor(\n readonly configService: ConfigService,\n readonly diskFileService: DiskFileService,\n readonly s3FileService: S3FileService,\n private readonly mediaDownloadUrlService: MediaDownloadUrlService,\n @InjectEntityManager()\n readonly entityManager: EntityManager,\n // @InjectRepository(Media, 'default')\n // readonly repo: Repository<Media>,\n readonly repo: MediaRepository,\n // @InjectRepository(ModelMetadata)\n // private readonly modelMetadataRepo: Repository<ModelMetadata>,\n // @InjectRepository(MediaStorageProviderMetadata)\n // private readonly mediaStorageProviderMetadataRepo: Repository<MediaStorageProviderMetadata>,\n // @InjectRepository(FieldMetadata)\n // private readonly fieldMetadataRepo: Repository<FieldMetadata>,\n @Inject(forwardRef(() => ModelMetadataRepository))\n private readonly modelMetadataRepo: ModelMetadataRepository,\n private readonly mediaStorageProviderMetadataRepo: MediaStorageProviderMetadataRepository,\n private readonly fieldMetadataRepo: FieldMetadataRepository,\n readonly moduleRef: ModuleRef,\n ) {\n super(entityManager, repo, 'media', 'solid-core', moduleRef);\n }\n\n async find(basicFilterDto: BasicFilterDto, solidRequestContext: any = {}) {\n const data = await super.find(basicFilterDto, solidRequestContext);\n if (data.records) {\n await this.decorateMediaRecords(data.records);\n }\n if (data.groupRecords) {\n for (const group of data.groupRecords) {\n await this.decorateMediaRecords(group.groupData.records);\n }\n }\n return data\n }\n\n async findOne(id: number, query: any = {}, solidRequestContext: any = {}) {\n const media = await super.findOne(id, query, solidRequestContext);\n if (media) {\n await this.decorateMediaRecord(media);\n }\n return media;\n }\n\n async upload(createDto: any, files: Array<Express.Multer.File>, _solidRequestContext: any = {}) {\n\n if (!files || files.length === 0) {\n throw new NotFoundException(ERROR_MESSAGES.FILE_NOT_FOUND);\n\n }\n\n createDto['fieldMetadata'] = await this.fieldMetadataRepo.findOne({\n where: {\n id: createDto['fieldMetadataId']\n },\n relations: ['mediaStorageProvider', 'model'],\n });\n createDto['modelMetadata'] = await this.modelMetadataRepo.findOne({\n where: {\n id: createDto['modelMetadataId']\n },\n });\n createDto['mediaStorageProviderMetadata'] = await this.mediaStorageProviderMetadataRepo.findOne({\n where: {\n id: createDto['mediaStorageProviderMetadataId']\n },\n });\n createDto['mediaStorageProviderMetadata'] = createDto['mediaStorageProviderMetadata'] || createDto['fieldMetadata']?.mediaStorageProvider;\n createDto['modelMetadata'] = createDto['modelMetadata'] || createDto['fieldMetadata']?.model;\n\n if (!createDto['mediaStorageProviderMetadata']) {\n throw new NotFoundException('Media storage provider metadata not found');\n }\n\n const savedMedias = [];\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const storageProvider = createDto.mediaStorageProviderMetadata as MediaStorageProviderMetadata;\n const fileName = buildStoredMediaFileName(file);\n\n switch (storageProvider.type) {\n case MediaStorageProviderType.Filesystem:\n const fileStoragePath = buildDiskMediaPath(fileName, this.settingService, storageProvider);\n await this.diskFileService.copy(file.path, fileStoragePath);\n createDto['relativeUri'] = fileName;\n break;\n case MediaStorageProviderType.AwsS3:\n const bucketName = storageProvider.bucketName;\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n\n // Read file from disk and upload to S3\n const fileData = await this.diskFileService.read(file.path);\n await this.s3FileService.write(`${bucketName}:${fileName}`, fileData, { contentType: file.mimetype, region });\n\n createDto['relativeUri'] = fileName;\n break;\n default:\n break;\n }\n // Delete temp file from disk\n await this.diskFileService.delete(file.path);\n\n createDto['isPublic'] = resolveStoredMediaIsPublic(createDto['isPublic'], storageProvider);\n const media = this.repo.create(createDto as Partial<Media>) as Media;\n const savedMedia = await this.repo.save(media);\n savedMedia.isPublic = resolveStoredMediaIsPublic(savedMedia.isPublic, storageProvider);\n savedMedias.push(savedMedia)\n }\n return savedMedias\n }\n\n async remove(id: number) {\n // const lov = await this.findOne(id);\n const media = await this.repo.findOne({\n where: {\n id: id,\n },\n relations: ['mediaStorageProviderMetadata', 'fieldMetadata', 'fieldMetadata.model', 'fieldMetadata.mediaStorageProvider'],\n });\n const modelEntity = await this.modelMetadataRepo.findOne({\n where: {\n id: media.entityId,\n }\n }\n );\n const storageProviderType = media.mediaStorageProviderMetadata.type as MediaStorageProviderType;\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n await storageProvider.delete(modelEntity, media.fieldMetadata);\n\n return this.repo.remove(media);\n }\n\n async fileDownloadStream(media: Media): Promise<{ stream: Readable | null, fileName: string, mimeType: string, redirectUrl?: string }> {\n const loadedMedia = await this.repo.findOne({\n where: { id: media.id },\n relations: ['mediaStorageProviderMetadata'],\n });\n\n if (!loadedMedia || !loadedMedia.mediaStorageProviderMetadata) {\n throw new NotFoundException(`Media with id ${media.id} not found`);\n }\n\n const fileName = loadedMedia.originalFileName || path.basename(loadedMedia.relativeUri || `${loadedMedia.id}`);\n const mimeType = loadedMedia.mimeType || 'application/octet-stream';\n\n switch (loadedMedia.mediaStorageProviderMetadata.type as MediaStorageProviderType) {\n case MediaStorageProviderType.Filesystem:\n return {\n stream: await this.diskFileService.readStream(\n buildDiskMediaPath(loadedMedia.relativeUri, this.settingService, loadedMedia.mediaStorageProviderMetadata),\n ),\n fileName,\n mimeType,\n };\n default:\n throw new Error(`Unsupported media storage provider type ${loadedMedia.mediaStorageProviderMetadata.type}`);\n }\n }\n\n async delete(id: number, solidRequestContext: any = {}) {\n const media = await this.repo.findOne({\n where: { id },\n relations: ['mediaStorageProviderMetadata'],\n });\n\n const result = await super.delete(id, solidRequestContext);\n\n if (media) {\n await this.deletePhysicalFile(media);\n }\n\n return result;\n }\n\n async deleteMany(ids: number[], solidRequestContext: any = {}) {\n const mediaRecords = await this.repo.find({\n where: {\n id: In(ids),\n },\n relations: ['mediaStorageProviderMetadata'],\n });\n\n const result = await super.deleteMany(ids, solidRequestContext);\n\n for (const media of mediaRecords) {\n await this.deletePhysicalFile(media);\n }\n\n return result;\n }\n\n private async decorateMediaRecords(medias: Media[]): Promise<void> {\n for (const media of medias) {\n await this.decorateMediaRecord(media);\n }\n }\n\n private async decorateMediaRecord(media: Media): Promise<void> {\n const mediaStorageProvider = await this.resolveMediaStorageProvider(media);\n media.isPublic = resolveStoredMediaIsPublic(media.isPublic, mediaStorageProvider);\n media.relativeUri = await this.resolveMediaUrl(media, mediaStorageProvider);\n }\n\n private async resolveMediaUrl(media: Media, mediaStorageProvider?: MediaStorageProviderMetadata): Promise<string> {\n const resolvedMediaStorageProvider = mediaStorageProvider || await this.resolveMediaStorageProvider(media);\n const isPublic = resolveStoredMediaIsPublic(media.isPublic, resolvedMediaStorageProvider);\n\n if (isPublic === false) {\n return this.mediaDownloadUrlService.resolveDownloadUrl(media.id, media.relativeUri, resolvedMediaStorageProvider);\n }\n\n if (resolvedMediaStorageProvider?.type === MediaStorageProviderType.Filesystem) {\n return this.diskFileService.getUrl(buildDiskMediaPath(media.relativeUri, this.settingService, resolvedMediaStorageProvider));\n }\n\n if (resolvedMediaStorageProvider?.type === MediaStorageProviderType.AwsS3) {\n return this.s3FileService.getUrl(\n `${resolvedMediaStorageProvider.bucketName}:${media.relativeUri}`,\n { region: getEffectiveS3Region(this.configService, resolvedMediaStorageProvider.region), expiresIn: 0 },\n );\n }\n\n return media.relativeUri;\n }\n\n private async deletePhysicalFile(media: Media): Promise<void> {\n if (!media?.relativeUri) {\n return;\n }\n\n try {\n const mediaStorageProvider = await this.resolveMediaStorageProvider(media);\n if (!mediaStorageProvider) {\n return;\n }\n\n switch (mediaStorageProvider.type as MediaStorageProviderType) {\n case MediaStorageProviderType.Filesystem:\n await this.diskFileService.delete(buildDiskMediaPath(media.relativeUri, this.settingService, mediaStorageProvider));\n return;\n case MediaStorageProviderType.AwsS3:\n await this.s3FileService.delete(\n `${mediaStorageProvider.bucketName}:${media.relativeUri}`,\n { region: getEffectiveS3Region(this.configService, mediaStorageProvider.region) },\n );\n return;\n default:\n this.logger.warn(`Skipping physical delete for unsupported media storage provider type ${mediaStorageProvider.type}`);\n }\n } catch (error: any) {\n const message = error?.message ?? String(error);\n this.logger.warn(`Failed to delete physical media file for media id ${media.id}: ${message}`);\n }\n }\n\n private async resolveMediaStorageProvider(media: Media): Promise<MediaStorageProviderMetadata | undefined> {\n if (media.mediaStorageProviderMetadata) {\n return media.mediaStorageProviderMetadata;\n }\n\n if (!media.id) {\n return undefined;\n }\n\n const loadedMedia = await this.repo.findOne({\n where: { id: media.id },\n relations: ['mediaStorageProviderMetadata'],\n });\n\n return loadedMedia?.mediaStorageProviderMetadata;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"media.service.js","sourceRoot":"","sources":["../../src/services/media.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { forwardRef, Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';\nimport { ModuleRef } from \"@nestjs/core\";\nimport { InjectEntityManager } from '@nestjs/typeorm';\nimport { EntityManager, In } from 'typeorm';\nimport * as path from 'path';\nimport { Readable } from 'stream';\n\nimport { ConfigService } from '@nestjs/config';\nimport { CRUDService } from 'src/services/crud.service';\nimport { DiskFileService, S3FileService } from 'src/services/file';\nimport { MediaDownloadUrlService } from 'src/services/media-download-url.service';\n\n\nimport { ERROR_MESSAGES } from 'src/constants/error-messages';\nimport { BasicFilterDto } from 'src/dtos/basic-filters.dto';\nimport { MediaStorageProviderType } from 'src/dtos/create-media-storage-provider-metadata.dto';\nimport { Media } from 'src/entities/media.entity';\nimport { MediaStorageProviderMetadata } from 'src/entities/media-storage-provider-metadata.entity';\nimport { FieldMetadataRepository } from 'src/repository/field-metadata.repository';\nimport { MediaStorageProviderMetadataRepository } from 'src/repository/media-storage-provider-metadata.repository';\nimport { MediaRepository } from 'src/repository/media.repository';\nimport { ModelMetadataRepository } from 'src/repository/model-metadata.repository';\nimport { buildDiskMediaPath, buildStoredMediaFileName, getEffectiveS3Region, resolveMediaIsPublic, } from 'src/services/media-storage.utils';\nimport { getMediaStorageProvider } from \"./mediaStorageProviders\";\n\n@Injectable()\nexport class MediaService extends CRUDService<Media> {\n private readonly logger = new Logger(MediaService.name);\n\n constructor(\n readonly configService: ConfigService,\n readonly diskFileService: DiskFileService,\n readonly s3FileService: S3FileService,\n private readonly mediaDownloadUrlService: MediaDownloadUrlService,\n @InjectEntityManager()\n readonly entityManager: EntityManager,\n // @InjectRepository(Media, 'default')\n // readonly repo: Repository<Media>,\n readonly repo: MediaRepository,\n // @InjectRepository(ModelMetadata)\n // private readonly modelMetadataRepo: Repository<ModelMetadata>,\n // @InjectRepository(MediaStorageProviderMetadata)\n // private readonly mediaStorageProviderMetadataRepo: Repository<MediaStorageProviderMetadata>,\n // @InjectRepository(FieldMetadata)\n // private readonly fieldMetadataRepo: Repository<FieldMetadata>,\n @Inject(forwardRef(() => ModelMetadataRepository))\n private readonly modelMetadataRepo: ModelMetadataRepository,\n private readonly mediaStorageProviderMetadataRepo: MediaStorageProviderMetadataRepository,\n private readonly fieldMetadataRepo: FieldMetadataRepository,\n readonly moduleRef: ModuleRef,\n ) {\n super(entityManager, repo, 'media', 'solid-core', moduleRef);\n }\n\n async find(basicFilterDto: BasicFilterDto, solidRequestContext: any = {}) {\n const data = await super.find(basicFilterDto, solidRequestContext);\n if (data.records) {\n await this.decorateMediaRecords(data.records);\n }\n if (data.groupRecords) {\n for (const group of data.groupRecords) {\n await this.decorateMediaRecords(group.groupData.records);\n }\n }\n return data\n }\n\n async findOne(id: number, query: any = {}, solidRequestContext: any = {}) {\n const media = await super.findOne(id, query, solidRequestContext);\n if (media) {\n await this.decorateMediaRecord(media);\n }\n return media;\n }\n\n async upload(createDto: any, files: Array<Express.Multer.File>, _solidRequestContext: any = {}) {\n\n if (!files || files.length === 0) {\n throw new NotFoundException(ERROR_MESSAGES.FILE_NOT_FOUND);\n\n }\n\n createDto['fieldMetadata'] = await this.fieldMetadataRepo.findOne({\n where: {\n id: createDto['fieldMetadataId']\n },\n relations: ['mediaStorageProvider', 'model'],\n });\n createDto['modelMetadata'] = await this.modelMetadataRepo.findOne({\n where: {\n id: createDto['modelMetadataId']\n },\n });\n createDto['mediaStorageProviderMetadata'] = await this.mediaStorageProviderMetadataRepo.findOne({\n where: {\n id: createDto['mediaStorageProviderMetadataId']\n },\n });\n createDto['mediaStorageProviderMetadata'] = createDto['mediaStorageProviderMetadata'] || createDto['fieldMetadata']?.mediaStorageProvider;\n createDto['modelMetadata'] = createDto['modelMetadata'] || createDto['fieldMetadata']?.model;\n\n if (!createDto['mediaStorageProviderMetadata']) {\n throw new NotFoundException('Media storage provider metadata not found');\n }\n\n const savedMedias = [];\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n const storageProvider = createDto.mediaStorageProviderMetadata as MediaStorageProviderMetadata;\n const fileName = buildStoredMediaFileName(file);\n\n switch (storageProvider.type) {\n case MediaStorageProviderType.Filesystem:\n const fileStoragePath = buildDiskMediaPath(fileName, this.settingService, storageProvider);\n await this.diskFileService.copy(file.path, fileStoragePath);\n createDto['relativeUri'] = fileName;\n break;\n case MediaStorageProviderType.AwsS3:\n const bucketName = storageProvider.bucketName;\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n\n // Read file from disk and upload to S3\n const fileData = await this.diskFileService.read(file.path);\n await this.s3FileService.write(`${bucketName}:${fileName}`, fileData, { contentType: file.mimetype, region });\n\n createDto['relativeUri'] = fileName;\n break;\n default:\n break;\n }\n // Delete temp file from disk\n await this.diskFileService.delete(file.path);\n\n delete createDto['isPublic'];\n const media = this.repo.create(createDto as Partial<Media>) as Media;\n const savedMedia = await this.repo.save(media);\n savedMedias.push(savedMedia)\n }\n return savedMedias\n }\n\n async remove(id: number) {\n // const lov = await this.findOne(id);\n const media = await this.repo.findOne({\n where: {\n id: id,\n },\n relations: ['mediaStorageProviderMetadata', 'fieldMetadata', 'fieldMetadata.model', 'fieldMetadata.mediaStorageProvider'],\n });\n const modelEntity = await this.modelMetadataRepo.findOne({\n where: {\n id: media.entityId,\n }\n }\n );\n const storageProviderType = media.mediaStorageProviderMetadata.type as MediaStorageProviderType;\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n await storageProvider.delete(modelEntity, media.fieldMetadata);\n\n return this.repo.remove(media);\n }\n\n async fileDownloadStream(media: Media): Promise<{ stream: Readable | null, fileName: string, mimeType: string, redirectUrl?: string }> {\n const loadedMedia = await this.repo.findOne({\n where: { id: media.id },\n relations: ['mediaStorageProviderMetadata'],\n });\n\n if (!loadedMedia || !loadedMedia.mediaStorageProviderMetadata) {\n throw new NotFoundException(`Media with id ${media.id} not found`);\n }\n\n const fileName = loadedMedia.originalFileName || path.basename(loadedMedia.relativeUri || `${loadedMedia.id}`);\n const mimeType = loadedMedia.mimeType || 'application/octet-stream';\n\n switch (loadedMedia.mediaStorageProviderMetadata.type as MediaStorageProviderType) {\n case MediaStorageProviderType.Filesystem:\n return {\n stream: await this.diskFileService.readStream(\n buildDiskMediaPath(loadedMedia.relativeUri, this.settingService, loadedMedia.mediaStorageProviderMetadata),\n ),\n fileName,\n mimeType,\n };\n default:\n throw new Error(`Unsupported media storage provider type ${loadedMedia.mediaStorageProviderMetadata.type}`);\n }\n }\n\n async delete(id: number, solidRequestContext: any = {}) {\n const media = await this.repo.findOne({\n where: { id },\n relations: ['mediaStorageProviderMetadata'],\n });\n\n const result = await super.delete(id, solidRequestContext);\n\n if (media) {\n await this.deletePhysicalFile(media);\n }\n\n return result;\n }\n\n async deleteMany(ids: number[], solidRequestContext: any = {}) {\n const mediaRecords = await this.repo.find({\n where: {\n id: In(ids),\n },\n relations: ['mediaStorageProviderMetadata'],\n });\n\n const result = await super.deleteMany(ids, solidRequestContext);\n\n for (const media of mediaRecords) {\n await this.deletePhysicalFile(media);\n }\n\n return result;\n }\n\n private async decorateMediaRecords(medias: Media[]): Promise<void> {\n for (const media of medias) {\n await this.decorateMediaRecord(media);\n }\n }\n\n private async decorateMediaRecord(media: Media): Promise<void> {\n const mediaStorageProvider = await this.resolveMediaStorageProvider(media);\n media.relativeUri = await this.resolveMediaUrl(media, mediaStorageProvider);\n }\n\n private async resolveMediaUrl(media: Media, mediaStorageProvider?: MediaStorageProviderMetadata): Promise<string> {\n const resolvedMediaStorageProvider = mediaStorageProvider || await this.resolveMediaStorageProvider(media);\n const isPublic = resolveMediaIsPublic(resolvedMediaStorageProvider);\n\n if (isPublic === false) {\n return this.mediaDownloadUrlService.getPrivateUrl(media.id, media.relativeUri, resolvedMediaStorageProvider);\n }\n\n if (resolvedMediaStorageProvider?.type === MediaStorageProviderType.Filesystem) {\n return this.diskFileService.getUrl(buildDiskMediaPath(media.relativeUri, this.settingService, resolvedMediaStorageProvider));\n }\n\n if (resolvedMediaStorageProvider?.type === MediaStorageProviderType.AwsS3) {\n return this.s3FileService.getUrl(\n `${resolvedMediaStorageProvider.bucketName}:${media.relativeUri}`,\n { region: getEffectiveS3Region(this.configService, resolvedMediaStorageProvider.region), expiresIn: 0 },\n );\n }\n\n return media.relativeUri;\n }\n\n private async deletePhysicalFile(media: Media): Promise<void> {\n if (!media?.relativeUri) {\n return;\n }\n\n try {\n const mediaStorageProvider = await this.resolveMediaStorageProvider(media);\n if (!mediaStorageProvider) {\n return;\n }\n\n switch (mediaStorageProvider.type as MediaStorageProviderType) {\n case MediaStorageProviderType.Filesystem:\n await this.diskFileService.delete(buildDiskMediaPath(media.relativeUri, this.settingService, mediaStorageProvider));\n return;\n case MediaStorageProviderType.AwsS3:\n await this.s3FileService.delete(\n `${mediaStorageProvider.bucketName}:${media.relativeUri}`,\n { region: getEffectiveS3Region(this.configService, mediaStorageProvider.region) },\n );\n return;\n default:\n this.logger.warn(`Skipping physical delete for unsupported media storage provider type ${mediaStorageProvider.type}`);\n }\n } catch (error: any) {\n const message = error?.message ?? String(error);\n this.logger.warn(`Failed to delete physical media file for media id ${media.id}: ${message}`);\n }\n }\n\n private async resolveMediaStorageProvider(media: Media): Promise<MediaStorageProviderMetadata | undefined> {\n if (media.mediaStorageProviderMetadata) {\n return media.mediaStorageProviderMetadata;\n }\n\n if (!media.id) {\n return undefined;\n }\n\n const loadedMedia = await this.repo.findOne({\n where: { id: media.id },\n relations: ['mediaStorageProviderMetadata'],\n });\n\n return loadedMedia?.mediaStorageProviderMetadata;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-s3-storage-provider.d.ts","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-s3-storage-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAGnE,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAQlF,qBACa,qBAAqB,CAAC,CAAC,CAAE,YAAW,oBAAoB,CAAC,CAAC,CAAC;IAIhE,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,QAAQ,CAAC,eAAe,EAAE,eAAe;IACzC,QAAQ,CAAC,aAAa,EAAE,aAAa;IACrC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IAP5C,OAAO,CAAC,MAAM,CAA0C;gBAGnC,aAAa,EAAE,aAAa,EACpC,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,eAAe,EACxB,uBAAuB,EAAE,uBAAuB;IAG/D,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"file-s3-storage-provider.d.ts","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-s3-storage-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAGnE,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAQlF,qBACa,qBAAqB,CAAC,CAAC,CAAE,YAAW,oBAAoB,CAAC,CAAC,CAAC;IAIhE,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,QAAQ,CAAC,eAAe,EAAE,eAAe;IACzC,QAAQ,CAAC,aAAa,EAAE,aAAa;IACrC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IAP5C,OAAO,CAAC,MAAM,CAA0C;gBAGnC,aAAa,EAAE,aAAa,EACpC,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,eAAe,EACxB,uBAAuB,EAAE,uBAAuB;IAG/D,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA+B/G,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA0BxE,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAkCnG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAenE,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAYtD,OAAO,CAAC,oBAAoB;CAW/B"}
|
|
@@ -47,7 +47,6 @@ let FileS3StorageProvider = FileS3StorageProvider_1 = class FileS3StorageProvide
|
|
|
47
47
|
relativeUri: fileName,
|
|
48
48
|
fileSize,
|
|
49
49
|
}));
|
|
50
|
-
mediaEntity.isPublic = (0, media_storage_utils_1.resolveStoredMediaIsPublic)(mediaEntity.isPublic, storageProvider);
|
|
51
50
|
result.push(mediaEntity);
|
|
52
51
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
53
52
|
}
|
|
@@ -58,10 +57,9 @@ let FileS3StorageProvider = FileS3StorageProvider_1 = class FileS3StorageProvide
|
|
|
58
57
|
const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);
|
|
59
58
|
for (const m of media) {
|
|
60
59
|
const storageMeta = m.mediaStorageProviderMetadata;
|
|
61
|
-
const isPublic = (0, media_storage_utils_1.
|
|
62
|
-
m.isPublic = isPublic;
|
|
60
|
+
const isPublic = (0, media_storage_utils_1.resolveMediaIsPublic)(storageMeta);
|
|
63
61
|
m['_full_url'] = isPublic === false
|
|
64
|
-
? await this.mediaDownloadUrlService.
|
|
62
|
+
? await this.mediaDownloadUrlService.getPrivateUrl(m.id, m.relativeUri, storageMeta)
|
|
65
63
|
: await this.s3FileService.getUrl(`${storageMeta.bucketName}:${m.relativeUri}`, { region: (0, media_storage_utils_1.getEffectiveS3Region)(this.configService, storageMeta.region), expiresIn: 0 });
|
|
66
64
|
}
|
|
67
65
|
return media;
|
|
@@ -84,7 +82,6 @@ let FileS3StorageProvider = FileS3StorageProvider_1 = class FileS3StorageProvide
|
|
|
84
82
|
fileSize: file.size,
|
|
85
83
|
originalFileName: file.originalname,
|
|
86
84
|
}));
|
|
87
|
-
mediaEntity.isPublic = (0, media_storage_utils_1.resolveStoredMediaIsPublic)(mediaEntity.isPublic, storageProvider);
|
|
88
85
|
result.push(mediaEntity);
|
|
89
86
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
90
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-s3-storage-provider.js","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-s3-storage-provider.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,2CAA+C;AAC/C,gEAA0D;AAE1D,8HAA6G;AAC7G,kHAAwG;AAGxG,kCAAmE;AAEnE,wEAAkE;AAClE,8EAAkF;AAClF,gEAK0C;AAGnC,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IAG9B,YACqB,aAA4B,EACpC,eAAgC,EAChC,aAA4B,EAC5B,eAAgC,EACxB,uBAAgD;QAJhD,kBAAa,GAAb,aAAa,CAAe;QACpC,oBAAe,GAAf,eAAe,CAAiB;QAChC,kBAAa,GAAb,aAAa,CAAe;QAC5B,oBAAe,GAAf,eAAe,CAAiB;QACxB,4BAAuB,GAAvB,uBAAuB,CAAyB;QAP7D,WAAM,GAAG,IAAI,eAAM,CAAC,uBAAqB,CAAC,IAAI,CAAC,CAAC;IAQpD,CAAC;IAEL,KAAK,CAAC,YAAY,CAAC,WAAiC,EAAE,MAAS,EAAE,kBAAiC;QAC9F,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,MAAM,GAAY,EAAE,CAAC;QAC3B,MAAM,eAAe,GAAG,kBAAkB,CAAC,oBAAoB,CAAC;QAChE,MAAM,MAAM,GAAG,IAAA,0CAAoB,EAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;QAEhF,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,WAAW,EAAE,CAAC;YAC3C,MAAM,UAAU,GAAG,eAAe,CAAC,UAAU,CAAC;YAG9C,MAAM,MAAM,GAAa,EAAE,CAAC;YAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACrE,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACvC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC;YAEjC,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,UAAU,IAAI,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAElF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CACtD,IAAA,iDAA2B,EAAC,QAAQ,EAAE,kBAAkB,EAAE,eAAe,EAAE;gBACvE,WAAW,EAAE,QAAQ;gBACrB,QAAQ;aACX,CAAC,CACe,CAAC;YACtB,WAAW,CAAC,QAAQ,GAAG,IAAA,gDAA0B,EAAC,WAAW,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;YACzF,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAS,EAAE,kBAAiC;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAEnD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,0CAA0C,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,8BAA8B,CAAC,CAAC,CAAC;QAKpL,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACpB,MAAM,WAAW,GAAG,CAAC,CAAC,4BAA4B,CAAC;YACnD,MAAM,QAAQ,GAAG,IAAA,gDAA0B,EAAC,CAAC,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;YACrE,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC;YACtB,CAAC,CAAC,WAAW,CAAC,GAAG,QAAQ,KAAK,KAAK;gBAC/B,CAAC,CAAC,MAAM,IAAI,CAAC,uBAAuB,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC;gBACzF,CAAC,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAC7B,GAAG,WAAW,CAAC,UAAU,IAAI,CAAC,CAAC,WAAW,EAAE,EAC5C,EAAE,MAAM,EAAE,IAAA,0CAAoB,EAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CACzF,CAAC;QACV,CAAC;QAED,OAAO,KAAK,CAAC;IAKjB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAA4B,EAAE,MAAS,EAAE,kBAAiC;QAClF,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,MAAM,GAAY,EAAE,CAAC;QAC3B,MAAM,eAAe,GAAG,kBAAkB,CAAC,oBAAoB,CAAC;QAChE,MAAM,MAAM,GAAG,IAAA,0CAAoB,EAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;QAEhF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,IAAA,8CAAwB,EAAC,IAAI,CAAC,CAAC;YAChD,MAAM,UAAU,GAAG,eAAe,CAAC,UAAU,CAAC;YAG9C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,UAAU,IAAI,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;YAG9G,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE7C,MAAM,UAAU,GAAG,QAAQ,CAAC;YAG5B,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CACtD,IAAA,iDAA2B,EAAC,QAAQ,EAAE,kBAAkB,EAAE,eAAe,EAAE;gBACvE,WAAW,EAAE,UAAU;gBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,gBAAgB,EAAE,IAAI,CAAC,YAAY;aACtC,CAAC,CACe,CAAC;YACtB,WAAW,CAAC,QAAQ,GAAG,IAAA,gDAA0B,EAAC,WAAW,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;YACzF,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;QACxD,CAAC;QAAA,CAAC;QACF,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAS,EAAE,kBAAiC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,eAAe,GAAG,kBAAkB,CAAC,oBAAoB,CAAC;QAChE,MAAM,MAAM,GAAG,IAAA,0CAAoB,EAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;QAGhF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,0CAA0C,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,8BAA8B,CAAC,CAAC,CAAC;QAE5L,IAAI,CAAC,eAAe,CAAC,4CAA4C,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAChI,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,eAAe,CAAC,UAAU,CAAC;YAC9C,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,UAAU,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACtF,CAAC;IACL,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,KAAY;QAClC,MAAM,eAAe,GAAG,KAAK,EAAE,4BAA4B,CAAC;QAC5D,IAAI,CAAC,eAAe,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,8DAA8D,KAAK,EAAE,EAAE,IAAI,SAAS,EAAE,CAAC,CAAC;QAC5G,CAAC;QACD,IAAI,CAAC,eAAe,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC;YACtD,OAAO;QACX,CAAC;QACD,MAAM,MAAM,GAAG,IAAA,0CAAoB,EAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;QAChF,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,eAAe,CAAC,UAAU,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACtG,CAAC;IAEO,oBAAoB,CAAC,MAAS;QAClC,MAAM,iBAAiB,GAAG,MAAM,YAAY,4BAAY;eACjD,MAAM,YAAY,+EAAgC;eAClD,MAAM,YAAY,0EAAiC,CAAC;QAE3D,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,mHAAmH,CAAC,CAAC;QACzI,CAAC;QAED,OAAQ,MAAc,CAAC,EAAE,CAAC;IAC9B,CAAC;CACJ,CAAA;AA/IY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;qCAK2B,sBAAa;QACnB,sBAAe;QACjB,oBAAa;QACX,kCAAe;QACC,oDAAuB;GAR5D,qBAAqB,CA+IjC","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { ConfigService } from \"@nestjs/config\";\nimport { CommonEntity } from \"src/entities/common.entity\";\nimport { FieldMetadata } from \"src/entities/field-metadata.entity\";\nimport { LegacyCommonEntityWithExistingId } from \"src/entities/legacy-common.entity-with-existing-id.entity\";\nimport { LegacyCommonEntityWithGeneratedId } from \"src/entities/legacy-common-with-generated-id.entity\";\nimport { Media } from \"src/entities/media.entity\";\nimport { MediaStorageProvider } from \"src/interfaces\";\nimport { DiskFileService, S3FileService } from \"src/services/file\";\nimport { Readable } from \"stream\";\nimport { MediaRepository } from \"src/repository/media.repository\";\nimport { MediaDownloadUrlService } from \"src/services/media-download-url.service\";\nimport {\n buildMediaRecordCreateInput,\n buildStoredMediaFileName,\n getEffectiveS3Region,\n resolveStoredMediaIsPublic,\n} from \"src/services/media-storage.utils\";\n\n@Injectable()\nexport class FileS3StorageProvider<T> implements MediaStorageProvider<T> {\n private logger = new Logger(FileS3StorageProvider.name);\n\n constructor(\n private readonly configService: ConfigService,\n readonly diskFileService: DiskFileService,\n readonly s3FileService: S3FileService,\n readonly mediaRepository: MediaRepository,\n private readonly mediaDownloadUrlService: MediaDownloadUrlService,\n ) { }\n\n async storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n const entityId = this.getSupportedEntityId(entity);\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n\n for (const [stream, fileName] of streamPairs) {\n const bucketName = storageProvider.bucketName;\n\n // Buffer the stream so we can get the byte count and upload in one pass\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const fileData = Buffer.concat(chunks);\n const fileSize = fileData.length;\n\n await this.s3FileService.write(`${bucketName}:${fileName}`, fileData, { region });\n\n const mediaEntity = await this.mediaRepository.createMedia(\n buildMediaRecordCreateInput(entityId, mediaFieldMetadata, storageProvider, {\n relativeUri: fileName,\n fileSize,\n })\n ) as unknown as Media;\n mediaEntity.isPublic = resolveStoredMediaIsPublic(mediaEntity.isPublic, storageProvider);\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n }\n return result;\n }\n\n async retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n const entityId = this.getSupportedEntityId(entity);\n // @ts-ignore\n const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n\n // TODO: Check if the mediaStorageProvider (s3 in this case) is configured with a public bucket or not.\n // If private bucket then we need to return a \"signed-url\", the timeout for the signed url can be configured in the media storage provider entity and modified using the CRUD interface.\n // Add the full URL to the media\n for (const m of media) {\n const storageMeta = m.mediaStorageProviderMetadata;\n const isPublic = resolveStoredMediaIsPublic(m.isPublic, storageMeta);\n m.isPublic = isPublic;\n m['_full_url'] = isPublic === false\n ? await this.mediaDownloadUrlService.resolveDownloadUrl(m.id, m.relativeUri, storageMeta)\n : await this.s3FileService.getUrl(\n `${storageMeta.bucketName}:${m.relativeUri}`,\n { region: getEffectiveS3Region(this.configService, storageMeta.region), expiresIn: 0 },\n );\n }\n\n return media;\n // media.forEach(m => {\n // m['_full_url'] = this.getFullFilePath(m);\n // });\n // return media;\n }\n\n async store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n const entityId = this.getSupportedEntityId(entity);\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n\n for (const file of files) {\n const fileName = buildStoredMediaFileName(file);\n const bucketName = storageProvider.bucketName;\n\n // Read file from disk and upload to S3\n const fileData = await this.diskFileService.read(file.path);\n await this.s3FileService.write(`${bucketName}:${fileName}`, fileData, { contentType: file.mimetype, region });\n\n // Delete temp file from disk\n await this.diskFileService.delete(file.path);\n\n const awsFileUrl = fileName;\n\n // Create an entry in the media table\n const mediaEntity = await this.mediaRepository.createMedia(\n buildMediaRecordCreateInput(entityId, mediaFieldMetadata, storageProvider, {\n relativeUri: awsFileUrl,\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n })\n ) as unknown as Media;\n mediaEntity.isPublic = resolveStoredMediaIsPublic(mediaEntity.isPublic, storageProvider);\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n };\n return result;\n }\n\n async delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void> {\n const entityId = this.getSupportedEntityId(entity);\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n\n // @ts-ignore\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n // @ts-ignore\n this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id);\n for (const media of existingMedia) {\n const bucketName = storageProvider.bucketName;\n await this.s3FileService.delete(`${bucketName}:${media.relativeUri}`, { region });\n }\n }\n\n async deleteByMediaRecord(media: Media): Promise<void> {\n const storageProvider = media?.mediaStorageProviderMetadata;\n if (!storageProvider) {\n throw new Error(`mediaStorageProviderMetadata is not populated for media id ${media?.id ?? 'unknown'}`);\n }\n if (!storageProvider?.bucketName || !media?.relativeUri) {\n return;\n }\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n await this.s3FileService.delete(`${storageProvider.bucketName}:${media.relativeUri}`, { region });\n }\n\n private getSupportedEntityId(entity: T): number {\n const isSupportedEntity = entity instanceof CommonEntity\n || entity instanceof LegacyCommonEntityWithExistingId\n || entity instanceof LegacyCommonEntityWithGeneratedId;\n\n if (!isSupportedEntity) {\n throw new Error(\"Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId\");\n }\n\n return (entity as any).id;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"file-s3-storage-provider.js","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-s3-storage-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { ConfigService } from \"@nestjs/config\";\nimport { CommonEntity } from \"src/entities/common.entity\";\nimport { FieldMetadata } from \"src/entities/field-metadata.entity\";\nimport { LegacyCommonEntityWithExistingId } from \"src/entities/legacy-common.entity-with-existing-id.entity\";\nimport { LegacyCommonEntityWithGeneratedId } from \"src/entities/legacy-common-with-generated-id.entity\";\nimport { Media } from \"src/entities/media.entity\";\nimport { MediaStorageProvider } from \"src/interfaces\";\nimport { DiskFileService, S3FileService } from \"src/services/file\";\nimport { Readable } from \"stream\";\nimport { MediaRepository } from \"src/repository/media.repository\";\nimport { MediaDownloadUrlService } from \"src/services/media-download-url.service\";\nimport {\nbuildMediaRecordCreateInput,\nbuildStoredMediaFileName,\ngetEffectiveS3Region,\nresolveMediaIsPublic,\n} from \"src/services/media-storage.utils\";\n\n@Injectable()\nexport class FileS3StorageProvider<T> implements MediaStorageProvider<T> {\n private logger = new Logger(FileS3StorageProvider.name);\n\n constructor(\n private readonly configService: ConfigService,\n readonly diskFileService: DiskFileService,\n readonly s3FileService: S3FileService,\n readonly mediaRepository: MediaRepository,\n private readonly mediaDownloadUrlService: MediaDownloadUrlService,\n ) { }\n\n async storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n const entityId = this.getSupportedEntityId(entity);\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n\n for (const [stream, fileName] of streamPairs) {\n const bucketName = storageProvider.bucketName;\n\n // Buffer the stream so we can get the byte count and upload in one pass\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n const fileData = Buffer.concat(chunks);\n const fileSize = fileData.length;\n\n await this.s3FileService.write(`${bucketName}:${fileName}`, fileData, { region });\n\n const mediaEntity = await this.mediaRepository.createMedia(\n buildMediaRecordCreateInput(entityId, mediaFieldMetadata, storageProvider, {\n relativeUri: fileName,\n fileSize,\n })\n ) as unknown as Media;\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n }\n return result;\n }\n\n async retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n const entityId = this.getSupportedEntityId(entity);\n // @ts-ignore\n const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n\n // TODO: Check if the mediaStorageProvider (s3 in this case) is configured with a public bucket or not.\n // If private bucket then we need to return a \"signed-url\", the timeout for the signed url can be configured in the media storage provider entity and modified using the CRUD interface.\n // Add the full URL to the media\n for (const m of media) {\n const storageMeta = m.mediaStorageProviderMetadata;\n const isPublic = resolveMediaIsPublic(storageMeta);\n m['_full_url'] = isPublic === false\n ? await this.mediaDownloadUrlService.getPrivateUrl(m.id, m.relativeUri, storageMeta)\n : await this.s3FileService.getUrl(\n `${storageMeta.bucketName}:${m.relativeUri}`,\n { region: getEffectiveS3Region(this.configService, storageMeta.region), expiresIn: 0 },\n );\n }\n\n return media;\n // media.forEach(m => {\n // m['_full_url'] = this.getFullFilePath(m);\n // });\n // return media;\n }\n\n async store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n const entityId = this.getSupportedEntityId(entity);\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n\n for (const file of files) {\n const fileName = buildStoredMediaFileName(file);\n const bucketName = storageProvider.bucketName;\n\n // Read file from disk and upload to S3\n const fileData = await this.diskFileService.read(file.path);\n await this.s3FileService.write(`${bucketName}:${fileName}`, fileData, { contentType: file.mimetype, region });\n\n // Delete temp file from disk\n await this.diskFileService.delete(file.path);\n\n const awsFileUrl = fileName;\n\n // Create an entry in the media table\n const mediaEntity = await this.mediaRepository.createMedia(\n buildMediaRecordCreateInput(entityId, mediaFieldMetadata, storageProvider, {\n relativeUri: awsFileUrl,\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n })\n ) as unknown as Media;\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n };\n return result;\n }\n\n async delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void> {\n const entityId = this.getSupportedEntityId(entity);\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n\n // @ts-ignore\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n // @ts-ignore\n this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id);\n for (const media of existingMedia) {\n const bucketName = storageProvider.bucketName;\n await this.s3FileService.delete(`${bucketName}:${media.relativeUri}`, { region });\n }\n }\n\n async deleteByMediaRecord(media: Media): Promise<void> {\n const storageProvider = media?.mediaStorageProviderMetadata;\n if (!storageProvider) {\n throw new Error(`mediaStorageProviderMetadata is not populated for media id ${media?.id ?? 'unknown'}`);\n }\n if (!storageProvider?.bucketName || !media?.relativeUri) {\n return;\n }\n const region = getEffectiveS3Region(this.configService, storageProvider.region);\n await this.s3FileService.delete(`${storageProvider.bucketName}:${media.relativeUri}`, { region });\n }\n\n private getSupportedEntityId(entity: T): number {\n const isSupportedEntity = entity instanceof CommonEntity\n || entity instanceof LegacyCommonEntityWithExistingId\n || entity instanceof LegacyCommonEntityWithGeneratedId;\n\n if (!isSupportedEntity) {\n throw new Error(\"Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId\");\n }\n\n return (entity as any).id;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-storage-provider.d.ts","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-storage-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAGlF,qBACa,mBAAmB,CAAC,CAAC,CAAE,YAAW,oBAAoB,CAAC,CAAC,CAAC;IAI9D,QAAQ,CAAC,WAAW,EAAE,eAAe;IACrC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IAN5C,OAAO,CAAC,MAAM,CAAwC;gBAGzC,WAAW,EAAE,eAAe,EAC5B,eAAe,EAAE,eAAe,EACxB,cAAc,EAAE,cAAc,EAC9B,uBAAuB,EAAE,uBAAuB;IAI/D,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"file-storage-provider.d.ts","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-storage-provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAGlF,qBACa,mBAAmB,CAAC,CAAC,CAAE,YAAW,oBAAoB,CAAC,CAAC,CAAC;IAI9D,QAAQ,CAAC,WAAW,EAAE,eAAe;IACrC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IAN5C,OAAO,CAAC,MAAM,CAAwC;gBAGzC,WAAW,EAAE,eAAe,EAC5B,eAAe,EAAE,eAAe,EACxB,cAAc,EAAE,cAAc,EAC9B,uBAAuB,EAAE,uBAAuB;IAI/D,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAqBxE,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA4BnG,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAwB/G,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBnE,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtD,OAAO,CAAC,2BAA2B;IAInC,OAAO,CAAC,WAAW;CAGtB"}
|
|
@@ -63,10 +63,9 @@ let FileStorageProvider = FileStorageProvider_1 = class FileStorageProvider {
|
|
|
63
63
|
const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(this.getEntityId(entity), mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);
|
|
64
64
|
for (const m of media) {
|
|
65
65
|
const storageProvider = this.resolveMediaStorageProvider(m, mediaFieldMetadata);
|
|
66
|
-
const isPublic = (0, media_storage_utils_1.
|
|
67
|
-
m.isPublic = isPublic;
|
|
66
|
+
const isPublic = (0, media_storage_utils_1.resolveMediaIsPublic)(storageProvider);
|
|
68
67
|
m['_full_url'] = isPublic === false
|
|
69
|
-
? await this.mediaDownloadUrlService.
|
|
68
|
+
? await this.mediaDownloadUrlService.getPrivateUrl(m.id, m.relativeUri, storageProvider)
|
|
70
69
|
: await this.fileService.getUrl((0, media_storage_utils_1.buildDiskMediaPath)(m.relativeUri, this.settingService, storageProvider));
|
|
71
70
|
}
|
|
72
71
|
return media;
|
|
@@ -85,7 +84,6 @@ let FileStorageProvider = FileStorageProvider_1 = class FileStorageProvider {
|
|
|
85
84
|
fileSize: file.size,
|
|
86
85
|
originalFileName: file.originalname,
|
|
87
86
|
}));
|
|
88
|
-
mediaEntity.isPublic = (0, media_storage_utils_1.resolveStoredMediaIsPublic)(mediaEntity.isPublic, storageProvider);
|
|
89
87
|
result.push(mediaEntity);
|
|
90
88
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
91
89
|
}
|
|
@@ -105,7 +103,6 @@ let FileStorageProvider = FileStorageProvider_1 = class FileStorageProvider {
|
|
|
105
103
|
relativeUri: fileName,
|
|
106
104
|
fileSize,
|
|
107
105
|
}));
|
|
108
|
-
mediaEntity.isPublic = (0, media_storage_utils_1.resolveStoredMediaIsPublic)(mediaEntity.isPublic, storageProvider);
|
|
109
106
|
result.push(mediaEntity);
|
|
110
107
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
111
108
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-storage-provider.js","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-storage-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { FieldMetadata } from \"src/entities/field-metadata.entity\";\nimport { Media } from \"src/entities/media.entity\";\nimport { MediaStorageProviderMetadata } from \"src/entities/media-storage-provider-metadata.entity\";\nimport { MediaStorageProvider } from \"src/interfaces\";\nimport { MediaRepository } from \"src/repository/media.repository\";\nimport { DiskFileService } from \"src/services/file\";\nimport { Readable } from \"stream\";\nimport * as fs from \"fs\";\nimport { SettingService } from \"../setting.service\";\nimport { MediaDownloadUrlService } from \"src/services/media-download-url.service\";\nimport { buildDiskMediaPath, buildMediaRecordCreateInput, buildStoredMediaFileName, resolveStoredMediaIsPublic, } from \"src/services/media-storage.utils\";\n\n@Injectable()\nexport class FileStorageProvider<T> implements MediaStorageProvider<T> {\n private logger = new Logger(FileStorageProvider.name);\n\n constructor(\n readonly fileService: DiskFileService,\n readonly mediaRepository: MediaRepository,\n private readonly settingService: SettingService,\n private readonly mediaDownloadUrlService: MediaDownloadUrlService,\n\n ) { }\n\n async retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n // if (!(entity instanceof CommonEntity)) {\n // throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n // }\n //@ts-ignore\n const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(this.getEntityId(entity), mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n // Add the full URL to the media\n // media.forEach(m => {\n // });\n for (const m of media) {\n const storageProvider = this.resolveMediaStorageProvider(m, mediaFieldMetadata);\n const isPublic = resolveStoredMediaIsPublic(m.isPublic, storageProvider);\n m.isPublic = isPublic;\n m['_full_url'] = isPublic === false\n ? await this.mediaDownloadUrlService.resolveDownloadUrl(m.id, m.relativeUri, storageProvider)\n : await this.fileService.getUrl(buildDiskMediaPath(m.relativeUri, this.settingService, storageProvider));\n }\n\n\n return media;\n }\n\n async store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n // if (!(entity instanceof CommonEntity)) {\n // throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n // }\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n for (const file of files) {\n // Store the file in the configured file storage directory\n const fileName = buildStoredMediaFileName(file);\n const fileStoragePath = buildDiskMediaPath(fileName, this.settingService, storageProvider);\n await this.fileService.copy(file.path, fileStoragePath);\n await this.fileService.delete(file.path);\n\n // Create an entry in the media table\n const mediaEntity = await this.mediaRepository.createMedia(\n buildMediaRecordCreateInput(this.getEntityId(entity), mediaFieldMetadata, storageProvider, {\n relativeUri: fileName,\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n })\n ) as unknown as Media;\n mediaEntity.isPublic = resolveStoredMediaIsPublic(mediaEntity.isPublic, storageProvider);\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n };\n return result;\n }\n\n async storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n // if (!(entity instanceof CommonEntity)) {\n // throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n // }\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n for (const pair of streamPairs) {\n const stream = pair[0];\n const fileName = pair[1];\n const fullPath = buildDiskMediaPath(fileName, this.settingService, storageProvider);\n await this.fileService.writeStream(fullPath, stream);\n const { size: fileSize } = await fs.promises.stat(fullPath);\n const mediaEntity = await this.mediaRepository.createMedia(\n buildMediaRecordCreateInput(this.getEntityId(entity), mediaFieldMetadata, storageProvider, {\n relativeUri: fileName,\n fileSize,\n })\n ) as unknown as Media;\n mediaEntity.isPublic = resolveStoredMediaIsPublic(mediaEntity.isPublic, storageProvider);\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n };\n return result;\n }\n\n async delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void> {\n // if (!(entity instanceof CommonEntity)) {\n // throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n // }\n const entityId = this.getEntityId(entity);\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n await this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id);\n\n for (const media of existingMedia) {\n const storageProvider = this.resolveMediaStorageProvider(media, mediaFieldMetadata);\n await this.fileService.delete(buildDiskMediaPath(media.relativeUri, this.settingService, storageProvider));\n }\n // existingMedia.forEach(media => {\n // });\n }\n\n async deleteByMediaRecord(media: Media): Promise<void> {\n if (!media?.relativeUri) {\n return;\n }\n await this.fileService.delete(buildDiskMediaPath(media.relativeUri, this.settingService, media.mediaStorageProviderMetadata));\n }\n\n private resolveMediaStorageProvider(media: Media, mediaFieldMetadata?: FieldMetadata): MediaStorageProviderMetadata | undefined {\n return media.mediaStorageProviderMetadata || mediaFieldMetadata?.mediaStorageProvider;\n }\n\n private getEntityId(entity: T): number {\n return (entity as any).id;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"file-storage-provider.js","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-storage-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { FieldMetadata } from \"src/entities/field-metadata.entity\";\nimport { Media } from \"src/entities/media.entity\";\nimport { MediaStorageProviderMetadata } from \"src/entities/media-storage-provider-metadata.entity\";\nimport { MediaStorageProvider } from \"src/interfaces\";\nimport { MediaRepository } from \"src/repository/media.repository\";\nimport { DiskFileService } from \"src/services/file\";\nimport { Readable } from \"stream\";\nimport * as fs from \"fs\";\nimport { SettingService } from \"../setting.service\";\nimport { MediaDownloadUrlService } from \"src/services/media-download-url.service\";\nimport {buildDiskMediaPath,buildMediaRecordCreateInput,buildStoredMediaFileName,resolveMediaIsPublic,} from \"src/services/media-storage.utils\";\n\n@Injectable()\nexport class FileStorageProvider<T> implements MediaStorageProvider<T> {\n private logger = new Logger(FileStorageProvider.name);\n\n constructor(\n readonly fileService: DiskFileService,\n readonly mediaRepository: MediaRepository,\n private readonly settingService: SettingService,\n private readonly mediaDownloadUrlService: MediaDownloadUrlService,\n\n ) { }\n\n async retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n // if (!(entity instanceof CommonEntity)) {\n // throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n // }\n //@ts-ignore\n const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(this.getEntityId(entity), mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n // Add the full URL to the media\n // media.forEach(m => {\n // });\n for (const m of media) {\n const storageProvider = this.resolveMediaStorageProvider(m, mediaFieldMetadata);\n const isPublic = resolveMediaIsPublic(storageProvider);\n m['_full_url'] = isPublic === false\n ? await this.mediaDownloadUrlService.getPrivateUrl(m.id, m.relativeUri, storageProvider)\n : await this.fileService.getUrl(buildDiskMediaPath(m.relativeUri, this.settingService, storageProvider));\n }\n\n\n return media;\n }\n\n async store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n // if (!(entity instanceof CommonEntity)) {\n // throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n // }\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n for (const file of files) {\n // Store the file in the configured file storage directory\n const fileName = buildStoredMediaFileName(file);\n const fileStoragePath = buildDiskMediaPath(fileName, this.settingService, storageProvider);\n await this.fileService.copy(file.path, fileStoragePath);\n await this.fileService.delete(file.path);\n\n // Create an entry in the media table\n const mediaEntity = await this.mediaRepository.createMedia(\n buildMediaRecordCreateInput(this.getEntityId(entity), mediaFieldMetadata, storageProvider, {\n relativeUri: fileName,\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n })\n ) as unknown as Media;\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n };\n return result;\n }\n\n async storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n // if (!(entity instanceof CommonEntity)) {\n // throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n // }\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n for (const pair of streamPairs) {\n const stream = pair[0];\n const fileName = pair[1];\n const fullPath = buildDiskMediaPath(fileName, this.settingService, storageProvider);\n await this.fileService.writeStream(fullPath, stream);\n const { size: fileSize } = await fs.promises.stat(fullPath);\n const mediaEntity = await this.mediaRepository.createMedia(\n buildMediaRecordCreateInput(this.getEntityId(entity), mediaFieldMetadata, storageProvider, {\n relativeUri: fileName,\n fileSize,\n })\n ) as unknown as Media;\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n };\n return result;\n }\n\n async delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void> {\n // if (!(entity instanceof CommonEntity)) {\n // throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n // }\n const entityId = this.getEntityId(entity);\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n await this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id);\n\n for (const media of existingMedia) {\n const storageProvider = this.resolveMediaStorageProvider(media, mediaFieldMetadata);\n await this.fileService.delete(buildDiskMediaPath(media.relativeUri, this.settingService, storageProvider));\n }\n // existingMedia.forEach(media => {\n // });\n }\n\n async deleteByMediaRecord(media: Media): Promise<void> {\n if (!media?.relativeUri) {\n return;\n }\n await this.fileService.delete(buildDiskMediaPath(media.relativeUri, this.settingService, media.mediaStorageProviderMetadata));\n }\n\n private resolveMediaStorageProvider(media: Media, mediaFieldMetadata?: FieldMetadata): MediaStorageProviderMetadata | undefined {\n return media.mediaStorageProviderMetadata || mediaFieldMetadata?.mediaStorageProvider;\n }\n\n private getEntityId(entity: T): number {\n return (entity as any).id;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidxai/core",
|
|
3
|
-
"version": "0.1.12-beta.
|
|
3
|
+
"version": "0.1.12-beta.9",
|
|
4
4
|
"description": "This module is a NestJS module containing all the required core providers required by a Solid application",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -7,7 +7,6 @@ import { MediaStorageProviderMetadataRepository } from './media-storage-provider
|
|
|
7
7
|
import { ModelMetadataRepository } from './model-metadata.repository';
|
|
8
8
|
import { SecurityRuleRepository } from './security-rule.repository';
|
|
9
9
|
import { SolidBaseRepository } from './solid-base.repository';
|
|
10
|
-
import { resolveStoredMediaIsPublic } from 'src/services/media-storage.utils';
|
|
11
10
|
|
|
12
11
|
@Injectable()
|
|
13
12
|
export class MediaRepository extends SolidBaseRepository<Media> {
|
|
@@ -45,7 +44,7 @@ export class MediaRepository extends SolidBaseRepository<Media> {
|
|
|
45
44
|
id: createDto['mediaStorageProviderMetadataId']
|
|
46
45
|
},
|
|
47
46
|
});
|
|
48
|
-
|
|
47
|
+
// delete createDto['isPublic'];
|
|
49
48
|
const media = this.create(createDto);
|
|
50
49
|
return this.save(media);
|
|
51
50
|
}
|
|
@@ -1704,18 +1704,6 @@
|
|
|
1704
1704
|
"columnName": "original_file_name",
|
|
1705
1705
|
"isSystem": true
|
|
1706
1706
|
},
|
|
1707
|
-
{
|
|
1708
|
-
"name": "isPublic",
|
|
1709
|
-
"displayName": "Is Public",
|
|
1710
|
-
"type": "boolean",
|
|
1711
|
-
"required": false,
|
|
1712
|
-
"unique": false,
|
|
1713
|
-
"index": false,
|
|
1714
|
-
"private": false,
|
|
1715
|
-
"encrypt": false,
|
|
1716
|
-
"columnName": "is_public",
|
|
1717
|
-
"isSystem": true
|
|
1718
|
-
},
|
|
1719
1707
|
{
|
|
1720
1708
|
"name": "modelMetadata",
|
|
1721
1709
|
"displayName": "Model Metadata",
|
|
@@ -8789,13 +8777,6 @@
|
|
|
8789
8777
|
"sortable": false
|
|
8790
8778
|
}
|
|
8791
8779
|
},
|
|
8792
|
-
{
|
|
8793
|
-
"type": "field",
|
|
8794
|
-
"attrs": {
|
|
8795
|
-
"name": "isPublic",
|
|
8796
|
-
"sortable": true
|
|
8797
|
-
}
|
|
8798
|
-
},
|
|
8799
8780
|
{
|
|
8800
8781
|
"type": "field",
|
|
8801
8782
|
"attrs": {
|
|
@@ -8891,14 +8872,6 @@
|
|
|
8891
8872
|
"isSearchable": true
|
|
8892
8873
|
}
|
|
8893
8874
|
},
|
|
8894
|
-
{
|
|
8895
|
-
"type": "field",
|
|
8896
|
-
"attrs": {
|
|
8897
|
-
"name": "isPublic",
|
|
8898
|
-
"label": "isPublic",
|
|
8899
|
-
"isSearchable": true
|
|
8900
|
-
}
|
|
8901
|
-
},
|
|
8902
8875
|
{
|
|
8903
8876
|
"type": "field",
|
|
8904
8877
|
"attrs": {
|
|
@@ -8967,12 +8940,6 @@
|
|
|
8967
8940
|
"name": "mediaStorageProviderMetadata"
|
|
8968
8941
|
}
|
|
8969
8942
|
},
|
|
8970
|
-
{
|
|
8971
|
-
"type": "field",
|
|
8972
|
-
"attrs": {
|
|
8973
|
-
"name": "isPublic"
|
|
8974
|
-
}
|
|
8975
|
-
},
|
|
8976
8943
|
{
|
|
8977
8944
|
"type": "field",
|
|
8978
8945
|
"attrs": {
|
|
@@ -14581,12 +14548,6 @@
|
|
|
14581
14548
|
"isPublic": true,
|
|
14582
14549
|
"localPath": "media-files-storage"
|
|
14583
14550
|
},
|
|
14584
|
-
{
|
|
14585
|
-
"name": "private-filesystem",
|
|
14586
|
-
"type": "filesystem",
|
|
14587
|
-
"isPublic": false,
|
|
14588
|
-
"localPath": "media-private-files-storage"
|
|
14589
|
-
},
|
|
14590
14551
|
{
|
|
14591
14552
|
"name": "default-aws-s3",
|
|
14592
14553
|
"type": "aws-s3"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Injectable, Logger } from '@nestjs/common';
|
|
2
|
-
import { ConfigService } from '@nestjs/config';
|
|
3
2
|
import { JwtService } from '@nestjs/jwt';
|
|
4
3
|
import { MediaStorageProviderType } from 'src/dtos/create-media-storage-provider-metadata.dto';
|
|
5
4
|
import { MediaStorageProviderMetadata } from 'src/entities/media-storage-provider-metadata.entity';
|
|
6
|
-
import { S3FileService } from 'src/services/file';
|
|
7
|
-
import { getEffectiveS3Region } from 'src/services/media-storage.utils';
|
|
8
5
|
import { SettingService } from 'src/services/setting.service';
|
|
9
6
|
import type { SolidCoreSetting } from 'src/services/settings/default-settings-provider.service';
|
|
7
|
+
import { getEffectiveS3Region } from './media-storage.utils';
|
|
8
|
+
import { ConfigService } from '@nestjs/config';
|
|
9
|
+
import { S3FileService } from './file';
|
|
10
10
|
|
|
11
11
|
export const MEDIA_DOWNLOAD_TOKEN_AUDIENCE = 'media-download';
|
|
12
12
|
const DEFAULT_SIGNED_URL_EXPIRY_MINUTES = 60;
|
|
@@ -26,10 +26,14 @@ export class MediaDownloadUrlService {
|
|
|
26
26
|
private readonly configService: ConfigService,
|
|
27
27
|
) { }
|
|
28
28
|
|
|
29
|
-
async resolveDownloadUrl(
|
|
29
|
+
async resolveDownloadUrl(
|
|
30
|
+
mediaId: number,
|
|
31
|
+
relativeUri: string,
|
|
32
|
+
storageProvider?: MediaStorageProviderMetadata,
|
|
33
|
+
): Promise<string> {
|
|
30
34
|
const expiryMinutes = storageProvider?.signedUrlExpiry ?? DEFAULT_SIGNED_URL_EXPIRY_MINUTES;
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
if ((storageProvider?.type as MediaStorageProviderType) === MediaStorageProviderType.AwsS3) {
|
|
33
37
|
if (storageProvider?.bucketName) {
|
|
34
38
|
return this.s3FileService.getUrl(
|
|
35
39
|
`${storageProvider.bucketName}:${relativeUri}`,
|
|
@@ -38,7 +42,6 @@ export class MediaDownloadUrlService {
|
|
|
38
42
|
}
|
|
39
43
|
this.logger.warn(`Media id ${mediaId}: AwsS3 provider missing bucketName; falling back to app-hosted token URL`);
|
|
40
44
|
}
|
|
41
|
-
|
|
42
45
|
// Filesystem (or misconfigured S3) has no native presigned-URL mechanism, so mint our
|
|
43
46
|
// own short-lived token and embed it in the download URL - the token alone authorizes
|
|
44
47
|
// the request (see MediaSignedUrlGuard), so it works in a plain <img src> with no
|
|
@@ -49,6 +52,10 @@ export class MediaDownloadUrlService {
|
|
|
49
52
|
return `${String(baseUrl).replace(/\/+$/, '')}${downloadPath}`;
|
|
50
53
|
}
|
|
51
54
|
|
|
55
|
+
async getPrivateUrl(mediaId: number, relativeUri: string, storageProvider?: MediaStorageProviderMetadata): Promise<string> {
|
|
56
|
+
return this.resolveDownloadUrl(mediaId, relativeUri, storageProvider);
|
|
57
|
+
}
|
|
58
|
+
|
|
52
59
|
async verifyDownloadToken(token: string): Promise<MediaDownloadTokenPayload> {
|
|
53
60
|
return this.jwtService.verifyAsync<MediaDownloadTokenPayload>(token, {
|
|
54
61
|
secret: this.settingService.getConfigValue<SolidCoreSetting>('secret'),
|
|
@@ -6,7 +6,6 @@ import { SettingService } from 'src/services/setting.service';
|
|
|
6
6
|
import { DEFAULT_MEDIA_FILE_STORAGE_DIR } from 'src/services/settings/default-settings-provider.service';
|
|
7
7
|
import type { SolidCoreSetting } from 'src/services/settings/default-settings-provider.service';
|
|
8
8
|
|
|
9
|
-
export const DEFAULT_PRIVATE_MEDIA_STORAGE_DIR = 'media-private-files-storage';
|
|
10
9
|
|
|
11
10
|
export interface MediaRecordCreateInput {
|
|
12
11
|
entityId: number;
|
|
@@ -17,7 +16,6 @@ export interface MediaRecordCreateInput {
|
|
|
17
16
|
mimeType?: string;
|
|
18
17
|
fileSize?: number;
|
|
19
18
|
originalFileName?: string;
|
|
20
|
-
isPublic?: boolean;
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
// Builds the stored file name format shared by media storage implementations.
|
|
@@ -28,8 +26,10 @@ export function buildStoredMediaFileName(file: Pick<Express.Multer.File, 'filena
|
|
|
28
26
|
// Resolves the on-disk path for a media file based on settings and provider visibility.
|
|
29
27
|
export function buildDiskMediaPath(fileName: string,settingService: Pick<SettingService, 'getConfigValue'>,storageProvider?: Pick<MediaStorageProviderMetadata, 'localPath' | 'isPublic'>,): string {
|
|
30
28
|
const publicBase = settingService.getConfigValue<SolidCoreSetting>('fileStorageDir') || DEFAULT_MEDIA_FILE_STORAGE_DIR;
|
|
31
|
-
const privateBase =
|
|
32
|
-
const
|
|
29
|
+
const privateBase = `${publicBase}-private`;
|
|
30
|
+
// const localPath = storageProvider?.localPath;
|
|
31
|
+
// const isUsingLegacyDefaultPath = localPath === publicBase || localPath === privateBase || localPath === privateBase;
|
|
32
|
+
const providerBase = storageProvider?.isPublic === false ? privateBase : publicBase
|
|
33
33
|
|
|
34
34
|
if ( path.isAbsolute(fileName) || fileName.startsWith(`${publicBase}/`) || fileName.startsWith(`${privateBase}/`) || (!!storageProvider?.localPath && fileName.startsWith(`${storageProvider.localPath}/`))) {
|
|
35
35
|
return fileName;
|
|
@@ -39,12 +39,12 @@ export function buildDiskMediaPath(fileName: string,settingService: Pick<Setting
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// Returns the S3 region from the provider when present, otherwise falls back to app config.
|
|
42
|
-
export function getEffectiveS3Region(configService: Pick<ConfigService, 'get'>,providerRegion?: string
|
|
42
|
+
export function getEffectiveS3Region(configService: Pick<ConfigService, 'get'>, providerRegion?: string): string | undefined {
|
|
43
43
|
return providerRegion || configService.get<string>('S3_AWS_REGION_NAME');
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
// Resolves the effective public/private flag for a media storage provider.
|
|
47
|
-
export function resolveMediaIsPublic(storageProvider?: Pick<MediaStorageProviderMetadata, 'isPublic'
|
|
47
|
+
export function resolveMediaIsPublic(storageProvider?: Pick<MediaStorageProviderMetadata, 'isPublic'>): boolean | undefined {
|
|
48
48
|
if (!storageProvider) {
|
|
49
49
|
return undefined;
|
|
50
50
|
}
|
|
@@ -52,15 +52,6 @@ export function resolveMediaIsPublic(storageProvider?: Pick<MediaStorageProvider
|
|
|
52
52
|
return storageProvider.isPublic !== false;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// Preserves an explicit media visibility value or derives it from the storage provider.
|
|
56
|
-
export function resolveStoredMediaIsPublic(currentValue: boolean | undefined,storageProvider?:Pick<MediaStorageProviderMetadata, 'isPublic'>,): boolean | undefined {
|
|
57
|
-
if (typeof currentValue === 'boolean') {
|
|
58
|
-
return currentValue;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return resolveMediaIsPublic(storageProvider);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
55
|
// Builds the shared media record payload used before saving media metadata to the database.
|
|
65
56
|
export function buildMediaRecordCreateInput(
|
|
66
57
|
entityId: number,
|
|
@@ -20,7 +20,7 @@ import { FieldMetadataRepository } from 'src/repository/field-metadata.repositor
|
|
|
20
20
|
import { MediaStorageProviderMetadataRepository } from 'src/repository/media-storage-provider-metadata.repository';
|
|
21
21
|
import { MediaRepository } from 'src/repository/media.repository';
|
|
22
22
|
import { ModelMetadataRepository } from 'src/repository/model-metadata.repository';
|
|
23
|
-
import { buildDiskMediaPath, buildStoredMediaFileName, getEffectiveS3Region,
|
|
23
|
+
import { buildDiskMediaPath, buildStoredMediaFileName, getEffectiveS3Region, resolveMediaIsPublic, } from 'src/services/media-storage.utils';
|
|
24
24
|
import { getMediaStorageProvider } from "./mediaStorageProviders";
|
|
25
25
|
|
|
26
26
|
@Injectable()
|
|
@@ -131,10 +131,9 @@ export class MediaService extends CRUDService<Media> {
|
|
|
131
131
|
// Delete temp file from disk
|
|
132
132
|
await this.diskFileService.delete(file.path);
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
delete createDto['isPublic'];
|
|
135
135
|
const media = this.repo.create(createDto as Partial<Media>) as Media;
|
|
136
136
|
const savedMedia = await this.repo.save(media);
|
|
137
|
-
savedMedia.isPublic = resolveStoredMediaIsPublic(savedMedia.isPublic, storageProvider);
|
|
138
137
|
savedMedias.push(savedMedia)
|
|
139
138
|
}
|
|
140
139
|
return savedMedias
|
|
@@ -228,16 +227,15 @@ export class MediaService extends CRUDService<Media> {
|
|
|
228
227
|
|
|
229
228
|
private async decorateMediaRecord(media: Media): Promise<void> {
|
|
230
229
|
const mediaStorageProvider = await this.resolveMediaStorageProvider(media);
|
|
231
|
-
media.isPublic = resolveStoredMediaIsPublic(media.isPublic, mediaStorageProvider);
|
|
232
230
|
media.relativeUri = await this.resolveMediaUrl(media, mediaStorageProvider);
|
|
233
231
|
}
|
|
234
232
|
|
|
235
233
|
private async resolveMediaUrl(media: Media, mediaStorageProvider?: MediaStorageProviderMetadata): Promise<string> {
|
|
236
234
|
const resolvedMediaStorageProvider = mediaStorageProvider || await this.resolveMediaStorageProvider(media);
|
|
237
|
-
const isPublic =
|
|
235
|
+
const isPublic = resolveMediaIsPublic(resolvedMediaStorageProvider);
|
|
238
236
|
|
|
239
237
|
if (isPublic === false) {
|
|
240
|
-
return this.mediaDownloadUrlService.
|
|
238
|
+
return this.mediaDownloadUrlService.getPrivateUrl(media.id, media.relativeUri, resolvedMediaStorageProvider);
|
|
241
239
|
}
|
|
242
240
|
|
|
243
241
|
if (resolvedMediaStorageProvider?.type === MediaStorageProviderType.Filesystem) {
|
|
@@ -11,10 +11,10 @@ import { Readable } from "stream";
|
|
|
11
11
|
import { MediaRepository } from "src/repository/media.repository";
|
|
12
12
|
import { MediaDownloadUrlService } from "src/services/media-download-url.service";
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
buildMediaRecordCreateInput,
|
|
15
|
+
buildStoredMediaFileName,
|
|
16
|
+
getEffectiveS3Region,
|
|
17
|
+
resolveMediaIsPublic,
|
|
18
18
|
} from "src/services/media-storage.utils";
|
|
19
19
|
|
|
20
20
|
@Injectable()
|
|
@@ -54,7 +54,6 @@ export class FileS3StorageProvider<T> implements MediaStorageProvider<T> {
|
|
|
54
54
|
fileSize,
|
|
55
55
|
})
|
|
56
56
|
) as unknown as Media;
|
|
57
|
-
mediaEntity.isPublic = resolveStoredMediaIsPublic(mediaEntity.isPublic, storageProvider);
|
|
58
57
|
result.push(mediaEntity);
|
|
59
58
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
60
59
|
}
|
|
@@ -71,10 +70,9 @@ export class FileS3StorageProvider<T> implements MediaStorageProvider<T> {
|
|
|
71
70
|
// Add the full URL to the media
|
|
72
71
|
for (const m of media) {
|
|
73
72
|
const storageMeta = m.mediaStorageProviderMetadata;
|
|
74
|
-
const isPublic =
|
|
75
|
-
m.isPublic = isPublic;
|
|
73
|
+
const isPublic = resolveMediaIsPublic(storageMeta);
|
|
76
74
|
m['_full_url'] = isPublic === false
|
|
77
|
-
? await this.mediaDownloadUrlService.
|
|
75
|
+
? await this.mediaDownloadUrlService.getPrivateUrl(m.id, m.relativeUri, storageMeta)
|
|
78
76
|
: await this.s3FileService.getUrl(
|
|
79
77
|
`${storageMeta.bucketName}:${m.relativeUri}`,
|
|
80
78
|
{ region: getEffectiveS3Region(this.configService, storageMeta.region), expiresIn: 0 },
|
|
@@ -116,7 +114,6 @@ export class FileS3StorageProvider<T> implements MediaStorageProvider<T> {
|
|
|
116
114
|
originalFileName: file.originalname,
|
|
117
115
|
})
|
|
118
116
|
) as unknown as Media;
|
|
119
|
-
mediaEntity.isPublic = resolveStoredMediaIsPublic(mediaEntity.isPublic, storageProvider);
|
|
120
117
|
result.push(mediaEntity);
|
|
121
118
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
122
119
|
};
|
|
@@ -9,7 +9,7 @@ import { Readable } from "stream";
|
|
|
9
9
|
import * as fs from "fs";
|
|
10
10
|
import { SettingService } from "../setting.service";
|
|
11
11
|
import { MediaDownloadUrlService } from "src/services/media-download-url.service";
|
|
12
|
-
import {
|
|
12
|
+
import {buildDiskMediaPath,buildMediaRecordCreateInput,buildStoredMediaFileName,resolveMediaIsPublic,} from "src/services/media-storage.utils";
|
|
13
13
|
|
|
14
14
|
@Injectable()
|
|
15
15
|
export class FileStorageProvider<T> implements MediaStorageProvider<T> {
|
|
@@ -34,10 +34,9 @@ export class FileStorageProvider<T> implements MediaStorageProvider<T> {
|
|
|
34
34
|
// });
|
|
35
35
|
for (const m of media) {
|
|
36
36
|
const storageProvider = this.resolveMediaStorageProvider(m, mediaFieldMetadata);
|
|
37
|
-
const isPublic =
|
|
38
|
-
m.isPublic = isPublic;
|
|
37
|
+
const isPublic = resolveMediaIsPublic(storageProvider);
|
|
39
38
|
m['_full_url'] = isPublic === false
|
|
40
|
-
? await this.mediaDownloadUrlService.
|
|
39
|
+
? await this.mediaDownloadUrlService.getPrivateUrl(m.id, m.relativeUri, storageProvider)
|
|
41
40
|
: await this.fileService.getUrl(buildDiskMediaPath(m.relativeUri, this.settingService, storageProvider));
|
|
42
41
|
}
|
|
43
42
|
|
|
@@ -67,7 +66,6 @@ export class FileStorageProvider<T> implements MediaStorageProvider<T> {
|
|
|
67
66
|
originalFileName: file.originalname,
|
|
68
67
|
})
|
|
69
68
|
) as unknown as Media;
|
|
70
|
-
mediaEntity.isPublic = resolveStoredMediaIsPublic(mediaEntity.isPublic, storageProvider);
|
|
71
69
|
result.push(mediaEntity);
|
|
72
70
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
73
71
|
};
|
|
@@ -92,7 +90,6 @@ export class FileStorageProvider<T> implements MediaStorageProvider<T> {
|
|
|
92
90
|
fileSize,
|
|
93
91
|
})
|
|
94
92
|
) as unknown as Media;
|
|
95
|
-
mediaEntity.isPublic = resolveStoredMediaIsPublic(mediaEntity.isPublic, storageProvider);
|
|
96
93
|
result.push(mediaEntity);
|
|
97
94
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
98
95
|
};
|