@solidxai/core 0.1.12-beta.0 → 0.1.12-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/seed.command.d.ts.map +1 -1
- package/dist/commands/seed.command.js +10 -2
- package/dist/commands/seed.command.js.map +1 -1
- package/dist/constants/error-messages.d.ts +1 -0
- package/dist/constants/error-messages.d.ts.map +1 -1
- package/dist/constants/error-messages.js +1 -0
- package/dist/constants/error-messages.js.map +1 -1
- package/dist/constants/media-file-types.d.ts +5 -0
- package/dist/constants/media-file-types.d.ts.map +1 -0
- package/dist/constants/media-file-types.js +27 -0
- package/dist/constants/media-file-types.js.map +1 -0
- package/dist/controllers/media.controller.d.ts +14 -11
- package/dist/controllers/media.controller.d.ts.map +1 -1
- package/dist/controllers/media.controller.js +72 -33
- package/dist/controllers/media.controller.js.map +1 -1
- package/dist/dtos/create-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/create-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/create-chatter-message.dto.js +7 -1
- package/dist/dtos/create-chatter-message.dto.js.map +1 -1
- package/dist/dtos/create-media.dto.d.ts +1 -0
- package/dist/dtos/create-media.dto.d.ts.map +1 -1
- package/dist/dtos/create-media.dto.js +7 -1
- package/dist/dtos/create-media.dto.js.map +1 -1
- package/dist/dtos/create-role-metadata.dto.d.ts +2 -0
- package/dist/dtos/create-role-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-role-metadata.dto.js +3 -1
- package/dist/dtos/create-role-metadata.dto.js.map +1 -1
- package/dist/dtos/post-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/post-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/post-chatter-message.dto.js +6 -1
- package/dist/dtos/post-chatter-message.dto.js.map +1 -1
- package/dist/dtos/update-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/update-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/update-chatter-message.dto.js +8 -1
- package/dist/dtos/update-chatter-message.dto.js.map +1 -1
- package/dist/dtos/update-chatter-note-message.dto.d.ts +1 -0
- package/dist/dtos/update-chatter-note-message.dto.d.ts.map +1 -1
- package/dist/dtos/update-chatter-note-message.dto.js +7 -1
- package/dist/dtos/update-chatter-note-message.dto.js.map +1 -1
- package/dist/dtos/update-media.dto.d.ts +1 -0
- package/dist/dtos/update-media.dto.d.ts.map +1 -1
- package/dist/dtos/update-media.dto.js +7 -1
- package/dist/dtos/update-media.dto.js.map +1 -1
- package/dist/entities/chatter-message.entity.d.ts +1 -0
- package/dist/entities/chatter-message.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message.entity.js +5 -1
- package/dist/entities/chatter-message.entity.js.map +1 -1
- package/dist/entities/media.entity.js.map +1 -1
- package/dist/enums/auth-type.enum.d.ts +2 -1
- package/dist/enums/auth-type.enum.d.ts.map +1 -1
- package/dist/enums/auth-type.enum.js +1 -0
- package/dist/enums/auth-type.enum.js.map +1 -1
- package/dist/guards/authentication.guard.d.ts +3 -1
- package/dist/guards/authentication.guard.d.ts.map +1 -1
- package/dist/guards/authentication.guard.js +5 -1
- package/dist/guards/authentication.guard.js.map +1 -1
- package/dist/guards/media-signed-url.guard.d.ts +9 -0
- package/dist/guards/media-signed-url.guard.d.ts.map +1 -0
- package/dist/guards/media-signed-url.guard.js +49 -0
- package/dist/guards/media-signed-url.guard.js.map +1 -0
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +10 -13
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.js +9 -0
- package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
- package/dist/interfaces/chatter-mention-notification.interface.d.ts +27 -0
- package/dist/interfaces/chatter-mention-notification.interface.d.ts.map +1 -0
- package/dist/interfaces/chatter-mention-notification.interface.js +3 -0
- package/dist/interfaces/chatter-mention-notification.interface.js.map +1 -0
- package/dist/interfaces.d.ts +19 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js +2 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts +17 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts.map +1 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js +106 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts +12 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js +39 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts +8 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js +10 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts +20 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js +48 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts +12 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js +39 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts +8 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js +10 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts +18 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js +45 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts +12 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js +39 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts +8 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js +10 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts +18 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js +45 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js.map +1 -0
- package/dist/repository/media.repository.d.ts.map +1 -1
- package/dist/repository/media.repository.js.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts +7 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +87 -3
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/permission-metadata-seeder.service.d.ts +1 -0
- package/dist/seeders/permission-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/permission-metadata-seeder.service.js +6 -1
- package/dist/seeders/permission-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +95 -13
- package/dist/services/authentication.service.d.ts +2 -2
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +52 -43
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts +7 -1
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +85 -4
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/media-download-url.service.d.ts +22 -0
- package/dist/services/media-download-url.service.d.ts.map +1 -0
- package/dist/services/media-download-url.service.js +70 -0
- package/dist/services/media-download-url.service.js.map +1 -0
- package/dist/services/media-storage.utils.d.ts +24 -0
- package/dist/services/media-storage.utils.d.ts.map +1 -0
- package/dist/services/media-storage.utils.js +73 -0
- package/dist/services/media-storage.utils.js.map +1 -0
- package/dist/services/media.service.d.ts +20 -4
- package/dist/services/media.service.d.ts.map +1 -1
- package/dist/services/media.service.js +155 -55
- package/dist/services/media.service.js.map +1 -1
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.d.ts +4 -4
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.d.ts.map +1 -1
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.js +34 -63
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
- package/dist/services/mediaStorageProviders/file-storage-provider.d.ts +5 -5
- package/dist/services/mediaStorageProviders/file-storage-provider.d.ts.map +1 -1
- package/dist/services/mediaStorageProviders/file-storage-provider.js +34 -38
- package/dist/services/mediaStorageProviders/file-storage-provider.js.map +1 -1
- package/dist/services/role-metadata.service.d.ts +1 -0
- package/dist/services/role-metadata.service.d.ts.map +1 -1
- package/dist/services/role-metadata.service.js +8 -5
- package/dist/services/role-metadata.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +25 -1
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/audit.subscriber.js +1 -1
- package/dist/subscribers/audit.subscriber.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/seed.command.ts +12 -3
- package/src/constants/error-messages.ts +1 -0
- package/src/constants/media-file-types.ts +44 -0
- package/src/controllers/media.controller.ts +44 -24
- package/src/dtos/create-chatter-message.dto.ts +5 -0
- package/src/dtos/create-media.dto.ts +8 -3
- package/src/dtos/create-role-metadata.dto.ts +2 -0
- package/src/dtos/post-chatter-message.dto.ts +4 -0
- package/src/dtos/update-chatter-message.dto.ts +6 -0
- package/src/dtos/update-chatter-note-message.dto.ts +5 -0
- package/src/dtos/update-media.dto.ts +8 -3
- package/src/entities/chatter-message.entity.ts +3 -0
- package/src/entities/media.entity.ts +1 -1
- package/src/enums/auth-type.enum.ts +1 -0
- package/src/guards/authentication.guard.ts +3 -0
- package/src/guards/media-signed-url.guard.ts +41 -0
- package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +12 -24
- package/src/helpers/solid-core-error-codes-provider.service.ts +9 -0
- package/src/interfaces/chatter-mention-notification.interface.ts +29 -0
- package/src/interfaces.ts +20 -0
- package/src/jobs/chatter-mention-notification-email-queue-handler.service.ts +114 -0
- package/src/jobs/database/chatter-mention-notification-email-publisher-database.service.ts +23 -0
- package/src/jobs/database/chatter-mention-notification-email-queue-options-database.ts +9 -0
- package/src/jobs/database/chatter-mention-notification-email-subscriber-database.service.ts +32 -0
- package/src/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.ts +23 -0
- package/src/jobs/rabbitmq/chatter-mention-notification-email-queue-options.ts +9 -0
- package/src/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.ts +30 -0
- package/src/jobs/redis/chatter-mention-notification-email-publisher-redis.service.ts +23 -0
- package/src/jobs/redis/chatter-mention-notification-email-queue-options-redis.ts +9 -0
- package/src/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.ts +30 -0
- package/src/repository/media.repository.ts +1 -0
- package/src/seeders/module-metadata-seeder.service.ts +109 -3
- package/src/seeders/permission-metadata-seeder.service.ts +6 -1
- package/src/seeders/seed-data/email-templates/chatter-mention-notification.handlebars.html +200 -0
- package/src/seeders/seed-data/solid-core-metadata.json +95 -13
- package/src/services/authentication.service.ts +66 -55
- package/src/services/chatter-message.service.ts +97 -2
- package/src/services/media-download-url.service.ts +74 -0
- package/src/services/media-storage.utils.ts +70 -0
- package/src/services/media.service.ts +187 -59
- package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +49 -76
- package/src/services/mediaStorageProviders/file-storage-provider.ts +41 -48
- package/src/services/role-metadata.service.ts +17 -5
- package/src/solid-core.module.ts +35 -2
- package/src/subscribers/audit.subscriber.ts +1 -1
|
@@ -5,20 +5,20 @@ import { MediaStorageProvider } from "../../interfaces";
|
|
|
5
5
|
import { DiskFileService, S3FileService } from "../../services/file";
|
|
6
6
|
import { Readable } from "stream";
|
|
7
7
|
import { MediaRepository } from "../../repository/media.repository";
|
|
8
|
+
import { MediaDownloadUrlService } from "../../services/media-download-url.service";
|
|
8
9
|
export declare class FileS3StorageProvider<T> implements MediaStorageProvider<T> {
|
|
9
10
|
private readonly configService;
|
|
10
11
|
readonly diskFileService: DiskFileService;
|
|
11
12
|
readonly s3FileService: S3FileService;
|
|
12
13
|
readonly mediaRepository: MediaRepository;
|
|
14
|
+
private readonly mediaDownloadUrlService;
|
|
13
15
|
private logger;
|
|
14
|
-
constructor(configService: ConfigService, diskFileService: DiskFileService, s3FileService: S3FileService, mediaRepository: MediaRepository);
|
|
16
|
+
constructor(configService: ConfigService, diskFileService: DiskFileService, s3FileService: S3FileService, mediaRepository: MediaRepository, mediaDownloadUrlService: MediaDownloadUrlService);
|
|
15
17
|
storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
|
|
16
18
|
retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
|
|
17
19
|
store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
|
|
18
20
|
delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void>;
|
|
19
21
|
deleteByMediaRecord(media: Media): Promise<void>;
|
|
20
|
-
private
|
|
21
|
-
private getFullFilePath;
|
|
22
|
-
private getFileName;
|
|
22
|
+
private getSupportedEntityId;
|
|
23
23
|
}
|
|
24
24
|
//# sourceMappingURL=file-s3-storage-provider.d.ts.map
|
|
@@ -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;
|
|
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"}
|
|
@@ -18,24 +18,22 @@ const legacy_common_entity_with_existing_id_entity_1 = require("../../entities/l
|
|
|
18
18
|
const legacy_common_with_generated_id_entity_1 = require("../../entities/legacy-common-with-generated-id.entity");
|
|
19
19
|
const file_1 = require("../file");
|
|
20
20
|
const media_repository_1 = require("../../repository/media.repository");
|
|
21
|
+
const media_download_url_service_1 = require("../media-download-url.service");
|
|
22
|
+
const media_storage_utils_1 = require("../media-storage.utils");
|
|
21
23
|
let FileS3StorageProvider = FileS3StorageProvider_1 = class FileS3StorageProvider {
|
|
22
|
-
constructor(configService, diskFileService, s3FileService, mediaRepository) {
|
|
24
|
+
constructor(configService, diskFileService, s3FileService, mediaRepository, mediaDownloadUrlService) {
|
|
23
25
|
this.configService = configService;
|
|
24
26
|
this.diskFileService = diskFileService;
|
|
25
27
|
this.s3FileService = s3FileService;
|
|
26
28
|
this.mediaRepository = mediaRepository;
|
|
29
|
+
this.mediaDownloadUrlService = mediaDownloadUrlService;
|
|
27
30
|
this.logger = new common_1.Logger(FileS3StorageProvider_1.name);
|
|
28
31
|
}
|
|
29
32
|
async storeStreams(streamPairs, entity, mediaFieldMetadata) {
|
|
30
|
-
const
|
|
31
|
-
|| entity instanceof legacy_common_entity_with_existing_id_entity_1.LegacyCommonEntityWithExistingId
|
|
32
|
-
|| entity instanceof legacy_common_with_generated_id_entity_1.LegacyCommonEntityWithGeneratedId;
|
|
33
|
-
if (!isSupportedEntity) {
|
|
34
|
-
throw new Error("Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId");
|
|
35
|
-
}
|
|
33
|
+
const entityId = this.getSupportedEntityId(entity);
|
|
36
34
|
const result = [];
|
|
37
35
|
const storageProvider = mediaFieldMetadata.mediaStorageProvider;
|
|
38
|
-
const region = this.
|
|
36
|
+
const region = (0, media_storage_utils_1.getEffectiveS3Region)(this.configService, storageProvider.region);
|
|
39
37
|
for (const [stream, fileName] of streamPairs) {
|
|
40
38
|
const bucketName = storageProvider.bucketName;
|
|
41
39
|
const chunks = [];
|
|
@@ -45,67 +43,45 @@ let FileS3StorageProvider = FileS3StorageProvider_1 = class FileS3StorageProvide
|
|
|
45
43
|
const fileData = Buffer.concat(chunks);
|
|
46
44
|
const fileSize = fileData.length;
|
|
47
45
|
await this.s3FileService.write(`${bucketName}:${fileName}`, fileData, { region });
|
|
48
|
-
const mediaEntity = await this.mediaRepository.createMedia({
|
|
49
|
-
entityId: entity.id,
|
|
50
|
-
modelMetadataId: mediaFieldMetadata.model.id,
|
|
46
|
+
const mediaEntity = await this.mediaRepository.createMedia((0, media_storage_utils_1.buildMediaRecordCreateInput)(entityId, mediaFieldMetadata, storageProvider, {
|
|
51
47
|
relativeUri: fileName,
|
|
52
48
|
fileSize,
|
|
53
|
-
|
|
54
|
-
fieldMetadataId: mediaFieldMetadata.id
|
|
55
|
-
});
|
|
49
|
+
}));
|
|
56
50
|
result.push(mediaEntity);
|
|
57
51
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
58
52
|
}
|
|
59
53
|
return result;
|
|
60
54
|
}
|
|
61
55
|
async retrieve(entity, mediaFieldMetadata) {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|| entity instanceof legacy_common_with_generated_id_entity_1.LegacyCommonEntityWithGeneratedId;
|
|
65
|
-
if (!isSupportedEntity) {
|
|
66
|
-
throw new Error("Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId");
|
|
67
|
-
}
|
|
68
|
-
const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);
|
|
56
|
+
const entityId = this.getSupportedEntityId(entity);
|
|
57
|
+
const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);
|
|
69
58
|
for (const m of media) {
|
|
70
59
|
const storageMeta = m.mediaStorageProviderMetadata;
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
m['_full_url'] = this.getFullFilePath(m);
|
|
78
|
-
}
|
|
60
|
+
const isPublic = (0, media_storage_utils_1.resolveMediaIsPublic)(storageMeta);
|
|
61
|
+
m['_full_url'] = isPublic === false
|
|
62
|
+
? await this.mediaDownloadUrlService.getPrivateUrl(m.id, m.relativeUri, storageMeta)
|
|
63
|
+
: await this.s3FileService.getUrl(`${storageMeta.bucketName}:${m.relativeUri}`, { region: (0, media_storage_utils_1.getEffectiveS3Region)(this.configService, storageMeta.region), expiresIn: 0 });
|
|
79
64
|
}
|
|
80
65
|
return media;
|
|
81
66
|
}
|
|
82
67
|
async store(files, entity, mediaFieldMetadata) {
|
|
83
|
-
const
|
|
84
|
-
|| entity instanceof legacy_common_entity_with_existing_id_entity_1.LegacyCommonEntityWithExistingId
|
|
85
|
-
|| entity instanceof legacy_common_with_generated_id_entity_1.LegacyCommonEntityWithGeneratedId;
|
|
86
|
-
if (!isSupportedEntity) {
|
|
87
|
-
throw new Error("Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId");
|
|
88
|
-
}
|
|
68
|
+
const entityId = this.getSupportedEntityId(entity);
|
|
89
69
|
const result = [];
|
|
90
70
|
const storageProvider = mediaFieldMetadata.mediaStorageProvider;
|
|
91
|
-
const region = this.
|
|
71
|
+
const region = (0, media_storage_utils_1.getEffectiveS3Region)(this.configService, storageProvider.region);
|
|
92
72
|
for (const file of files) {
|
|
93
|
-
const fileName =
|
|
73
|
+
const fileName = (0, media_storage_utils_1.buildStoredMediaFileName)(file);
|
|
94
74
|
const bucketName = storageProvider.bucketName;
|
|
95
75
|
const fileData = await this.diskFileService.read(file.path);
|
|
96
76
|
await this.s3FileService.write(`${bucketName}:${fileName}`, fileData, { contentType: file.mimetype, region });
|
|
97
77
|
await this.diskFileService.delete(file.path);
|
|
98
78
|
const awsFileUrl = fileName;
|
|
99
|
-
const mediaEntity = await this.mediaRepository.createMedia({
|
|
100
|
-
entityId: entity.id,
|
|
101
|
-
modelMetadataId: mediaFieldMetadata.model.id,
|
|
79
|
+
const mediaEntity = await this.mediaRepository.createMedia((0, media_storage_utils_1.buildMediaRecordCreateInput)(entityId, mediaFieldMetadata, storageProvider, {
|
|
102
80
|
relativeUri: awsFileUrl,
|
|
103
81
|
mimeType: file.mimetype,
|
|
104
82
|
fileSize: file.size,
|
|
105
83
|
originalFileName: file.originalname,
|
|
106
|
-
|
|
107
|
-
fieldMetadataId: mediaFieldMetadata.id
|
|
108
|
-
});
|
|
84
|
+
}));
|
|
109
85
|
result.push(mediaEntity);
|
|
110
86
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
111
87
|
}
|
|
@@ -113,16 +89,11 @@ let FileS3StorageProvider = FileS3StorageProvider_1 = class FileS3StorageProvide
|
|
|
113
89
|
return result;
|
|
114
90
|
}
|
|
115
91
|
async delete(entity, mediaFieldMetadata) {
|
|
116
|
-
const
|
|
117
|
-
|| entity instanceof legacy_common_entity_with_existing_id_entity_1.LegacyCommonEntityWithExistingId
|
|
118
|
-
|| entity instanceof legacy_common_with_generated_id_entity_1.LegacyCommonEntityWithGeneratedId;
|
|
119
|
-
if (!isSupportedEntity) {
|
|
120
|
-
throw new Error("Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId");
|
|
121
|
-
}
|
|
92
|
+
const entityId = this.getSupportedEntityId(entity);
|
|
122
93
|
const storageProvider = mediaFieldMetadata.mediaStorageProvider;
|
|
123
|
-
const region = this.
|
|
124
|
-
const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(
|
|
125
|
-
this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(
|
|
94
|
+
const region = (0, media_storage_utils_1.getEffectiveS3Region)(this.configService, storageProvider.region);
|
|
95
|
+
const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);
|
|
96
|
+
this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id);
|
|
126
97
|
for (const media of existingMedia) {
|
|
127
98
|
const bucketName = storageProvider.bucketName;
|
|
128
99
|
await this.s3FileService.delete(`${bucketName}:${media.relativeUri}`, { region });
|
|
@@ -136,18 +107,17 @@ let FileS3StorageProvider = FileS3StorageProvider_1 = class FileS3StorageProvide
|
|
|
136
107
|
if (!storageProvider?.bucketName || !media?.relativeUri) {
|
|
137
108
|
return;
|
|
138
109
|
}
|
|
139
|
-
const region = this.
|
|
110
|
+
const region = (0, media_storage_utils_1.getEffectiveS3Region)(this.configService, storageProvider.region);
|
|
140
111
|
await this.s3FileService.delete(`${storageProvider.bucketName}:${media.relativeUri}`, { region });
|
|
141
112
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return `${file.filename}-${file.originalname}`;
|
|
113
|
+
getSupportedEntityId(entity) {
|
|
114
|
+
const isSupportedEntity = entity instanceof common_entity_1.CommonEntity
|
|
115
|
+
|| entity instanceof legacy_common_entity_with_existing_id_entity_1.LegacyCommonEntityWithExistingId
|
|
116
|
+
|| entity instanceof legacy_common_with_generated_id_entity_1.LegacyCommonEntityWithGeneratedId;
|
|
117
|
+
if (!isSupportedEntity) {
|
|
118
|
+
throw new Error("Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId");
|
|
119
|
+
}
|
|
120
|
+
return entity.id;
|
|
151
121
|
}
|
|
152
122
|
};
|
|
153
123
|
exports.FileS3StorageProvider = FileS3StorageProvider;
|
|
@@ -156,6 +126,7 @@ exports.FileS3StorageProvider = FileS3StorageProvider = FileS3StorageProvider_1
|
|
|
156
126
|
__metadata("design:paramtypes", [config_1.ConfigService,
|
|
157
127
|
file_1.DiskFileService,
|
|
158
128
|
file_1.S3FileService,
|
|
159
|
-
media_repository_1.MediaRepository
|
|
129
|
+
media_repository_1.MediaRepository,
|
|
130
|
+
media_download_url_service_1.MediaDownloadUrlService])
|
|
160
131
|
], FileS3StorageProvider);
|
|
161
132
|
//# sourceMappingURL=file-s3-storage-provider.js.map
|
|
@@ -1 +1 @@
|
|
|
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\";\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 ) { }\n\n async storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n const isSupportedEntity = entity instanceof CommonEntity\n || entity instanceof LegacyCommonEntityWithExistingId\n || entity instanceof LegacyCommonEntityWithGeneratedId;\n if (!isSupportedEntity) {\n throw new Error(\"Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId\");\n }\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n const region = this.getEffectiveRegion(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 // @ts-ignore\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: fileName,\n fileSize,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\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 isSupportedEntity = entity instanceof CommonEntity\n || entity instanceof LegacyCommonEntityWithExistingId\n || entity instanceof LegacyCommonEntityWithGeneratedId;\n if (!isSupportedEntity) {\n throw new Error(\"Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId\"); // FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n // @ts-ignore\n const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, 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 region = this.getEffectiveRegion(storageMeta.region);\n if (storageMeta.isPublic === false) {\n // Generate signed URL\n const expiryInSeconds = (storageMeta.signedUrlExpiry ?? 60) * 60;\n m['_full_url'] = await this.s3FileService.getUrl(`${storageMeta?.bucketName}:${m.relativeUri}`, { expiresIn: expiryInSeconds, region });\n } else {\n // Public S3 or local filesystem: use normal URL\n m['_full_url'] = this.getFullFilePath(m);\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 isSupportedEntity = entity instanceof CommonEntity\n || entity instanceof LegacyCommonEntityWithExistingId\n || entity instanceof LegacyCommonEntityWithGeneratedId;\n if (!isSupportedEntity) {\n throw new Error(\"Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId\"); // FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const result: Media[] = [];\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n const region = this.getEffectiveRegion(storageProvider.region);\n\n for (const file of files) {\n const fileName = this.getFileName(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 // @ts-ignore\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: awsFileUrl,\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\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 isSupportedEntity = entity instanceof CommonEntity\n || entity instanceof LegacyCommonEntityWithExistingId\n || entity instanceof LegacyCommonEntityWithGeneratedId;\n if (!isSupportedEntity) {\n throw new Error(\"Entity must be an instance of CommonEntity, LegacyCommonEntityWithExistingId or LegacyCommonEntityWithGeneratedId\"); // FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const storageProvider = mediaFieldMetadata.mediaStorageProvider;\n const region = this.getEffectiveRegion(storageProvider.region);\n\n // @ts-ignore\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n // @ts-ignore\n this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entity.id, 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 = this.getEffectiveRegion(storageProvider.region);\n await this.s3FileService.delete(`${storageProvider.bucketName}:${media.relativeUri}`, { region });\n }\n\n /**\n * Get the effective region to use for S3 operations.\n * Uses the provider-specific region if configured, otherwise falls back to env variable.\n */\n private getEffectiveRegion(providerRegion?: string): string | undefined {\n return providerRegion || this.configService.get('S3_AWS_REGION_NAME');\n }\n\n private getFullFilePath(media: Media): string {\n // Use provider region if available, fallback to env variable\n const region = this.getEffectiveRegion(media.mediaStorageProviderMetadata.region);\n // https://lunarismedia.s3.ap-south-1.amazonaws.com/LUNARIS_CP_REGISTRATION_CREATIVE.jpg\n return `https://${media.mediaStorageProviderMetadata.bucketName}.s3.${region}.amazonaws.com/${media.relativeUri}`;\n }\n\n private getFileName(file: Express.Multer.File): string {\n return `${file.filename}-${file.originalname}`;\n }\n}\n"]}
|
|
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,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,0CAAoB,EAAC,WAAW,CAAC,CAAC;YACnD,CAAC,CAAC,WAAW,CAAC,GAAG,QAAQ,KAAK,KAAK;gBAC/B,CAAC,CAAC,MAAM,IAAI,CAAC,uBAAuB,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC;gBACpF,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,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;AA5IY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;qCAK2B,sBAAa;QACnB,sBAAe;QACjB,oBAAa;QACX,kCAAe;QACC,oDAAuB;GAR5D,qBAAqB,CA4IjC","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,4 +1,3 @@
|
|
|
1
|
-
import { ConfigService } from "@nestjs/config";
|
|
2
1
|
import { FieldMetadata } from "../../entities/field-metadata.entity";
|
|
3
2
|
import { Media } from "../../entities/media.entity";
|
|
4
3
|
import { MediaStorageProvider } from "../../interfaces";
|
|
@@ -6,19 +5,20 @@ import { MediaRepository } from "../../repository/media.repository";
|
|
|
6
5
|
import { DiskFileService } from "../../services/file";
|
|
7
6
|
import { Readable } from "stream";
|
|
8
7
|
import { SettingService } from "../setting.service";
|
|
8
|
+
import { MediaDownloadUrlService } from "../../services/media-download-url.service";
|
|
9
9
|
export declare class FileStorageProvider<T> implements MediaStorageProvider<T> {
|
|
10
|
-
private readonly configService;
|
|
11
10
|
readonly fileService: DiskFileService;
|
|
12
11
|
readonly mediaRepository: MediaRepository;
|
|
13
12
|
private readonly settingService;
|
|
13
|
+
private readonly mediaDownloadUrlService;
|
|
14
14
|
private logger;
|
|
15
|
-
constructor(
|
|
15
|
+
constructor(fileService: DiskFileService, mediaRepository: MediaRepository, settingService: SettingService, mediaDownloadUrlService: MediaDownloadUrlService);
|
|
16
16
|
retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
|
|
17
17
|
store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
|
|
18
18
|
storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
|
|
19
19
|
delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void>;
|
|
20
20
|
deleteByMediaRecord(media: Media): Promise<void>;
|
|
21
|
-
private
|
|
22
|
-
private
|
|
21
|
+
private resolveMediaStorageProvider;
|
|
22
|
+
private getEntityId;
|
|
23
23
|
}
|
|
24
24
|
//# sourceMappingURL=file-storage-provider.d.ts.map
|
|
@@ -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,
|
|
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"}
|
|
@@ -45,44 +45,45 @@ var FileStorageProvider_1;
|
|
|
45
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
46
|
exports.FileStorageProvider = void 0;
|
|
47
47
|
const common_1 = require("@nestjs/common");
|
|
48
|
-
const config_1 = require("@nestjs/config");
|
|
49
48
|
const media_repository_1 = require("../../repository/media.repository");
|
|
50
49
|
const file_1 = require("../file");
|
|
51
|
-
const path = __importStar(require("path"));
|
|
52
50
|
const fs = __importStar(require("fs"));
|
|
53
51
|
const setting_service_1 = require("../setting.service");
|
|
54
|
-
const
|
|
52
|
+
const media_download_url_service_1 = require("../media-download-url.service");
|
|
53
|
+
const media_storage_utils_1 = require("../media-storage.utils");
|
|
55
54
|
let FileStorageProvider = FileStorageProvider_1 = class FileStorageProvider {
|
|
56
|
-
constructor(
|
|
57
|
-
this.configService = configService;
|
|
55
|
+
constructor(fileService, mediaRepository, settingService, mediaDownloadUrlService) {
|
|
58
56
|
this.fileService = fileService;
|
|
59
57
|
this.mediaRepository = mediaRepository;
|
|
60
58
|
this.settingService = settingService;
|
|
59
|
+
this.mediaDownloadUrlService = mediaDownloadUrlService;
|
|
61
60
|
this.logger = new common_1.Logger(FileStorageProvider_1.name);
|
|
62
61
|
}
|
|
63
62
|
async retrieve(entity, mediaFieldMetadata) {
|
|
64
|
-
const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity
|
|
63
|
+
const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(this.getEntityId(entity), mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);
|
|
65
64
|
for (const m of media) {
|
|
66
|
-
|
|
65
|
+
const storageProvider = this.resolveMediaStorageProvider(m, mediaFieldMetadata);
|
|
66
|
+
const isPublic = (0, media_storage_utils_1.resolveMediaIsPublic)(storageProvider);
|
|
67
|
+
m['_full_url'] = isPublic === false
|
|
68
|
+
? await this.mediaDownloadUrlService.getPrivateUrl(m.id, m.relativeUri, storageProvider)
|
|
69
|
+
: await this.fileService.getUrl((0, media_storage_utils_1.buildDiskMediaPath)(m.relativeUri, this.settingService, storageProvider));
|
|
67
70
|
}
|
|
68
71
|
return media;
|
|
69
72
|
}
|
|
70
73
|
async store(files, entity, mediaFieldMetadata) {
|
|
71
74
|
const result = [];
|
|
75
|
+
const storageProvider = mediaFieldMetadata.mediaStorageProvider;
|
|
72
76
|
for (const file of files) {
|
|
73
|
-
const
|
|
77
|
+
const fileName = (0, media_storage_utils_1.buildStoredMediaFileName)(file);
|
|
78
|
+
const fileStoragePath = (0, media_storage_utils_1.buildDiskMediaPath)(fileName, this.settingService, storageProvider);
|
|
74
79
|
await this.fileService.copy(file.path, fileStoragePath);
|
|
75
80
|
await this.fileService.delete(file.path);
|
|
76
|
-
const mediaEntity = await this.mediaRepository.createMedia({
|
|
77
|
-
|
|
78
|
-
modelMetadataId: mediaFieldMetadata.model.id,
|
|
79
|
-
relativeUri: this.getFileName(file),
|
|
81
|
+
const mediaEntity = await this.mediaRepository.createMedia((0, media_storage_utils_1.buildMediaRecordCreateInput)(this.getEntityId(entity), mediaFieldMetadata, storageProvider, {
|
|
82
|
+
relativeUri: fileName,
|
|
80
83
|
mimeType: file.mimetype,
|
|
81
84
|
fileSize: file.size,
|
|
82
85
|
originalFileName: file.originalname,
|
|
83
|
-
|
|
84
|
-
fieldMetadataId: mediaFieldMetadata.id
|
|
85
|
-
});
|
|
86
|
+
}));
|
|
86
87
|
result.push(mediaEntity);
|
|
87
88
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
88
89
|
}
|
|
@@ -91,56 +92,51 @@ let FileStorageProvider = FileStorageProvider_1 = class FileStorageProvider {
|
|
|
91
92
|
}
|
|
92
93
|
async storeStreams(streamPairs, entity, mediaFieldMetadata) {
|
|
93
94
|
const result = [];
|
|
95
|
+
const storageProvider = mediaFieldMetadata.mediaStorageProvider;
|
|
94
96
|
for (const pair of streamPairs) {
|
|
95
97
|
const stream = pair[0];
|
|
96
98
|
const fileName = pair[1];
|
|
97
|
-
const fullPath =
|
|
99
|
+
const fullPath = (0, media_storage_utils_1.buildDiskMediaPath)(fileName, this.settingService, storageProvider);
|
|
98
100
|
await this.fileService.writeStream(fullPath, stream);
|
|
99
101
|
const { size: fileSize } = await fs.promises.stat(fullPath);
|
|
100
|
-
const mediaEntity = await this.mediaRepository.createMedia({
|
|
101
|
-
entityId: entity.id,
|
|
102
|
-
modelMetadataId: mediaFieldMetadata.model.id,
|
|
102
|
+
const mediaEntity = await this.mediaRepository.createMedia((0, media_storage_utils_1.buildMediaRecordCreateInput)(this.getEntityId(entity), mediaFieldMetadata, storageProvider, {
|
|
103
103
|
relativeUri: fileName,
|
|
104
104
|
fileSize,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
});
|
|
105
|
+
}));
|
|
106
|
+
result.push(mediaEntity);
|
|
108
107
|
this.logger.debug(`Stored media with`, mediaEntity);
|
|
109
108
|
}
|
|
110
109
|
;
|
|
111
110
|
return result;
|
|
112
111
|
}
|
|
113
112
|
async delete(entity, mediaFieldMetadata) {
|
|
114
|
-
const
|
|
115
|
-
this.mediaRepository.
|
|
113
|
+
const entityId = this.getEntityId(entity);
|
|
114
|
+
const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);
|
|
115
|
+
await this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entityId, mediaFieldMetadata.id, mediaFieldMetadata.model.id);
|
|
116
116
|
for (const media of existingMedia) {
|
|
117
|
-
|
|
117
|
+
const storageProvider = this.resolveMediaStorageProvider(media, mediaFieldMetadata);
|
|
118
|
+
await this.fileService.delete((0, media_storage_utils_1.buildDiskMediaPath)(media.relativeUri, this.settingService, storageProvider));
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
async deleteByMediaRecord(media) {
|
|
121
122
|
if (!media?.relativeUri) {
|
|
122
123
|
return;
|
|
123
124
|
}
|
|
124
|
-
await this.fileService.delete(
|
|
125
|
+
await this.fileService.delete((0, media_storage_utils_1.buildDiskMediaPath)(media.relativeUri, this.settingService, media.mediaStorageProviderMetadata));
|
|
125
126
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|| default_settings_provider_service_1.DEFAULT_MEDIA_FILE_STORAGE_DIR;
|
|
129
|
-
if (path.isAbsolute(fileName) || fileName.startsWith(`${base}/`)) {
|
|
130
|
-
return fileName;
|
|
131
|
-
}
|
|
132
|
-
return `${base}/${fileName}`;
|
|
127
|
+
resolveMediaStorageProvider(media, mediaFieldMetadata) {
|
|
128
|
+
return media.mediaStorageProviderMetadata || mediaFieldMetadata?.mediaStorageProvider;
|
|
133
129
|
}
|
|
134
|
-
|
|
135
|
-
return
|
|
130
|
+
getEntityId(entity) {
|
|
131
|
+
return entity.id;
|
|
136
132
|
}
|
|
137
133
|
};
|
|
138
134
|
exports.FileStorageProvider = FileStorageProvider;
|
|
139
135
|
exports.FileStorageProvider = FileStorageProvider = FileStorageProvider_1 = __decorate([
|
|
140
136
|
(0, common_1.Injectable)(),
|
|
141
|
-
__metadata("design:paramtypes", [
|
|
142
|
-
file_1.DiskFileService,
|
|
137
|
+
__metadata("design:paramtypes", [file_1.DiskFileService,
|
|
143
138
|
media_repository_1.MediaRepository,
|
|
144
|
-
setting_service_1.SettingService
|
|
139
|
+
setting_service_1.SettingService,
|
|
140
|
+
media_download_url_service_1.MediaDownloadUrlService])
|
|
145
141
|
], FileStorageProvider);
|
|
146
142
|
//# sourceMappingURL=file-storage-provider.js.map
|
|
@@ -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 { ConfigService } from \"@nestjs/config\";\nimport { CommonEntity } from \"src/entities/common.entity\";\nimport { FieldMetadata } from \"src/entities/field-metadata.entity\";\nimport { Media } from \"src/entities/media.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 path from \"path\";\nimport * as fs from \"fs\";\nimport { SettingService } from \"../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@Injectable()\nexport class FileStorageProvider<T> implements MediaStorageProvider<T> {\n private logger = new Logger(FileStorageProvider.name);\n\n constructor(\n // @Inject(appBuilderConfig.KEY)\n // private readonly appBuilderConfiguration: ConfigType<typeof appBuilderConfig>,\n private readonly configService: ConfigService,\n readonly fileService: DiskFileService,\n readonly mediaRepository: MediaRepository,\n private readonly settingService: SettingService\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(entity.id, 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 m['_full_url'] = `${this.settingService.getConfigValue<SolidCoreSetting>(\"baseUrl\")}/${this.getFullFilePath(m.relativeUri)}`;\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 for (const file of files) {\n // Store the file in the configured file storage directory\n const fileStoragePath = this.getFullFilePath(this.getFileName(file));\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 //@ts-ignore\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: this.getFileName(file),\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\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 for (const pair of streamPairs) {\n const stream = pair[0];\n const fileName = pair[1];\n const fullPath = this.getFullFilePath(fileName);\n await this.fileService.writeStream(fullPath, stream);\n const { size: fileSize } = await fs.promises.stat(fullPath);\n const mediaEntity = await this.mediaRepository.createMedia({\n //@ts-ignore\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: fileName,\n fileSize,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\n }) as unknown as Media;\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 //@ts-ignore\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n //@ts-ignore\n this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id);\n\n for (const media of existingMedia) {\n await this.fileService.delete(this.getFullFilePath(media.relativeUri));\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(this.getFullFilePath(media.relativeUri));\n }\n\n private getFullFilePath(fileName: string): string {\n const base = this.settingService.getConfigValue<SolidCoreSetting>(\"fileStorageDir\")\n || DEFAULT_MEDIA_FILE_STORAGE_DIR;\n if (path.isAbsolute(fileName) || fileName.startsWith(`${base}/`)) {\n return fileName;\n }\n return `${base}/${fileName}`;\n }\n\n private getFileName(file: Express.Multer.File): string {\n return `${file.filename}-${file.originalname}`;\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"]}
|
|
@@ -18,6 +18,7 @@ export declare class RoleMetadataService extends CRUDService<RoleMetadata> {
|
|
|
18
18
|
createRolesIfNotExists(roles: CreateRoleMetadataDto[]): Promise<void>;
|
|
19
19
|
private resolveRoleModule;
|
|
20
20
|
addAllPermissionsToRole(roleName: string): Promise<RoleMetadata>;
|
|
21
|
+
addAllPermissionsToRoleExceptPrefixes(roleName: string, excludedPermissionPrefixes: string[]): Promise<RoleMetadata>;
|
|
21
22
|
addPermissionsToRole(roleName: string, permissionNames: string[]): Promise<RoleMetadata>;
|
|
22
23
|
addPermissionToRole(roleName: string, permissionName: string[]): Promise<RoleMetadata>;
|
|
23
24
|
private _addPermissionsToRole;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-metadata.service.d.ts","sourceRoot":"","sources":["../../src/services/role-metadata.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAM,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,4BAA4B,EAAE,MAAM,+CAA+C,CAAC;AAC7F,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAGzE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAEhE,qBACa,mBAAoB,SAAQ,WAAW,CAAC,YAAY,CAAC;IAM9D,QAAQ,CAAC,aAAa,EAAE,aAAa;IAGrC,QAAQ,CAAC,IAAI,EAAE,sBAAsB;IAGrC,QAAQ,CAAC,oBAAoB,EAAE,4BAA4B;IAC3D,QAAQ,CAAC,SAAS,EAAE,SAAS;IAZ/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAAO;gBAI1C,aAAa,EAAE,aAAa,EAG5B,IAAI,EAAE,sBAAsB,EAG5B,oBAAoB,EAAE,4BAA4B,EAClD,SAAS,EAAE,SAAS;IAMzB,cAAc,CAAC,QAAQ,EAAE,MAAM;IAe/B,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAevD,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,EAAE;YA0D7C,iBAAiB;IAgBzB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIhE,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAIxF,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE;YAItD,qBAAqB;
|
|
1
|
+
{"version":3,"file":"role-metadata.service.d.ts","sourceRoot":"","sources":["../../src/services/role-metadata.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAM,MAAM,SAAS,CAAC;AAG5C,OAAO,EAAE,4BAA4B,EAAE,MAAM,+CAA+C,CAAC;AAC7F,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAGzE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAEhE,qBACa,mBAAoB,SAAQ,WAAW,CAAC,YAAY,CAAC;IAM9D,QAAQ,CAAC,aAAa,EAAE,aAAa;IAGrC,QAAQ,CAAC,IAAI,EAAE,sBAAsB;IAGrC,QAAQ,CAAC,oBAAoB,EAAE,4BAA4B;IAC3D,QAAQ,CAAC,SAAS,EAAE,SAAS;IAZ/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAAO;gBAI1C,aAAa,EAAE,aAAa,EAG5B,IAAI,EAAE,sBAAsB,EAG5B,oBAAoB,EAAE,4BAA4B,EAClD,SAAS,EAAE,SAAS;IAMzB,cAAc,CAAC,QAAQ,EAAE,MAAM;IAe/B,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAevD,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,EAAE;YA0D7C,iBAAiB;IAgBzB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIhE,qCAAqC,CAAC,QAAQ,EAAE,MAAM,EAAE,0BAA0B,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAIpH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAIxF,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE;YAItD,qBAAqB;IAkD7B,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;YAsBrF,uBAAuB;YAUvB,qBAAqB;IAqBnC,OAAO,CAAC,yBAAyB;YAmBnB,4BAA4B;CAsB3C"}
|
|
@@ -110,13 +110,16 @@ let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService exte
|
|
|
110
110
|
async addAllPermissionsToRole(roleName) {
|
|
111
111
|
return await this._addPermissionsToRole(roleName, null);
|
|
112
112
|
}
|
|
113
|
+
async addAllPermissionsToRoleExceptPrefixes(roleName, excludedPermissionPrefixes) {
|
|
114
|
+
return await this._addPermissionsToRole(roleName, null, excludedPermissionPrefixes);
|
|
115
|
+
}
|
|
113
116
|
async addPermissionsToRole(roleName, permissionNames) {
|
|
114
117
|
return await this._addPermissionsToRole(roleName, permissionNames);
|
|
115
118
|
}
|
|
116
119
|
async addPermissionToRole(roleName, permissionName) {
|
|
117
120
|
return await this._addPermissionsToRole(roleName, permissionName);
|
|
118
121
|
}
|
|
119
|
-
async _addPermissionsToRole(roleName, permissionNames) {
|
|
122
|
+
async _addPermissionsToRole(roleName, permissionNames, excludedPermissionPrefixes = []) {
|
|
120
123
|
const role = await this.repo.findOne({
|
|
121
124
|
where: { name: roleName },
|
|
122
125
|
select: {
|
|
@@ -128,7 +131,7 @@ let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService exte
|
|
|
128
131
|
throw new Error(`Role '${roleName}' not found.`);
|
|
129
132
|
}
|
|
130
133
|
const joinInfo = this.getRolePermissionJoinInfo();
|
|
131
|
-
const targetPermissions = await this.loadTargetPermissions(permissionNames);
|
|
134
|
+
const targetPermissions = await this.loadTargetPermissions(permissionNames, excludedPermissionPrefixes);
|
|
132
135
|
if (!permissionNames || permissionNames.length === 0) {
|
|
133
136
|
await this.entityManager
|
|
134
137
|
.createQueryBuilder()
|
|
@@ -179,20 +182,20 @@ let RoleMetadataService = RoleMetadataService_1 = class RoleMetadataService exte
|
|
|
179
182
|
}
|
|
180
183
|
return existingPermission;
|
|
181
184
|
}
|
|
182
|
-
async loadTargetPermissions(permissionNames) {
|
|
185
|
+
async loadTargetPermissions(permissionNames, excludedPermissionPrefixes = []) {
|
|
183
186
|
if (permissionNames && permissionNames.length !== 0) {
|
|
184
187
|
const uniquePermissionNames = [...new Set(permissionNames)];
|
|
185
188
|
const permissions = await this.permissionRepository.find({ where: { name: (0, typeorm_2.In)(uniquePermissionNames) } });
|
|
186
189
|
if (permissions.length !== uniquePermissionNames.length) {
|
|
187
190
|
throw new Error(`One or more permissions not found.`);
|
|
188
191
|
}
|
|
189
|
-
return permissions;
|
|
192
|
+
return permissions.filter((permission) => !excludedPermissionPrefixes.some((prefix) => permission.name.startsWith(prefix)));
|
|
190
193
|
}
|
|
191
194
|
const permissions = await this.permissionRepository.find();
|
|
192
195
|
if (permissions.length === 0) {
|
|
193
196
|
throw new Error(`No permissions configured in the system. Did you forget to run the PermissionSeederService?`);
|
|
194
197
|
}
|
|
195
|
-
return permissions;
|
|
198
|
+
return permissions.filter((permission) => !excludedPermissionPrefixes.some((prefix) => permission.name.startsWith(prefix)));
|
|
196
199
|
}
|
|
197
200
|
getRolePermissionJoinInfo() {
|
|
198
201
|
const relation = this.repo.metadata.relations.find((candidate) => candidate.propertyName === 'permissions');
|